diff --git a/CMakeLists.txt b/CMakeLists.txt index f792863..f1a8525 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.4.0) -project(fcitx5-zhuyin VERSION 5.1.0) +project(fcitx5-zhuyin VERSION 5.1.1) find_package(ECM 1.0.0 REQUIRED) set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH}) diff --git a/org.fcitx.Fcitx5.Addon.Zhuyin.metainfo.xml.in b/org.fcitx.Fcitx5.Addon.Zhuyin.metainfo.xml.in index e54fc9e..cb306a4 100644 --- a/org.fcitx.Fcitx5.Addon.Zhuyin.metainfo.xml.in +++ b/org.fcitx.Fcitx5.Addon.Zhuyin.metainfo.xml.in @@ -14,6 +14,7 @@ https://github.com/fcitx/fcitx5-zhuyin Fcitx + diff --git a/src/zhuyinbuffer.cpp b/src/zhuyinbuffer.cpp index 089e35d..a4aba0c 100644 --- a/src/zhuyinbuffer.cpp +++ b/src/zhuyinbuffer.cpp @@ -15,293 +15,291 @@ namespace fcitx { ZhuyinBuffer::ZhuyinBuffer(ZhuyinProviderInterface *provider) : provider_(provider), context_(provider->context()), instance_(zhuyin_alloc_instance(context_)) { - // Put a place holder. - sections_.emplace_back(ZhuyinSectionType::Symbol, provider_, this); - cursor_ = sections_.begin(); + // Put a place holder. + sections_.emplace_back(ZhuyinSectionType::Symbol, provider_, this); + cursor_ = sections_.begin(); } void ZhuyinBuffer::moveCursorToBeginning() { cursor_ = sections_.begin(); } void ZhuyinBuffer::moveCursorToEnd() { - cursor_ = std::prev(sections_.end()); - if (cursor_->sectionType() == ZhuyinSectionType::Zhuyin) { - cursor_->setCursor(cursor_->size()); - } + cursor_ = std::prev(sections_.end()); + if (cursor_->sectionType() == ZhuyinSectionType::Zhuyin) { + cursor_->setCursor(cursor_->size()); + } } bool ZhuyinBuffer::moveCursorLeft() { - if (cursor_ == sections_.begin()) { - return false; - } - // Move within the section. - if (cursor_->sectionType() == ZhuyinSectionType::Zhuyin) { - if (auto prevChar = cursor_->prevChar(); prevChar > 0) { - cursor_->setCursor(prevChar); - return true; - } + if (cursor_ == sections_.begin()) { + return false; + } + // Move within the section. + if (cursor_->sectionType() == ZhuyinSectionType::Zhuyin) { + if (auto prevChar = cursor_->prevChar(); prevChar > 0) { + cursor_->setCursor(prevChar); + return true; } + } - // Move across the section. - cursor_ = std::prev(cursor_); - // Fix the cursor within the section. - if (cursor_->sectionType() == ZhuyinSectionType::Zhuyin) { - cursor_->setCursor(cursor_->size()); - } - return true; + // Move across the section. + cursor_ = std::prev(cursor_); + // Fix the cursor within the section. + if (cursor_->sectionType() == ZhuyinSectionType::Zhuyin) { + cursor_->setCursor(cursor_->size()); + } + return true; } bool ZhuyinBuffer::moveCursorRight() { - if (isCursorAtTheEnd()) { - return false; - } - // Move within the section. - if (cursor_->sectionType() == ZhuyinSectionType::Zhuyin && - cursor_->cursor() < cursor_->size()) { - cursor_->setCursor(cursor_->nextChar()); - return true; - } - - cursor_ = std::next(cursor_); - // Fix the cursor within the section. - if (cursor_->sectionType() == ZhuyinSectionType::Zhuyin) { - cursor_->setCursor(0); - cursor_->setCursor(cursor_->nextChar()); - } + if (isCursorAtTheEnd()) { + return false; + } + // Move within the section. + if (cursor_->sectionType() == ZhuyinSectionType::Zhuyin && + cursor_->cursor() < cursor_->size()) { + cursor_->setCursor(cursor_->nextChar()); return true; + } + + cursor_ = std::next(cursor_); + // Fix the cursor within the section. + if (cursor_->sectionType() == ZhuyinSectionType::Zhuyin) { + cursor_->setCursor(0); + cursor_->setCursor(cursor_->nextChar()); + } + return true; } bool ZhuyinBuffer::isCursorAtTheEnd() const { - return std::next(cursor_) == sections_.end() && isCursorOnEdge(cursor_); + return std::next(cursor_) == sections_.end() && isCursorOnEdge(cursor_); } bool ZhuyinBuffer::isCursorOnEdge(SectionIterator cursor) { - return cursor->size() == cursor->cursor(); + return cursor->size() == cursor->cursor(); } void ZhuyinBuffer::type(uint32_t c) { - gchar **symbols = nullptr; - if (c <= std::numeric_limits::max() && - ((provider_->isZhuyin() && - zhuyin_in_chewing_keyboard(instance_.get(), c, &symbols)) || - (!provider_->isZhuyin() && - (charutils::islower(c) || (c >= '1' && c <= '5'))))) { - g_strfreev(symbols); - if (cursor_->sectionType() == ZhuyinSectionType::Zhuyin) { - cursor_->type(c); - if (isCursorOnEdge(cursor_) && c == ' ' && - cursor_->parsedZhuyinLength() != cursor_->size()) { - backspace(); - auto next = std::next(cursor_); - cursor_ = sections_.emplace(next, c, ZhuyinSectionType::Symbol, - provider_, this); - } - } else if (isCursorOnEdge(cursor_)) { - auto next = std::next(cursor_); - if (c == ' ') { - cursor_ = sections_.emplace(next, c, ZhuyinSectionType::Symbol, - provider_, this); - } else if (next == sections_.end() || - next->sectionType() != ZhuyinSectionType::Zhuyin) { - cursor_ = sections_.emplace(next, c, ZhuyinSectionType::Zhuyin, - provider_, this); - } else { - next->setCursor(0); - next->type(c); - cursor_ = next; - } - } - } else { - if (isCursorOnEdge(cursor_)) { - cursor_ = - sections_.emplace(std::next(cursor_), c, + gchar **symbols = nullptr; + if (c <= std::numeric_limits::max() && + ((provider_->isZhuyin() && + zhuyin_in_chewing_keyboard(instance_.get(), c, &symbols)) || + (!provider_->isZhuyin() && + (charutils::islower(c) || (c >= '1' && c <= '5'))))) { + g_strfreev(symbols); + if (cursor_->sectionType() == ZhuyinSectionType::Zhuyin) { + cursor_->type(c); + if (isCursorOnEdge(cursor_) && c == ' ' && + cursor_->parsedZhuyinLength() != cursor_->size()) { + backspace(); + auto next = std::next(cursor_); + cursor_ = sections_.emplace(next, c, ZhuyinSectionType::Symbol, + provider_, this); + } + } else if (isCursorOnEdge(cursor_)) { + auto next = std::next(cursor_); + if (c == ' ') { + cursor_ = sections_.emplace(next, c, ZhuyinSectionType::Symbol, + provider_, this); + } else if (next == sections_.end() || + next->sectionType() != ZhuyinSectionType::Zhuyin) { + cursor_ = sections_.emplace(next, c, ZhuyinSectionType::Zhuyin, + provider_, this); + } else { + next->setCursor(0); + next->type(c); + cursor_ = next; + } + } + } else { + if (isCursorOnEdge(cursor_)) { + cursor_ = sections_.emplace(std::next(cursor_), c, ZhuyinSectionType::Symbol, provider_, this); - } else { - assert((cursor_)->sectionType() == ZhuyinSectionType::Zhuyin); - assert(cursor_->cursor() != 0); + } else { + assert((cursor_)->sectionType() == ZhuyinSectionType::Zhuyin); + assert(cursor_->cursor() != 0); - auto next = std::next(cursor_); - auto offset = cursor_->cursorByChar(); - auto subText = cursor_->userInput().substr(offset); + auto next = std::next(cursor_); + auto offset = cursor_->cursorByChar(); + auto subText = cursor_->userInput().substr(offset); - cursor_->erase(offset, cursor_->size()); + cursor_->erase(offset, cursor_->size()); - // Add new symbol. - cursor_ = sections_.emplace(next, c, ZhuyinSectionType::Symbol, - provider_, this); - // Add split section. - auto subZhuyin = sections_.emplace(next, ZhuyinSectionType::Zhuyin, - provider_, this); - subZhuyin->type(subText); - } + // Add new symbol. + cursor_ = sections_.emplace(next, c, ZhuyinSectionType::Symbol, provider_, + this); + // Add split section. + auto subZhuyin = + sections_.emplace(next, ZhuyinSectionType::Zhuyin, provider_, this); + subZhuyin->type(subText); } + } } void ZhuyinBuffer::backspace() { - if (cursor_ == sections_.begin()) { - return; + if (cursor_ == sections_.begin()) { + return; + } + + if (cursor_->sectionType() == ZhuyinSectionType::Zhuyin) { + assert(cursor_->cursor() != 0); + auto prevChar = cursor_->prevChar(); + cursor_->erase(prevChar, cursor_->cursor()); + // Remove this section. + if (cursor_->empty()) { + auto newCursor = std::prev(cursor_); + sections_.erase(cursor_); + cursor_ = newCursor; + } else if (cursor_->cursor() == 0) { + cursor_ = std::prev(cursor_); + } else { + return; } + // Fix the cursor within the section. if (cursor_->sectionType() == ZhuyinSectionType::Zhuyin) { - assert(cursor_->cursor() != 0); - auto prevChar = cursor_->prevChar(); - cursor_->erase(prevChar, cursor_->cursor()); - // Remove this section. - if (cursor_->empty()) { - auto newCursor = std::prev(cursor_); - sections_.erase(cursor_); - cursor_ = newCursor; - } else if (cursor_->cursor() == 0) { - cursor_ = std::prev(cursor_); - } else { - return; - } - - // Fix the cursor within the section. - if (cursor_->sectionType() == ZhuyinSectionType::Zhuyin) { - cursor_->setCursor(cursor_->size()); - } - return; + cursor_->setCursor(cursor_->size()); } + return; + } - auto newCursor = std::prev(cursor_); - sections_.erase(cursor_); - cursor_ = newCursor; - if (cursor_->sectionType() == ZhuyinSectionType::Zhuyin) { - cursor_->setCursor(cursor_->size()); - auto next = std::next(cursor_); - if (next != sections_.end() && - next->sectionType() == ZhuyinSectionType::Zhuyin) { - // Merge cursor_ and next. - auto currentSize = cursor_->size(); - cursor_->type(next->userInput()); - cursor_->setCursor(currentSize); - sections_.erase(next); - } + auto newCursor = std::prev(cursor_); + sections_.erase(cursor_); + cursor_ = newCursor; + if (cursor_->sectionType() == ZhuyinSectionType::Zhuyin) { + cursor_->setCursor(cursor_->size()); + auto next = std::next(cursor_); + if (next != sections_.end() && + next->sectionType() == ZhuyinSectionType::Zhuyin) { + // Merge cursor_ and next. + auto currentSize = cursor_->size(); + cursor_->type(next->userInput()); + cursor_->setCursor(currentSize); + sections_.erase(next); } + } } void ZhuyinBuffer::del() { - if (moveCursorRight()) { - backspace(); - } + if (moveCursorRight()) { + backspace(); + } } Text ZhuyinBuffer::preedit() const { - Text text; - text.setCursor(0); - for (auto iter = std::next(sections_.begin()), end = sections_.end(); - iter != end; ++iter) { - auto [preedit, cursor] = iter->preeditWithCursor(); - if (cursor_ == iter) { - text.setCursor(text.textLength() + cursor); - } - text.append(preedit, TextFormatFlag::Underline); + Text text; + text.setCursor(0); + for (auto iter = std::next(sections_.begin()), end = sections_.end(); + iter != end; ++iter) { + auto [preedit, cursor] = iter->preeditWithCursor(); + if (cursor_ == iter) { + text.setCursor(text.textLength() + cursor); } - return text; + text.append(preedit, TextFormatFlag::Underline); + } + return text; } std::string ZhuyinBuffer::rawText() const { - std::string result; - for (auto iter = std::next(sections_.begin()), end = sections_.end(); - iter != end; ++iter) { - result.append(iter->userInput()); - } - return result; + std::string result; + for (auto iter = std::next(sections_.begin()), end = sections_.end(); + iter != end; ++iter) { + result.append(iter->userInput()); + } + return result; } void ZhuyinBuffer::learn() { - for (auto iter = std::next(sections_.begin()), end = sections_.end(); - iter != end; ++iter) { - iter->learn(); - } + for (auto iter = std::next(sections_.begin()), end = sections_.end(); + iter != end; ++iter) { + iter->learn(); + } } void ZhuyinBuffer::reset() { - sections_.erase(std::next(sections_.begin()), sections_.end()); - cursor_ = sections_.begin(); + sections_.erase(std::next(sections_.begin()), sections_.end()); + cursor_ = sections_.begin(); } void ZhuyinBuffer::showCandidate( const std::function)> &callback) { - auto callbackWrapper = - [this, &callback](std::unique_ptr candidate) { - if (candidate->isZhuyin()) { - auto *zhuyinCandidate = - static_cast(candidate.get()); - zhuyinCandidate->connect( - [this](SectionIterator iter) { - cursor_ = iter; - if (cursor_->cursor() == 0 && - cursor_ != sections_.begin()) { - cursor_ = std::prev(cursor_); - cursor_->setCursor(cursor_->size()); - } - }); - } - callback(std::move(candidate)); - }; - if (isCursorAtTheEnd()) { - cursor_->showCandidate(callbackWrapper, cursor_, cursor_->prevChar()); - } else if (isCursorOnEdge(cursor_)) { - auto section = std::next(cursor_); - section->showCandidate(callbackWrapper, section, 0); - } else { - cursor_->showCandidate(callbackWrapper, cursor_, cursor_->cursor()); - } + auto callbackWrapper = + [this, &callback](std::unique_ptr candidate) { + if (candidate->isZhuyin()) { + auto *zhuyinCandidate = + static_cast(candidate.get()); + zhuyinCandidate->connect( + [this](SectionIterator iter) { + cursor_ = iter; + if (cursor_->cursor() == 0 && cursor_ != sections_.begin()) { + cursor_ = std::prev(cursor_); + cursor_->setCursor(cursor_->size()); + } + }); + } + callback(std::move(candidate)); + }; + if (isCursorAtTheEnd()) { + cursor_->showCandidate(callbackWrapper, cursor_, cursor_->prevChar()); + } else if (isCursorOnEdge(cursor_)) { + auto section = std::next(cursor_); + section->showCandidate(callbackWrapper, section, 0); + } else { + cursor_->showCandidate(callbackWrapper, cursor_, cursor_->cursor()); + } } void ZhuyinBuffer::setZhuyinSymbolTo(SectionIterator iter, size_t offset, std::string symbol) { - assert(iter->sectionType() == ZhuyinSectionType::Zhuyin); - if (offset >= iter->size()) { - return; - } - auto next = std::next(iter); - auto beforeSize = offset; - auto chr = iter->charAt(offset); - auto after = iter->userInput().substr(offset + 1); - if (beforeSize == 0) { - sections_.erase(iter); - } else { - iter->erase(offset, iter->size()); - } - auto newSymbol = sections_.emplace(next, chr, ZhuyinSectionType::Symbol, - provider_, this); - newSymbol->setSymbol(std::move(symbol)); - if (!after.empty()) { - auto newSection = - sections_.emplace(next, ZhuyinSectionType::Zhuyin, provider_, this); - newSection->type(after); - } - cursor_ = newSymbol; + assert(iter->sectionType() == ZhuyinSectionType::Zhuyin); + if (offset >= iter->size()) { + return; + } + auto next = std::next(iter); + auto beforeSize = offset; + auto chr = iter->charAt(offset); + auto after = iter->userInput().substr(offset + 1); + if (beforeSize == 0) { + sections_.erase(iter); + } else { + iter->erase(offset, iter->size()); + } + auto newSymbol = + sections_.emplace(next, chr, ZhuyinSectionType::Symbol, provider_, this); + newSymbol->setSymbol(std::move(symbol)); + if (!after.empty()) { + auto newSection = + sections_.emplace(next, ZhuyinSectionType::Zhuyin, provider_, this); + newSection->type(after); + } + cursor_ = newSymbol; } std::string ZhuyinBuffer::dump() const { - bool first = true; - std::stringstream sstream; - sstream << "ZhuyinBuffer("; - for (const auto §ion : sections_) { - if (first) { - first = false; - continue; - } - sstream << ""; + bool first = true; + std::stringstream sstream; + sstream << "ZhuyinBuffer("; + for (const auto §ion : sections_) { + if (first) { + first = false; + continue; + } + sstream << ""; + } + auto preeditText = preedit(); + sstream << "Preedit:" << preeditText.toString() << "," << preeditText.cursor() + << ")"; - return sstream.str(); + return sstream.str(); } } // namespace fcitx diff --git a/src/zhuyinbuffer.h b/src/zhuyinbuffer.h index a64437a..e480043 100644 --- a/src/zhuyinbuffer.h +++ b/src/zhuyinbuffer.h @@ -23,9 +23,9 @@ class ZhuyinSection; // Helper class to separate the data needed from engine. class ZhuyinProviderInterface { public: - virtual zhuyin_context_t *context() = 0; - virtual bool isZhuyin() const = 0; - virtual const ZhuyinSymbol &symbol() const = 0; + virtual zhuyin_context_t *context() = 0; + virtual bool isZhuyin() const = 0; + virtual const ZhuyinSymbol &symbol() const = 0; }; // Class that manages a list of ZhuyinSection. @@ -34,45 +34,45 @@ class ZhuyinProviderInterface { // to simplify the code need to handle the section logic. class ZhuyinBuffer { public: - ZhuyinBuffer(ZhuyinProviderInterface *provider); - // Type a single character into the buffer. - void type(uint32_t c); - bool empty() const { return sections_.size() == 1; } - // Clear the buffer. - void reset(); + ZhuyinBuffer(ZhuyinProviderInterface *provider); + // Type a single character into the buffer. + void type(uint32_t c); + bool empty() const { return sections_.size() == 1; } + // Clear the buffer. + void reset(); - std::string text() const { return preedit().toStringForCommit(); } - std::string rawText() const; - bool isCursorAtTheEnd() const; + std::string text() const { return preedit().toStringForCommit(); } + std::string rawText() const; + bool isCursorAtTheEnd() const; - Text preedit() const; + Text preedit() const; - bool moveCursorLeft(); - bool moveCursorRight(); - void moveCursorToBeginning(); - void moveCursorToEnd(); - void del(); - void backspace(); - void learn(); + bool moveCursorLeft(); + bool moveCursorRight(); + void moveCursorToBeginning(); + void moveCursorToEnd(); + void del(); + void backspace(); + void learn(); - void showCandidate( - const std::function)> &callback); - void setZhuyinSymbolTo(SectionIterator iter, size_t offset, - std::string symbol); + void showCandidate( + const std::function)> &callback); + void setZhuyinSymbolTo(SectionIterator iter, size_t offset, + std::string symbol); - std::string dump() const; + std::string dump() const; - auto instance() const { return instance_.get(); } + auto instance() const { return instance_.get(); } private: - static bool isCursorOnEdge(SectionIterator cursor); + static bool isCursorOnEdge(SectionIterator cursor); - ZhuyinProviderInterface *provider_; - zhuyin_context_t *context_; - // Dummy instance for query. - UniqueCPtr instance_; - SectionIterator cursor_; - std::list sections_; + ZhuyinProviderInterface *provider_; + zhuyin_context_t *context_; + // Dummy instance for query. + UniqueCPtr instance_; + SectionIterator cursor_; + std::list sections_; }; } // namespace fcitx diff --git a/src/zhuyincandidate.cpp b/src/zhuyincandidate.cpp index 5adf9e7..4cd18fd 100644 --- a/src/zhuyincandidate.cpp +++ b/src/zhuyincandidate.cpp @@ -13,41 +13,41 @@ ZhuyinSectionCandidate::ZhuyinSectionCandidate(SectionIterator section, unsigned int i) : section_(section), index_(i) { - lookup_candidate_t *candidate = NULL; - if (!zhuyin_get_candidate(section->instance(), i, &candidate)) { - throw std::runtime_error("Failed to get candidate"); - } - - const gchar *word = NULL; - if (!zhuyin_get_candidate_string(section->instance(), candidate, &word)) { - throw std::runtime_error("Failed to get string"); - } - setText(Text(word)); + lookup_candidate_t *candidate = NULL; + if (!zhuyin_get_candidate(section->instance(), i, &candidate)) { + throw std::runtime_error("Failed to get candidate"); + } + + const gchar *word = NULL; + if (!zhuyin_get_candidate_string(section->instance(), candidate, &word)) { + throw std::runtime_error("Failed to get string"); + } + setText(Text(word)); } void ZhuyinSectionCandidate::select(InputContext *) const { - lookup_candidate_t *candidate = NULL; - if (!zhuyin_get_candidate(section_->instance(), index_, &candidate)) { - return; - } - auto newOffset = zhuyin_choose_candidate(section_->instance(), - section_->prevChar(), candidate); - zhuyin_guess_sentence(section_->instance()); - section_->setCursor(newOffset); - emit(section_); - emit(); + lookup_candidate_t *candidate = NULL; + if (!zhuyin_get_candidate(section_->instance(), index_, &candidate)) { + return; + } + auto newOffset = zhuyin_choose_candidate(section_->instance(), + section_->prevChar(), candidate); + zhuyin_guess_sentence(section_->instance()); + section_->setCursor(newOffset); + emit(section_); + emit(); } SymbolSectionCandidate::SymbolSectionCandidate(SectionIterator section, std::string symbol) : section_(section), symbol_(std::move(symbol)) { - setText(Text(symbol_)); + setText(Text(symbol_)); } void SymbolSectionCandidate::select(InputContext *) const { - section_->setSymbol(symbol_); - emit(); + section_->setSymbol(symbol_); + emit(); } SymbolZhuyinSectionCandidate::SymbolZhuyinSectionCandidate( @@ -56,8 +56,8 @@ SymbolZhuyinSectionCandidate::SymbolZhuyinSectionCandidate( : SymbolSectionCandidate(section, std::move(symbol)), offset_(offset) {} void SymbolZhuyinSectionCandidate::select(InputContext *) const { - section_->buffer()->setZhuyinSymbolTo(section_, offset_, symbol_); - emit(); + section_->buffer()->setZhuyinSymbolTo(section_, offset_, symbol_); + emit(); } } // namespace fcitx diff --git a/src/zhuyincandidate.h b/src/zhuyincandidate.h index a3cbedf..451b57f 100644 --- a/src/zhuyincandidate.h +++ b/src/zhuyincandidate.h @@ -16,49 +16,48 @@ namespace fcitx { // Base class for Zhuyin candidate. class ZhuyinCandidate : public CandidateWord, public ConnectableObject { public: - virtual bool isZhuyin() const { return false; }; - FCITX_DECLARE_SIGNAL(ZhuyinCandidate, selected, void()); + virtual bool isZhuyin() const { return false; }; + FCITX_DECLARE_SIGNAL(ZhuyinCandidate, selected, void()); private: - FCITX_DEFINE_SIGNAL(ZhuyinCandidate, selected); + FCITX_DEFINE_SIGNAL(ZhuyinCandidate, selected); }; // Candidate for zhuyin section. class ZhuyinSectionCandidate : public ZhuyinCandidate { public: - ZhuyinSectionCandidate(SectionIterator section, unsigned int i); - bool isZhuyin() const override { return true; } - void select(InputContext *) const override; - FCITX_DECLARE_SIGNAL(ZhuyinSectionCandidate, selected, - void(SectionIterator)); + ZhuyinSectionCandidate(SectionIterator section, unsigned int i); + bool isZhuyin() const override { return true; } + void select(InputContext *) const override; + FCITX_DECLARE_SIGNAL(ZhuyinSectionCandidate, selected, void(SectionIterator)); private: - FCITX_DEFINE_SIGNAL(ZhuyinSectionCandidate, selected); - SectionIterator section_; - unsigned int index_; + FCITX_DEFINE_SIGNAL(ZhuyinSectionCandidate, selected); + SectionIterator section_; + unsigned int index_; }; // Candidate for symbol section. class SymbolSectionCandidate : public ZhuyinCandidate { public: - SymbolSectionCandidate(SectionIterator section, std::string symbol); - void select(InputContext *) const override; + SymbolSectionCandidate(SectionIterator section, std::string symbol); + void select(InputContext *) const override; protected: - FCITX_DEFINE_SIGNAL(ZhuyinSectionCandidate, selected); - SectionIterator section_; - std::string symbol_; + FCITX_DEFINE_SIGNAL(ZhuyinSectionCandidate, selected); + SectionIterator section_; + std::string symbol_; }; // Candidate for symbol section. class SymbolZhuyinSectionCandidate : public SymbolSectionCandidate { public: - SymbolZhuyinSectionCandidate(SectionIterator section, std::string symbol, - size_t offset); - void select(InputContext *) const override; + SymbolZhuyinSectionCandidate(SectionIterator section, std::string symbol, + size_t offset); + void select(InputContext *) const override; private: - size_t offset_; + size_t offset_; }; } // namespace fcitx diff --git a/src/zhuyinengine.cpp b/src/zhuyinengine.cpp index b061258..454200d 100644 --- a/src/zhuyinengine.cpp +++ b/src/zhuyinengine.cpp @@ -29,496 +29,488 @@ ZhuyinState::ZhuyinState(ZhuyinEngine *engine, InputContext *ic) : engine_(engine), buffer_(engine), ic_(ic) {} void ZhuyinState::reset() { - buffer_.reset(); - updateUI(); + buffer_.reset(); + updateUI(); } void ZhuyinState::commit() { - ic_->commitString(buffer_.text()); - buffer_.learn(); - reset(); + ic_->commitString(buffer_.text()); + buffer_.learn(); + reset(); } void ZhuyinState::keyEvent(KeyEvent &keyEvent) { - auto *ic = keyEvent.inputContext(); - auto key = keyEvent.key(); - if (keyEvent.isRelease()) { - return; + auto *ic = keyEvent.inputContext(); + auto key = keyEvent.key(); + if (keyEvent.isRelease()) { + return; + } + + if (auto candidateList = ic->inputPanel().candidateList(); + candidateList && candidateList->size()) { + auto idx = key.keyListIndex(engine_->selectionKeys()); + if (idx >= 0) { + candidateList->candidate(idx).select(ic); + return keyEvent.filterAndAccept(); } - if (auto candidateList = ic->inputPanel().candidateList(); - candidateList && candidateList->size()) { - auto idx = key.keyListIndex(engine_->selectionKeys()); - if (idx >= 0) { - candidateList->candidate(idx).select(ic); - return keyEvent.filterAndAccept(); - } - - if (candidateList->cursorIndex() >= 0 && - (key.check(FcitxKey_space) || key.check(FcitxKey_Return))) { - candidateList->candidate(candidateList->cursorIndex()).select(ic); - return keyEvent.filterAndAccept(); - } - - if (key.checkKeyList(*engine_->config().prevPage)) { - candidateList->toPageable()->prev(); - ic_->updateUserInterface(UserInterfaceComponent::InputPanel); - return keyEvent.filterAndAccept(); - } - - if (key.checkKeyList(*engine_->config().nextPage)) { - candidateList->toPageable()->next(); - ic_->updateUserInterface(UserInterfaceComponent::InputPanel); - return keyEvent.filterAndAccept(); - } - - if (key.checkKeyList(*engine_->config().prevCandidate)) { - candidateList->toCursorMovable()->prevCandidate(); - ic_->updateUserInterface(UserInterfaceComponent::InputPanel); - return keyEvent.filterAndAccept(); - } - - if (key.checkKeyList(*engine_->config().nextCandidate)) { - candidateList->toCursorMovable()->nextCandidate(); - ic_->updateUserInterface(UserInterfaceComponent::InputPanel); - return keyEvent.filterAndAccept(); - } - - if (key.check(FcitxKey_Escape)) { - ic->inputPanel().setCandidateList(nullptr); - ic_->updateUserInterface(UserInterfaceComponent::InputPanel); - return keyEvent.filterAndAccept(); - } - if (key.check(FcitxKey_Home)) { - candidateList->toPageable()->setPage(0); - ic_->updateUserInterface(UserInterfaceComponent::InputPanel); - return keyEvent.filterAndAccept(); - } - if (key.check(FcitxKey_End)) { - candidateList->toPageable()->setPage( - candidateList->toPageable()->totalPages() - 1); - ic_->updateUserInterface(UserInterfaceComponent::InputPanel); - return keyEvent.filterAndAccept(); - } - - return keyEvent.filterAndAccept(); + if (candidateList->cursorIndex() >= 0 && + (key.check(FcitxKey_space) || key.check(FcitxKey_Return))) { + candidateList->candidate(candidateList->cursorIndex()).select(ic); + return keyEvent.filterAndAccept(); } - if (!buffer_.empty()) { - if (key.check(FcitxKey_Home)) { - buffer_.moveCursorToBeginning(); - updateUI(); - return keyEvent.filterAndAccept(); - } - if (key.check(FcitxKey_End)) { - buffer_.moveCursorToEnd(); - updateUI(); - return keyEvent.filterAndAccept(); - } - if (key.check(FcitxKey_Escape)) { - reset(); - return keyEvent.filterAndAccept(); - } - if (key.check(FcitxKey_BackSpace)) { - buffer_.backspace(); - updateUI(); - return keyEvent.filterAndAccept(); - } - if (key.check(FcitxKey_Delete)) { - buffer_.del(); - updateUI(); - return keyEvent.filterAndAccept(); - } - if (key.check(FcitxKey_Return)) { - commit(); - return keyEvent.filterAndAccept(); - } - if (key.check(FcitxKey_Left)) { - buffer_.moveCursorLeft(); - updateUI(); - return keyEvent.filterAndAccept(); - } - if (key.check(FcitxKey_Right)) { - buffer_.moveCursorRight(); - updateUI(); - return keyEvent.filterAndAccept(); - } - if (key.check(FcitxKey_Return, KeyState::Shift)) { - ic->commitString(buffer_.rawText()); - reset(); - return keyEvent.filterAndAccept(); - } - - if (key.check(FcitxKey_Down)) { - updateUI(true); - } - - if (key.isCursorMove()) { - return keyEvent.filterAndAccept(); - } + if (key.checkKeyList(*engine_->config().prevPage)) { + candidateList->toPageable()->prev(); + ic_->updateUserInterface(UserInterfaceComponent::InputPanel); + return keyEvent.filterAndAccept(); } - auto c = Key::keySymToUnicode(key.sym()); - if (buffer_.empty()) { - if (key.check(*engine_->config().quickphraseKey) && - engine_->quickphrase()) { - std::string keyString; - std::string output, altOutput; - if (c) { - keyString = utf8::UCS4ToUTF8(c); - altOutput = keyString; - } else { - keyString = engine_->config().quickphraseKey->toString( - KeyStringFormat::Localized); - } - output = *engine_->config().quickphraseKeySymbol; - if (output.empty()) { - output = altOutput; - altOutput.clear(); - } - - if (!output.empty() && !altOutput.empty()) { - std::string text = - fmt::format(_("Press {} for {} and Return for {}"), - keyString, output, altOutput); - engine_->quickphrase()->call( - ic, text, "", output, altOutput, - *engine_->config().quickphraseKey); - } else if (!output.empty()) { - std::string text = - fmt::format(_("Press {} for {}"), keyString, output); - engine_->quickphrase()->call( - ic, text, "", output, altOutput, - *engine_->config().quickphraseKey); - } else { - engine_->quickphrase()->call( - ic, "", "", "", "", Key()); - } - - keyEvent.filterAndAccept(); - return; - } + if (key.checkKeyList(*engine_->config().nextPage)) { + candidateList->toPageable()->next(); + ic_->updateUserInterface(UserInterfaceComponent::InputPanel); + return keyEvent.filterAndAccept(); } - if (key.hasModifier()) { - return; + if (key.checkKeyList(*engine_->config().prevCandidate)) { + candidateList->toCursorMovable()->prevCandidate(); + ic_->updateUserInterface(UserInterfaceComponent::InputPanel); + return keyEvent.filterAndAccept(); } - if (c <= std::numeric_limits::max() && - !charutils::isprint(c)) { - if (!buffer_.empty()) { - keyEvent.filterAndAccept(); - } - return; + if (key.checkKeyList(*engine_->config().nextCandidate)) { + candidateList->toCursorMovable()->nextCandidate(); + ic_->updateUserInterface(UserInterfaceComponent::InputPanel); + return keyEvent.filterAndAccept(); } - if (c) { - buffer_.type(c); - if (utf8::length(buffer_.preedit().toStringForCommit()) > - MAX_INPUT_LENGTH) { - ic->commitString(buffer_.text()); - buffer_.learn(); - reset(); - } else { - updateUI(); - } - keyEvent.filterAndAccept(); + if (key.check(FcitxKey_Escape)) { + ic->inputPanel().setCandidateList(nullptr); + ic_->updateUserInterface(UserInterfaceComponent::InputPanel); + return keyEvent.filterAndAccept(); + } + if (key.check(FcitxKey_Home)) { + candidateList->toPageable()->setPage(0); + ic_->updateUserInterface(UserInterfaceComponent::InputPanel); + return keyEvent.filterAndAccept(); + } + if (key.check(FcitxKey_End)) { + candidateList->toPageable()->setPage( + candidateList->toPageable()->totalPages() - 1); + ic_->updateUserInterface(UserInterfaceComponent::InputPanel); + return keyEvent.filterAndAccept(); } -} -void ZhuyinState::updateUI(bool showCandidate) { - ic_->inputPanel().reset(); - Text preedit(buffer_.preedit()); - if (ic_->capabilityFlags().test(CapabilityFlag::Preedit)) { - ic_->inputPanel().setClientPreedit(preedit); - ic_->updatePreedit(); + return keyEvent.filterAndAccept(); + } + + if (!buffer_.empty()) { + if (key.check(FcitxKey_Home)) { + buffer_.moveCursorToBeginning(); + updateUI(); + return keyEvent.filterAndAccept(); + } + if (key.check(FcitxKey_End)) { + buffer_.moveCursorToEnd(); + updateUI(); + return keyEvent.filterAndAccept(); + } + if (key.check(FcitxKey_Escape)) { + reset(); + return keyEvent.filterAndAccept(); + } + if (key.check(FcitxKey_BackSpace)) { + buffer_.backspace(); + updateUI(); + return keyEvent.filterAndAccept(); + } + if (key.check(FcitxKey_Delete)) { + buffer_.del(); + updateUI(); + return keyEvent.filterAndAccept(); + } + if (key.check(FcitxKey_Return)) { + commit(); + return keyEvent.filterAndAccept(); + } + if (key.check(FcitxKey_Left)) { + buffer_.moveCursorLeft(); + updateUI(); + return keyEvent.filterAndAccept(); + } + if (key.check(FcitxKey_Right)) { + buffer_.moveCursorRight(); + updateUI(); + return keyEvent.filterAndAccept(); + } + if (key.check(FcitxKey_Return, KeyState::Shift)) { + ic->commitString(buffer_.rawText()); + reset(); + return keyEvent.filterAndAccept(); + } + + if (key.check(FcitxKey_Down)) { + updateUI(true); + } + + if (key.isCursorMove()) { + return keyEvent.filterAndAccept(); + } + } + + auto c = Key::keySymToUnicode(key.sym()); + if (buffer_.empty()) { + if (key.check(*engine_->config().quickphraseKey) && + engine_->quickphrase()) { + std::string keyString; + std::string output, altOutput; + if (c) { + keyString = utf8::UCS4ToUTF8(c); + altOutput = keyString; + } else { + keyString = engine_->config().quickphraseKey->toString( + KeyStringFormat::Localized); + } + output = *engine_->config().quickphraseKeySymbol; + if (output.empty()) { + output = altOutput; + altOutput.clear(); + } + + if (!output.empty() && !altOutput.empty()) { + std::string text = fmt::format(_("Press {} for {} and Return for {}"), + keyString, output, altOutput); + engine_->quickphrase()->call( + ic, text, "", output, altOutput, *engine_->config().quickphraseKey); + } else if (!output.empty()) { + std::string text = fmt::format(_("Press {} for {}"), keyString, output); + engine_->quickphrase()->call( + ic, text, "", output, altOutput, *engine_->config().quickphraseKey); + } else { + engine_->quickphrase()->call(ic, "", "", "", "", + Key()); + } + + keyEvent.filterAndAccept(); + return; + } + } + + if (key.hasModifier()) { + return; + } + + if (c <= std::numeric_limits::max() && !charutils::isprint(c)) { + if (!buffer_.empty()) { + keyEvent.filterAndAccept(); + } + return; + } + + if (c) { + buffer_.type(c); + if (utf8::length(buffer_.preedit().toStringForCommit()) > + MAX_INPUT_LENGTH) { + ic->commitString(buffer_.text()); + buffer_.learn(); + reset(); } else { - ic_->inputPanel().setPreedit(preedit); + updateUI(); } + keyEvent.filterAndAccept(); + } +} - if (showCandidate) { - auto candidateList = std::make_unique(); - candidateList->setCursorPositionAfterPaging( - CursorPositionAfterPaging::SameAsLast); - candidateList->setLayoutHint(CandidateLayoutHint::Vertical); - candidateList->setPageSize(*engine_->config().pageSize); - candidateList->setSelectionKey(engine_->selectionKeys()); - buffer_.showCandidate( - [this, &candidateList](std::unique_ptr candidate) { - candidate->connect( - [this]() { updateUI(); }); - candidateList->append(std::move(candidate)); - }); - if (candidateList->size()) { - candidateList->setGlobalCursorIndex(0); - ic_->inputPanel().setCandidateList(std::move(candidateList)); - } +void ZhuyinState::updateUI(bool showCandidate) { + ic_->inputPanel().reset(); + Text preedit(buffer_.preedit()); + if (ic_->capabilityFlags().test(CapabilityFlag::Preedit)) { + ic_->inputPanel().setClientPreedit(preedit); + ic_->updatePreedit(); + } else { + ic_->inputPanel().setPreedit(preedit); + } + + if (showCandidate) { + auto candidateList = std::make_unique(); + candidateList->setCursorPositionAfterPaging( + CursorPositionAfterPaging::SameAsLast); + candidateList->setLayoutHint(CandidateLayoutHint::Vertical); + candidateList->setPageSize(*engine_->config().pageSize); + candidateList->setSelectionKey(engine_->selectionKeys()); + buffer_.showCandidate([this, &candidateList]( + std::unique_ptr candidate) { + candidate->connect([this]() { updateUI(); }); + candidateList->append(std::move(candidate)); + }); + if (candidateList->size()) { + candidateList->setGlobalCursorIndex(0); + ic_->inputPanel().setCandidateList(std::move(candidateList)); } + } - ic_->updateUserInterface(UserInterfaceComponent::InputPanel); + ic_->updateUserInterface(UserInterfaceComponent::InputPanel); } ZhuyinEngine::ZhuyinEngine(Instance *instance) : instance_(instance), factory_([this](InputContext &ic) { - return new ZhuyinState(this, &ic); + return new ZhuyinState(this, &ic); }) { - auto userDir = stringutils::joinPath( - StandardPath::global().userDirectory(StandardPath::Type::PkgData), - "zhuyin"); - if (!fs::makePath(userDir)) { - if (fs::isdir(userDir)) { - ZHUYIN_DEBUG() << "Failed to create user directory: " << userDir; - } + auto userDir = stringutils::joinPath( + StandardPath::global().userDirectory(StandardPath::Type::PkgData), + "zhuyin"); + if (!fs::makePath(userDir)) { + if (fs::isdir(userDir)) { + ZHUYIN_DEBUG() << "Failed to create user directory: " << userDir; } - context_.reset( - zhuyin_init(StandardPath::fcitxPath("pkgdatadir", "zhuyin").data(), - userDir.data())); + } + context_.reset(zhuyin_init( + StandardPath::fcitxPath("pkgdatadir", "zhuyin").data(), userDir.data())); - instance->inputContextManager().registerProperty("zhuyinState", &factory_); - reloadConfig(); + instance->inputContextManager().registerProperty("zhuyinState", &factory_); + reloadConfig(); } void ZhuyinEngine::activate(const InputMethodEntry &, InputContextEvent &event) { - auto *inputContext = event.inputContext(); - // Request full width. - fullwidth(); - chttrans(); - for (const auto *actionName : {"chttrans", "fullwidth"}) { - if (auto *action = - instance_->userInterfaceManager().lookupAction(actionName)) { - inputContext->statusArea().addAction(StatusGroup::InputMethod, - action); - } + auto *inputContext = event.inputContext(); + // Request full width. + fullwidth(); + chttrans(); + for (const auto *actionName : {"chttrans", "fullwidth"}) { + if (auto *action = + instance_->userInterfaceManager().lookupAction(actionName)) { + inputContext->statusArea().addAction(StatusGroup::InputMethod, action); } + } } void ZhuyinEngine::deactivate(const InputMethodEntry &entry, InputContextEvent &event) { - auto *inputContext = event.inputContext(); - if (event.type() == EventType::InputContextSwitchInputMethod) { - if (*config_.commitOnSwitch) { - auto *state = event.inputContext()->propertyFor(&factory_); - state->commit(); - } + auto *inputContext = event.inputContext(); + if (event.type() == EventType::InputContextSwitchInputMethod) { + if (*config_.commitOnSwitch) { + auto *state = event.inputContext()->propertyFor(&factory_); + state->commit(); } - reset(entry, event); + } + reset(entry, event); } void ZhuyinEngine::keyEvent(const InputMethodEntry &, KeyEvent &keyEvent) { - auto *state = keyEvent.inputContext()->propertyFor(&factory_); - state->keyEvent(keyEvent); + auto *state = keyEvent.inputContext()->propertyFor(&factory_); + state->keyEvent(keyEvent); } void ZhuyinEngine::reset(const InputMethodEntry &, InputContextEvent &event) { - auto *state = event.inputContext()->propertyFor(&factory_); - state->reset(); + auto *state = event.inputContext()->propertyFor(&factory_); + state->reset(); } void ZhuyinEngine::save() { zhuyin_save(context_.get()); } void ZhuyinEngine::setConfig(const RawConfig &rawConfig) { - config_.load(rawConfig, true); - safeSaveAsIni(config_, "conf/zhuyin.conf"); - reloadConfig(); + config_.load(rawConfig, true); + safeSaveAsIni(config_, "conf/zhuyin.conf"); + reloadConfig(); } const Configuration *ZhuyinEngine::getConfig() const { return &config_; } void ZhuyinEngine::reloadConfig() { - readAsIni(config_, "conf/zhuyin.conf"); - // Keep fd live before fclose. - StandardPathFile fd; - UniqueFilePtr file; - if (*config_.useEasySymbol) { - fd = StandardPath::global().open(StandardPath::Type::PkgData, - "zhuyin/easysymbols.txt", O_RDONLY); - if (fd.isValid()) { - file.reset(fdopen(fd.fd(), "r")); - if (file) { - fd.release(); - } - } - } - symbol_.load(file.get()); - - isZhuyin_ = true; - ZhuyinScheme scheme = ZHUYIN_STANDARD; - FullPinyinScheme pyScheme = FULL_PINYIN_HANYU; - switch (*config_.layout) { - case Scheme::Standard: - scheme = ZHUYIN_STANDARD; - break; - case Scheme::Hsu: - scheme = ZHUYIN_HSU; - break; - case Scheme::IBM: - scheme = ZHUYIN_IBM; - break; - case Scheme::GinYieh: - scheme = ZHUYIN_GINYIEH; - break; - case Scheme::Eten: - scheme = ZHUYIN_ETEN; - break; - case Scheme::Eten26: - scheme = ZHUYIN_ETEN26; - break; - case Scheme::Dvorak: - scheme = ZHUYIN_STANDARD_DVORAK; - break; - case Scheme::HsuDvorak: - scheme = ZHUYIN_HSU_DVORAK; - break; - case Scheme::DachenCP26: - scheme = ZHUYIN_DACHEN_CP26; - break; - case Scheme::Hanyu: - pyScheme = FULL_PINYIN_HANYU; - isZhuyin_ = false; - break; - case Scheme::Luoma: - pyScheme = FULL_PINYIN_LUOMA; - isZhuyin_ = false; - break; - case Scheme::SecondaryZhuyin: - pyScheme = FULL_PINYIN_SECONDARY_ZHUYIN; - isZhuyin_ = false; - break; - } - if (isZhuyin_) { - zhuyin_set_chewing_scheme(context_.get(), scheme); - } else { - zhuyin_set_full_pinyin_scheme(context_.get(), pyScheme); - } - - constexpr KeySym syms[][10] = { - { - FcitxKey_1, - FcitxKey_2, - FcitxKey_3, - FcitxKey_4, - FcitxKey_5, - FcitxKey_6, - FcitxKey_7, - FcitxKey_8, - FcitxKey_9, - FcitxKey_0, - }, - - { - FcitxKey_a, - FcitxKey_s, - FcitxKey_d, - FcitxKey_f, - FcitxKey_g, - FcitxKey_h, - FcitxKey_j, - FcitxKey_k, - FcitxKey_l, - FcitxKey_semicolon, - }, - - { - FcitxKey_a, - FcitxKey_s, - FcitxKey_d, - FcitxKey_f, - FcitxKey_z, - FcitxKey_x, - FcitxKey_c, - FcitxKey_v, - FcitxKey_8, - FcitxKey_9, - }, - - { - FcitxKey_a, - FcitxKey_s, - FcitxKey_d, - FcitxKey_f, - FcitxKey_j, - FcitxKey_k, - FcitxKey_l, - FcitxKey_7, - FcitxKey_8, - FcitxKey_9, - }, - - { - FcitxKey_1, - FcitxKey_2, - FcitxKey_3, - FcitxKey_4, - FcitxKey_q, - FcitxKey_w, - FcitxKey_e, - FcitxKey_r, - FcitxKey_a, - FcitxKey_s, - }, - { - FcitxKey_d, - FcitxKey_s, - FcitxKey_t, - FcitxKey_n, - FcitxKey_a, - FcitxKey_e, - FcitxKey_o, - FcitxKey_7, - FcitxKey_8, - FcitxKey_9, - }, - }; - - KeyStates states = KeyState::NoState; - - for (auto sym : syms[static_cast(*config_.selectionKey)]) { - selectionKeys_.emplace_back(sym, states); - } - - pinyin_option_t options = USE_TONE | ZHUYIN_CORRECT_ALL; - if (isZhuyin_ && *config_.needTone) { - options |= FORCE_TONE; - } - if (*config_.fuzzy->fuzzyCCh) { - options |= PINYIN_AMB_C_CH; - } - if (*config_.fuzzy->fuzzySSh) { - options |= PINYIN_AMB_S_SH; + readAsIni(config_, "conf/zhuyin.conf"); + // Keep fd live before fclose. + StandardPathFile fd; + UniqueFilePtr file; + if (*config_.useEasySymbol) { + fd = StandardPath::global().open(StandardPath::Type::PkgData, + "zhuyin/easysymbols.txt", O_RDONLY); + if (fd.isValid()) { + file.reset(fdopen(fd.fd(), "r")); + if (file) { + fd.release(); + } } - if (*config_.fuzzy->fuzzyZZh) { - options |= PINYIN_AMB_Z_ZH; - } - if (*config_.fuzzy->fuzzyFH) { - options |= PINYIN_AMB_F_H; - } - if (*config_.fuzzy->fuzzyGK) { - options |= PINYIN_AMB_G_K; - } - if (*config_.fuzzy->fuzzyLN) { - options |= PINYIN_AMB_L_N; - } - if (*config_.fuzzy->fuzzyLR) { - options |= PINYIN_AMB_L_R; - } - if (*config_.fuzzy->fuzzyAnAng) { - options |= PINYIN_AMB_AN_ANG; - } - if (*config_.fuzzy->fuzzyEnEng) { - options |= PINYIN_AMB_EN_ENG; - } - if (*config_.fuzzy->fuzzyInIng) { - options |= PINYIN_AMB_IN_ING; - } - - zhuyin_set_options(context_.get(), options); - - instance_->inputContextManager().foreach([this](InputContext *ic) { - auto *state = ic->propertyFor(&factory_); - state->reset(); - return true; - }); + } + symbol_.load(file.get()); + + isZhuyin_ = true; + ZhuyinScheme scheme = ZHUYIN_STANDARD; + FullPinyinScheme pyScheme = FULL_PINYIN_HANYU; + switch (*config_.layout) { + case Scheme::Standard: + scheme = ZHUYIN_STANDARD; + break; + case Scheme::Hsu: + scheme = ZHUYIN_HSU; + break; + case Scheme::IBM: + scheme = ZHUYIN_IBM; + break; + case Scheme::GinYieh: + scheme = ZHUYIN_GINYIEH; + break; + case Scheme::Eten: + scheme = ZHUYIN_ETEN; + break; + case Scheme::Eten26: + scheme = ZHUYIN_ETEN26; + break; + case Scheme::Dvorak: + scheme = ZHUYIN_STANDARD_DVORAK; + break; + case Scheme::HsuDvorak: + scheme = ZHUYIN_HSU_DVORAK; + break; + case Scheme::DachenCP26: + scheme = ZHUYIN_DACHEN_CP26; + break; + case Scheme::Hanyu: + pyScheme = FULL_PINYIN_HANYU; + isZhuyin_ = false; + break; + case Scheme::Luoma: + pyScheme = FULL_PINYIN_LUOMA; + isZhuyin_ = false; + break; + case Scheme::SecondaryZhuyin: + pyScheme = FULL_PINYIN_SECONDARY_ZHUYIN; + isZhuyin_ = false; + break; + } + if (isZhuyin_) { + zhuyin_set_chewing_scheme(context_.get(), scheme); + } else { + zhuyin_set_full_pinyin_scheme(context_.get(), pyScheme); + } + + constexpr KeySym syms[][10] = { + { + FcitxKey_1, + FcitxKey_2, + FcitxKey_3, + FcitxKey_4, + FcitxKey_5, + FcitxKey_6, + FcitxKey_7, + FcitxKey_8, + FcitxKey_9, + FcitxKey_0, + }, + + { + FcitxKey_a, + FcitxKey_s, + FcitxKey_d, + FcitxKey_f, + FcitxKey_g, + FcitxKey_h, + FcitxKey_j, + FcitxKey_k, + FcitxKey_l, + FcitxKey_semicolon, + }, + + { + FcitxKey_a, + FcitxKey_s, + FcitxKey_d, + FcitxKey_f, + FcitxKey_z, + FcitxKey_x, + FcitxKey_c, + FcitxKey_v, + FcitxKey_8, + FcitxKey_9, + }, + + { + FcitxKey_a, + FcitxKey_s, + FcitxKey_d, + FcitxKey_f, + FcitxKey_j, + FcitxKey_k, + FcitxKey_l, + FcitxKey_7, + FcitxKey_8, + FcitxKey_9, + }, + + { + FcitxKey_1, + FcitxKey_2, + FcitxKey_3, + FcitxKey_4, + FcitxKey_q, + FcitxKey_w, + FcitxKey_e, + FcitxKey_r, + FcitxKey_a, + FcitxKey_s, + }, + { + FcitxKey_d, + FcitxKey_s, + FcitxKey_t, + FcitxKey_n, + FcitxKey_a, + FcitxKey_e, + FcitxKey_o, + FcitxKey_7, + FcitxKey_8, + FcitxKey_9, + }, + }; + + KeyStates states = KeyState::NoState; + + for (auto sym : syms[static_cast(*config_.selectionKey)]) { + selectionKeys_.emplace_back(sym, states); + } + + pinyin_option_t options = USE_TONE | ZHUYIN_CORRECT_ALL; + if (isZhuyin_ && *config_.needTone) { + options |= FORCE_TONE; + } + if (*config_.fuzzy->fuzzyCCh) { + options |= PINYIN_AMB_C_CH; + } + if (*config_.fuzzy->fuzzySSh) { + options |= PINYIN_AMB_S_SH; + } + if (*config_.fuzzy->fuzzyZZh) { + options |= PINYIN_AMB_Z_ZH; + } + if (*config_.fuzzy->fuzzyFH) { + options |= PINYIN_AMB_F_H; + } + if (*config_.fuzzy->fuzzyGK) { + options |= PINYIN_AMB_G_K; + } + if (*config_.fuzzy->fuzzyLN) { + options |= PINYIN_AMB_L_N; + } + if (*config_.fuzzy->fuzzyLR) { + options |= PINYIN_AMB_L_R; + } + if (*config_.fuzzy->fuzzyAnAng) { + options |= PINYIN_AMB_AN_ANG; + } + if (*config_.fuzzy->fuzzyEnEng) { + options |= PINYIN_AMB_EN_ENG; + } + if (*config_.fuzzy->fuzzyInIng) { + options |= PINYIN_AMB_IN_ING; + } + + zhuyin_set_options(context_.get(), options); + + instance_->inputContextManager().foreach ([this](InputContext *ic) { + auto *state = ic->propertyFor(&factory_); + state->reset(); + return true; + }); - zhuyin_load_phrase_library(context_.get(), USER_DICTIONARY); + zhuyin_load_phrase_library(context_.get(), USER_DICTIONARY); } } // namespace fcitx diff --git a/src/zhuyinengine.h b/src/zhuyinengine.h index b0993eb..92f8aaa 100644 --- a/src/zhuyinengine.h +++ b/src/zhuyinengine.h @@ -23,28 +23,28 @@ namespace fcitx { enum class Scheme { - Standard, - Hsu, - IBM, - GinYieh, - Eten, - Eten26, - Dvorak, - HsuDvorak, - DachenCP26, - Hanyu, - Luoma, - SecondaryZhuyin + Standard, + Hsu, + IBM, + GinYieh, + Eten, + Eten26, + Dvorak, + HsuDvorak, + DachenCP26, + Hanyu, + Luoma, + SecondaryZhuyin }; enum class SelectionKey { - Digit, - asdfghjkl, - asdfzxcv89, - asdfjkl789, - aoeuhtn789, - _1234qweras, - dstnaeo789 + Digit, + asdfghjkl, + asdfzxcv89, + asdfjkl789, + aoeuhtn789, + _1234qweras, + dstnaeo789 }; FCITX_CONFIG_ENUM_NAME(SelectionKey, "1234567890", "asdfghjkl;", "asdfzxcv89", @@ -116,64 +116,64 @@ class ZhuyinEngine; class ZhuyinState final : public InputContextProperty { public: - ZhuyinState(ZhuyinEngine *engine, InputContext *ic); + ZhuyinState(ZhuyinEngine *engine, InputContext *ic); - void keyEvent(KeyEvent &keyEvent); - void reset(); - void commit(); + void keyEvent(KeyEvent &keyEvent); + void reset(); + void commit(); - void updateUI(bool showCandidate = false); + void updateUI(bool showCandidate = false); private: - ZhuyinEngine *engine_; - ZhuyinBuffer buffer_; - InputContext *ic_; + ZhuyinEngine *engine_; + ZhuyinBuffer buffer_; + InputContext *ic_; }; class ZhuyinEngine : public InputMethodEngine, public ZhuyinProviderInterface { public: - explicit ZhuyinEngine(Instance *instance); - - void keyEvent(const fcitx::InputMethodEntry &entry, - fcitx::KeyEvent &keyEvent) override; - void activate(const fcitx::InputMethodEntry &, - fcitx::InputContextEvent &) override; - void deactivate(const fcitx::InputMethodEntry &entry, - fcitx::InputContextEvent &event) override; - void reset(const fcitx::InputMethodEntry &, - fcitx::InputContextEvent &) override; - const fcitx::Configuration *getConfig() const override; - void setConfig(const fcitx::RawConfig &) override; - void save() override; - void reloadConfig() override; - - zhuyin_context_t *context() override { return context_.get(); } - bool isZhuyin() const override { return isZhuyin_; } - const auto &config() const { return config_; } - const ZhuyinSymbol &symbol() const override { return symbol_; } - - const KeyList &selectionKeys() const { return selectionKeys_; } - - FCITX_ADDON_DEPENDENCY_LOADER(fullwidth, instance_->addonManager()); - FCITX_ADDON_DEPENDENCY_LOADER(chttrans, instance_->addonManager()); - FCITX_ADDON_DEPENDENCY_LOADER(quickphrase, instance_->addonManager()); + explicit ZhuyinEngine(Instance *instance); + + void keyEvent(const fcitx::InputMethodEntry &entry, + fcitx::KeyEvent &keyEvent) override; + void activate(const fcitx::InputMethodEntry &, + fcitx::InputContextEvent &) override; + void deactivate(const fcitx::InputMethodEntry &entry, + fcitx::InputContextEvent &event) override; + void reset(const fcitx::InputMethodEntry &, + fcitx::InputContextEvent &) override; + const fcitx::Configuration *getConfig() const override; + void setConfig(const fcitx::RawConfig &) override; + void save() override; + void reloadConfig() override; + + zhuyin_context_t *context() override { return context_.get(); } + bool isZhuyin() const override { return isZhuyin_; } + const auto &config() const { return config_; } + const ZhuyinSymbol &symbol() const override { return symbol_; } + + const KeyList &selectionKeys() const { return selectionKeys_; } + + FCITX_ADDON_DEPENDENCY_LOADER(fullwidth, instance_->addonManager()); + FCITX_ADDON_DEPENDENCY_LOADER(chttrans, instance_->addonManager()); + FCITX_ADDON_DEPENDENCY_LOADER(quickphrase, instance_->addonManager()); private: - Instance *instance_; - UniqueCPtr context_; - FactoryFor factory_; - ZhuyinSymbol symbol_; - ZhuyinConfig config_; - KeyList selectionKeys_; - bool isZhuyin_ = true; + Instance *instance_; + UniqueCPtr context_; + FactoryFor factory_; + ZhuyinSymbol symbol_; + ZhuyinConfig config_; + KeyList selectionKeys_; + bool isZhuyin_ = true; }; class ZhuyinEngineFactory final : public AddonFactory { public: - fcitx::AddonInstance *create(fcitx::AddonManager *manager) override { - registerDomain("fcitx5-zhuiyin", FCITX_INSTALL_LOCALEDIR); - return new ZhuyinEngine(manager->instance()); - } + fcitx::AddonInstance *create(fcitx::AddonManager *manager) override { + registerDomain("fcitx5-zhuiyin", FCITX_INSTALL_LOCALEDIR); + return new ZhuyinEngine(manager->instance()); + } }; } // namespace fcitx diff --git a/src/zhuyinsection.cpp b/src/zhuyinsection.cpp index 4fa6e9e..e921057 100644 --- a/src/zhuyinsection.cpp +++ b/src/zhuyinsection.cpp @@ -27,199 +27,197 @@ ZhuyinSection::ZhuyinSection(uint32_t init, ZhuyinSectionType type, ZhuyinProviderInterface *provider, ZhuyinBuffer *buffer) : ZhuyinSection(type, provider, buffer) { - this->type(init); + this->type(init); } bool ZhuyinSection::typeImpl(const char *s, size_t length) { - InputBuffer::typeImpl(s, length); - if (!instance_) { - const auto &candidates = provider_->symbol().lookup(userInput()); - if (candidates.empty()) { - currentSymbol_ = userInput(); - } else { - currentSymbol_ = candidates[0]; - } - return true; - } - if (provider_->isZhuyin()) { - zhuyin_parse_more_chewings(instance_.get(), userInput().data()); + InputBuffer::typeImpl(s, length); + if (!instance_) { + const auto &candidates = provider_->symbol().lookup(userInput()); + if (candidates.empty()) { + currentSymbol_ = userInput(); } else { - zhuyin_parse_more_full_pinyins(instance_.get(), userInput().data()); + currentSymbol_ = candidates[0]; } - zhuyin_guess_sentence(instance_.get()); return true; + } + if (provider_->isZhuyin()) { + zhuyin_parse_more_chewings(instance_.get(), userInput().data()); + } else { + zhuyin_parse_more_full_pinyins(instance_.get(), userInput().data()); + } + zhuyin_guess_sentence(instance_.get()); + return true; } size_t ZhuyinSection::prevChar() const { - if (cursor() == 0 || !instance_) { - return 0; - } - - auto length = parsedZhuyinLength(); - if (cursor() > length) { - return cursor() - 1; - } - size_t offset = 0; - size_t prevCursor = cursor() - 1; - zhuyin_get_zhuyin_offset(instance_.get(), prevCursor, &offset); - return offset; + if (cursor() == 0 || !instance_) { + return 0; + } + + auto length = parsedZhuyinLength(); + if (cursor() > length) { + return cursor() - 1; + } + size_t offset = 0; + size_t prevCursor = cursor() - 1; + zhuyin_get_zhuyin_offset(instance_.get(), prevCursor, &offset); + return offset; } size_t ZhuyinSection::nextChar() const { - if (cursor() == size()) { - return cursor(); - } - - auto length = parsedZhuyinLength(); - if (cursor() + 1 >= length) { - return cursor() + 1; - } - size_t offset = 0, right = 0; - size_t nextCursor = cursor() + 1; - zhuyin_get_zhuyin_offset(instance_.get(), nextCursor, &offset); - zhuyin_get_right_zhuyin_offset(instance_.get(), offset, &right); - return right; + if (cursor() == size()) { + return cursor(); + } + + auto length = parsedZhuyinLength(); + if (cursor() + 1 >= length) { + return cursor() + 1; + } + size_t offset = 0, right = 0; + size_t nextCursor = cursor() + 1; + zhuyin_get_zhuyin_offset(instance_.get(), nextCursor, &offset); + zhuyin_get_right_zhuyin_offset(instance_.get(), offset, &right); + return right; } void ZhuyinSection::erase(size_t from, size_t to) { - InputBuffer::erase(from, to); - if (provider_->isZhuyin()) { - zhuyin_parse_more_chewings(instance_.get(), userInput().data()); - } else { - zhuyin_parse_more_full_pinyins(instance_.get(), userInput().data()); - } - zhuyin_guess_sentence(instance_.get()); + InputBuffer::erase(from, to); + if (provider_->isZhuyin()) { + zhuyin_parse_more_chewings(instance_.get(), userInput().data()); + } else { + zhuyin_parse_more_full_pinyins(instance_.get(), userInput().data()); + } + zhuyin_guess_sentence(instance_.get()); } void ZhuyinSection::setSymbol(std::string symbol) { - currentSymbol_ = std::move(symbol); + currentSymbol_ = std::move(symbol); } std::string ZhuyinSection::preedit() const { return preeditWithCursor().first; } void ZhuyinSection::learn() { - if (!instance_) { - return; - } - zhuyin_train(instance_.get()); + if (!instance_) { + return; + } + zhuyin_train(instance_.get()); } std::pair ZhuyinSection::preeditWithCursor() const { - std::string result; - if (!instance_) { - return {currentSymbol_, currentSymbol_.size()}; - } - - auto length = parsedZhuyinLength(); - char *sentence = nullptr; - if (length) { - zhuyin_get_sentence(instance_.get(), &sentence); - } - + std::string result; + if (!instance_) { + return {currentSymbol_, currentSymbol_.size()}; + } + + auto length = parsedZhuyinLength(); + char *sentence = nullptr; + if (length) { + zhuyin_get_sentence(instance_.get(), &sentence); + } + + if (sentence) { + result.append(sentence); + } + + auto preeditCursor = cursor(); + if (preeditCursor >= length) { + preeditCursor -= length; if (sentence) { - result.append(sentence); + preeditCursor += strlen(sentence); } + } else { + size_t offset; + zhuyin_get_character_offset(instance_.get(), sentence, cursor(), &offset); + preeditCursor = utf8::ncharByteLength(sentence, offset); + } - auto preeditCursor = cursor(); - if (preeditCursor >= length) { - preeditCursor -= length; - if (sentence) { - preeditCursor += strlen(sentence); - } + free(sentence); + for (; length < size(); length++) { + if (provider_->isZhuyin()) { + gchar **symbols = nullptr; + zhuyin_in_chewing_keyboard(instance_.get(), charAt(length), &symbols); + if (symbols && symbols[0]) { + result.append(symbols[0]); + } + g_strfreev(symbols); } else { - size_t offset; - zhuyin_get_character_offset(instance_.get(), sentence, cursor(), - &offset); - preeditCursor = utf8::ncharByteLength(sentence, offset); + result.push_back(static_cast(charAt(length))); } - free(sentence); - for (; length < size(); length++) { - if (provider_->isZhuyin()) { - gchar **symbols = nullptr; - zhuyin_in_chewing_keyboard(instance_.get(), charAt(length), - &symbols); - if (symbols && symbols[0]) { - result.append(symbols[0]); - } - g_strfreev(symbols); - } else { - result.push_back(static_cast(charAt(length))); - } - - if (length + 1 == cursor()) { - preeditCursor = result.size(); - } + if (length + 1 == cursor()) { + preeditCursor = result.size(); } - return {result, preeditCursor}; + } + return {result, preeditCursor}; } size_t ZhuyinSection::parsedZhuyinLength() const { - if (!instance_) { - throw std::runtime_error("Bug in fcitx5-zhuyin"); - } - return zhuyin_get_parsed_input_length(instance_.get()); + if (!instance_) { + throw std::runtime_error("Bug in fcitx5-zhuyin"); + } + return zhuyin_get_parsed_input_length(instance_.get()); } void ZhuyinSection::showCandidate( const std::function)> &callback, SectionIterator iter, size_t offset) { - assert(&*iter == this); - if (!instance_) { - if (size() == 1) { - auto c = charAt(offset); - gchar **symbols = nullptr; - if (c < std::numeric_limits::max() && - zhuyin_in_chewing_keyboard(buffer_->instance(), c, &symbols)) { - // Make sure we have two symbol. - if (symbols[0] && symbols[1]) { - for (size_t i = 0; symbols[i]; i++) { - callback(std::make_unique( - iter, symbols[i])); - } - } - g_strfreev(symbols); - return; - } - } - - auto candidates = provider_->symbol().lookup(userInput()); - if (candidates.empty()) { - return; - } - for (const auto &symbol : candidates) { - callback(std::make_unique(iter, symbol)); + assert(&*iter == this); + if (!instance_) { + if (size() == 1) { + auto c = charAt(offset); + gchar **symbols = nullptr; + if (c < std::numeric_limits::max() && + zhuyin_in_chewing_keyboard(buffer_->instance(), c, &symbols)) { + // Make sure we have two symbol. + if (symbols[0] && symbols[1]) { + for (size_t i = 0; symbols[i]; i++) { + callback( + std::make_unique(iter, symbols[i])); + } } + g_strfreev(symbols); return; + } } - if (offset >= parsedZhuyinLength()) { - if (!provider_->isZhuyin() || offset >= size()) { - return; - } - auto c = charAt(offset); - gchar **symbols = nullptr; - if (c < std::numeric_limits::max() && - zhuyin_in_chewing_keyboard(instance_.get(), c, &symbols)) { - // Make sure we have two symbol. - if (symbols[0] && symbols[1]) { - for (size_t i = 0; symbols[i]; i++) { - callback(std::make_unique( - iter, symbols[i], offset)); - } - } - g_strfreev(symbols); - } - return; + auto candidates = provider_->symbol().lookup(userInput()); + if (candidates.empty()) { + return; } + for (const auto &symbol : candidates) { + callback(std::make_unique(iter, symbol)); + } + return; + } - zhuyin_get_zhuyin_offset(instance_.get(), offset, &offset); - zhuyin_guess_candidates_after_cursor(instance_.get(), offset); - guint len = 0; - zhuyin_get_n_candidate(instance_.get(), &len); - for (size_t i = 0; i < len; i++) { - callback(std::make_unique(iter, i)); + if (offset >= parsedZhuyinLength()) { + if (!provider_->isZhuyin() || offset >= size()) { + return; } + auto c = charAt(offset); + gchar **symbols = nullptr; + if (c < std::numeric_limits::max() && + zhuyin_in_chewing_keyboard(instance_.get(), c, &symbols)) { + // Make sure we have two symbol. + if (symbols[0] && symbols[1]) { + for (size_t i = 0; symbols[i]; i++) { + callback(std::make_unique( + iter, symbols[i], offset)); + } + } + g_strfreev(symbols); + } + return; + } + + zhuyin_get_zhuyin_offset(instance_.get(), offset, &offset); + zhuyin_guess_candidates_after_cursor(instance_.get(), offset); + guint len = 0; + zhuyin_get_n_candidate(instance_.get(), &len); + for (size_t i = 0; i < len; i++) { + callback(std::make_unique(iter, i)); + } } } // namespace fcitx diff --git a/src/zhuyinsection.h b/src/zhuyinsection.h index 9e36c4e..0e941a7 100644 --- a/src/zhuyinsection.h +++ b/src/zhuyinsection.h @@ -22,47 +22,47 @@ class ZhuyinProviderInterface; using SectionIterator = std::list::iterator; enum class ZhuyinSectionType { - Zhuyin, - Symbol, + Zhuyin, + Symbol, }; // A section of preedit, it can be either a single symbol, or a series of // Zhuyin. class ZhuyinSection : public InputBuffer { public: - ZhuyinSection(ZhuyinSectionType type, ZhuyinProviderInterface *provider, - ZhuyinBuffer *buffer); - ZhuyinSection(uint32_t init, ZhuyinSectionType type, - ZhuyinProviderInterface *provider, ZhuyinBuffer *buffer); + ZhuyinSection(ZhuyinSectionType type, ZhuyinProviderInterface *provider, + ZhuyinBuffer *buffer); + ZhuyinSection(uint32_t init, ZhuyinSectionType type, + ZhuyinProviderInterface *provider, ZhuyinBuffer *buffer); - ZhuyinSectionType sectionType() const { return type_; } + ZhuyinSectionType sectionType() const { return type_; } - size_t parsedZhuyinLength() const; + size_t parsedZhuyinLength() const; - std::string preedit() const; - std::pair preeditWithCursor() const; - size_t prevChar() const; - size_t nextChar() const; + std::string preedit() const; + std::pair preeditWithCursor() const; + size_t prevChar() const; + size_t nextChar() const; - void erase(size_t from, size_t to) override; - void setSymbol(std::string symbol); + void erase(size_t from, size_t to) override; + void setSymbol(std::string symbol); - void showCandidate( - const std::function)> &callback, - SectionIterator iter, size_t offset); - void learn(); - auto instance() const { return instance_.get(); } - auto buffer() const { return buffer_; } + void showCandidate( + const std::function)> &callback, + SectionIterator iter, size_t offset); + void learn(); + auto instance() const { return instance_.get(); } + auto buffer() const { return buffer_; } protected: - bool typeImpl(const char *s, size_t length) override; + bool typeImpl(const char *s, size_t length) override; private: - ZhuyinProviderInterface *provider_; - ZhuyinBuffer *buffer_; - const ZhuyinSectionType type_; - std::string currentSymbol_; - UniqueCPtr instance_; + ZhuyinProviderInterface *provider_; + ZhuyinBuffer *buffer_; + const ZhuyinSectionType type_; + std::string currentSymbol_; + UniqueCPtr instance_; }; } // namespace fcitx diff --git a/src/zhuyinsymbol.cpp b/src/zhuyinsymbol.cpp index f704e51..d84991e 100644 --- a/src/zhuyinsymbol.cpp +++ b/src/zhuyinsymbol.cpp @@ -19,247 +19,244 @@ ZhuyinSymbol::ZhuyinSymbol() { initBuiltin(); } const std::vector & ZhuyinSymbol::lookup(const std::string &key) const { - if (auto iter = symbols_.find(key); iter != symbols_.end()) { - return iter->second; - } - return empty; + if (auto iter = symbols_.find(key); iter != symbols_.end()) { + return iter->second; + } + return empty; } void ZhuyinSymbol::load(std::FILE *file) { - symbols_.clear(); - initBuiltin(); + symbols_.clear(); + initBuiltin(); - if (!file) { - for (char c = 'A'; c <= 'Z'; c++) { - char latin[] = {c, '\0'}; - symbols_.erase(latin); - } - return; + if (!file) { + for (char c = 'A'; c <= 'Z'; c++) { + char latin[] = {c, '\0'}; + symbols_.erase(latin); + } + return; + } + UniqueCPtr line; + size_t size = 0; + while (getline(line, &size, file) >= 0) { + auto trimmed = stringutils::trim(line.get()); + if (trimmed.empty()) { + continue; } - UniqueCPtr line; - size_t size = 0; - while (getline(line, &size, file) >= 0) { - auto trimmed = stringutils::trim(line.get()); - if (trimmed.empty()) { - continue; - } - auto space = trimmed.find(' '); - auto key = trimmed.substr(0, space); - auto value = trimmed.substr(space + 1); - if (key.empty() || value.empty()) { - continue; - } + auto space = trimmed.find(' '); + auto key = trimmed.substr(0, space); + auto value = trimmed.substr(space + 1); + if (key.empty() || value.empty()) { + continue; + } - std::vector items; - items.push_back(std::move(value)); - items.push_back(key); - if (auto iter = symbolToGroup_.find(items[0]); - iter != symbolToGroup_.end()) { - for (const auto &item : groups_[iter->second]) { - if (item != items[0]) { - items.push_back(item); - } - } + std::vector items; + items.push_back(std::move(value)); + items.push_back(key); + if (auto iter = symbolToGroup_.find(items[0]); + iter != symbolToGroup_.end()) { + for (const auto &item : groups_[iter->second]) { + if (item != items[0]) { + items.push_back(item); } - symbols_[key] = std::move(items); + } } + symbols_[key] = std::move(items); + } } void ZhuyinSymbol::initBuiltin() { - symbolToGroup_.clear(); - groups_.clear(); - constexpr const char *const symbolGroup[][50] = { - {"0", "\xC3\xB8", nullptr}, - /* "ø" */ - {"[", "\xE3\x80\x8C", "\xE3\x80\x8E", "\xE3\x80\x8A", "\xE3\x80\x88", - "\xE3\x80\x90", "\xE3\x80\x94", nullptr}, - /* "「", "『", "《", "〈", "【", "〔" */ - {"]", "\xE3\x80\x8D", "\xE3\x80\x8F", "\xE3\x80\x8B", "\xE3\x80\x89", - "\xE3\x80\x91", "\xE3\x80\x95", nullptr}, - /* "」", "』", "》", "〉", "】", "〕" */ - {"{", "\xEF\xBD\x9B", nullptr}, - /* "{" */ - {"}", "\xEF\xBD\x9D", nullptr}, - /* "}" */ - {"<", "\xEF\xBC\x8C", "\xE2\x86\x90", nullptr}, - /* ",", "←" */ - {">", "\xE3\x80\x82", "\xE2\x86\x92", "\xEF\xBC\x8E", nullptr}, - /* "。", "→", "." */ - {"?", "\xEF\xBC\x9F", "\xC2\xBF", nullptr}, - /* "?", "¿" */ - {"!", "\xEF\xBC\x81", "\xE2\x85\xA0", "\xC2\xA1", nullptr}, - /* "!", "Ⅰ","¡" */ - {"@", "\xEF\xBC\xA0", "\xE2\x85\xA1", "\xE2\x8A\x95", "\xE2\x8A\x99", - "\xE3\x8A\xA3", "\xEF\xB9\xAB", nullptr}, - /* "@", "Ⅱ", "⊕", "⊙", "㊣", "﹫" */ - {"#", "\xEF\xBC\x83", "\xE2\x85\xA2", "\xEF\xB9\x9F", nullptr}, - /* "#", "Ⅲ", "﹟" */ - {"$", "\xEF\xBC\x84", "\xE2\x85\xA3", "\xE2\x82\xAC", "\xEF\xB9\xA9", - "\xEF\xBF\xA0", "\xE2\x88\xAE", "\xEF\xBF\xA1", "\xEF\xBF\xA5", - nullptr}, - /* "$", "Ⅳ", "€", "﹩", "¢", "∮","£", "¥" */ - {"%", "\xEF\xBC\x85", "\xE2\x85\xA4", nullptr}, - /* "%", "Ⅴ" */ - {"^", "\xEF\xB8\xBF", "\xE2\x85\xA5", "\xEF\xB9\x80", "\xEF\xB8\xBD", - "\xEF\xB8\xBE", nullptr}, - /* "︿", "Ⅵ", "﹀", "︽", "︾" */ - {"&", "\xEF\xBC\x86", "\xE2\x85\xA6", "\xEF\xB9\xA0", nullptr}, - /* "&", "Ⅶ", "﹠" */ - {"*", "\xEF\xBC\x8A", "\xE2\x85\xA7", "\xC3\x97", "\xE2\x80\xBB", - "\xE2\x95\xB3", "\xEF\xB9\xA1", "\xE2\x98\xAF", "\xE2\x98\x86", - "\xE2\x98\x85", nullptr}, - /* "*", "Ⅷ", "×", "※", "╳", "﹡", "☯", "☆", "★" */ - {"(", "\xEF\xBC\x88", "\xE2\x85\xA8", nullptr}, - /* "(", "Ⅸ" */ - {")", "\xEF\xBC\x89", "\xE2\x85\xA9", nullptr}, - /* ")", "Ⅹ" */ - {"_", "\xEF\xBC\xBF", "\xE2\x80\xA6", "\xE2\x80\xA5", "\xE2\x86\x90", - "\xE2\x86\x92", "\xEF\xB9\x8D", "\xEF\xB9\x89", "\xCB\x8D", - "\xEF\xBF\xA3", "\xE2\x80\x93", "\xE2\x80\x94", "\xC2\xAF", - "\xEF\xB9\x8A", "\xEF\xB9\x8E", "\xEF\xB9\x8F", "\xEF\xB9\xA3", - "\xEF\xBC\x8D", nullptr}, - /* "_", "…", "‥", "←", "→", "﹍", "﹉", "ˍ", " ̄" - * "–", "—", "¯", "﹊", "﹎", "﹏", "﹣", "-" */ - {"+", "\xEF\xBC\x8B", "\xC2\xB1", "\xEF\xB9\xA2", nullptr}, - /* "+", "±", "﹢" */ - {"=", "\xEF\xBC\x9D", "\xE2\x89\x92", "\xE2\x89\xA0", "\xE2\x89\xA1", - "\xE2\x89\xA6", "\xE2\x89\xA7", "\xEF\xB9\xA6", nullptr}, - /* "=", "≒", "≠", "≡", "≦", "≧", "﹦" */ - {"`", "\xE3\x80\x8F", "\xE3\x80\x8E", "\xE2\x80\xB2", "\xE2\x80\xB5", - nullptr}, - /* "』", "『", "′", "‵" */ - {"~", "\xEF\xBD\x9E", nullptr}, - /* "~" */ - {":", "\xEF\xBC\x9A", "\xEF\xBC\x9B", "\xEF\xB8\xB0", "\xEF\xB9\x95", - nullptr}, - /* ":", ";", "︰", "﹕" */ - {"\"", "\xEF\xBC\x9B", nullptr}, - /* ";" */ - {"\'", "\xE3\x80\x81", "\xE2\x80\xA6", "\xE2\x80\xA5", nullptr}, - /* "、", "…", "‥" */ - {"\\", "\xEF\xBC\xBC", "\xE2\x86\x96", "\xE2\x86\x98", "\xEF\xB9\xA8", - nullptr}, - /* "\", "↖", "↘", "﹨" */ - {"-", - "\xEF\xBC\x8D", - "\xEF\xBC\xBF", - "\xEF\xBF\xA3", - "\xC2\xAF", - "\xCB\x8D", - "\xE2\x80\x93", - "\xE2\x80\x94", - "\xE2\x80\xA5", - "\xE2\x80\xA6", - "\xE2\x86\x90", - "\xE2\x86\x92", - "\xE2\x95\xB4", - "\xEF\xB9\x89", - "\xEF\xB9\x8A", - "\xEF\xB9\x8D", - "\xEF\xB9\x8E", - "\xEF\xB9\x8F", - "\xEF\xB9\xA3", - nullptr}, - /* "-", "_", " ̄", "¯", "ˍ", "–", "—", "‥", "…" - * "←", "→", "╴", "﹉", "﹊", "﹍", "﹎", "﹏", "﹣" */ - {"/", "\xEF\xBC\x8F", "\xC3\xB7", "\xE2\x86\x97", "\xE2\x86\x99", - "\xE2\x88\x95", nullptr}, - /* "/","÷","↗","↙","∕" */ - {"|", "\xE2\x86\x91", "\xE2\x86\x93", "\xE2\x88\xA3", "\xE2\x88\xA5", - "\xEF\xB8\xB1", "\xEF\xB8\xB3", "\xEF\xB8\xB4", 0}, - /* "↑", "↓", "∣", "∥", "︱", "︳", "︴" */ - {"A", "\xC3\x85", "\xCE\x91", "\xCE\xB1", "\xE2\x94\x9C", - "\xE2\x95\xA0", "\xE2\x95\x9F", "\xE2\x95\x9E", nullptr}, - /* "Å","Α", "α", "├", "╠", "╟", "╞" */ - {"B", "\xCE\x92", "\xCE\xB2", "\xE2\x88\xB5", nullptr}, - /* "Β", "β","∵" */ - {"C", "\xCE\xA7", "\xCF\x87", "\xE2\x94\x98", "\xE2\x95\xAF", - "\xE2\x95\x9D", "\xE2\x95\x9C", "\xE2\x95\x9B", "\xE3\x8F\x84", - "\xE2\x84\x83", "\xE3\x8E\x9D", "\xE2\x99\xA3", "\xC2\xA9", nullptr}, - /* "Χ", "χ", "┘", "╯", "╝", "╜", "╛" - * "㏄", "℃", "㎝", "♣", "©" */ - {"D", "\xCE\x94", "\xCE\xB4", "\xE2\x97\x87", "\xE2\x97\x86", - "\xE2\x94\xA4", "\xE2\x95\xA3", "\xE2\x95\xA2", "\xE2\x95\xA1", - "\xE2\x99\xA6", nullptr}, - /* "Δ", "δ", "◇", "◆", "┤", "╣", "╢", "╡","♦" */ - {"E", "\xCE\x95", "\xCE\xB5", "\xE2\x94\x90", "\xE2\x95\xAE", - "\xE2\x95\x97", "\xE2\x95\x93", "\xE2\x95\x95", nullptr}, - /* "Ε", "ε", "┐", "╮", "╗", "╓", "╕" */ - {"F", "\xCE\xA6", "\xCF\x88", "\xE2\x94\x82", "\xE2\x95\x91", - "\xE2\x99\x80", nullptr}, - /* "Φ", "ψ", "│", "║", "♀" */ - {"G", "\xCE\x93", "\xCE\xB3", nullptr}, - /* "Γ", "γ" */ - {"H", "\xCE\x97", "\xCE\xB7", "\xE2\x99\xA5", nullptr}, - /* "Η", "η","♥" */ - {"I", "\xCE\x99", "\xCE\xB9", nullptr}, - /* "Ι", "ι" */ - {"J", "\xCF\x86", nullptr}, - /* "φ" */ - {"K", "\xCE\x9A", "\xCE\xBA", "\xE3\x8E\x9E", "\xE3\x8F\x8E", nullptr}, - /* "Κ", "κ","㎞", "㏎" */ - {"L", "\xCE\x9B", "\xCE\xBB", "\xE3\x8F\x92", "\xE3\x8F\x91", nullptr}, - /* "Λ", "λ","㏒", "㏑" */ - {"M", "\xCE\x9C", "\xCE\xBC", "\xE2\x99\x82", "\xE2\x84\x93", - "\xE3\x8E\x8E", "\xE3\x8F\x95", "\xE3\x8E\x9C", "\xE3\x8E\xA1", - nullptr}, - /* "Μ", "μ", "♂", "ℓ", "㎎", "㏕", "㎜","㎡" */ - {"N", "\xCE\x9D", "\xCE\xBD", "\xE2\x84\x96", nullptr}, - /* "Ν", "ν","№" */ - {"O", "\xCE\x9F", "\xCE\xBF", nullptr}, - /* "Ο", "ο" */ - {"P", "\xCE\xA0", "\xCF\x80", nullptr}, - /* "Π", "π" */ - {"Q", "\xCE\x98", "\xCE\xB8", "\xD0\x94", "\xE2\x94\x8C", - "\xE2\x95\xAD", "\xE2\x95\x94", "\xE2\x95\x93", "\xE2\x95\x92", - nullptr}, - /* "Θ", "θ","Д","┌", "╭", "╔", "╓", "╒" */ - {"R", "\xCE\xA1", "\xCF\x81", "\xE2\x94\x80", "\xE2\x95\x90", - "\xC2\xAE", nullptr}, - /* "Ρ", "ρ", "─", "═" ,"®" */ - {"S", "\xCE\xA3", "\xCF\x83", "\xE2\x88\xB4", "\xE2\x96\xA1", - "\xE2\x96\xA0", "\xE2\x94\xBC", "\xE2\x95\xAC", "\xE2\x95\xAA", - "\xE2\x95\xAB", "\xE2\x88\xAB", "\xC2\xA7", "\xE2\x99\xA0", nullptr}, - /* "Σ", "σ", "∴", "□", "■", "┼", "╬", "╪", "╫" - * "∫", "§", "♠" */ - {"T", "\xCE\xA4", "\xCF\x84", "\xCE\xB8", "\xE2\x96\xB3", - "\xE2\x96\xB2", "\xE2\x96\xBD", "\xE2\x96\xBC", "\xE2\x84\xA2", - "\xE2\x8A\xBF", "\xE2\x84\xA2", nullptr}, - /* "Τ", "τ","θ","△","▲","▽","▼","™","⊿", "™" */ - {"U", "\xCE\xA5", "\xCF\x85", "\xCE\xBC", "\xE2\x88\xAA", - "\xE2\x88\xA9", nullptr}, - /* "Υ", "υ","μ","∪", "∩" */ - {"V", "\xCE\xBD", nullptr}, - {"W", "\xE2\x84\xA6", "\xCF\x89", "\xE2\x94\xAC", "\xE2\x95\xA6", - "\xE2\x95\xA4", "\xE2\x95\xA5", nullptr}, - /* "Ω", "ω", "┬", "╦", "╤", "╥" */ - {"X", "\xCE\x9E", "\xCE\xBE", "\xE2\x94\xB4", "\xE2\x95\xA9", - "\xE2\x95\xA7", "\xE2\x95\xA8", nullptr}, - /* "Ξ", "ξ", "┴", "╩", "╧", "╨" */ - {"Y", "\xCE\xA8", nullptr}, - /* "Ψ" */ - {"Z", "\xCE\x96", "\xCE\xB6", "\xE2\x94\x94", "\xE2\x95\xB0", - "\xE2\x95\x9A", "\xE2\x95\x99", "\xE2\x95\x98", nullptr}, - /* "Ζ", "ζ", "└", "╰", "╚", "╙", "╘" */ - }; + symbolToGroup_.clear(); + groups_.clear(); + constexpr const char *const symbolGroup[][50] = { + {"0", "\xC3\xB8", nullptr}, + /* "ø" */ + {"[", "\xE3\x80\x8C", "\xE3\x80\x8E", "\xE3\x80\x8A", "\xE3\x80\x88", + "\xE3\x80\x90", "\xE3\x80\x94", nullptr}, + /* "「", "『", "《", "〈", "【", "〔" */ + {"]", "\xE3\x80\x8D", "\xE3\x80\x8F", "\xE3\x80\x8B", "\xE3\x80\x89", + "\xE3\x80\x91", "\xE3\x80\x95", nullptr}, + /* "」", "』", "》", "〉", "】", "〕" */ + {"{", "\xEF\xBD\x9B", nullptr}, + /* "{" */ + {"}", "\xEF\xBD\x9D", nullptr}, + /* "}" */ + {"<", "\xEF\xBC\x8C", "\xE2\x86\x90", nullptr}, + /* ",", "←" */ + {">", "\xE3\x80\x82", "\xE2\x86\x92", "\xEF\xBC\x8E", nullptr}, + /* "。", "→", "." */ + {"?", "\xEF\xBC\x9F", "\xC2\xBF", nullptr}, + /* "?", "¿" */ + {"!", "\xEF\xBC\x81", "\xE2\x85\xA0", "\xC2\xA1", nullptr}, + /* "!", "Ⅰ","¡" */ + {"@", "\xEF\xBC\xA0", "\xE2\x85\xA1", "\xE2\x8A\x95", "\xE2\x8A\x99", + "\xE3\x8A\xA3", "\xEF\xB9\xAB", nullptr}, + /* "@", "Ⅱ", "⊕", "⊙", "㊣", "﹫" */ + {"#", "\xEF\xBC\x83", "\xE2\x85\xA2", "\xEF\xB9\x9F", nullptr}, + /* "#", "Ⅲ", "﹟" */ + {"$", "\xEF\xBC\x84", "\xE2\x85\xA3", "\xE2\x82\xAC", "\xEF\xB9\xA9", + "\xEF\xBF\xA0", "\xE2\x88\xAE", "\xEF\xBF\xA1", "\xEF\xBF\xA5", nullptr}, + /* "$", "Ⅳ", "€", "﹩", "¢", "∮","£", "¥" */ + {"%", "\xEF\xBC\x85", "\xE2\x85\xA4", nullptr}, + /* "%", "Ⅴ" */ + {"^", "\xEF\xB8\xBF", "\xE2\x85\xA5", "\xEF\xB9\x80", "\xEF\xB8\xBD", + "\xEF\xB8\xBE", nullptr}, + /* "︿", "Ⅵ", "﹀", "︽", "︾" */ + {"&", "\xEF\xBC\x86", "\xE2\x85\xA6", "\xEF\xB9\xA0", nullptr}, + /* "&", "Ⅶ", "﹠" */ + {"*", "\xEF\xBC\x8A", "\xE2\x85\xA7", "\xC3\x97", "\xE2\x80\xBB", + "\xE2\x95\xB3", "\xEF\xB9\xA1", "\xE2\x98\xAF", "\xE2\x98\x86", + "\xE2\x98\x85", nullptr}, + /* "*", "Ⅷ", "×", "※", "╳", "﹡", "☯", "☆", "★" */ + {"(", "\xEF\xBC\x88", "\xE2\x85\xA8", nullptr}, + /* "(", "Ⅸ" */ + {")", "\xEF\xBC\x89", "\xE2\x85\xA9", nullptr}, + /* ")", "Ⅹ" */ + {"_", "\xEF\xBC\xBF", "\xE2\x80\xA6", "\xE2\x80\xA5", "\xE2\x86\x90", + "\xE2\x86\x92", "\xEF\xB9\x8D", "\xEF\xB9\x89", "\xCB\x8D", + "\xEF\xBF\xA3", "\xE2\x80\x93", "\xE2\x80\x94", "\xC2\xAF", + "\xEF\xB9\x8A", "\xEF\xB9\x8E", "\xEF\xB9\x8F", "\xEF\xB9\xA3", + "\xEF\xBC\x8D", nullptr}, + /* "_", "…", "‥", "←", "→", "﹍", "﹉", "ˍ", " ̄" + * "–", "—", "¯", "﹊", "﹎", "﹏", "﹣", "-" */ + {"+", "\xEF\xBC\x8B", "\xC2\xB1", "\xEF\xB9\xA2", nullptr}, + /* "+", "±", "﹢" */ + {"=", "\xEF\xBC\x9D", "\xE2\x89\x92", "\xE2\x89\xA0", "\xE2\x89\xA1", + "\xE2\x89\xA6", "\xE2\x89\xA7", "\xEF\xB9\xA6", nullptr}, + /* "=", "≒", "≠", "≡", "≦", "≧", "﹦" */ + {"`", "\xE3\x80\x8F", "\xE3\x80\x8E", "\xE2\x80\xB2", "\xE2\x80\xB5", + nullptr}, + /* "』", "『", "′", "‵" */ + {"~", "\xEF\xBD\x9E", nullptr}, + /* "~" */ + {":", "\xEF\xBC\x9A", "\xEF\xBC\x9B", "\xEF\xB8\xB0", "\xEF\xB9\x95", + nullptr}, + /* ":", ";", "︰", "﹕" */ + {"\"", "\xEF\xBC\x9B", nullptr}, + /* ";" */ + {"\'", "\xE3\x80\x81", "\xE2\x80\xA6", "\xE2\x80\xA5", nullptr}, + /* "、", "…", "‥" */ + {"\\", "\xEF\xBC\xBC", "\xE2\x86\x96", "\xE2\x86\x98", "\xEF\xB9\xA8", + nullptr}, + /* "\", "↖", "↘", "﹨" */ + {"-", + "\xEF\xBC\x8D", + "\xEF\xBC\xBF", + "\xEF\xBF\xA3", + "\xC2\xAF", + "\xCB\x8D", + "\xE2\x80\x93", + "\xE2\x80\x94", + "\xE2\x80\xA5", + "\xE2\x80\xA6", + "\xE2\x86\x90", + "\xE2\x86\x92", + "\xE2\x95\xB4", + "\xEF\xB9\x89", + "\xEF\xB9\x8A", + "\xEF\xB9\x8D", + "\xEF\xB9\x8E", + "\xEF\xB9\x8F", + "\xEF\xB9\xA3", + nullptr}, + /* "-", "_", " ̄", "¯", "ˍ", "–", "—", "‥", "…" + * "←", "→", "╴", "﹉", "﹊", "﹍", "﹎", "﹏", "﹣" */ + {"/", "\xEF\xBC\x8F", "\xC3\xB7", "\xE2\x86\x97", "\xE2\x86\x99", + "\xE2\x88\x95", nullptr}, + /* "/","÷","↗","↙","∕" */ + {"|", "\xE2\x86\x91", "\xE2\x86\x93", "\xE2\x88\xA3", "\xE2\x88\xA5", + "\xEF\xB8\xB1", "\xEF\xB8\xB3", "\xEF\xB8\xB4", 0}, + /* "↑", "↓", "∣", "∥", "︱", "︳", "︴" */ + {"A", "\xC3\x85", "\xCE\x91", "\xCE\xB1", "\xE2\x94\x9C", "\xE2\x95\xA0", + "\xE2\x95\x9F", "\xE2\x95\x9E", nullptr}, + /* "Å","Α", "α", "├", "╠", "╟", "╞" */ + {"B", "\xCE\x92", "\xCE\xB2", "\xE2\x88\xB5", nullptr}, + /* "Β", "β","∵" */ + {"C", "\xCE\xA7", "\xCF\x87", "\xE2\x94\x98", "\xE2\x95\xAF", + "\xE2\x95\x9D", "\xE2\x95\x9C", "\xE2\x95\x9B", "\xE3\x8F\x84", + "\xE2\x84\x83", "\xE3\x8E\x9D", "\xE2\x99\xA3", "\xC2\xA9", nullptr}, + /* "Χ", "χ", "┘", "╯", "╝", "╜", "╛" + * "㏄", "℃", "㎝", "♣", "©" */ + {"D", "\xCE\x94", "\xCE\xB4", "\xE2\x97\x87", "\xE2\x97\x86", + "\xE2\x94\xA4", "\xE2\x95\xA3", "\xE2\x95\xA2", "\xE2\x95\xA1", + "\xE2\x99\xA6", nullptr}, + /* "Δ", "δ", "◇", "◆", "┤", "╣", "╢", "╡","♦" */ + {"E", "\xCE\x95", "\xCE\xB5", "\xE2\x94\x90", "\xE2\x95\xAE", + "\xE2\x95\x97", "\xE2\x95\x93", "\xE2\x95\x95", nullptr}, + /* "Ε", "ε", "┐", "╮", "╗", "╓", "╕" */ + {"F", "\xCE\xA6", "\xCF\x88", "\xE2\x94\x82", "\xE2\x95\x91", + "\xE2\x99\x80", nullptr}, + /* "Φ", "ψ", "│", "║", "♀" */ + {"G", "\xCE\x93", "\xCE\xB3", nullptr}, + /* "Γ", "γ" */ + {"H", "\xCE\x97", "\xCE\xB7", "\xE2\x99\xA5", nullptr}, + /* "Η", "η","♥" */ + {"I", "\xCE\x99", "\xCE\xB9", nullptr}, + /* "Ι", "ι" */ + {"J", "\xCF\x86", nullptr}, + /* "φ" */ + {"K", "\xCE\x9A", "\xCE\xBA", "\xE3\x8E\x9E", "\xE3\x8F\x8E", nullptr}, + /* "Κ", "κ","㎞", "㏎" */ + {"L", "\xCE\x9B", "\xCE\xBB", "\xE3\x8F\x92", "\xE3\x8F\x91", nullptr}, + /* "Λ", "λ","㏒", "㏑" */ + {"M", "\xCE\x9C", "\xCE\xBC", "\xE2\x99\x82", "\xE2\x84\x93", + "\xE3\x8E\x8E", "\xE3\x8F\x95", "\xE3\x8E\x9C", "\xE3\x8E\xA1", nullptr}, + /* "Μ", "μ", "♂", "ℓ", "㎎", "㏕", "㎜","㎡" */ + {"N", "\xCE\x9D", "\xCE\xBD", "\xE2\x84\x96", nullptr}, + /* "Ν", "ν","№" */ + {"O", "\xCE\x9F", "\xCE\xBF", nullptr}, + /* "Ο", "ο" */ + {"P", "\xCE\xA0", "\xCF\x80", nullptr}, + /* "Π", "π" */ + {"Q", "\xCE\x98", "\xCE\xB8", "\xD0\x94", "\xE2\x94\x8C", "\xE2\x95\xAD", + "\xE2\x95\x94", "\xE2\x95\x93", "\xE2\x95\x92", nullptr}, + /* "Θ", "θ","Д","┌", "╭", "╔", "╓", "╒" */ + {"R", "\xCE\xA1", "\xCF\x81", "\xE2\x94\x80", "\xE2\x95\x90", "\xC2\xAE", + nullptr}, + /* "Ρ", "ρ", "─", "═" ,"®" */ + {"S", "\xCE\xA3", "\xCF\x83", "\xE2\x88\xB4", "\xE2\x96\xA1", + "\xE2\x96\xA0", "\xE2\x94\xBC", "\xE2\x95\xAC", "\xE2\x95\xAA", + "\xE2\x95\xAB", "\xE2\x88\xAB", "\xC2\xA7", "\xE2\x99\xA0", nullptr}, + /* "Σ", "σ", "∴", "□", "■", "┼", "╬", "╪", "╫" + * "∫", "§", "♠" */ + {"T", "\xCE\xA4", "\xCF\x84", "\xCE\xB8", "\xE2\x96\xB3", "\xE2\x96\xB2", + "\xE2\x96\xBD", "\xE2\x96\xBC", "\xE2\x84\xA2", "\xE2\x8A\xBF", + "\xE2\x84\xA2", nullptr}, + /* "Τ", "τ","θ","△","▲","▽","▼","™","⊿", "™" */ + {"U", "\xCE\xA5", "\xCF\x85", "\xCE\xBC", "\xE2\x88\xAA", "\xE2\x88\xA9", + nullptr}, + /* "Υ", "υ","μ","∪", "∩" */ + {"V", "\xCE\xBD", nullptr}, + {"W", "\xE2\x84\xA6", "\xCF\x89", "\xE2\x94\xAC", "\xE2\x95\xA6", + "\xE2\x95\xA4", "\xE2\x95\xA5", nullptr}, + /* "Ω", "ω", "┬", "╦", "╤", "╥" */ + {"X", "\xCE\x9E", "\xCE\xBE", "\xE2\x94\xB4", "\xE2\x95\xA9", + "\xE2\x95\xA7", "\xE2\x95\xA8", nullptr}, + /* "Ξ", "ξ", "┴", "╩", "╧", "╨" */ + {"Y", "\xCE\xA8", nullptr}, + /* "Ψ" */ + {"Z", "\xCE\x96", "\xCE\xB6", "\xE2\x94\x94", "\xE2\x95\xB0", + "\xE2\x95\x9A", "\xE2\x95\x99", "\xE2\x95\x98", nullptr}, + /* "Ζ", "ζ", "└", "╰", "╚", "╙", "╘" */ + }; - for (size_t i = 0; i < FCITX_ARRAY_SIZE(symbolGroup); i++) { - symbolToGroup_[symbolGroup[i][0]] = groups_.size(); + for (size_t i = 0; i < FCITX_ARRAY_SIZE(symbolGroup); i++) { + symbolToGroup_[symbolGroup[i][0]] = groups_.size(); - std::vector items; - std::vector items2; - for (size_t j = 1; symbolGroup[i][j]; j++) { - items.push_back(symbolGroup[i][j]); - items2.push_back(symbolGroup[i][j]); - symbolToGroup_[symbolGroup[i][j]] = groups_.size(); - if (j == 1) { - items2.push_back(symbolGroup[i][0]); - } - } - symbols_[symbolGroup[i][0]] = std::move(items2); - groups_.push_back(std::move(items)); + std::vector items; + std::vector items2; + for (size_t j = 1; symbolGroup[i][j]; j++) { + items.push_back(symbolGroup[i][j]); + items2.push_back(symbolGroup[i][j]); + symbolToGroup_[symbolGroup[i][j]] = groups_.size(); + if (j == 1) { + items2.push_back(symbolGroup[i][0]); + } } + symbols_[symbolGroup[i][0]] = std::move(items2); + groups_.push_back(std::move(items)); + } } } // namespace fcitx diff --git a/src/zhuyinsymbol.h b/src/zhuyinsymbol.h index 3dcf40c..04dcb37 100644 --- a/src/zhuyinsymbol.h +++ b/src/zhuyinsymbol.h @@ -16,16 +16,16 @@ namespace fcitx { class ZhuyinSymbol { public: - ZhuyinSymbol(); - void load(std::FILE *file); - const std::vector &lookup(const std::string &key) const; - void initBuiltin(); - void clear(); + ZhuyinSymbol(); + void load(std::FILE *file); + const std::vector &lookup(const std::string &key) const; + void initBuiltin(); + void clear(); private: - std::unordered_map> symbols_; - std::unordered_map symbolToGroup_; - std::vector> groups_; + std::unordered_map> symbols_; + std::unordered_map symbolToGroup_; + std::vector> groups_; }; } // namespace fcitx diff --git a/test/testzhuyinbuffer.cpp b/test/testzhuyinbuffer.cpp index d5d169e..0c408b6 100644 --- a/test/testzhuyinbuffer.cpp +++ b/test/testzhuyinbuffer.cpp @@ -13,158 +13,157 @@ using namespace fcitx; class TestZhuyinProvider : public ZhuyinProviderInterface { public: - TestZhuyinProvider() { - context_.reset( - zhuyin_init(TESTING_BINARY_DIR "/data", "/Invalid/Path")); - zhuyin_set_options(context_.get(), USE_TONE | ZHUYIN_CORRECT_ALL | - FORCE_TONE | DYNAMIC_ADJUST); - zhuyin_set_chewing_scheme(context_.get(), ZHUYIN_STANDARD); - } + TestZhuyinProvider() { + context_.reset(zhuyin_init(TESTING_BINARY_DIR "/data", "/Invalid/Path")); + zhuyin_set_options(context_.get(), USE_TONE | ZHUYIN_CORRECT_ALL | + FORCE_TONE | DYNAMIC_ADJUST); + zhuyin_set_chewing_scheme(context_.get(), ZHUYIN_STANDARD); + } - zhuyin_context_t *context() override { return context_.get(); } + zhuyin_context_t *context() override { return context_.get(); } - bool isZhuyin() const override { return true; } - const ZhuyinSymbol &symbol() const override { return symbol_; } + bool isZhuyin() const override { return true; } + const ZhuyinSymbol &symbol() const override { return symbol_; } private: - ZhuyinSymbol symbol_; - UniqueCPtr context_; + ZhuyinSymbol symbol_; + UniqueCPtr context_; }; void test_basic() { - TestZhuyinProvider provider; - ZhuyinBuffer buffer(&provider); - buffer.type('z'); - FCITX_INFO() << buffer.dump(); - buffer.type('p'); - FCITX_INFO() << buffer.dump(); - buffer.type(' '); - FCITX_INFO() << buffer.dump(); + TestZhuyinProvider provider; + ZhuyinBuffer buffer(&provider); + buffer.type('z'); + FCITX_INFO() << buffer.dump(); + buffer.type('p'); + FCITX_INFO() << buffer.dump(); + buffer.type(' '); + FCITX_INFO() << buffer.dump(); - buffer.backspace(); - FCITX_INFO() << buffer.dump(); + buffer.backspace(); + FCITX_INFO() << buffer.dump(); - buffer.reset(); + buffer.reset(); - FCITX_INFO() << buffer.dump(); - buffer.type('z'); - buffer.type('\\'); - buffer.type('p'); - buffer.type('\\'); - buffer.type('p'); - buffer.type('a'); - FCITX_INFO() << buffer.dump(); + FCITX_INFO() << buffer.dump(); + buffer.type('z'); + buffer.type('\\'); + buffer.type('p'); + buffer.type('\\'); + buffer.type('p'); + buffer.type('a'); + FCITX_INFO() << buffer.dump(); - buffer.moveCursorLeft(); - buffer.type('b'); - buffer.type('c'); - FCITX_INFO() << buffer.dump(); - buffer.moveCursorLeft(); - buffer.moveCursorLeft(); - buffer.moveCursorLeft(); - buffer.moveCursorLeft(); - buffer.type('e'); - FCITX_INFO() << buffer.dump(); - buffer.moveCursorRight(); - buffer.type('e'); - FCITX_INFO() << buffer.dump(); - buffer.moveCursorLeft(); - buffer.del(); - FCITX_INFO() << buffer.dump(); - buffer.reset(); - buffer.type('z'); - buffer.type(0x263a); - buffer.type('p'); - FCITX_INFO() << buffer.dump(); - buffer.backspace(); - buffer.backspace(); - buffer.type(' '); - FCITX_INFO() << buffer.dump(); - buffer.reset(); - buffer.type('z'); - buffer.type('p'); - buffer.moveCursorLeft(); - buffer.type(' '); - FCITX_INFO() << buffer.dump(); - buffer.moveCursorLeft(); - buffer.del(); - buffer.moveCursorRight(); - buffer.type(' '); - FCITX_INFO() << buffer.dump(); - buffer.reset(); - buffer.type('z'); - buffer.type('p'); - buffer.type(' '); - FCITX_INFO() << buffer.dump(); - buffer.type('z'); - buffer.type('p'); - buffer.type(' '); - FCITX_INFO() << buffer.dump(); - buffer.moveCursorLeft(); - buffer.type('a'); - buffer.type('p'); - buffer.type(' '); - FCITX_INFO() << buffer.dump(); - buffer.moveCursorRight(); - buffer.type('a'); - buffer.type('p'); - buffer.type(' '); - FCITX_INFO() << buffer.dump(); - buffer.backspace(); - FCITX_INFO() << buffer.dump(); - buffer.backspace(); - FCITX_INFO() << buffer.dump(); - buffer.backspace(); - FCITX_INFO() << buffer.dump(); - buffer.backspace(); - FCITX_INFO() << buffer.dump(); - buffer.type('z'); - buffer.type('p'); - buffer.type(' '); - buffer.type('z'); - buffer.type('p'); - buffer.type(' '); - buffer.moveCursorToBeginning(); - FCITX_INFO() << buffer.dump(); - buffer.type('.'); - buffer.type('p'); - FCITX_INFO() << buffer.dump(); - buffer.backspace(); - FCITX_INFO() << buffer.dump(); - buffer.reset(); - buffer.type('z'); - buffer.type('p'); - buffer.type(' '); - buffer.type('n'); - buffer.type('i'); - buffer.type('f'); - buffer.moveCursorToBeginning(); - buffer.moveCursorRight(); - buffer.del(); - FCITX_INFO() << buffer.dump(); + buffer.moveCursorLeft(); + buffer.type('b'); + buffer.type('c'); + FCITX_INFO() << buffer.dump(); + buffer.moveCursorLeft(); + buffer.moveCursorLeft(); + buffer.moveCursorLeft(); + buffer.moveCursorLeft(); + buffer.type('e'); + FCITX_INFO() << buffer.dump(); + buffer.moveCursorRight(); + buffer.type('e'); + FCITX_INFO() << buffer.dump(); + buffer.moveCursorLeft(); + buffer.del(); + FCITX_INFO() << buffer.dump(); + buffer.reset(); + buffer.type('z'); + buffer.type(0x263a); + buffer.type('p'); + FCITX_INFO() << buffer.dump(); + buffer.backspace(); + buffer.backspace(); + buffer.type(' '); + FCITX_INFO() << buffer.dump(); + buffer.reset(); + buffer.type('z'); + buffer.type('p'); + buffer.moveCursorLeft(); + buffer.type(' '); + FCITX_INFO() << buffer.dump(); + buffer.moveCursorLeft(); + buffer.del(); + buffer.moveCursorRight(); + buffer.type(' '); + FCITX_INFO() << buffer.dump(); + buffer.reset(); + buffer.type('z'); + buffer.type('p'); + buffer.type(' '); + FCITX_INFO() << buffer.dump(); + buffer.type('z'); + buffer.type('p'); + buffer.type(' '); + FCITX_INFO() << buffer.dump(); + buffer.moveCursorLeft(); + buffer.type('a'); + buffer.type('p'); + buffer.type(' '); + FCITX_INFO() << buffer.dump(); + buffer.moveCursorRight(); + buffer.type('a'); + buffer.type('p'); + buffer.type(' '); + FCITX_INFO() << buffer.dump(); + buffer.backspace(); + FCITX_INFO() << buffer.dump(); + buffer.backspace(); + FCITX_INFO() << buffer.dump(); + buffer.backspace(); + FCITX_INFO() << buffer.dump(); + buffer.backspace(); + FCITX_INFO() << buffer.dump(); + buffer.type('z'); + buffer.type('p'); + buffer.type(' '); + buffer.type('z'); + buffer.type('p'); + buffer.type(' '); + buffer.moveCursorToBeginning(); + FCITX_INFO() << buffer.dump(); + buffer.type('.'); + buffer.type('p'); + FCITX_INFO() << buffer.dump(); + buffer.backspace(); + FCITX_INFO() << buffer.dump(); + buffer.reset(); + buffer.type('z'); + buffer.type('p'); + buffer.type(' '); + buffer.type('n'); + buffer.type('i'); + buffer.type('f'); + buffer.moveCursorToBeginning(); + buffer.moveCursorRight(); + buffer.del(); + FCITX_INFO() << buffer.dump(); } void test_candidate() { - TestZhuyinProvider provider; - ZhuyinBuffer buffer(&provider); - auto printCandidate = [](std::unique_ptr candidate) { - FCITX_INFO() << candidate->text().toString(); - }; - buffer.type('z'); - buffer.type('p'); - buffer.type(' '); - buffer.type('a'); - buffer.type('p'); - buffer.type(' '); - buffer.showCandidate(printCandidate); - buffer.moveCursorLeft(); - buffer.showCandidate(printCandidate); - buffer.moveCursorLeft(); - buffer.showCandidate(printCandidate); + TestZhuyinProvider provider; + ZhuyinBuffer buffer(&provider); + auto printCandidate = [](std::unique_ptr candidate) { + FCITX_INFO() << candidate->text().toString(); + }; + buffer.type('z'); + buffer.type('p'); + buffer.type(' '); + buffer.type('a'); + buffer.type('p'); + buffer.type(' '); + buffer.showCandidate(printCandidate); + buffer.moveCursorLeft(); + buffer.showCandidate(printCandidate); + buffer.moveCursorLeft(); + buffer.showCandidate(printCandidate); } int main() { - test_basic(); - test_candidate(); - return 0; + test_basic(); + test_candidate(); + return 0; }