diff options
| author | Walker Thompson <walker.thompson@urz.uni-heidelberg.de> | 2026-06-03 21:29:42 +0200 |
|---|---|---|
| committer | Walker Thompson <walker.thompson@urz.uni-heidelberg.de> | 2026-06-03 21:29:42 +0200 |
| commit | 25b73b9e3afe877b08816a6eaab5c1e95b5cadfd (patch) | |
| tree | 82c1cf1263057e198abed6329ac76d863021e033 /translit.cpp | |
Initial commit
Diffstat (limited to 'translit.cpp')
| -rw-r--r-- | translit.cpp | 219 |
1 files changed, 219 insertions, 0 deletions
diff --git a/translit.cpp b/translit.cpp new file mode 100644 index 0000000..7a54cf3 --- /dev/null +++ b/translit.cpp @@ -0,0 +1,219 @@ +#include "translit.h" + +IMPLEMENT_APP(TranslitGUI) + +bool TranslitGUI::OnInit() +{ + TranslitFrame *translitFrame = new TranslitFrame(); + translitFrame->Show(true); + + return true; +} + +TranslitFrame::TranslitFrame(): + wxFrame(nullptr, wxID_ANY, wxEmptyString, + wxDefaultPosition, wxSize(640,540), + wxDEFAULT_FRAME_STYLE | wxRESIZE_BORDER, wxEmptyString) +{ + main_panel = new wxPanel(this, wxID_ANY); + main_sizer = new wxBoxSizer(wxVERTICAL); + + textfield_in = new wxTextCtrl(main_panel, wxID_ANY, wxEmptyString, + wxDefaultPosition, wxSize(640,240), + wxTE_MULTILINE, wxDefaultValidator); + textfield_out = new wxTextCtrl(main_panel, wxID_ANY, wxEmptyString, + wxDefaultPosition, wxSize(640,240), + wxTE_MULTILINE, wxDefaultValidator); + + select_scheme = new wxComboBox(main_panel, wxID_ANY, wxEmptyString, + wxDefaultPosition, wxDefaultSize, 0, NULL, + wxCB_READONLY, wxDefaultValidator); + select_scheme->Insert(wxT("ALA-LC (Library of Congress)"), SCHEME_LC); + select_scheme->Insert(wxT("DIN 1460 (German academic)"), SCHEME_DIN); + select_scheme->Insert(wxT("BGN/PCGN (British official)"), SCHEME_PCGN); + select_scheme->Insert(wxT("ISO/R9 (Hybrid 1954/1968, OUP)"), SCHEME_OUP); + select_scheme->Insert(wxT("ISO/R9 (invertible, international)"), SCHEME_ISO); + select_scheme->Insert(wxT("Serbian national/official"), SCHEME_SRB); +#ifdef TRANSLIT_OUP + select_scheme->SetSelection(SCHEME_OUP); +#else + select_scheme->SetSelection(SCHEME_LC); +#endif + select_scheme->Bind(wxEVT_COMBOBOX, &TranslitFrame::set_lang_options, this); + + select_lang = new wxComboBox(main_panel, wxID_ANY, wxEmptyString, + wxDefaultPosition, wxDefaultSize, 0, NULL, + wxCB_READONLY, wxDefaultValidator); + select_lang->Insert(wxT("Russian"), LANG_RUS); + select_lang->Insert(wxT("Ukrainian"), LANG_UKR); + select_lang->Insert(wxT("Belarusian"), LANG_BEL); + select_lang->Insert(wxT("Bulgarian"), LANG_BG); + select_lang->Insert(wxT("Historical"), LANG_CS); + select_lang->SetSelection(LANG_RUS); + + select_sizer = new wxBoxSizer(wxHORIZONTAL); + select_sizer->Add(select_scheme, 2, wxEXPAND | wxALL); + select_sizer->Add(select_lang, 2, wxEXPAND | wxALL); + + translit_button = new wxButton(main_panel, wxID_OK, wxT("Run")); + translit_button->Bind(wxEVT_BUTTON, &TranslitFrame::do_translit, this); + + clear_button = new wxButton(main_panel, wxID_CLEAR, wxT("Clear")); + clear_button->Bind(wxEVT_BUTTON, &TranslitFrame::clear_text, this); + + copy_button = new wxButton(main_panel, wxID_COPY, wxT("Copy")); + copy_button->Bind(wxEVT_BUTTON, &TranslitFrame::copy_text, this); + + quit_button = new wxButton(main_panel, wxID_EXIT, wxT("Exit")); + quit_button->Bind(wxEVT_BUTTON, &TranslitFrame::OnExit, this); + + button_sizer = new wxBoxSizer(wxHORIZONTAL); + button_sizer->Add(translit_button, 2, wxEXPAND | wxALL); + button_sizer->Add(quit_button, 2, wxEXPAND | wxALL); + button_sizer->Add(copy_button, 2, wxEXPAND | wxALL); + button_sizer->Add(clear_button, 2, wxEXPAND | wxALL); + + main_sizer->Add(select_sizer, 0, wxEXPAND | wxALL, 5); + main_sizer->Add(textfield_in, 2, wxEXPAND | wxALL, 5); + main_sizer->Add(textfield_out, 2, wxEXPAND | wxALL, 5); + main_sizer->Add(button_sizer, 0, wxEXPAND | wxALL, 2); + + main_panel->SetSizer(main_sizer); +} + +void TranslitFrame::OnExit(wxCommandEvent& WXUNUSED(event)) +{ + Close(true); +} + +void TranslitFrame::set_lang_options(wxCommandEvent& WXUNUSED(event)) +{ + if (select_scheme->GetSelection() == SCHEME_SRB || + select_scheme->GetSelection() == SCHEME_ISO) + select_lang->Enable(false); + else + select_lang->Enable(true); +} + +void TranslitFrame::do_translit(wxCommandEvent& WXUNUSED(event)) +{ + map<wxString, wxString> char_map; + + wxString text_lat; + wxString text_cyr = textfield_in->GetValue(); + + int scheme_selected = select_scheme->GetSelection(); + int lang_selected = select_lang->GetSelection(); + + switch (scheme_selected) { + case SCHEME_LC: + char_map = ala_lc[0]; + char_map.insert(ala_lc[lang_selected + 1].begin(), + ala_lc[lang_selected + 1].end()); + break; + case SCHEME_DIN: + char_map = din_1460[0]; + char_map.insert(din_1460[lang_selected + 1].begin(), + din_1460[lang_selected + 1].end()); + break; + case SCHEME_PCGN: + char_map = bgp_pcgn[0]; + char_map.insert(bgp_pcgn[lang_selected + 1].begin(), + bgp_pcgn[lang_selected + 1].end()); + break; + case SCHEME_OUP: + char_map = iso9_old[0]; + char_map.insert(iso9_old[lang_selected + 1].begin(), + iso9_old[lang_selected + 1].end()); + break; + case SCHEME_ISO: + char_map = iso9_new; + break; + case SCHEME_SRB: + char_map = srb_nat; + break; + } + + text_lat = replace_chars(text_cyr, char_map, + scheme_selected, + lang_selected); + + textfield_out->ChangeValue(text_lat); +} + +void TranslitFrame::clear_text(wxCommandEvent& WXUNUSED(event)) +{ + textfield_out->Clear(); + textfield_in->Clear(); +} + +void TranslitFrame::copy_text(wxCommandEvent& WXUNUSED(event)) +{ + wxString text_to_copy = textfield_out->GetValue(); + if (wxTheClipboard->Open()) + { + wxTheClipboard->SetData(new wxTextDataObject(text_to_copy)); + wxTheClipboard->Close(); + } +} + +wxString TranslitFrame::replace_chars(wxString& text_in, + map<wxString, wxString> char_map, int scheme_type, int lang) +{ + wxString text_out, subst; + wxChar char_curr, char_prev, char_next; + size_t char_no, char_max; + + const static wxRegEx match_vowels(wxT("[АЕЁИЙІОУЮЯЭЬЪѢѴаеёийіоуюяьъѣѵ]+")); + const static wxRegEx match_upper(wxT("[А-ЯЪЬЀ-ЏҐѰѲѴѢѤѦѨѪѬѠ]+")); + + text_out.Clear(); + + char_max = text_in.length(); + for (char_no = 0; char_no < char_max; char_no++) + { + char_curr = text_in[char_no]; + if (char_no > 0) + char_prev = text_in[char_no - 1]; + if (char_no < char_max - 1) + char_next = text_in[char_no + 1]; + + if (scheme_type == SCHEME_PCGN && lang == LANG_RUS) { + if ((char_prev && match_vowels.Matches(char_prev)) || + (char_no == 0 || + char_prev == ' ' || + char_prev == '\n')) { + if (char_curr == L'е' || char_curr == L'ё') { + text_out += L'y' + char_curr; + continue; + } else if (char_curr == L'Е' ) { + if (char_next && match_upper.Matches(char_next)) + text_out += L"YE"; + else text_out += L"Ye"; + continue; + } else if (char_curr == L'Ë') { + if (char_next && match_upper.Matches(char_next)) + text_out += L"YË"; + else text_out += L"Yë"; + continue; + } + } + } + + if (char_map.count(char_curr) > 0) { + subst = char_map.find(char_curr)->second; + + // heuristic for smart detection of capitalization + // TO DO: this doesn't work yet for diacritics + if (char_next && match_upper.Matches(char_next) + && match_upper.Matches(char_curr)) + subst = subst.Upper(); + + text_out += subst; + } else { + text_out += char_curr; + } + } + + return text_out; +} |
