// OVIMPOJHolo.cpp: prototype for POJ IM // Copyright (c) 2004 by Lukhnos D. Liu, Kang-ming Liu, and Pek-tiong Tan #define OV_DEBUG #include "OVIMPOJ-Holo.h" #include OV_SINGLE_MODULE_WRAPPER(OVIMPOJHolo); OVIMPOJHolo::OVIMPOJHolo() { fullPOJOutput=asciioutput=keylayout=0; cintab=NULL; } const char* OVIMPOJHolo::identifier() { return "OVIMPOJ-Holo"; } const char* OVIMPOJHolo::localizedName(const char *cfge) { if (!strcmp(cfge, "zh_TW")) return "河洛白話字漢羅 (POJ)"; if (!strcmp(cfge, "zh_CN")) return "河洛白話字汉罗 (POJ)"; return "OV Holo Pe̍h-ōe-jī (POJ)"; } int OVIMPOJHolo::initialize(OVDictionary* cfg, OVService* s, const char* lp) { // update configuration update(cfg, s); char cinpath[1024]; sprintf(cinpath, "%sOVIMPOJ-Holo\\poj-holo.cin", lp); murmur ("OVIMPOJHolo: loading poj-holo.cin at %s", cinpath); cintab=new OVCIN(cinpath); return 1; } void OVIMPOJHolo::update(OVDictionary* cfg, OVService*) { asciioutput=cfg->getIntegerWithDefault("ASCIIOutput", 0); keylayout=cfg->getIntegerWithDefault("keyboardLayout", 0); fullPOJOutput=cfg->getIntegerWithDefault("fullPOJOutput", 0); } OVInputMethodContext *OVIMPOJHolo::newContext() { return new OVIMPOJHoloContext(this, cintab); } OVIMPOJHoloContext::OVIMPOJHoloContext(OVIMPOJHolo *p, OVCIN *ct) { parent=p; cintab=ct; } OVIMPOJHoloContext::~OVIMPOJHoloContext() { } void OVIMPOJHoloContext::clear() { candi.cancel(); seq.clear(); } int OVIMPOJHoloContext::keyEvent(OVKeyCode *key, OVBuffer *buf, OVCandidate *textbar, OVService *srv) { if (candi.onDuty()) return candidateEvent(key, buf, textbar, srv); int ascii=parent->isAsciiOutput(); int c=key->code(); //Ignore arrow keys. if (c==ovkDown || c==ovkUp || c==ovkLeft || c==ovkRight) { if(!seq.isEmpty()) return 1; else return 0; } // if backspace of delete key is pressed if ((c==ovkBackspace || c==ovkDelete) && !buf->isEmpty()) { seq.remove(); buf->clear()->append(seq.compose(false))->update(); return 1; } // if enter or compose key is hit if ((c==ovkReturn || seq.isComposeKey(c)) && !buf->isEmpty()) { if (key->code()!=ovkReturn) seq.add(c); seq.finalize(); // normalize & finalize the key buf->clear()->append(seq.compose(ascii))->update(); queryAndCompose(seq.sequence(), seq.compose(ascii), buf, textbar, srv); seq.clear(); return 1; } // key=[a-z][A-Z], so add to our key sequence if (isalpha(c) || (parent->getKeyLayout() && seq.toneMark(c))) { seq.add(c, parent->getKeyLayout()); buf->clear()->append(seq.compose())->update(); return 1; } // we find it's not a "valid" character, so we send up the buffer, // then tell the app the process the character itself if (!buf->isEmpty()) { seq.normalize(); buf->clear()->append(seq.compose(ascii))->send(); } seq.clear(); return 0; } void OVIMPOJHoloContext::queryAndCompose(const char *qstr, const char *disp, OVBuffer *buf, OVCandidate *textbar, OVService *srv) { if (parent->isFullPOJ()) { buf->send(); return; } // we have to "lowercase" every character in the query string char p[256], *q=p; strcpy (p, qstr); while (*q) { *q=tolower(*q); q++; } vector l; int result=cintab->getWordVectorByChar(p, l); if (!result) { buf->send(); } else { list.clear(); list.push_back(disp); for (size_t i=0; igetSelKey()).c_str(), textbar); } } int OVIMPOJHoloContext::candidateEvent(OVKeyCode *key, OVBuffer *buf, OVCandidate *textbar, OVService *srv) { int c=key->code(); if (c==ovkEsc ||c==ovkBackspace) { textbar->hide()->clear(); candi.cancel(); buf->clear()->update(); return 1; } if ((c==ovkDown || c==ovkLeft || c=='>') || (!candi.onePage() && c==ovkSpace)) { candi.pageDown()->update(textbar); return 1; } if (c==ovkUp || c==ovkRight || c=='<') { candi.pageUp()->update(textbar); return 1; } // enter == first candidate // space (when candidate list has only one page) == first candidate if (c==ovkReturn || (candi.onePage() && key->code()==ovkSpace) || key->code()=='-') c=cintab->getSelKey()[0]; string output; if (candi.select((char)c, output)) { buf->clear()->append(output.c_str()); if (candi.onePage() && key->code()==ovkSpace) buf->append(" "); else if (key->code()=='-') buf->append("-"); buf->send(); candi.cancel(); textbar->hide()->clear(); return 1; } srv->beep(); return 1; }