diff --git a/src/ipa-sil.cpp b/src/ipa-sil.cpp index 821cbb7..f329b7a 100644 --- a/src/ipa-sil.cpp +++ b/src/ipa-sil.cpp @@ -229,15 +229,35 @@ static std::unordered_map< }}, }; +// This maps KeySyms to a list of characters indicating what repeating the key +// should convert to. +static std::unordered_map const> const + keyToRepeatConversion = { + {FcitxKey_colon, {"ː", "ˑ", "ːː"}}, + {FcitxKey_braceright, {"ˈ", "ˌ"}}, +}; + +// Maps regular IPA characters to their superscript variants +static std::unordered_map const superscripts = { + {"-", "⁻"}, + {"h", "ʰ"}, + {"w", "ʷ"}, + {"j", "ʲ"}, + {"ɣ", "ˠ"}, + {"ʕ", "ˤ"}, + {"n", "ⁿ"}, + {"l", "ˡ"}, + + // TODO: Find a complete list of all IPA superscripts and complete this. +}; + std::optional getIPAForSIL(std::string baseCharacter, fcitx::KeySym silModifier) { - FCITX_INFO() << "Figuring IPA for " << baseCharacter << " & " - << silModifier; try { return SILtoIPA.at(baseCharacter).at(silModifier); } catch (std::out_of_range& e) { - FCITX_INFO() << "Couldn't get IPA character: " << e.what(); return {}; } } @@ -250,20 +270,58 @@ bool isSILModifier(fcitx::KeySym key) void SILState::handleAlphaKey(fcitx::Key key) { - // TODO: Don't make this a special case, have a better system for handling - // this! - if (key.check(FcitxKey_colon)) { - m_buffer.type("ː"); + // This ignores all non-alpha keys, with built-in flags and by banning + // modifiers ranges. + if (key.isModifier() || key.isCursorMove() || key.hasModifier() || + ((key.sym() & 0xff00) == 0xff00 || (key.sym() & 0xff00) == 0xfe00)) + return; + + if (keyToRepeatConversion.contains(key.sym())) { + auto keyConversions = keyToRepeatConversion.at(key.sym()); + if (m_repeatedKeyCount == 0) { + m_buffer.type(keyConversions[m_repeatedKeyCount++]); + m_repeatedKey = key.sym(); + } else { + if (m_repeatedKey == key.sym()) { + if (m_repeatedKeyCount >= keyConversions.size()) { + m_buffer.type(keyConversions[0]); + m_repeatedKeyCount = 1; + return; + } + + for (size_t i = 0; + i < keyConversions[m_repeatedKeyCount - 1].size(); + ++i) + m_buffer.backspace(); + m_buffer.type(keyConversions[m_repeatedKeyCount++]); + return; + } + m_buffer.type(keyConversions[0]); + m_repeatedKey = key.sym(); + m_repeatedKeyCount = 0; + } return; } - if (!isSILModifier(key.sym()) || getLastCharacter().empty()) { + m_repeatedKeyCount = 0; + m_repeatedKey = FcitxKey_None; + + auto lastCharacter = getLastCharacter(); + + if (key.sym() == FcitxKey_asciicircum && + superscripts.contains(lastCharacter)) { + m_buffer.backspace(); + m_buffer.type(superscripts.at(lastCharacter)); + return; + } + + if (!isSILModifier(key.sym()) || lastCharacter.empty()) { m_buffer.type(key.sym()); return; } if (isSILModifier(key.sym())) { - auto ipaChar = getIPAForSIL(getLastCharacter(), key.sym()); + auto ipaChar = getIPAForSIL(lastCharacter, key.sym()); if (ipaChar) { m_buffer.backspace(); m_buffer.type(*ipaChar); diff --git a/src/ipa-sil.hpp b/src/ipa-sil.hpp index a4e2a78..1b1d8b1 100644 --- a/src/ipa-sil.hpp +++ b/src/ipa-sil.hpp @@ -45,6 +45,9 @@ class SILState : public fcitx::InputContextProperty SILEngine* m_engine; fcitx::InputContext* m_ic; fcitx::InputBuffer m_buffer{{fcitx::InputBufferOption::NoOption}}; + + fcitx::KeySym m_repeatedKey = FcitxKey_None; + uint16_t m_repeatedKeyCount = 0; }; class SILEngine : public fcitx::InputMethodEngineV2