requires 2.0.0 %alltop{ /* * Copyright © 2009 Red Hat, Inc. All rights reserved. * Copyright © 2009 Ding-Yi Chen * * This file is part of the ibus-chewing Project. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include #include #include #include #include #define GETTEXT_PACKAGE "gtk20" #include #include #include #include #include %} enum CHEWING_KBTYPE{ INVALID=-1, DEFAULT, HSU, IBM, GIN_YIEH, ETEN, ETEN26, DVORAK, DVORAK_HSU, DACHEN_CP26, HAN_YU } Chewing:KbType; enum CHEWING_MODIFIER_SYNC{ DISABLE, FROM_KEYBOARD, FROM_IM } Chewing:Modifier:Sync; /** * ChewingInputMode: * @BYPASS: Bypass the cursor movement keys. * @EDITING: Forming Chinese character (in pre-edit buffer). * @SELECTING: Selecting candidate. Immediately after character is formed. * @SELECTING_DONE: A candidate is manually selected. * * Chewing input (key handling) mode. */ enum CHEWING_INPUT_MODE{ BYPASS, EDITING, SELECTING, SELECTING_DONE } Chewing:Input:Mode; enum CHEWING_OUTPUT_CHARSET{ AUTO, BIG5, UTF8 } Chewing:Output:Charset; %h{ #include "maker-dialog.h" #define GCONF_KEY_PREFIX "/desktop/ibus/engine/Chewing/" #define EASY_SYMBOL_INPUT_WORK_AROUND extern PropertySpec propSpecs[]; extern const gchar *page_labels[]; extern const gchar *button_labels[]; extern GtkResponseType button_responses[]; #define ZHUYIN_BUFFER_SIZE 12 #define ENGINE_FLAG_INITIALIZED 1 #define ENGINE_FLAG_ENABLED 2 #define ENGINE_FLAG_FOCUS_IN 4 #define ENGINE_FLAG_SHOW_CANDIDATE 8 #define ibus_chewing_engine_set_flag(cengine,f) cengine->_priv->flags |= f #define ibus_chewing_engine_clear_flag(cengine,f) cengine->_priv->flags &= ~f #ifdef IBUS_1_1 /* * Dummy data structure for ibus 1.1 and early. */ typedef void IBusKeymap; IBusKeymap *ibus_keymap_new(gchar *keymap_name); #endif /* IBUS_1_1 */ #define G_DEBUG_MSG(level, msg, args...) if (level<=ibus_chewing_verbose) g_debug(msg, ##args) %} %privateheader{ gboolean ibus_chewing_engine_process_key_event(IBusEngine *engine, guint keyval, guint modifiers); #ifndef IBUS_1_1 gboolean ibus_chewing_engine_process_key_event_1_2(IBusEngine *engine, guint keyval_ignore, guint keycode, guint modifiers); #endif /* IBUS_1_1 */ %} %{ extern gboolean ibus_chewing_verbose; //extern IBusConfig *iConfig; #define IBUS_CHEWING_MAIN #include "IBusChewingEngine-def.c" #ifdef IBUS_1_1 IBusKeymap *ibus_keymap_new(gchar *keymap_name){ return NULL; } #endif /* IBUS_1_1 */ %} class IBus:Chewing:Engine from IBus:Engine{ public ChewingContext *context=NULL destroywith chewing_delete; public Chewing:Modifier:Sync syncCapsLock_local=CHEWING_MODIFIER_SYNC_FROM_KEYBOARD; public GtkWidget *setting_dialog={ GTK_WIDGET(maker_dialog_new_full(_("Setting"),3,page_labels,1,button_labels,button_responses))}; protected gint selKeys[MAX_SELKEY]; /* Plain Zhuyin mode */ protected gboolean plainZhuyin=FALSE; protected ChewingInputMode inputMode=CHEWING_INPUT_MODE_BYPASS; protected gboolean forceLowercaseEnglish=FALSE; protected gboolean numpadAlwaysNumber=TRUE; /* For init work around */ private gboolean flags=0; /* For easy symbol input work around */ private gboolean easySymbolInput; protected IBusLookupTable *table=NULL destroywith ibus_lookup_table_clear; public IBusProperty *chieng_prop={ ibus_property_new("chewing_chieng_prop",PROP_TYPE_NORMAL, SELF_GET_CLASS(self)->chieng_prop_label_chi, NULL, NULL, TRUE, TRUE, PROP_STATE_UNCHECKED, NULL) } destroywith g_object_unref; public IBusProperty *alnumSize_prop={ ibus_property_new("chewing_alnumSize_prop",PROP_TYPE_NORMAL, SELF_GET_CLASS(self)->alnumSize_prop_label_half, NULL, NULL, TRUE, TRUE, PROP_STATE_UNCHECKED, NULL); } destroywith g_object_unref; public IBusProperty *settings_prop={ ibus_property_new("chewing_settings_prop",PROP_TYPE_TOGGLE, SELF_GET_CLASS(self)->settings_prop_label, PKGDATADIR "/icons/settings.png", NULL, TRUE, TRUE, PROP_STATE_UNCHECKED, NULL); } destroywith g_object_unref; public IBusPropList *prop_list={ibus_prop_list_new()} destroywith g_object_unref; public IBusConfig *config=NULL; protected IBusKeymap *keymap_us={ibus_keymap_new("us")}; private Display *pDisplay = {XOpenDisplay( NULL )} destroywith XCloseDisplay; private guint key_last=0; private gchar zhuyin_latest[ZHUYIN_BUFFER_SIZE]; classwide IBusText *chieng_prop_label_chi={ibus_text_new_from_static_string(_("Chi"))}; classwide IBusText *chieng_prop_label_eng={ibus_text_new_from_static_string(_("Eng"))}; classwide IBusText *alnumSize_prop_label_full={ibus_text_new_from_static_string(_("Full"))}; classwide IBusText *alnumSize_prop_label_half={ibus_text_new_from_static_string(_("Half"))}; classwide IBusText *settings_prop_label={ibus_text_new_from_static_string(_("Settings"))}; init (self) { /* initialize the object here */ G_DEBUG_MSG(1,"[I1] init()"); if (!(self->_priv->flags & ENGINE_FLAG_INITIALIZED)){ maker_dialog_set_verbose_level(MAKER_DIALOG(self->setting_dialog),ibus_chewing_verbose); gchar buf[100]; g_snprintf(buf,100,"%s/.chewing",getenv("HOME")); chewing_Init(CHEWING_DATADIR, buf); self->context=chewing_new(); chewing_set_ChiEngMode(self->context,CHINESE_MODE); self->inputMode=CHEWING_INPUT_MODE_EDITING; /* init properties */ ibus_prop_list_append(self->prop_list,self->chieng_prop); ibus_prop_list_append(self->prop_list,self->alnumSize_prop); ibus_prop_list_append(self->prop_list,self->settings_prop); ibus_chewing_engine_set_flag(self,ENGINE_FLAG_INITIALIZED); } } class_init(klass){ #ifdef IBUS_1_1 ibus_engine_class->process_key_event = ibus_chewing_engine_process_key_event; #else ibus_engine_class->process_key_event = ibus_chewing_engine_process_key_event_1_2; #endif /* IBUS_1_1 */ } private void load_setting(self){ #define BUFFER_SIZE_LOCAL 200 G_DEBUG_MSG(3,"[I3] load_setting()"); int i; gchar buf[BUFFER_SIZE_LOCAL]; GValue gValue={0}; for (i=0; propSpecs[i].valueType!=G_TYPE_INVALID;i++){ G_DEBUG_MSG(4,"[I4] load_setting(), i=%d",i); if (ibus_config_get_value(self->config, "engine/Chewing",propSpecs[i].key, &gValue)){ switch(propSpecs[i].valueType){ case G_TYPE_BOOLEAN: buf[0]=(g_value_get_boolean(&gValue))? '1' : '0'; buf[1]='\0'; break; case G_TYPE_UINT: g_snprintf(buf,BUFFER_SIZE_LOCAL,"%u", g_value_get_uint(&gValue)); break; case G_TYPE_INT: g_snprintf(buf,BUFFER_SIZE_LOCAL,"%d", g_value_get_int(&gValue)); break; case G_TYPE_STRING: g_strlcpy(buf,g_value_get_string(&gValue), BUFFER_SIZE_LOCAL); break; default: break; } }else{ g_warning("[WW] %s /desktop/ibus/engine/Chewing/%s, %s %s", _("Warning: cannot load configure key"), propSpecs[i].key, (propSpecs[i].defaultValue)? _(" Use default value:") : _(" No default value, skipped.") , (propSpecs[i].defaultValue)? propSpecs[i].defaultValue : "" ); if (propSpecs[i].defaultValue){ g_strlcpy(buf,propSpecs[i].defaultValue, BUFFER_SIZE_LOCAL); }else{ continue; } } /* Add property to dialog */ maker_dialog_add_property(MAKER_DIALOG(self->setting_dialog),&propSpecs[i],buf,self); maker_dialog_apply_widget_value(MAKER_DIALOG(self->setting_dialog),propSpecs[i].key); g_value_unset(&gValue); } for (i=0; page_labels[i]!=NULL;i++){ maker_dialog_align_labels(MAKER_DIALOG(self->setting_dialog),page_labels[i],1.0f, 0.5f); } gtk_widget_hide(self->setting_dialog); #undef BUFFER_SIZE_LOCAL } /* commit string */ protected gboolean commit(self){ gboolean commit=chewing_commit_Check(self->context); G_DEBUG_MSG(2,"[I2] commit() %s", (commit) ? "TRUE": "FALSE"); if (commit){ IBusText *iText=NULL; gchar *commit_string=chewing_commit_String(self->context); G_DEBUG_MSG(3,"[I3] commit() commit_string=%s", commit_string); iText=ibus_text_new_from_string(commit_string); ibus_engine_commit_text(IBUS_ENGINE(self),iText); g_free(commit_string); g_object_unref(iText); } return commit; } protected void set_lookup_table_label(self,const gchar *labels){ int i,len=strlen(labels); g_array_set_size(self->table->labels,0); for(i=0;itable,text); } } private gchar *make_preedit_string(self, glong *zhuyin_item_written_ptr){ G_DEBUG_MSG(4, "[I3] make_preedit_string()"); gchar *buff_str=chewing_buffer_String(self->context); G_DEBUG_MSG(4, "[I4] make_preedit_string(): chewing_buffer_String=%s ", buff_str); int chiSymbolCursor = chewing_cursor_Current(self->context); int zhuyin_count; int zhuyin_tone=-1; gchar *zhuyin_str=chewing_zuin_String(self->context,&zhuyin_count); *zhuyin_item_written_ptr= (glong) zhuyin_count; G_DEBUG_MSG(4, "[I4] make_preedit_string(): chewing_zuin_String=%s count=%d inputMode=%d", zhuyin_str,zhuyin_count,self->inputMode); switch(self->inputMode){ case CHEWING_INPUT_MODE_EDITING: g_strlcpy(self->_priv->zhuyin_latest,zhuyin_str,ZHUYIN_BUFFER_SIZE); zhuyin_tone=0; break; case CHEWING_INPUT_MODE_SELECTING: zhuyin_tone=get_tone(chewing_get_KBType(self->context),self->_priv->key_last); add_tone(self->_priv->zhuyin_latest,zhuyin_tone); if (zhuyin_tone>0 ){ if (self->plainZhuyin){ /* Open candidate selection window */ if (chewing_get_spaceAsSelection(self->context)){ chewing_handle_Space(self->context); }else{ chewing_handle_Down(self->context); } } } break; case CHEWING_INPUT_MODE_SELECTING_DONE: self->_priv->zhuyin_latest[0]='\0'; zhuyin_tone=-1; self->inputMode=CHEWING_INPUT_MODE_EDITING; break; default: /* BYPASS */ break; } gsize len=strlen(zhuyin_str)+strlen(buff_str); gchar *preeditBuf=g_new(gchar, len+1); preeditBuf[0]='\0'; if (chiSymbolCursor>0){ g_utf8_strncpy(preeditBuf, buff_str, chiSymbolCursor); } gsize zhuyin_start=strlen(preeditBuf); /* Inserting zhuyinBuf */ if (zhuyin_count>0){ g_strlcat(preeditBuf,zhuyin_str,len+1); } /* Append rest chiSymbolBuf */ g_strlcat(preeditBuf,buff_str+zhuyin_start, len+1); g_free(buff_str); g_free(zhuyin_str); G_DEBUG_MSG(4, "[I4] make_preedit_string(): return preedit=%s zhuyin_latest=%s zhuyin_tone=%d inputMode=%d", preeditBuf, self->_priv->zhuyin_latest,zhuyin_tone,self->inputMode); return preeditBuf; } private void show_lookup_table(self, gboolean isShow){ ibus_engine_update_lookup_table(IBUS_ENGINE(self),self->table,isShow); if (isShow){ ibus_engine_show_lookup_table(IBUS_ENGINE(self)); ibus_chewing_engine_set_flag(self,ENGINE_FLAG_SHOW_CANDIDATE); }else{ ibus_engine_hide_lookup_table(IBUS_ENGINE(self)); ibus_chewing_engine_clear_flag(self,ENGINE_FLAG_SHOW_CANDIDATE); } } private void update_lookup_table(self){ ibus_lookup_table_clear(self->table); int choicePerPage=chewing_cand_ChoicePerPage(self->context); int i=0; char *candidate=NULL; IBusText *iText=NULL; G_DEBUG_MSG(4,"[I4] update_lookup_table() TotalChoice=%d CurrentPage=%d", chewing_cand_TotalChoice(self->context),chewing_cand_CurrentPage(self->context)); if (chewing_cand_TotalChoice(self->context) >0){ chewing_cand_Enumerate(self->context); for(i=0;icontext)){ candidate=chewing_cand_String(self->context); iText=ibus_text_new_from_string (candidate); ibus_lookup_table_append_candidate(self->table,iText); g_free(candidate); g_object_unref (iText); }else{ break; } } self_show_lookup_table(self, TRUE); }else{ self_show_lookup_table(self, FALSE); } } private void update_aux_string(self){ G_DEBUG_MSG(4,"[I4] update_aux_string()"); IBusText *iText=NULL; if (chewing_aux_Length(self->context)>0){ gchar *aux_string=chewing_aux_String(self->context); iText=ibus_text_new_from_string (aux_string); ibus_engine_update_auxiliary_text(IBUS_ENGINE(self),iText,TRUE); g_object_unref (iText); ibus_engine_show_auxiliary_text(IBUS_ENGINE(self)); g_free(aux_string); }else{ ibus_engine_hide_auxiliary_text(IBUS_ENGINE(self)); // iText=ibus_text_new_from_string(self->_priv->zhuyin_latest); // ibus_engine_update_auxiliary_text(IBUS_ENGINE(self),iText,TRUE); // g_object_unref (iText); // ibus_engine_show_auxiliary_text(IBUS_ENGINE(self)); } } private void update_preedit(self){ G_DEBUG_MSG(5,"[I5] update_preedit()"); glong zhuyin_item_written; gchar *preeditBuf=self_make_preedit_string(self, &zhuyin_item_written); IBusText *iText=ibus_text_new_from_string(preeditBuf); int chiSymbolCursor = chewing_cursor_Current(self->context); G_DEBUG_MSG(4,"[I4] update_preedit() chiSymbolCursor=%d preeditBuf=%s",chiSymbolCursor,preeditBuf ); g_free(preeditBuf); gint cursorRight=chiSymbolCursor + MAX(zhuyin_item_written,1); ibus_text_append_attribute (iText, IBUS_ATTR_TYPE_FOREGROUND, 0x00ffffff, chiSymbolCursor, cursorRight); ibus_text_append_attribute (iText, IBUS_ATTR_TYPE_BACKGROUND, 0x00000000, chiSymbolCursor, cursorRight); IntervalType it; chewing_interval_Enumerate(self->context); while(chewing_interval_hasNext(self->context)){ chewing_interval_Get(self->context,&it); ibus_text_append_attribute (iText, IBUS_ATTR_TYPE_UNDERLINE, IBUS_ATTR_UNDERLINE_DOUBLE, it.from, it.to); } ibus_text_append_attribute (iText, IBUS_ATTR_TYPE_UNDERLINE, IBUS_ATTR_UNDERLINE_SINGLE, 0, -1); ibus_engine_update_preedit_text (IBUS_ENGINE(self),iText, chiSymbolCursor, TRUE); g_object_unref (iText); G_DEBUG_MSG(5,"[I5] update_preedit(): return"); } protected gboolean update(self){ G_DEBUG_MSG(3,"[I3] update()"); self_update_aux_string(self); self_determine_input_mode(self); self_update_preedit(self); uint16 *phoneSeq=(chewing_get_phoneSeqLen(self->context)>0)? chewing_get_phoneSeq(self->context): NULL; G_DEBUG_MSG(4,"[I4] update() inputMode=%d nPhoneSeq=%d",self->inputMode, chewing_get_phoneSeqLen(self->context)); if (phoneSeq){ int i=0; for(i=0;icontext);i++){ G_DEBUG_MSG(5,"[I5] update() phoneSeq[%d]=%x",i,phoneSeq[i]); } free(phoneSeq); } self_update_lookup_table(self); self_commit(self); gboolean ret=TRUE; if (chewing_keystroke_CheckAbsorb(self->context)){ ret=TRUE; }else if (chewing_keystroke_CheckIgnore(self->context)){ ret=FALSE; } G_DEBUG_MSG(4,"[I4] update() return %s",(ret)? "TRUE": "FALSE"); return ret; } protected void refresh_property(self,const gchar *prop_name){ G_DEBUG_MSG(2,"[I2] refresh_property(%s)",prop_name); if (strcmp(prop_name,"chewing_chieng_prop")==0){ if (chewing_get_ChiEngMode(self->context)){ /* Chinese */ ibus_property_set_label(self->chieng_prop,SELF_GET_CLASS(self)->chieng_prop_label_chi); }else{ /* English */ ibus_property_set_label(self->chieng_prop,SELF_GET_CLASS(self)->chieng_prop_label_eng); } ibus_engine_update_property(IBUS_ENGINE(self),self->chieng_prop); }else if (strcmp(prop_name,"chewing_alnumSize_prop")==0){ if (chewing_get_ShapeMode(self->context)){ /* Full-Sized Shape */ ibus_property_set_label(self->alnumSize_prop,SELF_GET_CLASS(self)->alnumSize_prop_label_full); }else{ /* Half-Sized Shape */ ibus_property_set_label(self->alnumSize_prop,SELF_GET_CLASS(self)->alnumSize_prop_label_half); } ibus_engine_update_property(IBUS_ENGINE(self),self->alnumSize_prop); } } /** * refresh_property_list: * @self: this instances. * * Refresh the property list (language bar). */ public void refresh_property_list(self){ self_refresh_property(self,"chewing_chieng_prop"); self_refresh_property(self,"chewing_alnumSize_prop"); self_refresh_property(self,"chewing_settings_prop"); if (self->_priv->flags & (ENGINE_FLAG_ENABLED | ENGINE_FLAG_FOCUS_IN)){ ibus_engine_register_properties(IBUS_ENGINE(self),self->prop_list); IBUS_ENGINE_GET_CLASS(self)->property_show(IBUS_ENGINE(self),"chewing_chieng_prop"); IBUS_ENGINE_GET_CLASS(self)->property_show(IBUS_ENGINE(self),"chewing_alnumSize_prop"); IBUS_ENGINE_GET_CLASS(self)->property_show(IBUS_ENGINE(self),"chewing_settings_prop"); } } /** * hide_property_list: * @self: this instances. * * Hide the property list (language bar). */ public void hide_property_list(self){ IBUS_ENGINE_GET_CLASS(self)->property_hide(IBUS_ENGINE(self),"chewing_chieng_prop"); IBUS_ENGINE_GET_CLASS(self)->property_hide(IBUS_ENGINE(self),"chewing_alnumSize_prop"); IBUS_ENGINE_GET_CLASS(self)->property_hide(IBUS_ENGINE(self),"chewing_settings_prop"); } /** * save_config: * @self: this instances. * @key_suffix: key to be set. * @returns: TRUE if successful, FALSE otherwise. * * Save the property value to disk. */ public gboolean save_config(self, const gchar *key_suffix){ G_DEBUG_MSG(1,"[I1] save_config(%s,-)",key_suffix); GValue gValue={0}; maker_dialog_get_widget_value(MAKER_DIALOG(self->setting_dialog),key_suffix,&gValue); return ibus_config_set_value (self->config,"engine/Chewing",key_suffix,&gValue); } /** * save_config_all: * @self: this instances. * @key_suffix: key to be set. * @returns: TRUE if all successful, FALSE otherwise. * * Save alll property values to disk. */ public gboolean save_config_all(self){ int i; gboolean success=TRUE; for(i=0;propSpecs[i].valueType!=G_TYPE_INVALID;i++){ if (!self_save_config(self,propSpecs[i].key)){ success=FALSE; } } return success; } protected gboolean is_selectKey(self, guint keyval){ int j; for (j=0;j< MAX_SELKEY;j++){ if (self->selKeys[j]==keyval){ return TRUE; } } return FALSE; } protected void set_selKeys_string(self,const gchar* selKeys_str){ int j; int len_min= MIN(strlen(selKeys_str), MAX_SELKEY); for (j=0;j< len_min;j++){ self->selKeys[j]=(int) selKeys_str[j]; } chewing_set_selKey(self->context, self->selKeys,len_min); } private IBusProperty* get_iBusProperty(self, const gchar *prop_name){ if (strcmp(prop_name,"chewing_chieng_prop")==0){ return self->chieng_prop; }else if (strcmp(prop_name,"chewing_alnumSize_prop")==0){ return self->alnumSize_prop; }else if (strcmp(prop_name,"chewing_settings_prop")==0){ return self->settings_prop; } G_DEBUG_MSG(2,"[I2] get_iBusProperty(%s): NULL is returned",prop_name); return NULL; } protected void handle_Default(self, guint keyval, gboolean shiftPressed){ G_DEBUG_MSG(2,"[I2] IBusChewingEngine::handle_Default(-,%u) plainZhuyin=%s inputMode=%d", keyval,(self->plainZhuyin)? "TRUE": "FALSE",self->inputMode); #ifdef EASY_SYMBOL_INPUT_WORK_AROUND if (self->_priv->easySymbolInput){ /* If shift is pressed, turn on the easySymbolInput, turn off * otherwise */ chewing_set_easySymbolInput(self->context,(shiftPressed)? 1:0); } #endif if (self->forceLowercaseEnglish){ if (isupper(keyval) && !shiftPressed){ keyval=tolower(keyval); }else if (islower(keyval) && shiftPressed){ keyval=toupper(keyval); } } chewing_handle_Default(self->context,keyval); if (self->plainZhuyin){ if (self_is_selectKey(self,self->_priv->key_last) && self->inputMode==CHEWING_INPUT_MODE_SELECTING){ chewing_handle_Enter(self->context); self->inputMode= CHEWING_INPUT_MODE_SELECTING_DONE; } } } /* * determine_input_mode: * * Determine input mode. */ private void determine_input_mode(self){ gint zhuyin_count=-1; gchar *str_ptr=chewing_zuin_String(self->context,&zhuyin_count); G_DEBUG_MSG(3, "[I3] determine_input_mode(): chewing_zuin_String=%s count=%d inputMode=%d", str_ptr,zhuyin_count,self->inputMode); int zhuyin_tone=-1; if (zhuyin_count>0){ /* Incomplete Character*/ self->inputMode=CHEWING_INPUT_MODE_EDITING; }else{ /* Character/Phrase is completed. */ if (self->inputMode==CHEWING_INPUT_MODE_EDITING){ /* In EDITING mode */ zhuyin_tone=get_tone(chewing_get_KBType(self->context),self->_priv->key_last); if (zhuyin_tone>0 ){ /* Enter SELECTING mode */ self->inputMode=CHEWING_INPUT_MODE_SELECTING; } }else if (self->inputMode==CHEWING_INPUT_MODE_SELECTING_DONE){ /* In SELECTING_DONE mode */ /* One of selection keys is pressed */ }else{ /* In SELECTING mode */ } } if (chewing_buffer_Len(self->context)+ zhuyin_count==0){ /* If preedit buffer is empty, then enter BYPASS mode.*/ /* So cursor keys can be used freely. */ self->inputMode=CHEWING_INPUT_MODE_BYPASS; } g_free(str_ptr); G_DEBUG_MSG(3, "[I3] determine_input_mode() return: zhuyin_latest=%s zhuyin_tone=%d inputMode=%d", self->_priv->zhuyin_latest,zhuyin_tone,self->inputMode); } private void force_commit(self){ G_DEBUG_MSG(3,"[I3] force_commit() buffer=%d, commit=%d", chewing_buffer_Check(self->context),chewing_commit_Check(self->context)); /* Remove the incomplete zhuyin symbol */ if (self->inputMode==CHEWING_INPUT_MODE_EDITING) chewing_handle_Esc(self->context); if (chewing_buffer_Check(self->context)){ if (!chewing_commit_Check(self->context)){ /* Close candidate window */ if (self->_priv->flags & ENGINE_FLAG_SHOW_CANDIDATE){ chewing_handle_Esc(self->context); } chewing_handle_Enter(self->context); } self_update(self); } } /*============================================ * Overridden Parent (IBusEngine) methods */ override (IBus:Engine) void reset(IBus:Engine *engine){ G_DEBUG_MSG(1,"[I1] reset"); Self *self=SELF(engine); ibus_lookup_table_clear(self->table); /* Save KBType type, becaue chewing_Reset() will reset it to default. */ int kbType=chewing_get_KBType(self->context); chewing_Reset(self->context); chewing_set_KBType(self->context,kbType); ibus_engine_hide_auxiliary_text(IBUS_ENGINE(engine)); ibus_engine_hide_lookup_table(IBUS_ENGINE(self)); } override (IBus:Engine) void page_up(IBus:Engine *engine){ Self *self=SELF(engine); chewing_handle_PageUp(self->context); self_update(self); } override (IBus:Engine) void page_down(IBus:Engine *engine){ Self *self=SELF(engine); chewing_handle_PageDown(self->context); self_update(self); } override (IBus:Engine) void cursor_up(IBus:Engine *engine){ Self *self=SELF(engine); chewing_handle_Up(self->context); self_update(self); } override (IBus:Engine) void cursor_down(IBus:Engine *engine){ Self *self=SELF(engine); chewing_handle_Down(self->context); self_update(self); } override (IBus:Engine) void enable(IBus:Engine *engine){ G_DEBUG_MSG(2,"[I2] enable()"); Self *self=SELF(engine); if (!self->config){ /* connections_list is not avail in init, so we put it here */ GList *connections_list=ibus_service_get_connections(IBUS_SERVICE(engine)); g_assert(connections_list); g_assert(connections_list->data); IBusConnection *iConnection=(IBusConnection *) connections_list->data; self->config=ibus_config_new(iConnection); self_load_setting(self); } self_refresh_property_list(self); self->inputMode=CHEWING_INPUT_MODE_EDITING; ibus_chewing_engine_set_flag(self, ENGINE_FLAG_ENABLED); } override (IBus:Engine) void disable(IBus:Engine *engine){ G_DEBUG_MSG(2,"[I2] disable()"); Self *self=SELF(engine); self_force_commit(self); self_hide_property_list(self); self->inputMode=CHEWING_INPUT_MODE_BYPASS; ibus_chewing_engine_clear_flag(self,ENGINE_FLAG_ENABLED); } override (IBus:Engine) void focus_in(IBus:Engine *engine){ Self *self=SELF(engine); /* Sync Caps_Lock and ChiEngMode */ guint modifiers=keyModifier_get(self->_priv->pDisplay); gint caps_is_lock=(modifiers & IBUS_LOCK_MASK)!=0; G_DEBUG_MSG(2,"[I2] focus_in(): flags=%d ChiEng=%d IBUS_LOCK=%d", self->_priv->flags, chewing_get_ChiEngMode(self->context),caps_is_lock); if (chewing_get_ChiEngMode(self->context)==caps_is_lock){ /* Caps_lock and ChiEngMode does not agree each other */ switch(self->syncCapsLock_local){ case CHEWING_MODIFIER_SYNC_FROM_KEYBOARD: chewing_set_ChiEngMode(self->context,!caps_is_lock); break; case CHEWING_MODIFIER_SYNC_FROM_IM: /* fake event won't go through process_key_event */ key_send_fake_event(IBUS_Caps_Lock,self->_priv->pDisplay); break; default: g_warning("Caps_lock and ChiEngMode does not agree each other!"); break; } } self_refresh_property_list(self); self_update_preedit(self); ibus_chewing_engine_set_flag(self, ENGINE_FLAG_FOCUS_IN); G_DEBUG_MSG(4,"[I4] focus_in(): return"); } override (IBus:Engine) void focus_out(IBus:Engine *engine){ Self *self=SELF(engine); G_DEBUG_MSG(2,"[I2] focus_out(): flags=%d",self->_priv->flags); self_force_commit(self); ibus_chewing_engine_clear_flag(self, ENGINE_FLAG_FOCUS_IN); G_DEBUG_MSG(4,"[I4] focus_out(): return"); } override (IBus:Engine) void property_activate(IBus:Engine *engine, const gchar *prop_name, guint prop_state){ G_DEBUG_MSG(2,"[I2] property_activate(-, %s, %u)", prop_name, prop_state); Self *self=SELF(engine); gboolean needRefresh=TRUE; if (strcmp(prop_name,"chewing_chieng_prop")==0){ /* Toggle Chinese <-> English */ chewing_set_ChiEngMode(self->context, !chewing_get_ChiEngMode(self->context)); }else if (strcmp(prop_name,"chewing_alnumSize_prop")==0){ /* Toggle Full <-> Half */ chewing_set_ShapeMode(self->context, !chewing_get_ShapeMode(self->context)); }else if (strcmp(prop_name,"chewing_settings_prop")==0){ if (self->settings_prop->state==PROP_STATE_UNCHECKED){ if (gtk_dialog_run(GTK_DIALOG(self->setting_dialog))==GTK_RESPONSE_OK){ self_save_config_all(self); } gtk_widget_hide(self->setting_dialog); self->settings_prop->state=PROP_STATE_UNCHECKED; } }else{ G_DEBUG_MSG(2,"[I2] property_activate(-, %s, %u) not recognized",prop_name, prop_state); needRefresh=FALSE; } if (needRefresh) self_refresh_property(self,prop_name); } override (IBus:Engine) void property_show(IBus:Engine *engine, const gchar *prop_name){ G_DEBUG_MSG(2,"[I2] property_show(-, %s)",prop_name); Self *self=SELF(engine); IBusProperty *prop=self_get_iBusProperty(self, prop_name); ibus_property_set_visible(prop,TRUE); ibus_engine_update_property(engine,prop); } override (IBus:Engine) void property_hide(IBus:Engine *engine, const gchar *prop_name){ G_DEBUG_MSG(2,"[I2] property_hide(-, %s)",prop_name); Self *self=SELF(engine); IBusProperty *prop=self_get_iBusProperty(self, prop_name); ibus_property_set_visible(prop,FALSE); ibus_engine_update_property(engine,prop); } } %{ #include "IBusChewingEngine-keys.c" %}