Aegisub/traydict/kana_table.cpp
Rodrigo Braz Monteiro 4a2c0dbbfa Added the kanamemo & traydict side projects to repository
Originally committed to SVN as r436.
2006-06-29 23:14:54 +00:00

432 lines
10 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Copyright (c) 2006, Rodrigo Braz Monteiro
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of the Aegisub Group nor the names of its contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// -----------------------------------------------------------------------------
//
// AEGISUB
//
// Website: http://aegisub.cellosoft.com
// Contact: mailto:zeratul@cellosoft.com
//
///////////
// Headers
#include "kana_table.h"
///////////////
// Constructor
KanaTable::KanaTable() {
level = 0;
groups[0] = 0;
groups[1] = 0;
BeginGroup();
Insert(L"",L"",L"a");
Insert(L"",L"",L"i");
Insert(L"",L"",L"u");
Insert(L"",L"",L"e");
Insert(L"",L"",L"o");
BeginGroup();
Insert(L"",L"",L"ka");
Insert(L"",L"",L"ki");
Insert(L"",L"",L"ku");
Insert(L"",L"",L"ke");
Insert(L"",L"",L"ko");
BeginGroup();
Insert(L"",L"",L"sa");
Insert(L"",L"",L"shi");
Insert(L"",L"",L"su");
Insert(L"",L"",L"se");
Insert(L"",L"",L"so");
BeginGroup();
Insert(L"",L"",L"ta");
Insert(L"",L"",L"chi");
Insert(L"",L"",L"tsu");
Insert(L"",L"",L"te");
Insert(L"",L"",L"to");
BeginGroup();
Insert(L"",L"",L"na");
Insert(L"",L"",L"ni");
Insert(L"",L"",L"nu");
Insert(L"",L"",L"ne");
Insert(L"",L"",L"no");
BeginGroup();
Insert(L"",L"",L"ha");
Insert(L"",L"",L"hi");
Insert(L"",L"",L"fu");
Insert(L"",L"",L"he");
Insert(L"",L"",L"ho");
BeginGroup();
Insert(L"",L"",L"ma");
Insert(L"",L"",L"mi");
Insert(L"",L"",L"mu");
Insert(L"",L"",L"me");
Insert(L"",L"",L"mo");
BeginGroup();
Insert(L"",L"",L"ya");
Insert(L"",L"",L"yu");
Insert(L"",L"",L"yo");
BeginGroup();
Insert(L"",L"",L"ra");
Insert(L"",L"",L"ri");
Insert(L"",L"",L"ru");
Insert(L"",L"",L"re");
Insert(L"",L"",L"ro");
BeginGroup();
Insert(L"",L"",L"wa");
Insert(L"",L"",L"wi");
Insert(L"",L"",L"we");
Insert(L"",L"",L"wo");
BeginGroup();
level--;
Insert(L"",L"",L"n");
BeginGroup();
Insert(L"",L"",L"ga");
Insert(L"",L"",L"gi");
Insert(L"",L"",L"gu");
Insert(L"",L"",L"ge");
Insert(L"",L"",L"go");
BeginGroup();
Insert(L"",L"",L"za");
Insert(L"",L"",L"ji");
Insert(L"",L"",L"zu");
Insert(L"",L"",L"ze");
Insert(L"",L"",L"zo");
BeginGroup();
Insert(L"",L"",L"da");
Insert(L"",L"",L"ji");
Insert(L"",L"",L"zu");
Insert(L"",L"",L"de");
Insert(L"",L"",L"do");
BeginGroup();
Insert(L"",L"",L"ba");
Insert(L"",L"",L"bi");
Insert(L"",L"",L"bu");
Insert(L"",L"",L"be");
Insert(L"",L"",L"bo");
BeginGroup();
Insert(L"",L"",L"pa");
Insert(L"",L"",L"pi");
Insert(L"",L"",L"pu");
Insert(L"",L"",L"pe");
Insert(L"",L"",L"po");
BeginGroup();
Insert(L"きゃ",L"キャ",L"kya");
Insert(L"きゅ",L"キュ",L"kyu");
Insert(L"きょ",L"キョ",L"kyo");
BeginGroup();
Insert(L"しゃ",L"シャ",L"sha");
Insert(L"しゅ",L"シュ",L"shu");
Insert(L"しょ",L"ショ",L"sho");
BeginGroup();
Insert(L"ちゃ",L"チャ",L"cha");
Insert(L"ちゅ",L"チュ",L"chu");
Insert(L"ちょ",L"チョ",L"cho");
BeginGroup();
Insert(L"にゃ",L"ニャ",L"nya");
Insert(L"にゅ",L"ニュ",L"nyu");
Insert(L"にょ",L"ニョ",L"nyo");
BeginGroup();
Insert(L"ひゃ",L"ヒャ",L"hya");
Insert(L"ひゅ",L"ヒュ",L"hyu");
Insert(L"ひょ",L"ヒョ",L"hyo");
BeginGroup();
Insert(L"みゃ",L"ミャ",L"mya");
Insert(L"みゅ",L"ミュ",L"myu");
Insert(L"みょ",L"ミョ",L"myo");
BeginGroup();
Insert(L"りゃ",L"リャ",L"rya");
Insert(L"りゅ",L"リュ",L"ryu");
Insert(L"りょ",L"リョ",L"ryo");
BeginGroup();
Insert(L"ぎゃ",L"ギャ",L"gya");
Insert(L"ぎゅ",L"ギュ",L"gyu");
Insert(L"ぎょ",L"ギョ",L"gyo");
BeginGroup();
Insert(L"じゃ",L"ジャ",L"ja");
Insert(L"じゅ",L"ジュ",L"ju");
Insert(L"じょ",L"ジョ",L"jo");
BeginGroup();
Insert(L"ぢゃ",L"ヂャ",L"ja");
Insert(L"ぢゅ",L"ヂュ",L"ju");
Insert(L"ぢょ",L"ヂョ",L"jo");
BeginGroup();
Insert(L"びゃ",L"ビャ",L"bya");
Insert(L"びゅ",L"ビュ",L"byu");
Insert(L"びょ",L"ビョ",L"byo");
BeginGroup();
Insert(L"ぴゃ",L"ピャ",L"pya");
Insert(L"ぴゅ",L"ピュ",L"pyu");
Insert(L"ぴょ",L"ピョ",L"pyo");
BeginGroup();
Insert(L"",L"ファ",L"fa");
Insert(L"",L"フィ",L"fi");
Insert(L"",L"フェ",L"fe");
Insert(L"",L"フォ",L"fo");
BeginGroup();
Insert(L"",L"ヴァ",L"va");
Insert(L"",L"ヴィ",L"vi");
Insert(L"",L"",L"vu");
Insert(L"",L"ヴェ",L"ve");
Insert(L"",L"ヴォ",L"vo");
Insert(L"",L"フュ",L"fyu");
BeginGroup();
Insert(L"",L"イェ",L"ye");
Insert(L"",L"ウィ",L"wi");
Insert(L"",L"ウェ",L"we");
Insert(L"",L"ウォ",L"wo");
BeginGroup();
Insert(L"",L"ヴャ",L"vya");
Insert(L"",L"ヴュ",L"vyu");
Insert(L"",L"ヴョ",L"vyo");
BeginGroup();
Insert(L"",L"シェ",L"she");
Insert(L"",L"ジェ",L"je");
Insert(L"",L"チェ",L"che");
BeginGroup();
Insert(L"",L"ティ",L"ti");
Insert(L"",L"テゥ",L"tu");
Insert(L"",L"テュ",L"tyu");
BeginGroup();
Insert(L"",L"ディ",L"di");
Insert(L"",L"デゥ",L"du");
Insert(L"",L"デゥ",L"dyu");
BeginGroup();
Insert(L"",L"ツァ",L"tsa");
Insert(L"",L"ツィ",L"tsi");
Insert(L"",L"ツェ",L"tse");
Insert(L"",L"ツォ",L"tso");
}
//////////////
// Destructor
KanaTable::~KanaTable() {
}
///////////////
// Begin group
void KanaTable::BeginGroup() {
curGroup = _T("");
level++;
}
//////////
// Insert
void KanaTable::Insert(wchar_t *hira,wchar_t *kata,wchar_t *hep) {
#ifdef _UNICODE
KanaEntry entry(hira,kata,hep);
if (curGroup.IsEmpty()) curGroup = hep;
entry.group = curGroup;
entry.level = level;
if (!entry.hiragana.IsEmpty() && level > groups[0]) groups[0] = level;
if (!entry.katakana.IsEmpty() && level > groups[1]) groups[1] = level;
entries.push_back(entry);
#endif
}
/////////////////////
// Number of entries
int KanaTable::GetNumberEntries(int level) const {
if (level == -1) return entries.size();
else {
int count = 0;
int n = entries.size();
for (int i=0;i<n;i++) {
if (entries[i].level <= level) count++;
}
return count;
}
}
////////////////////////
// Get a specific entry
const KanaEntry &KanaTable::GetEntry(int i) const {
return entries.at(i);
}
//////////////////////////
// Find a specific romaji
const KanaEntry *KanaTable::FindByRomaji(wxString romaji) const {
int n = entries.size();
for (int i=0;i<n;i++) {
if (entries[i].hepburn == romaji) return &entries[i];
}
return NULL;
}
////////////////////////
// Find a specific kana
const KanaEntry *KanaTable::FindByKana(wxString kana) const {
int n = entries.size();
for (int i=0;i<n;i++) {
if (entries[i].hiragana == kana) return &entries[i];
if (entries[i].katakana == kana) return &entries[i];
}
return NULL;
}
/////////////////////////////////////////////
// Get number of levels for a specific table
int KanaTable::GetLevels(int table) const {
return groups[table];
}
//////////////////////////
// Convert kana to romaji
wxString KanaTable::KanaToRomaji(wxString kana,int type) {
// Prepare
wxString lastSyl;
wxString final;
bool ltsu = false;
bool longVowel = false;
// Look up the entries
for (size_t i=0;i<kana.Length();i++) {
// Find syllable
const KanaEntry *cur;
cur = FindByKana(kana.Mid(i,2));
if (cur) i++;
else cur = FindByKana(kana.Mid(i,1));
// Check if it's little tsu or long vowel in katakana
if (!cur) {
if (kana.Mid(i,1) == _T("") || kana.Mid(i,1) == _T("") || kana.Mid(i,1) == _T("")) {
ltsu = true;
continue;
}
if (kana.Mid(i,1) == _T("") || kana.Mid(i,1) == _T("-")) {
longVowel = true;
}
}
// Append
if (cur || longVowel) {
bool vetoAdd = false;
// Hepburn
if (type == 1) {
if (longVowel) {
longVowel = false;
final += 0x304;
vetoAdd = true;
}
else {
// Check for need to add apostrophe
wxString fl;
if (lastSyl == _T("n")) {
fl = cur->hepburn.Left(1);
bool add = false;
if (fl == _T("y") || fl == _T("a") || fl == _T("e") || fl == _T("i") || fl == _T("o") || fl == _T("u")) add = true;
if (fl == _T("n") && cur->hiragana == _T("")) add = true;
if (add) final += _T("'");
}
// Check if it needs to add a macron
wxString last = lastSyl.Right(1);
wxString curV = cur->hepburn;
if ((last == _T("o") && curV == _T("u")) || (last == curV && last != lastSyl && last != _T("n"))) {
final += 0x304;
vetoAdd = true;
}
}
}
// Wapura
else {
if (longVowel) {
longVowel = false;
final += lastSyl.Right(1);
vetoAdd = true;
}
}
// Add syllable
if (!vetoAdd) {
// Little tsu
if (ltsu) {
ltsu = false;
final += cur->hepburn.Left(1);
}
// Standard
final += cur->hepburn;
}
// Set last
if (cur) lastSyl = cur->hepburn;
}
}
return final;
}