Compare commits

..

No commits in common. "266f40864058a701578ecd42b56c58e409a02959" and "363b374fc84b9b8d471438e35cf6c0de433b01c7" have entirely different histories.

3 changed files with 61 additions and 311 deletions

View file

@ -3,8 +3,6 @@ target_link_libraries(ipa-sil PRIVATE Fcitx5::Core)
set_target_properties(ipa-sil PROPERTIES PREFIX "")
install(TARGETS ipa-sil DESTINATION "${FCITX_INSTALL_LIBDIR}/fcitx5")
set_property(TARGET ipa-sil PROPERTY CXX_STANDARD 20)
# Addon config file
# We need additional layer of conversion because we want PROJECT_VERSION in it.
configure_file(ipa-sil-addon.conf.in ipa-sil-addon.conf)

View file

@ -9,257 +9,58 @@
#include <fcitx/inputpanel.h>
#include <fcitx/instance.h>
#include <fcitx-utils/utf8.h>
#include <codecvt>
#include <locale>
#include <unordered_map>
// This is a giant map from a base character (stored as std::string because it's
// easier that way) to a map. This new map maps SIL modifiers to the resulting
// IPA character.
// In the end, SILtoIPA["s"][FcitxKey_equal] == "ʃ", as `s=`
// makes the IPA /ʃ/.
static std::unordered_map<
std::string,
std::unordered_map<fcitx::KeySym const, std::string const> const> const
SILtoIPA = {
// ----- Consonants
{"t",
{
{FcitxKey_less, "ʈ"},
}},
{"d",
{
{FcitxKey_less, "ɖ"},
}},
{"j",
{
{FcitxKey_greater, "ʄ"},
{FcitxKey_less, "ʝ"},
{FcitxKey_equal, "ɟ"},
}},
{"g",
{
{FcitxKey_greater, "ɠ"},
{FcitxKey_less, "ɡ"},
{FcitxKey_equal, "ɣ"},
}},
{"G",
{
{FcitxKey_greater, "ʛ"},
{FcitxKey_equal, "ɢ"},
}},
{"?",
{
{FcitxKey_less, "ʕ"},
{FcitxKey_equal, "ʔ"},
}},
{"m",
{
{FcitxKey_greater, "ɱ"},
}},
{"n",
{
{FcitxKey_greater, "ŋ"},
{FcitxKey_less, "ɳ"},
{FcitxKey_equal, "ɲ"},
}},
{"N",
{
{FcitxKey_equal, "ɴ"},
}},
{"B",
{
{FcitxKey_greater, "ʁ"},
{FcitxKey_equal, "ʙ"},
}},
{"R",
{
{FcitxKey_less, "ɻ"},
{FcitxKey_equal, "ʀ"},
}},
{"v",
{
{FcitxKey_less, ""},
{FcitxKey_equal, "ʋ"},
}},
{"r",
{
{FcitxKey_greater, "ɾ"},
{FcitxKey_equal, "ɹ"},
}},
{"f",
{
{FcitxKey_equal, "ɸ"},
}},
{"b",
{
{FcitxKey_greater, "ɓ"},
{FcitxKey_equal, "β"},
}},
{"t",
{
{FcitxKey_equal, "θ"},
}},
{"d",
{
{FcitxKey_greater, "ɗ"},
{FcitxKey_equal, "ð"},
}},
{"s",
{
{FcitxKey_less, "ʂ"},
{FcitxKey_equal, "ʃ"},
}},
{"z",
{
{FcitxKey_less, "ʐ"},
{FcitxKey_greater, "ʑ"},
{FcitxKey_equal, "ʒ"},
}},
{"c",
{
{FcitxKey_less, "ɕ"},
{FcitxKey_equal, "ç"},
}},
{"x",
{
{FcitxKey_equal, "χ"},
}},
{"h",
{
{FcitxKey_greater, "ħ"},
{FcitxKey_less, "ɦ"},
{FcitxKey_equal, "ɥ"},
}},
{"l",
{
{FcitxKey_greater, "ɮ"},
{FcitxKey_less, "ɭ"},
{FcitxKey_equal, "ɬ"},
}},
{"w",
{
{FcitxKey_greater, "ɰ"},
{FcitxKey_equal, "ʍ"},
}},
{"L",
{
{FcitxKey_greater, "ɺ"},
{FcitxKey_less, "ʎ"},
{FcitxKey_equal, "ʟ"},
}},
{"p",
{
{FcitxKey_equal, "ʘ"},
}},
{"!",
{
{FcitxKey_greater, "ǁ"},
{FcitxKey_equal, "ǂ"},
}},
{"y",
{
{FcitxKey_less, "ɥ"},
{FcitxKey_equal, "ʏ"},
}},
{"H",
{
{FcitxKey_greater, "ɧ"},
{FcitxKey_equal, "ʜ"},
}},
{"Q",
{
{FcitxKey_less, "ʢ"},
{FcitxKey_equal, "ʡ"},
}},
// ----- Vowels
{"I",
{
{FcitxKey_equal, "ɨ"},
}},
{"U",
{
{FcitxKey_equal, "ʉ"},
}},
{"u",
{
{FcitxKey_greater, "ʌ"},
{FcitxKey_equal, "ɯ"},
}},
{"i",
{
{FcitxKey_equal, "ɪ"},
}},
{"o",
{
{FcitxKey_less, "ɔ"},
{FcitxKey_greater, "ø"},
}},
{"E",
{
{FcitxKey_less, "œ"},
{FcitxKey_greater, "ɶ"},
{FcitxKey_equal, "ɘ"},
}},
{"O",
{
{FcitxKey_greater, "ɤ"},
{FcitxKey_equal, "ɵ"},
}},
{"e",
{
{FcitxKey_greater, "ɜ"},
{FcitxKey_less, "ɛ"},
{FcitxKey_equal, "ə"},
}},
{"O",
{
{FcitxKey_less, "ɞ"},
}},
{"a",
{
{FcitxKey_less, "æ"},
{FcitxKey_greater, "ɐ"},
{FcitxKey_equal, "ɑ"},
}},
};
// This maps KeySyms to a list of characters indicating what repeating the key
// should convert to.
static std::unordered_map<fcitx::KeySym const,
std::vector<std::string> const> const
keyToRepeatConversion = {
{FcitxKey_colon, {"ː", "ˑ", "ːː"}},
{FcitxKey_braceright, {"ˈ", "ˌ"}},
};
// Maps regular IPA characters to their superscript variants
static std::unordered_map<std::string, std::string> const superscripts = {
{"-", ""},
{"h", "ʰ"},
{"w", "ʷ"},
{"j", "ʲ"},
{"ɣ", "ˠ"},
{"ʕ", "ˤ"},
{"n", ""},
{"l", "ˡ"},
// TODO: Find a complete list of all IPA superscripts and complete this.
};
std::optional<std::string> getIPAForSIL(std::string baseCharacter,
fcitx::KeySym silModifier)
{
try {
return SILtoIPA.at(baseCharacter).at(silModifier);
} catch (std::out_of_range& e) {
return {};
// TODO: Use a proper data structure, like a hash map
// Even better: load that data off of a file!
// TODO: Add more characters! This is only enough for narrow RP
// transcriptions...
if (baseCharacter == "s") {
if (silModifier == FcitxKey_equal) return "ʃ";
}
if (baseCharacter == "z") {
if (silModifier == FcitxKey_equal) return "ʒ";
}
if (baseCharacter == "t") {
if (silModifier == FcitxKey_equal) return "θ";
}
if (baseCharacter == "d") {
if (silModifier == FcitxKey_equal) return "ð";
}
if (baseCharacter == "n") {
if (silModifier == FcitxKey_greater) return "ŋ";
}
if (baseCharacter == "i") {
if (silModifier == FcitxKey_equal) return "ɪ";
}
if (baseCharacter == "e") {
if (silModifier == FcitxKey_equal) return "ə";
}
if (baseCharacter == "a") {
if (silModifier == FcitxKey_less) return "æ";
if (silModifier == FcitxKey_equal) return "ɑ";
}
if (baseCharacter == "o") {
if (silModifier == FcitxKey_less) return "ɔ";
if (silModifier == FcitxKey_equal) return "ɒ";
}
if (baseCharacter == "u") {
if (silModifier == FcitxKey_greater) return "ʌ";
if (silModifier == FcitxKey_less) return "ʊ";
}
return {};
}
bool isSILModifier(fcitx::KeySym key)
@ -270,62 +71,27 @@ bool isSILModifier(fcitx::KeySym key)
void SILState::handleAlphaKey(fcitx::Key key)
{
// 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;
}
// TODO: Don't make this a special case, have a better system for handling
// this!
if (key.check(FcitxKey_colon)) {
m_buffer.type("ː");
m_lastKey.reset();
return;
}
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()) {
if (!isSILModifier(key.sym()) || !m_lastKey.has_value()) {
m_lastKey = key.toString();
m_buffer.type(key.sym());
return;
}
if (isSILModifier(key.sym())) {
auto ipaChar = getIPAForSIL(lastCharacter, key.sym());
auto ipaChar = getIPAForSIL(*m_lastKey, key.sym());
if (ipaChar) {
m_buffer.backspace();
m_buffer.type(*ipaChar);
}
m_lastKey.reset();
}
}
@ -344,9 +110,9 @@ void SILState::keyEvent(fcitx::KeyEvent& keyEvent)
reset();
} else if (keyEvent.key().check(FcitxKey_BackSpace))
m_buffer.backspace();
else
else if (keyEvent.key().isSimple())
handleAlphaKey(keyEvent.key());
// m_buffer.type(keyEvent.key().sym());
updateUI();
keyEvent.filterAndAccept();
@ -369,15 +135,6 @@ void SILState::updateUI()
m_ic->updatePreedit();
}
std::string SILState::getLastCharacter()
{
// TODO: Use fcitx::InputBuffer::charAt once
// https://github.com/fcitx/fcitx5/issues/965 is fixed.
if (m_buffer.size() == 0) return "";
auto text = m_buffer.userInput();
return std::string(&text[m_buffer.cursorByChar() - 1], 1);
}
SILEngine::SILEngine(fcitx::Instance* instance)
: m_factory(
[this](fcitx::InputContext& ic) { return new SILState(this, &ic); })

View file

@ -16,8 +16,6 @@
#include <optional>
#include <string>
#include <fcitx-utils/utf8.h>
class SILEngine;
class SILState : public fcitx::InputContextProperty
@ -39,15 +37,12 @@ class SILState : public fcitx::InputContextProperty
updateUI();
}
std::string getLastCharacter();
private:
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;
std::optional<std::string> m_lastKey{};
};
class SILEngine : public fcitx::InputMethodEngineV2