Home | History | Annotate | Download | only in cle
      1 /*
      2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
      3  *
      4  * Copyright (c) 2007 Sun Microsystems, Inc. All Rights Reserved.
      5  *
      6  * The contents of this file are subject to the terms of either the GNU Lesser
      7  * General Public License Version 2.1 only ("LGPL") or the Common Development and
      8  * Distribution License ("CDDL")(collectively, the "License"). You may not use this
      9  * file except in compliance with the License. You can obtain a copy of the CDDL at
     10  * http://www.opensource.org/licenses/cddl1.php and a copy of the LGPLv2.1 at
     11  * http://www.opensource.org/licenses/lgpl-license.php. See the License for the
     12  * specific language governing permissions and limitations under the License. When
     13  * distributing the software, include this License Header Notice in each file and
     14  * include the full text of the License in the License file as well as the
     15  * following notice:
     16  *
     17  * NOTICE PURSUANT TO SECTION 9 OF THE COMMON DEVELOPMENT AND DISTRIBUTION LICENSE
     18  * (CDDL)
     19  * For Covered Software in this distribution, this License shall be governed by the
     20  * laws of the State of California (excluding conflict-of-law provisions).
     21  * Any litigation relating to this License shall be subject to the jurisdiction of
     22  * the Federal Courts of the Northern District of California and the state courts
     23  * of the State of California, with venue lying in Santa Clara County, California.
     24  *
     25  * Contributor(s):
     26  *
     27  * If you wish your version of this file to be governed by only the CDDL or only
     28  * the LGPL Version 2.1, indicate your decision by adding "[Contributor]" elects to
     29  * include this software in this distribution under the [CDDL or LGPL Version 2.1]
     30  * license." If you don't indicate a single choice of license, a recipient has the
     31  * option to distribute your version of this file under either the CDDL or the LGPL
     32  * Version 2.1, or to extend the choice of license to its licensees as provided
     33  * above. However, if you add LGPL Version 2.1 code and therefore, elected the LGPL
     34  * Version 2 license, then the option applies only if the new code is made subject
     35  * to such option by the copyright holder.
     36  */
     37 
     38 #ifdef HAVE_CONFIG_H
     39 #include <config.h>
     40 #endif
     41 
     42 #include <cstdio>
     43 #include <cstdlib>
     44 
     45 #include "ime.h"
     46 
     47 #include "imi_data.h"
     48 #include "imi_view.h"
     49 #include "imi_clewin.h"
     50 #include "imi_options.h"
     51 #include "ic_history.h"
     52 
     53 #ifndef CLE_SUNPINYIN_DATADIR
     54     #define CLE_SUNPINYIN_DATADIR "/usr/lib/iiim/le/cle/input_methods/data"
     55 #endif
     56 
     57 static ImeResult sunpinyin_Initialize(ImeInfo ime_info);
     58 static ImeResult sunpinyin_Destroy(ImeInfo ime_info);
     59 static ImeResult sunpinyin_Process_Key_Event(ImeInputContext ic, ImeKey key_event);
     60 static ImeResult sunpinyin_Process_Aux_Event(ImeInputContext ic, ImeEvent pEvent);
     61 static ImeResult sunpinyin_Create_Session(ImeInputContext ic);
     62 static ImeResult sunpinyin_Destroy_Session(ImeInputContext ic);
     63 static ImeResult sunpinyin_focus_in(ImeInputContext ic);
     64 static ImeResult sunpinyin_Attach_User(ImeInputContext ic);
     65 static ImeResult sunpinyin_Dettach_User(ImeInputContext ic);
     66 static ImeResult sunpinyin_Attach_Desktop(ImeInputContext ic);
     67 static ImeResult sunpinyin_Dettach_Desktop(ImeInputContext ic);
     68 
     69 ImeMethodsRec sunpinyin_methods = {
     70     100,                              /* version */
     71     sunpinyin_Initialize,             /* ImeInitialize */
     72     sunpinyin_Destroy,                /* ImeDestroy  */
     73     sunpinyin_Process_Key_Event,      /* ImeProcessKeyEvent */
     74     sunpinyin_Process_Aux_Event,      /* ImeProcessAuxEvent  */
     75     sunpinyin_Create_Session,         /* ImeAttachSession */
     76     sunpinyin_Destroy_Session,        /* ImeDetachSession */
     77     sunpinyin_focus_in,               /* ImeFocusIn  */
     78     NULL,                             /* ImeFocusOut */
     79     sunpinyin_Attach_User,            /* ImeAttachUser */
     80     sunpinyin_Dettach_User,           /* ImeDetachUser */
     81     sunpinyin_Attach_Desktop,         /* ImeAttachDesktop */
     82     sunpinyin_Dettach_Desktop,        /* ImeDetachDesktop */
     83     NULL,                             /* ImeGetErrorMessage */
     84 };
     85 
     86 const char* InputStyleOptions[] = {
     87     "",
     88     "",
     89     NULL
     90 };
     91 
     92 const char* CharSetOptions[] = {
     93     "GB2312",
     94     "GBK",
     95     NULL
     96 };
     97 
     98 const char* LayoutOptions[] = {
     99     "",
    100     "",
    101     NULL
    102 };
    103 
    104 
    105 ImePropertyRec sunpinyin_options[] = {
    106     { 1, ENCODE_UTF8, "/input_style",    "", NULL, ImeProperty_Selection, {0, 0}, 0},
    107     { 2, ENCODE_UTF8, "/charset",        "",   NULL, ImeProperty_Selection, {0, 0}, 1},
    108 
    109     {30, ENCODE_UTF8, "/PageKey/Minus",   "-/=", NULL, ImeProperty_Toggle, {0, 0}, 1},
    110     {31, ENCODE_UTF8, "/PageKey/Braket",  "[/]", NULL, ImeProperty_Toggle, {0, 0}, 1},
    111     {32, ENCODE_UTF8, "/PageKey/Comma",   ",/.", NULL, ImeProperty_Toggle, {0, 0}, 0}
    112 
    113 #if 0
    114     ,
    115     { 3, ENCODE_UTF8, "/history_memory", "(0,10)", NULL, ImeProperty_Int, {0, 10}, 5},
    116     { 4, ENCODE_UTF8, "/ranking_method", "", NULL, ImeProperty_Toggle, {0, 0}, 1},
    117     { 5, ENCODE_UTF8, "/layout",         "", NULL, ImeProperty_Selection, {0, 0}, 0},
    118 
    119     { 7, ENCODE_UTF8, "/Fuzzy",          "", NULL, ImeProperty_Toggle, {0, 0}, 0},
    120     { 8, ENCODE_UTF8, "/Fuzzy/zh",       "zh = z", NULL, ImeProperty_Toggle, {0, 0}, 0},
    121     { 9, ENCODE_UTF8, "/Fuzzy/ch",       "ch = c", NULL, ImeProperty_Toggle, {0, 0}, 0},
    122     { 10,ENCODE_UTF8, "/Fuzzy/sh",       "sh = s", NULL, ImeProperty_Toggle, {0, 0}, 0},
    123     { 11,ENCODE_UTF8, "/Fuzzy/ln",       "l  = n", NULL, ImeProperty_Toggle, {0, 0}, 0},
    124     { 12,ENCODE_UTF8, "/Fuzzy/fh",       "f  = h", NULL, ImeProperty_Toggle, {0, 0}, 0},
    125     { 13,ENCODE_UTF8, "/Fuzzy/ang",      "an = ang",  NULL, ImeProperty_Toggle, {0, 0}, 0},
    126     { 14,ENCODE_UTF8, "/Fuzzy/eng",      "en = eng",  NULL, ImeProperty_Toggle, {0, 0}, 0},
    127     { 15,ENCODE_UTF8, "/Fuzzy/ing",      "in = ing", NULL, ImeProperty_Toggle, {0, 0}, 0},
    128     { 50,ENCODE_UTF8, "/owner_aux",      "", NULL, ImeProperty_Toggle, {0, 0}, 0},
    129 #endif
    130 };
    131 
    132 ImePropertyListRec sunpinyin_optionlist = {
    133     sizeof(sunpinyin_options)/sizeof(ImePropertyRec),
    134     sunpinyin_options
    135 };
    136 
    137 static void setOptionsFromPL(int count, ImePropertyRec* pl, CSunpinyinOptions* dst)
    138 {
    139     for (int i=0; i < count; ++i) {
    140         switch (pl[i].id) {
    141         case 1:
    142             dst->m_ViewType = pl[i].value.int_value; break;
    143         case 2:
    144             dst->m_GBK = pl[i].value.int_value; break;
    145 
    146         case 30:
    147             dst->m_MinusAsPageUp = pl[i].value.int_value; break;
    148         case 31:
    149             dst->m_BracketAsPageUp = pl[i].value.int_value; break;
    150         case 32:
    151             dst->m_CommaAsPageUp = pl[i].value.int_value; break;
    152 
    153 #if 0
    154         case 3:
    155             dst->m_MemoryPower = pl[i].value.int_value; break;
    156         case 4:
    157             dst->m_ContextRanking = pl[i].value.int_value; break;
    158         case 5:
    159             dst->m_LayoutVeritcal = pl[i].value.int_value; break;
    160         case 7:
    161             dst->m_Fuzzy = pl[i].value.int_value; break;
    162         case 8:
    163             dst->m_Fuzzy_zh = pl[i].value.int_value; break;
    164         case 9:
    165             dst->m_Fuzzy_ch = pl[i].value.int_value; break;
    166         case 10:
    167             dst->m_Fuzzy_sh = pl[i].value.int_value; break;
    168         case 11:
    169             dst->m_Fuzzy_ln = pl[i].value.int_value; break;
    170         case 12:
    171             dst->m_Fuzzy_fh = pl[i].value.int_value; break;
    172         case 13:
    173             dst->m_Fuzzy_ang = pl[i].value.int_value; break;
    174         case 14:
    175             dst->m_Fuzzy_eng = pl[i].value.int_value; break;
    176         case 15:
    177             dst->m_Fuzzy_ing = pl[i].value.int_value; break;
    178 
    179         case 50:
    180 #endif
    181 
    182         default:
    183             break;
    184         }
    185     }
    186 }
    187 
    188 static ImeInfoRec sunpinyin_inforec = {
    189     100,                                                   //version
    190     0,
    191     ENCODE_UTF8,
    192     "SunPinyin-ef1a0a92-9f0e-410b-b8a8-e6f296c1801c",      //uuid
    193     "Sun",                                             //name
    194     " <Phill.Zhang (at) sun.com>",
    195     "Sun's intelligent Pinyin IM",
    196     "Copyright (c) 2005 Sun Microsystems",
    197     "sunpinyin_logo.xpm",
    198     "zh_CN.GB18030,zh_CN.UTF-8,zh_CN.GBK,zh_CN.GB2312,zh",
    199     &sunpinyin_optionlist,
    200     NULL
    201 };
    202 
    203 ImmServices imm_services;
    204 
    205 class CSunpinyinUserData {
    206 public:
    207     CSunpinyinUserData() : m_pPref(NULL), m_pHistory(NULL) { }
    208 
    209     CSunpinyinOptions*      m_pPref;
    210     CBigramHistory*         m_pHistory;
    211 };
    212 
    213 extern "C" {
    214 
    215 ImeResult RegisterIME(ImmServices srvs, ImeInfo* ppinfo, ImeMethods* pmthds, int argc, char **argv)
    216 {
    217     #ifdef DEBUG
    218         printf("Register Sun Pinyin IM...\n");
    219         fflush(stdout);
    220     #endif
    221     sunpinyin_options[0].range.multiString_range = InputStyleOptions;
    222     sunpinyin_options[1].range.multiString_range = CharSetOptions;
    223     sunpinyin_options[4].range.multiString_range = LayoutOptions;
    224 
    225     CCLEWinHandler::sm_imm_srvs = imm_services = srvs;
    226 
    227     *ppinfo = &sunpinyin_inforec;
    228     *pmthds = &sunpinyin_methods;
    229 
    230     return (IME_OK);
    231 }
    232 
    233 }
    234 
    235 static const char* getLMPath(void)
    236 {
    237     return CLE_SUNPINYIN_DATADIR"/lm_sc.t3g";
    238 }
    239 
    240 static const char* getPYTriePath(void)
    241 {
    242     return CLE_SUNPINYIN_DATADIR"/pydict_sc.bin";
    243 }
    244 
    245 static CIMIData* s_pSunPinyinData = NULL;
    246 
    247 static ImeResult sunpinyin_Initialize(ImeInfo sunpinyin_info)
    248 {
    249     bool suc=false;
    250 
    251     #ifdef DEBUG
    252         printf("sunpinyin_Initialize...\n");
    253         fflush(stdout);
    254     #endif
    255 
    256     s_pSunPinyinData = new CIMIData();
    257     if (s_pSunPinyinData && s_pSunPinyinData->loadResource(getLMPath(), getPYTriePath())) {
    258         suc = true;
    259     }
    260 
    261     if (!suc) {
    262         delete s_pSunPinyinData;
    263         s_pSunPinyinData = NULL;
    264         return IME_FAIL;
    265     }
    266 
    267     return IME_OK;
    268 }
    269 
    270 static ImeResult sunpinyin_Attach_User(ImeInputContext ic)
    271 {
    272     CSunpinyinUserData* pud = NULL;
    273     if ((pud = (CSunpinyinUserData*)imm_services->ImmGetData(ic, IME_SCOPE_USER)) == NULL) {
    274         pud = new CSunpinyinUserData();
    275         pud->m_pPref = new CSunpinyinOptions();
    276         ImePropertyListRec* pl = imm_services->ImmGetPropertyList(ic);
    277         if (pl != NULL) { // It must be non-zero
    278             setOptionsFromPL(pl->count, pl->properties, pud->m_pPref);
    279         }
    280         pud->m_pHistory = new CBigramHistory();
    281         int sz = 0;
    282         unsigned *psaved = (unsigned*)imm_services->ImmLoadUserProfile(ic, "history", &sz);
    283         if (psaved != NULL) {
    284             pud->m_pHistory->loadFromBuffer(psaved, sz);
    285             imm_services->ImmFreeUserProfile(psaved);
    286         }
    287         imm_services->ImmSetData(ic, IME_SCOPE_USER, pud);
    288     }
    289     return IME_OK;
    290 }
    291 
    292 static ImeResult sunpinyin_Dettach_User(ImeInputContext ic)
    293 {
    294     CSunpinyinUserData* pud = NULL;
    295     if ((pud = (CSunpinyinUserData*)imm_services->ImmGetData(ic, IME_SCOPE_USER)) != NULL) {
    296         size_t sz = 0;
    297         void* pbuf = NULL;
    298         if (pud->m_pHistory) {
    299             pud->m_pHistory->bufferize(&pbuf, &sz);
    300             if (pbuf) {
    301                 imm_services->ImmSaveUserProfile(ic, "history", pbuf, int(sz));
    302                 free(pbuf);
    303             }
    304         }
    305         delete pud;
    306     }
    307     imm_services->ImmSetData(ic, IME_SCOPE_USER, NULL);
    308     return IME_OK;
    309 }
    310 
    311 static ImeResult sunpinyin_Attach_Desktop(ImeInputContext ic)
    312 {
    313     return IME_OK;
    314 }
    315 
    316 static ImeResult sunpinyin_Dettach_Desktop(ImeInputContext ic)
    317 {
    318     return IME_OK;
    319 }
    320 
    321 static ImeResult sunpinyin_Destroy(ImeInfo sunpinyin_info)
    322 {
    323     delete s_pSunPinyinData;
    324     s_pSunPinyinData = NULL;
    325     CCLEWinHandler::sm_imm_srvs = NULL;
    326 
    327     return (IME_OK);
    328 }
    329 
    330 static ImeResult
    331 _sunpinyin_Create_Session(ImeInputContext ic, int viewType)
    332 {
    333     #ifdef DEBUG
    334         printf(">>>>>>>> SunPinyin alloc private session data...\n");
    335         fflush(stdout);
    336     #endif
    337 
    338     CSunpinyinUserData* pud = (CSunpinyinUserData*)imm_services->ImmGetData(ic, IME_SCOPE_USER);
    339     if (pud == NULL) { //should not happen, but now, CLE make it happen
    340         sunpinyin_Attach_User(ic);
    341         pud = (CSunpinyinUserData*)imm_services->ImmGetData(ic, IME_SCOPE_USER);
    342     }
    343 
    344     CIMIData* pdata = s_pSunPinyinData;
    345 
    346     CIMIContext *pic = NULL;
    347     CIMIView *pv = NULL;
    348     CCLEWinHandler *pwh = NULL;
    349 
    350     #ifdef DEBUG
    351         printf("    -------->>>>Creating searching related core structure...\n");
    352         fflush(stdout);
    353     #endif
    354     pic = new CIMIContext();
    355     pic->setCoreData(pdata);
    356     pic->setHistoryMemory(pud->m_pHistory);
    357     pic->setNonCompleteSyllable(true);
    358     pic->clear();
    359 
    360     #ifdef DEBUG
    361         printf("    -------->>>>Creating view...\n");
    362         fflush(stdout);
    363     #endif
    364     pv = CIMIViewFactory::createView(viewType);
    365     #ifdef DEBUG
    366         printf("    -------->>>>Setting view options...\n");
    367         fflush(stdout);
    368     #endif
    369 
    370     bool enable_gbk = pud->m_pPref->m_GBK;
    371     if (imm_services->ImmGetSessionEncoding(ic) == ENCODE_GB2312)
    372         pud->m_pPref->m_GBK = false;
    373     pv->setPreference(pud->m_pPref);
    374     pud->m_pPref->m_GBK = enable_gbk;
    375 
    376     /* FIXME: we should add the candidate window size to preferences */
    377     pv->s_CandiWindowSize = 10;
    378 
    379     #ifdef DEBUG
    380         printf("    -------->>>>Bundle searching structure with view...\n");
    381         fflush(stdout);
    382     #endif
    383     pv->attachIC(pic);
    384 
    385     #ifdef DEBUG
    386         printf("    -------->>>>Creating GUI_Handler...\n");
    387         fflush(stdout);
    388     #endif
    389     pwh = new CCLEWinHandler();
    390     pwh->setOptions(pv->getPreference());
    391     pv->attachWinHandler(pwh);
    392     pwh->setMainWindow(ic);
    393 
    394     imm_services->ImmSetData(ic, IME_SCOPE_SESSION, pv);
    395     #ifdef DEBUG
    396         printf("    -------->>>>Done\n");
    397         fflush(stdout);
    398     #endif
    399     return (IME_OK);
    400 }
    401 
    402 static ImeResult
    403 sunpinyin_Create_Session(ImeInputContext ic)
    404 {
    405     CSunpinyinUserData* pud = (CSunpinyinUserData*)imm_services->ImmGetData(ic, IME_SCOPE_USER);
    406     if (pud == NULL) { //should not happen, but now, CLE make it happen
    407         sunpinyin_Attach_User(ic);
    408         pud = (CSunpinyinUserData*)imm_services->ImmGetData(ic, IME_SCOPE_USER);
    409     }
    410 
    411     int viewType = (pud->m_pPref->m_ViewType==0)?(CIMIViewFactory::SVT_CLASSIC):(CIMIViewFactory::SVT_MODERN);
    412     return _sunpinyin_Create_Session(ic, viewType);
    413 }
    414 
    415 static ImeResult sunpinyin_Destroy_Session(ImeInputContext ic)
    416 {
    417     CIMIView *pv = (CIMIView*)imm_services->ImmGetData(ic, IME_SCOPE_SESSION);
    418     imm_services->ImmSetData(ic, IME_SCOPE_SESSION, NULL);
    419 
    420     if (pv) {
    421         CIMIContext *pic = pv->getIC();
    422         CIMIWinHandler *pwh = pv->getWinHandler();
    423 
    424         delete pic;
    425         delete pwh;
    426         delete pv;
    427     }
    428 
    429     return (IME_OK);
    430 }
    431 
    432 static ImeResult sunpinyin_Process_Aux_Event(ImeInputContext ic, ImeEvent pEvent)
    433 {
    434     CIMIView *pv = (CIMIView*)imm_services->ImmGetData(ic, IME_SCOPE_SESSION);
    435 
    436     int pgno;
    437     bool relative;
    438 
    439     if (pv && pEvent) {
    440         switch (pEvent->type) {
    441         case IME_EVENT_IMM_NOTIFY:
    442             switch (pEvent->notify_event.trigger) {
    443             case IMM_TRIGGER_FULL_HALF_PUNC:
    444                 pv->setStatusAttrValue(CIMIWinHandler::STATUS_ID_FULLPUNC, pEvent->notify_event.value);
    445                 break;
    446             case IMM_TRIGGER_FULL_HALF_SIMBOL:
    447                 pv->setStatusAttrValue(CIMIWinHandler::STATUS_ID_FULLSIMBOL, pEvent->notify_event.value);
    448                 break;
    449             }
    450             return IME_OK;
    451 
    452         case IME_EVENT_PROPERTY:
    453             return sunpinyin_focus_in(ic);
    454 
    455         case IME_EVENT_CANDI_SELECT:
    456             pv->onCandidateSelectRequest(pEvent->candidate_select_event.param);
    457             return IME_OK;
    458 
    459         case IME_EVENT_CANDI_PAGE:
    460             switch (pEvent->candidate_page_event.param) {
    461             case ImeCandidatesPageFirst:
    462                 pgno = 0; relative = false; break;
    463             case ImeCandidatesPagePrevious:
    464                 pgno = -1; relative = true; break;
    465             case ImeCandidatesPageNext:
    466                 pgno = 1; relative = true; break;
    467             case ImeCandidatesPageLast:
    468                 pgno = -1; relative = false; break;
    469             default:
    470                 return IME_UNPROCESSED_EVENT;
    471             }
    472             pv->onCandidatePageRequest(pgno, relative);
    473             return IME_OK;
    474         }
    475     }
    476 
    477     return IME_UNPROCESSED_EVENT;
    478 }
    479 
    480 ImeResult  sunpinyin_focus_in(ImeInputContext ic)
    481 {
    482     CIMIView *pv = (CIMIView*)imm_services->ImmGetData(ic, IME_SCOPE_SESSION);
    483     if (pv) {
    484         CSunpinyinOptions* pup = ((CSunpinyinUserData*)imm_services->ImmGetData(ic, IME_SCOPE_USER))->m_pPref;
    485         ImePropertyListRec* pl = imm_services->ImmGetPropertyList(ic);
    486         setOptionsFromPL(pl->count, pl->properties, pup);
    487 
    488         CSunpinyinOptions* pvp = (CSunpinyinOptions*)pv->getPreference();
    489 
    490         if ((pup->m_GBK != pvp->m_GBK &&  imm_services->ImmGetSessionEncoding(ic) != ENCODE_GB2312) ||
    491                                                 (pup->m_ViewType != pvp->m_ViewType)) {
    492             sunpinyin_Destroy_Session(ic);
    493             imm_services->ImmHidePreedit(ic);
    494             imm_services->ImmHideCandidates(ic);
    495             sunpinyin_Create_Session(ic);
    496         } else {
    497             pvp->m_MinusAsPageUp   = pup->m_MinusAsPageUp;
    498             pvp->m_CommaAsPageUp   = pup->m_CommaAsPageUp;
    499             pvp->m_BracketAsPageUp = pup->m_BracketAsPageUp;
    500         }
    501     }
    502     return IME_OK;
    503 }
    504 
    505 static ImeResult sunpinyin_Process_Key_Event(ImeInputContext ic, ImeKey key_event)
    506 {
    507     int ret = IME_UNUSED_KEY;
    508 
    509     /* sunpinyin_focus_in(ic); */
    510 
    511     CIMIView *pv = (CIMIView*)imm_services->ImmGetData(ic, IME_SCOPE_SESSION);
    512 
    513     #ifdef DEBUG
    514         printf(">>>>>>>>SunPinyin Process a key [0x%X, 0x%X, 0x%X] on view @%X",
    515                     key_event->keycode, key_event->keychar, key_event->modifier,pv);
    516         fflush(stdout);
    517     #endif
    518 
    519     //switch input GUI style between classic/modern style
    520     if ((key_event->modifier & (IME_CTRL_MASK|IME_SHIFT_MASK|IME_ALT_MASK)) == IME_CTRL_MASK && key_event->keycode == IME_VK_BACK_QUOTE) {
    521 
    522         if (pv) {
    523             CSunpinyinOptions* pup = ((CSunpinyinUserData*)imm_services->ImmGetData(ic, IME_SCOPE_USER))->m_pPref;
    524             pup->m_ViewType = (pup->m_ViewType)?0:1;
    525             sunpinyin_focus_in(ic);
    526         }
    527         ret = IME_OK;
    528 
    529     } else if ((key_event->modifier & (IME_CTRL_MASK|IME_SHIFT_MASK|IME_ALT_MASK)) == IME_CTRL_MASK && key_event->keycode == IME_VK_K) {
    530         if (pv) {
    531             if (imm_services->ImmGetSessionEncoding(ic) != ENCODE_GB2312) {
    532                 CSunpinyinOptions* pup = ((CSunpinyinUserData*)imm_services->ImmGetData(ic, IME_SCOPE_USER))->m_pPref;
    533                 pup->m_GBK = (pup->m_GBK)?0:1;
    534                 sunpinyin_focus_in(ic);
    535             }
    536             ret = IME_OK;
    537         }
    538     } else if (pv) {
    539         ((CCLEWinHandler*)pv->getWinHandler())->setMainWindow(ic);
    540         if (pv->onKeyEvent(key_event->keycode, key_event->keychar, key_event->modifier))
    541             ret = IME_OK;
    542     }
    543 
    544     #ifdef DEBUG
    545         printf((ret == IME_OK)?"  ==>used!":"==>not used!");
    546         fflush(stdout);
    547     #endif
    548 
    549     return ImeResult(ret);
    550 }
    551