// OVIMSpaceChewing: Chewing Module for OpenVanilla // Originally written by Kang-min Liu, 2004-2005 // Maintained by zonble, 2005-2006 // Refactored by lukhnos, 2007 // This package is released under the Artistic License, // please refer to LICENSE.txt for the terms of use and distribution #define OV_DEBUG #include #include #include #include #include #include "chewing.h" #include "chewingio.h" #ifdef LIBCHEWING_VERSION_OSX_INCLUDE #include "libchewing_version.h" #include #endif #ifndef LIBCHEWING_VERSION #define LIBCHEWING_VERSION "(trunk)" #endif using namespace std; bool ChewingFileExist(const char *path, const char *file, const char *sep="/") { string fn; fn = path; fn += sep; fn += file; struct stat st; if (stat(fn.c_str(), &st)) return false; return true; } bool ChewingCheckData(const char *path) { char *files[8]={ "ch_index.dat", "dict.dat", "fonetree.dat", "ph_index.dat", "pinyin.tab", "swkb.dat", "symbols.dat", "us_freq.dat" }; for (int i=0; i<8; i++) if (!ChewingFileExist(path, files[i])) return false; return true; } CHEWING_API char *chewing_buffer_String_old( ChewingContext *chewingContext, int from, int to ) { int i; char *s = (char *) calloc( 1 + chewingContext->output->chiSymbolBufLen, sizeof(char) * MAX_UTF8_SIZE ); if(from >= 0 && to < chewingContext->output->chiSymbolBufLen ) { for ( i = from; i <= to; i++ ) { strcat( s, (char *) (chewingContext->output->chiSymbolBuf[ i ].s) ); } } return s; } CHEWING_API char *chewing_buffer_String_End_old( ChewingContext *chewingContext, int from) { return chewing_buffer_String_old(chewingContext, from, chewingContext->output->chiSymbolBufLen -1 ); } class OVIMSpaceChewing; class OVIMSpaceChewingContext : public OVInputMethodContext { public: OVIMSpaceChewingContext(ChewingContext *chewingContext) : im(chewingContext) {} virtual void start(OVBuffer *key, OVCandidate *textbar, OVService *srv) { } virtual void clear() { chewing_handle_Enter(im); } virtual void end() { chewing_handle_Enter(im); } virtual int keyEvent(OVKeyCode *key, OVBuffer *buf, OVCandidate *textbar, OVService *srv) { if(key->isCommand()) return 0; KeyPress(key,buf,textbar,srv); if(chewing_keystroke_CheckIgnore(im)) return 0; CandidateWindow(textbar, srv); Redraw(buf, srv); Notify(srv); return 1; } protected: void KeyPress(OVKeyCode *key, OVBuffer *buf, OVCandidate *textbar, OVService *srv) { int k = key->code(); Capslock(key,buf,textbar,srv); if(k == ovkSpace) { key->isShift() ? chewing_handle_ShiftSpace(im):chewing_handle_Space(im); } else if (k == ovkLeft) { key->isShift() ? chewing_handle_ShiftLeft(im):chewing_handle_Left(im); } else if (k == ovkRight) { key->isShift() ?chewing_handle_ShiftRight(im):chewing_handle_Right(im); } else if (k == ovkDown) { chewing_handle_Down(im); } else if (k == ovkUp) { chewing_handle_Up(im); } else if (k == ovkEsc) { chewing_handle_Esc(im); } else if (k == ovkTab) { chewing_handle_Tab(im); } else if (k == ovkHome) { chewing_handle_Home(im); } else if (k == ovkEnd) { chewing_handle_End(im); } else if (k == ovkDelete) { chewing_handle_Del(im); } else if (k == ovkBackspace) { chewing_handle_Backspace(im) ; } else if (k == ovkReturn) { chewing_handle_Enter(im); } else { DefaultKey(key,buf,textbar,srv); } } void DefaultKey(OVKeyCode *key, OVBuffer *buf, OVCandidate *textbar, OVService *srv) { if(key->isCtrl()) { if((key->code() >= '0') && (key->code() <= '9')) { chewing_handle_CtrlNum( im, (key->code())); } else if(key->isAlt()) { #warning chewing_handle_CtrlOption not found in libchewing trunk // chewing_handle_CtrlOption(im, (key->code())); } return; } chewing_handle_Default(im ,(key->isShift())?toupper(key->code()):tolower(key->code())); } void Capslock(OVKeyCode *key, OVBuffer *buf, OVCandidate *textbar, OVService *srv) { if(key->isCapslock()) { if(chewing_get_ChiEngMode(im) == CHINESE_MODE) { chewing_handle_Capslock(im); } } else if (chewing_get_ChiEngMode(im) != CHINESE_MODE) { chewing_handle_Capslock(im); } } void Redraw(OVBuffer *buf, OVService *srv) { if ( chewing_commit_Check( im ) ) { const char *s = chewing_commit_String( im ); buf->clear()->append(s)->send(); } int ps=-1, pe=-1; // int ips= chewing_point_Start(im), ipe= chewing_point_End(im); int ips = im->output->PointStart; int ipe = im->output->PointEnd; if (ips > -1 && ipe !=0) { if (ipe > 0) { ps=ips; pe=ps+ipe; } else { ps=ips+ipe; pe=ips; } } // murmur("ips=%d, ipe=%d, ps=%d, pe=%d\n", ips, ipe, ps, pe); const char *s1,*s2,*s3; int zuin_count; #warning libchewing inconsistency in mod_aux.h and mod_aux.c, bug report needed int pos = (int)chewing_cursor_Current(im); // murmur("==> %d\n", pos); s1 = chewing_buffer_String_old( im, 0 , pos-1); buf->clear()->append(s1); s2= chewing_zuin_String( im, &zuin_count); buf->append(s2); s3= chewing_buffer_String_End_old( im, pos); buf->append(s3)->update(pos, ps, pe); //murmur("==> %s%s%s",s1,s2,s3); } void Notify(OVService *srv) { if(chewing_aux_Length(im) != 0) srv->notify(chewing_aux_String(im)); } void CandidateWindow(OVCandidate *textbar, OVService *srv) { if(chewing_cand_TotalPage(im) > 0) { char s[64]; int i=1; char str[ 20 ]; char *cand_string; textbar->clear(); chewing_cand_Enumerate( im ); while ( chewing_cand_hasNext( im ) ) { if ( i > chewing_cand_ChoicePerPage( im ) ) break; sprintf( str, "%c.", im->data->config.selKey[i - 1]); textbar->append( str ); cand_string = chewing_cand_String( im ); sprintf( str, " %s ", cand_string ); textbar->append( str ); free( cand_string ); i++; if( i == 5) textbar->append("\n"); } sprintf(s," %d/%d", chewing_cand_CurrentPage(im) + 1, chewing_cand_TotalPage(im)); textbar->append((char*)s)->update()->show(); } else { textbar->hide(); } } protected: OVIMSpaceChewing *parent; ChewingContext *im; }; class OVIMSpaceChewing : public OVInputMethod { public: OVIMSpaceChewing() : chewingContext(NULL) { } virtual ~OVIMSpaceChewing() { delete chewingContext; } virtual int initialize(OVDictionary* l, OVService* s, const char* modulePath) { ChewingConfigData config; string hashdir; hashdir = s->userSpacePath(identifier()); // hashdir += s->pathSeparator(); string chewingpath; #ifdef LIBCHEWING_VERSION_OSX_INCLUDE CFBundleRef bundle = CFBundleGetBundleWithIdentifier(CFSTR("org.openvanilla.module.ovimspacechewing")); if (!bundle) return 0; CFURLRef url = CFBundleCopyResourcesDirectoryURL(bundle); if (!url) return 0; char buf[1024]; CFURLGetFileSystemRepresentation(url, TRUE, (UInt8*)buf, sizeof(buf)-1); chewingpath = buf; #else chewingpath = modulePath; chewingpath += identifier(); #endif if (!ChewingCheckData(chewingpath.c_str())) { murmur("OVIMSpaceChewing: chewing data missing at %s", chewingpath.c_str()); return 0; } murmur ("OVIMSpaceChewing: Chewing data=%s, userhash=%s", chewingpath.c_str(), hashdir.c_str()); chewing_Init(chewingpath.c_str(), hashdir.c_str()); chewingContext = chewing_new(); // set default layout to Standard int kb = l->getIntegerWithDefault("keyboardLayout", 0); chewing_set_KBType(chewingContext, kb); const char *selKey_define = "1234567890"; if (kb==KB_HSU) selKey_define = "asdfjkl789"; if (kb==KB_DVORAK_HSU) selKey_define = "aoeuhtn789"; for (int i=0; igetInteger("keyboardLayout")); } virtual const char *identifier() { return "OVIMSpaceChewing"; } virtual const char *localizedName(const char *locale) { if (!strcasecmp(locale, "zh_TW")) return "酷音 "LIBCHEWING_VERSION; if (!strcasecmp(locale, "zh_CN")) return "繁体酷音 "LIBCHEWING_VERSION; return "Chewing (Smart Phonetics) "LIBCHEWING_VERSION; } virtual OVInputMethodContext* newContext() { return new OVIMSpaceChewingContext(chewingContext); } protected: ChewingContext *chewingContext; }; // the module wrapper OV_SINGLE_MODULE_WRAPPER(OVIMSpaceChewing);