Back to index

im-sdk  12.3.91
XIMPInputContext.cpp
Go to the documentation of this file.
00001 /*
00002 Copyright 1990-2001 Sun Microsystems, Inc. All Rights Reserved.
00003 
00004 Permission is hereby granted, free of charge, to any person obtaining a
00005 copy of this software and associated documentation files (the
00006 "Software"), to deal in the Software without restriction, including
00007 without limitation the rights to use, copy, modify, merge, publish,
00008 distribute, sublicense, and/or sell copies of the Software, and to
00009 permit persons to whom the Software is furnished to do so, subject to
00010 the following conditions: The above copyright notice and this
00011 permission notice shall be included in all copies or substantial
00012 portions of the Software.
00013 
00014 
00015 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00016 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00017 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
00018 IN NO EVENT SHALL THE OPEN GROUP OR SUN MICROSYSTEMS, INC. BE LIABLE
00019 FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
00020 CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
00021 THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE EVEN IF
00022 ADVISED IN ADVANCE OF THE POSSIBILITY OF SUCH DAMAGES.
00023 
00024 
00025 Except as contained in this notice, the names of The Open Group and/or
00026 Sun Microsystems, Inc. shall not be used in advertising or otherwise to
00027 promote the sale, use or other dealings in this Software without prior
00028 written authorization from The Open Group and/or Sun Microsystems,
00029 Inc., as applicable.
00030 
00031 
00032 X Window System is a trademark of The Open Group
00033 
00034 OSF/1, OSF/Motif and Motif are registered trademarks, and OSF, the OSF
00035 logo, LBX, X Window System, and Xinerama are trademarks of the Open
00036 Group. All other trademarks and registered trademarks mentioned herein
00037 are the property of their respective owners. No right, title or
00038 interest in or to any trademark, service mark, logo or trade name of
00039 Sun Microsystems, Inc. or its licensors is granted.
00040 
00041 */
00042 #include <string.h>
00043 #ifndef ARCH
00044 #include <sys/systeminfo.h> /* For os_arch */
00045 #endif
00046 #include <sys/utsname.h>    /* For os_name and os_version */
00047 #include <sys/types.h>
00048 #include <unistd.h>
00049 #include <pwd.h>
00050 #include "XIMProtocol.hh"
00051 #include "XIMPInputContext.hh"
00052 #include "Xfactory.hh"
00053 #include <X11/Xutil.h>
00054 
00055 void
00056 XIMPInputContext::
00057 DelayBind() {
00058   CreateXIC();
00059   register_clientwin_destroy_filter();
00060 
00061   SetExtensionCallbacks();
00062   if (inputstyle & XIMPreeditCallbacks) {
00063     SetPreeditCallbacks();
00064   }
00065   if (inputstyle & XIMStatusCallbacks) {
00066     SetStatusCallbacks();
00067   }
00068   if (focus_win && xic) {
00069     XSetICValues(xic,
00070                XNFocusWindow, focus_win,
00071                0);
00072   }
00073 }
00074 
00075 void
00076 XIMPInputContext::
00077 CreateXIC() {
00078   XIM xim = 0;
00079   if ((xim = ximp_protocol->getXIM())) {
00080     xic = XCreateIC(xim,
00081                   XNInputStyle, inputstyle,
00082                   XNClientWindow, client_win,
00083                   0);
00084     if (!xic) {
00085       // need to reconnect
00086       ximp_protocol->CloseIM();
00087       ximp_protocol->OpenIM();
00088       if ((xim = ximp_protocol->getXIM())) {
00089        xic = XCreateIC(xim,
00090                      XNInputStyle, inputstyle,
00091                      XNClientWindow, client_win,
00092                      0);
00093       }
00094     }
00095   }
00096   return;
00097 }
00098 
00099 void
00100 XIMPInputContext::
00101 SetExtensionCallbacks() {
00102   if (xic)
00103     XSetICValues(xic,
00104                XNPreeditStateNotifyCallback, state_notify_cb,
00105                // private XIC attribute
00106                "commitStringCallback", commit_string_cb,
00107                "forwardEventCallback", forward_event_cb,
00108                0);
00109   return;
00110 }
00111 
00112 void
00113 XIMPInputContext::
00114 SetPreeditCallbacks() {
00115   if (xic) {
00116     XVaNestedList preedit_attr = XVaCreateNestedList(0,
00117                           XNPreeditStartCallback, preedit_start_cb,
00118                           XNPreeditDrawCallback, preedit_draw_cb,
00119                           XNPreeditCaretCallback, preedit_caret_cb,
00120                           XNPreeditDoneCallback, preedit_done_cb,
00121                           0);
00122     XSetICValues(xic,
00123                XNPreeditAttributes, preedit_attr,
00124                0);
00125     XFree(preedit_attr);
00126   }
00127   return;
00128 }
00129 
00130 void
00131 XIMPInputContext::
00132 SetStatusCallbacks() {
00133   if (xic) {
00134     XVaNestedList status_attr = XVaCreateNestedList(0,
00135                          XNStatusStartCallback, status_start_cb,
00136                          XNStatusDrawCallback, status_draw_cb,
00137                          XNStatusDoneCallback, status_done_cb,
00138                          0);
00139     XSetICValues(xic,
00140                XNStatusAttributes, status_attr,
00141                0);
00142     XFree(status_attr);
00143   }
00144 }
00145 
00146 XIMPInputContext::
00147 XIMPInputContext(XIMProtocol *ximp, XClientMessageEvent *ev) {
00148   ximp_protocol = ximp;
00149   xic = 0;
00150   ev_flow_type = 0;
00151   ev_masks = 0;
00152   filters = 0;
00153   preedit_maxlen = 0;
00154   preedit_caret_position = 0;
00155   is_conv_on = 0;
00156   og_code = og_state = 0;
00157 
00158   // for XIMProtocol::reset() can return reset text
00159   being_reset = False;
00160   reset_text = "";
00161 
00162   inputstyle = 0;
00163   client_win = focus_win = 0;
00164   preedit_fontname = 0;
00165   status_fontname = 0;
00166   attr_mask = 0;
00167   preedit_start_cb = 0;
00168   preedit_draw_cb = 0;
00169   preedit_caret_cb = 0;
00170   preedit_done_cb = 0;
00171   status_start_cb = 0;
00172   status_draw_cb = 0;
00173   status_done_cb = 0;
00174   dpy = ev->display;
00175 
00176   user_name = getpwuid(getuid())->pw_name;
00177   application_name = "Unused";
00178 
00179   xDisplayName = DisplayString(dpy);
00180   xServerVendor = ServerVendor(dpy);
00181 
00182   /* os properties */
00183   {
00184     struct utsname name;
00185 #if 0
00186     char arch[12];
00187 #endif
00188     uname(&name);
00189     os_name = name.sysname;
00190     os_version = name.release;
00191 
00192 #ifdef ARCH
00193     os_arch = ARCH;
00194 #else
00195     sysinfo(SI_ARCHITECTURE, arch, sizeof(arch));
00196     if (strcmp(arch,"sparc") == 0 ) {
00197       os_arch = "sparc";
00198     } else if (strcmp(arch,"i386") == 0 ) {
00199       /* use x86 to match the value received on win32 */
00200       os_arch = "x86";
00201     } else if (strcmp(arch, "ppc") == 0 ) {
00202       os_arch = "ppc";
00203     } else {
00204       os_arch = "Unknown";
00205     }
00206 #endif
00207   }
00208 
00209   memset((void*)&preedit_attr4, 0, sizeof(Ximp_PreeditPropRec4));
00210   memset((void*)&status_attr4, 0, sizeof(Ximp_StatusPropRec4));
00211 
00212   inputstyle = ev->data.l[2];
00213   set_client_window(ev->data.l[1]);
00214 
00215   char *prop_ret = (char*)0;
00216   proto_version = XIMP_VERSION_UNKNOWN;
00217 
00218   if (ximp_protocol->get_protocol_version(client_win, prop_ret)) {
00219     if (prop_ret != 0 && *prop_ret != 0) {
00220       if (!strcmp(prop_ret, "XIMP.4.0")) {
00221        proto_version = XIMP_VERSION_40;
00222       } else if (!strcmp(prop_ret, "XIMP.3.5")) {
00223        proto_version = XIMP_VERSION_35;
00224       } else if (!strcmp(prop_ret, "XIMP_1.0")) {
00225        proto_version = XIMP_VERSION_40;
00226       } else if (!strcmp(prop_ret, "XIMP.3.4")) {
00227        proto_version = XIMP_VERSION_35;
00228       }
00229       XFree(prop_ret);
00230     }
00231   }
00232 
00233   CreateXIC();
00234 
00235   register_clientwin_destroy_filter();
00236 
00237   state_notify_cb = new XIMCallback2;
00238   state_notify_cb->client_data = (char*)this;
00239   state_notify_cb->callback = state_notify_cbproc;
00240 
00241   commit_string_cb = new XIMCallback2;
00242   commit_string_cb->client_data = (char*)this;
00243   commit_string_cb->callback = commit_string_cbproc;
00244 
00245   forward_event_cb = new XIMCallback2;
00246   forward_event_cb->client_data = (char*)this;
00247   forward_event_cb->callback = forward_event_cbproc;
00248 
00249   SetExtensionCallbacks();
00250 
00251   // callback styles?
00252   if (inputstyle & XIMPreeditCallbacks) {
00253     preedit_start_cb = new XIMCallback1;
00254     preedit_start_cb->client_data = (char*)this;
00255     preedit_start_cb->callback = preedit_start_cbproc;
00256 
00257     preedit_draw_cb = new XIMCallback2;
00258     preedit_draw_cb->client_data = (char*)this;
00259     preedit_draw_cb->callback = preedit_draw_cbproc;
00260 
00261     preedit_caret_cb = new XIMCallback2;
00262     preedit_caret_cb->client_data = (char*)this;
00263     preedit_caret_cb->callback = preedit_caret_cbproc;
00264 
00265     preedit_done_cb = new XIMCallback2;
00266     preedit_done_cb->client_data = (char*)this;
00267     preedit_done_cb->callback = preedit_done_cbproc;
00268 
00269     SetPreeditCallbacks();
00270   }
00271   if (inputstyle & XIMStatusCallbacks) {
00272     status_start_cb = new XIMCallback2;
00273     status_start_cb->client_data = (char*)this;
00274     status_start_cb->callback = status_start_cbproc;
00275 
00276     status_draw_cb = new XIMCallback2;
00277     status_draw_cb->client_data = (char*)this;
00278     status_draw_cb->callback = status_draw_cbproc;
00279 
00280     status_done_cb = new XIMCallback2;
00281     status_done_cb->client_data = (char*)this;
00282     status_done_cb->callback = status_done_cbproc;
00283 
00284     SetStatusCallbacks();
00285   }
00286   unsigned long mask = ev->data.l[3];
00287   get_xicvalues(mask);
00288 
00289   if (focus_win == 0) {
00290     focus_win = client_win;
00291   }
00292 
00293   select_destroy_emask();
00294 
00295   if (is_version_40()) {
00296     if (((ev_flow_type == XIMProtocol::XIMP_FE_TYPE2) ||
00297         (ev_flow_type == XIMProtocol::XIMP_FE_TYPE3))) {
00298       select_keypress_emask();
00299       select_keyrelease_emask();
00300     }
00301   }
00302 }
00303 
00304 void
00305 XIMPInputContext::state_notify_cbproc(XIC xic, XPointer client_data,
00306                                    XPointer call_data_p) {
00307   XIMPreeditStateNotifyCallbackStruct *call_data =
00308     (XIMPreeditStateNotifyCallbackStruct *)call_data_p;
00309   XIMPInputContext *ic = (XIMPInputContext*)client_data;
00310   if (call_data->state == XIMPreeditDisable) {
00311     ic->conversion_end(False);
00312   }
00313   if (call_data->state == XIMPreeditEnable) {
00314     ic->conversion_start(False);
00315   }
00316 }
00317 
00318 // XIM callbacks
00319 int
00320 XIMPInputContext::preedit_start_cbproc(XIC xic, XPointer client_data,
00321                                    XPointer call_data) {
00322   XIMPInputContext *ic = (XIMPInputContext*)client_data;
00323   ic->preedit_start((IMPreeditStruct*)0);
00324   return -1;
00325 }
00326 
00327 void
00328 XIMPInputContext::preedit_draw_cbproc(XIC xic, XPointer client_data,
00329                                   XPointer call_data_p) {
00330   XIMPInputContext *ic = (XIMPInputContext*)client_data;
00331   XIMPreeditDrawCallbackStruct *call_data =
00332     (XIMPreeditDrawCallbackStruct*)call_data_p;
00333   char *mb_data;
00334   XTextProperty prop;
00335   prop.value = 0;
00336   if (call_data->text) {
00337     // call_data is native encoding, so need to convert to CT
00338     mb_data = call_data->text->string.multi_byte;
00339     XmbTextListToTextProperty(ic->dpy, &mb_data,
00340                            1, XCompoundTextStyle, &prop);
00341     call_data->text->string.multi_byte = (char*)prop.value;
00342   }
00343   ic->preedit_draw(call_data);
00344 
00345   if (call_data->text) call_data->text->string.multi_byte = mb_data;
00346   if (prop.value) XFree(prop.value);
00347   return;
00348 }
00349 void
00350 XIMPInputContext::preedit_caret_cbproc(XIC xic, XPointer client_data,
00351                                    XPointer call_data_p) {
00352   XIMPInputContext *ic = (XIMPInputContext*)client_data;
00353   XIMPreeditCaretCallbackStruct *call_data =
00354     (XIMPreeditCaretCallbackStruct*)call_data_p;
00355   ic->preedit_caret(call_data);
00356 }
00357 void
00358 XIMPInputContext::preedit_done_cbproc(XIC xic, XPointer client_data,
00359                                    XPointer call_data) {
00360   XIMPInputContext *ic = (XIMPInputContext*)client_data;
00361   ic->preedit_done((IMPreeditStruct*)0);
00362 }
00363 void
00364 XIMPInputContext::status_start_cbproc(XIC xic, XPointer client_data,
00365                                   XPointer call_data) {
00366   XIMPInputContext *ic = (XIMPInputContext*)client_data;
00367   ic->status_start((IMStatusStruct*)0);
00368 }
00369 void
00370 XIMPInputContext::status_draw_cbproc(XIC xic, XPointer client_data,
00371                                  XPointer call_data_p) {
00372   XIMPInputContext *ic = (XIMPInputContext*)client_data;
00373   XIMStatusDrawCallbackStruct *call_data =
00374     (XIMStatusDrawCallbackStruct*)call_data_p;
00375 
00376   XTextProperty prop;
00377   prop.value = 0;
00378   if (call_data->data.text) {
00379     // call_data is native encoding, so need to convert to CT
00380     char *mb_data = call_data->data.text->string.multi_byte;
00381     XmbTextListToTextProperty(ic->dpy, &mb_data,
00382                            1, XCompoundTextStyle, &prop);
00383     call_data->data.text->string.multi_byte = (char*)prop.value;
00384   }
00385 
00386   ic->status_draw(call_data);
00387 
00388   if (prop.value) XFree(prop.value);
00389   return;
00390 }
00391 void
00392 XIMPInputContext::status_done_cbproc(XIC xic, XPointer client_data,
00393                                  XPointer call_data) {
00394   XIMPInputContext *ic = (XIMPInputContext*)client_data;
00395   ic->status_done((IMStatusStruct*)0);
00396 }
00397 
00398 
00399 void
00400 XIMPInputContext::commit_string_cbproc(XIC xic, XPointer client_data,
00401                                    XPointer call_data_p) {
00402   XIMText *cbtext = (XIMText*)call_data_p;
00403   char *mb_data = (char*)cbtext->string.multi_byte;
00404   XIMPInputContext *ic = (XIMPInputContext*)client_data;
00405 
00406   if (mb_data == 0 || *mb_data == 0) return;
00407 
00408   // mb_data is native encoding, so need to convert to CT
00409   XTextProperty prop;
00410   XmbTextListToTextProperty(ic->dpy, &mb_data,
00411                          1, XCompoundTextStyle, &prop);
00412   char *ret = (char *)prop.value;
00413   if (ic->being_reset)
00414     ic->reset_text += ret;
00415   else
00416     ic->commit_string(ret);
00417 
00418   if (prop.value) XFree(prop.value);
00419   return;
00420 }
00421 
00422 void
00423 XIMPInputContext::forward_event_cbproc(XIC xic, XPointer client_data,
00424                                    XPointer call_data_p) {
00425   XEvent *call_data = (XEvent*)call_data_p;
00426   XIMPInputContext *ic = (XIMPInputContext*)client_data;
00427 
00428   ic->forward_xevent(call_data);
00429   return;
00430 }
00431 
00432 XIMPInputContext::~XIMPInputContext() {
00433   delete preedit_start_cb;
00434   delete preedit_draw_cb;
00435   delete preedit_caret_cb;
00436   delete preedit_done_cb;
00437   delete status_start_cb;
00438   delete status_draw_cb;
00439   delete status_done_cb;
00440 
00441   delete state_notify_cb;
00442   delete commit_string_cb;
00443   delete forward_event_cb;
00444 }
00445 
00446 const CompoundString&
00447 XIMPInputContext::
00448 getUser() const {
00449   return user_name;
00450 }
00451 
00452 const CompoundString&
00453 XIMPInputContext::
00454 getApplicationName() const {
00455   return application_name;
00456 }
00457 
00458 const CompoundString&
00459 XIMPInputContext::
00460 getOSName() const {
00461   return os_name;
00462 }
00463 
00464 const CompoundString&
00465 XIMPInputContext::
00466 getOSArch() const {
00467   return os_arch;
00468 }
00469 
00470 const CompoundString&
00471 XIMPInputContext::
00472 getOSVersion() const {
00473   return os_version;
00474 }
00475 
00476 // Client Display Info
00477 const CompoundString&
00478 XIMPInputContext::
00479 getXDisplayString() const {
00480   return xDisplayName;
00481 }
00482 
00483 const CompoundString&
00484 XIMPInputContext::
00485 getXServerVendor() const {
00486   return xServerVendor;
00487 }
00488 
00489 const CompoundString&
00490 XIMPInputContext::
00491 getLocaleName() const {
00492   return ximp_protocol->getPrimaryLocale();
00493 }
00494 
00495 const CompoundString&
00496 XIMPInputContext::
00497 getEngineName() const {
00498   return ximp_protocol->getIfName();
00499 }
00500 
00501 int
00502 XIMPInputContext::commit_string(IMText *text) {
00503   return True;
00504 }
00505 
00506 int
00507 XIMPInputContext::forward_event(IMKeyEventStruct *event) {
00508   return True;
00509 }
00510 
00511 int
00512 XIMPInputContext::preedit_start(IMPreeditStruct *preedit) {
00513   int input_context_id = ximp_protocol->getICID(this);
00514 
00515   ximp_protocol->send_client_message(focus_win,
00516                                  (is_version_40() ?
00517                                   XIMProtocol::XIMP_PREEDITSTART4 :
00518                                   XIMProtocol::XIMP_PREEDITSTART3),
00519                                  input_context_id,
00520                                  0, 0, 0);
00521   return True;
00522 }
00523 
00524 int
00525 XIMPInputContext::preedit_draw(IMPreeditStruct *preedit) {
00526   return True;
00527 }
00528 
00529 int
00530 XIMPInputContext::preedit_caret(IMPreeditStruct *preedit) {
00531   return True;
00532 }
00533 
00534 int
00535 XIMPInputContext::preedit_done(IMPreeditStruct *preedit) {
00536   int input_context_id = ximp_protocol->getICID(this);
00537 
00538   ximp_protocol->send_client_message(focus_win,
00539                                  (is_version_40() ?
00540                                   XIMProtocol::XIMP_PREEDITDONE4 :
00541                                   XIMProtocol::XIMP_PREEDITDONE3),
00542                                  input_context_id,
00543                                  0, 0, 0);
00544   return 0;
00545 }
00546 
00547 int
00548 XIMPInputContext::status_start(IMStatusStruct *status) {
00549   int input_context_id = ximp_protocol->getICID(this);
00550 
00551   ximp_protocol->send_client_message(focus_win,
00552                                  (is_version_40() ?
00553                                   XIMProtocol::XIMP_STATUSSTART4 :
00554                                   XIMProtocol::XIMP_STATUSSTART3),
00555                                  input_context_id,
00556                                  0, 0, 0);
00557   return True;
00558 }
00559 
00560 int
00561 XIMPInputContext::status_draw(IMStatusStruct *status) {
00562   return True;
00563 }
00564 
00565 int
00566 XIMPInputContext::status_done(IMStatusStruct *status) {
00567   int input_context_id = ximp_protocol->getICID(this);
00568 
00569   ximp_protocol->send_client_message(focus_win,
00570                                  (is_version_40() ?
00571                                   XIMProtocol::XIMP_STATUSDONE4 :
00572                                   XIMProtocol::XIMP_STATUSDONE3),
00573                                  input_context_id,
00574                                  0, 0, 0);
00575   return 0;
00576 }
00577 
00578 int
00579 XIMPInputContext::lookup_start(IMLookupStruct *lookup) {
00580   return 0;
00581 }
00582  
00583 int
00584 XIMPInputContext::lookup_draw(IMLookupStruct *lookup) {
00585   return True;
00586 }
00587 
00588 int
00589 XIMPInputContext::lookup_process(IMLookupStruct *lookup) {
00590   return 0;
00591 }
00592 
00593 int
00594 XIMPInputContext::lookup_done(IMLookupStruct *lookup) {
00595   return 0;
00596 }
00597 
00598 int
00599 XIMPInputContext::auxiliary_start(IMAuxStruct *auxiliary) {
00600   return 0;
00601 }
00602 int
00603 XIMPInputContext::auxiliary_draw(IMAuxStruct *auxiliary) {
00604   return 0;
00605 }
00606 int
00607 XIMPInputContext::auxiliary_done(IMAuxStruct *auxiliary) {
00608   return 0;
00609 }
00610 
00611 int
00612 XIMPInputContext::conversion_start() {
00613   return conversion_start(True);
00614 }
00615 int
00616 XIMPInputContext::conversion_end() {
00617   return conversion_end(True);
00618 }
00619 
00620 int
00621 XIMPInputContext::conversion_start(Bool reply_back) {
00622   int input_context_id = ximp_protocol->getICID(this);
00623   if (is_version_40()) {
00624     if (is_ximp_type(XIMProtocol::XIMP_FE_TYPE1)) {
00625       select_keypress_emask();
00626       select_keyrelease_emask();
00627     }
00628   } else {
00629     if (is_ximp_type(XIMProtocol::XIMP_FRONTEND)) {
00630       select_keypress_emask();
00631     }
00632   }
00633   set_conv_state(True);
00634 
00635   if (reply_back) {
00636     if (!xic) DelayBind();
00637     if (xic) {
00638       XSetICValues(xic,
00639                  XNPreeditState, XIMPreeditEnable,
00640                  0);
00641     } else {
00642       conversion_end();
00643       return 0;
00644     }
00645   }
00646 
00647   // this return message is necessary for XIMP_EXTENSION EXT_CONV
00648   ximp_protocol->send_client_message(focus_win,
00649                                  (is_version_40() ?
00650                                   XIMProtocol::XIMP_SPROC_STARTED4 :
00651                                   XIMProtocol::XIMP_PROCESS_BEGIN3),
00652                                  input_context_id,
00653                                  0, 0, 0);
00654   return 0;
00655 }
00656 
00657 int
00658 XIMPInputContext::conversion_end(Bool reply_back) {
00659   int input_context_id = ximp_protocol->getICID(this);
00660   unselect_keypress_emask();
00661   unselect_keyrelease_emask();
00662   set_conv_state(False);
00663 
00664   if (reply_back) {
00665     if (!xic) DelayBind();
00666     XSetICValues(xic,
00667                XNPreeditState, XIMPreeditDisable,
00668                0);
00669   }
00670 
00671   ximp_protocol->send_client_message(focus_win,
00672                                  (is_version_40() ?
00673                                   XIMProtocol::XIMP_SPROC_STOPPED4 :
00674                                   XIMProtocol::XIMP_PROCESS_END3),
00675                                  input_context_id,
00676                                  0, 0, 0);
00677   return 0;
00678 }
00679 
00680 Window
00681 XIMPInputContext::focus_window() {return focus_win;}
00682 
00683 Window
00684 XIMPInputContext::client_window() {return client_win;}
00685 
00686 // set IC attributes
00687 void
00688 XIMPInputContext::set_client_window(Window new_win) {
00689   if (client_win != new_win) {
00690     // We may have to unregister only in case of reregistering 
00691     filters &= ~FLT_DESTROY;
00692     unselect_destroy_clientwin_emask();
00693     unregister_clientwin_destroy_filter();
00694     client_win = new_win;
00695     if (xic) {
00696       // client_win might have been set already, but even for
00697       // such cases, we allow to set client_win again.
00698       XSetICValues(xic,
00699                  XNClientWindow, client_win,
00700                  0);
00701       filters &= ~FLT_DESTROY;
00702       select_destroy_clientwin_emask();
00703       register_clientwin_destroy_filter();
00704     }
00705   }
00706   return;
00707 }
00708 void
00709 XIMPInputContext::set_focus_window(Window new_win) {
00710   if (focus_win != new_win) {
00711     filters &= ~FLT_KEYPRESS;
00712     filters &= ~FLT_KEYRELEASE;
00713     filters &= ~FLT_DESTROY;
00714     focus_win = new_win;
00715     select_destroy_emask();
00716     if (ev_flow_type == XIMProtocol::XIMP_FE_TYPE2 ||
00717        ev_flow_type == XIMProtocol::XIMP_FE_TYPE3 ||
00718        (ev_flow_type == XIMProtocol::XIMP_FE_TYPE1 && is_conv_on)) {
00719       select_keypress_emask();
00720       select_keyrelease_emask();
00721     }
00722     // as XIM client
00723     if (!xic) DelayBind();
00724     if (xic)
00725       XSetICValues(xic,
00726                  XNFocusWindow, focus_win,
00727                  0);
00728   }
00729   return;
00730 }
00731 void
00732 XIMPInputContext::set_fwin_select_mask(long mask) {
00733   ev_masks = mask;
00734   return;
00735 }
00736 void
00737 XIMPInputContext::set_preedit_maxlen(unsigned long len) {
00738   preedit_maxlen = len;
00739   return;
00740 }
00741 
00742 void
00743 XIMPInputContext::set_preedit_caret_position(unsigned long pos) {
00744   preedit_caret_position = pos;
00745   return;
00746 }
00747 
00748 void
00749 XIMPInputContext::set_values(XClientMessageEvent *ev) {
00750   unsigned long mask = ev->data.l[2];
00751   if (is_version_40()) {
00752     mask &= ~(XIMP_FOCUS_WIN_MASK4|XIMP_SERVERTYPE_MASK4);
00753   }
00754   get_xicvalues(mask);
00755   return;
00756 }
00757 
00758 void
00759 XIMPInputContext::get_values(XClientMessageEvent *ev) {
00760   unsigned long mask = ev->data.l[2];
00761   set_xicvalues(mask);
00762   return;
00763 }
00764 
00765 void
00766 XIMPInputContext::set_match(int kcode, int state) {
00767   og_code = kcode; og_state = state;
00768   return;
00769 }
00770 
00771 Bool
00772 XIMPInputContext::process_match(int kcode, int state) {
00773   if (og_code == kcode && og_state == state) {
00774     return True;
00775   }
00776   return False;
00777 }
00778 
00779 Bool
00780 XIMPInputContext::
00781 get_xicvalues(unsigned long &u_mask) {
00782 
00783   long mask = (long)u_mask;
00784   if (is_version_40()) {
00785     if (mask & XIMP_FOCUS_WIN_MASK4) {
00786       if (get_focus_win())
00787        attr_mask |= XIMP_FOCUS_WIN_MASK4;
00788       else
00789        return False;
00790     }
00791     if (mask & XIMP_PRE_FONT_MASK4) {
00792       if (get_preedit_font())
00793        attr_mask |= XIMP_PRE_FONT_MASK4;
00794       else
00795        return False;
00796     }
00797     if (mask & XIMP_STS_FONT_MASK4) {
00798       if (get_status_font())
00799        attr_mask |= XIMP_STS_FONT_MASK4;
00800       else
00801        return False;
00802     }
00803     if (mask & PREEDIT_MASK4) {
00804       if (get_preedit4(mask))
00805        attr_mask |= mask & PREEDIT_MASK4;
00806       else
00807        return False;
00808     }
00809     if (mask & STATUS_MASK4) {
00810       if (get_status4(mask))
00811        attr_mask |= mask & STATUS_MASK4;
00812       else
00813        return False;
00814     }
00815     if (mask & XIMP_SERVERTYPE_MASK4) {
00816       if (get_server_type4())
00817        attr_mask |= mask & XIMP_SERVERTYPE_MASK4;
00818       else
00819        return False;
00820     }
00821   } else {
00822     if (mask & XIMP_FOCUS_WIN_MASK3) {
00823       if (get_focus_win())
00824        attr_mask |= XIMP_FOCUS_WIN_MASK3;
00825       else
00826        return False;
00827     }
00828     if (mask & XIMP_PRE_FONT_MASK3) {
00829       if (get_preedit_font())
00830        attr_mask |= XIMP_PRE_FONT_MASK3;
00831       else
00832        return False;
00833     }
00834     if (mask & XIMP_STS_FONT_MASK3) {
00835       if (get_status_font())
00836        attr_mask |= XIMP_STS_FONT_MASK3;
00837       else
00838        return False;
00839     }
00840     if (mask & PREEDIT_MASK3) {
00841       if (get_preedit3(mask))
00842        attr_mask |= mask & PREEDIT_MASK3;
00843       else
00844        return False;
00845     }
00846     if (mask & STATUS_MASK3) {
00847       if (get_status3(mask))
00848        attr_mask |= mask & STATUS_MASK3;
00849       else
00850        return False;
00851     }
00852   }
00853   return True;
00854 }
00855 
00856 Bool
00857 XIMPInputContext::
00858 get_focus_win() {
00859   Window new_focus_win;
00860   if (!ximp_protocol->get_focus_window(client_win,
00861                                    new_focus_win)) {
00862     return False;
00863   }
00864   set_focus_window(new_focus_win);
00865   return True;
00866 }
00867 
00868 Bool
00869 XIMPInputContext::
00870 get_preedit4(unsigned long mask) {
00871   if (!ximp_protocol->get_preedit4(client_win,
00872                                preedit_attr4)) {
00873     return False;
00874   }
00875   if (mask & XIMP_PRE_SPOTL_MASK4) {
00876     set_preedit_spot_location(preedit_attr4.spot_location.x,
00877                            preedit_attr4.spot_location.y);
00878   }
00879   if (mask & XIMP_PRE_AREA_MASK4) {
00880     set_preedit_area(preedit_attr4.area.x, preedit_attr4.area.y,
00881                    preedit_attr4.area.width, preedit_attr4.area.height);
00882   }
00883   if (mask & XIMP_PRE_AREANEED_MASK4) {
00884     set_preedit_area_needed(preedit_attr4.area_needed.width,
00885                          preedit_attr4.area_needed.height);
00886   } else if (preedit_attr4.area_needed.width == 0 ||
00887             preedit_attr4.area_needed.height == 0) {
00888     // the values was reset, so need to restore
00889     set_preedit_area_needed(preedit_attr4.area_needed.width,
00890                          preedit_attr4.area_needed.height);
00891   }
00892   if (mask & XIMP_PRE_COLORMAP_MASK4) {
00893     set_preedit_colormap(preedit_attr4.colormap);
00894   }
00895   if (mask & XIMP_PRE_FG_MASK4) {
00896     set_preedit_fg(preedit_attr4.foreground);
00897   }
00898   if (mask & XIMP_PRE_BG_MASK4) {
00899     set_preedit_bg(preedit_attr4.background);
00900   }
00901   if (mask & XIMP_PRE_BGPIXMAP_MASK4) {
00902     set_preedit_bg_pixmap(preedit_attr4.bg_pixmap);
00903   }
00904   if (mask & XIMP_PRE_LINESP_MASK4) {
00905     set_preedit_line_spacing(preedit_attr4.line_spacing);
00906   }
00907   if (mask & XIMP_PRE_CURSOR_MASK4) {
00908     set_preedit_cursor(preedit_attr4.cursor);
00909   }
00910   return True;
00911 }
00912 
00913 Bool
00914 XIMPInputContext::
00915 get_status4(unsigned long mask) {
00916   if (!ximp_protocol->get_status4(client_win,
00917                               status_attr4)) {
00918     return False;
00919   }
00920   if (mask & XIMP_STS_AREA_MASK4) {
00921     set_status_area(status_attr4.area.x, status_attr4.area.y,
00922                   status_attr4.area.width, status_attr4.area.height);
00923   }
00924   if (mask & XIMP_STS_AREANEED_MASK4) {
00925     set_status_area_needed(status_attr4.area_needed.width,
00926                         status_attr4.area_needed.height);
00927   } else if (status_attr4.area_needed.width == 0 ||
00928             status_attr4.area_needed.height == 0) {
00929     // the values was reset, so need to restore
00930     set_status_area_needed(status_attr4.area_needed.width,
00931                         status_attr4.area_needed.height);
00932   }
00933   if (mask & XIMP_STS_COLORMAP_MASK4) {
00934     set_status_colormap(status_attr4.colormap);
00935   }
00936   if (mask & XIMP_STS_FG_MASK4) {
00937     set_status_fg(status_attr4.foreground);
00938   }
00939   if (mask & XIMP_STS_BG_MASK4) {
00940     set_status_bg(status_attr4.background);
00941   }
00942   if (mask & XIMP_STS_BGPIXMAP_MASK4) {
00943     set_status_bg_pixmap(status_attr4.bg_pixmap);
00944   }
00945   if (mask & XIMP_STS_LINESP_MASK4) {
00946     set_status_line_spacing(status_attr4.line_spacing);
00947   }
00948   if (mask & XIMP_STS_CURSOR_MASK4) {
00949     set_status_cursor(status_attr4.cursor);
00950   }
00951   return True;
00952 }
00953 
00954 Bool
00955 XIMPInputContext::
00956 get_server_type4() {
00957   unsigned long ximp_type_mask;
00958   if (!ximp_protocol->get_server_type4(client_win,
00959                                    ximp_type_mask)) {
00960     return False;
00961   }
00962   ev_flow_type = ximp_type_mask;
00963   return True;
00964 }
00965 
00966 Bool
00967 XIMPInputContext::
00968 get_preedit3(unsigned long mask) {
00969   Ximp_PreeditPropRec3 preedit_attr3;
00970   if (!ximp_protocol->get_preedit3(client_win,
00971                                preedit_attr3)) {
00972     return False;
00973   }
00974   if (mask & XIMP_PRE_AREA_MASK3) {
00975     preedit_attr4.area.x = preedit_attr3.area.x;
00976     preedit_attr4.area.y = preedit_attr3.area.y;
00977     preedit_attr4.area.width = preedit_attr3.area.width;
00978     preedit_attr4.area.height = preedit_attr3.area.height;
00979     set_preedit_area(preedit_attr4.area.x, preedit_attr4.area.y,
00980                    preedit_attr4.area.width, preedit_attr4.area.height);
00981   }
00982   if (mask & XIMP_PRE_AREANEED_MASK3) {
00983     preedit_attr4.area_needed.width = preedit_attr3.area_needed.width;
00984     preedit_attr4.area_needed.height = preedit_attr3.area_needed.height;
00985     set_preedit_area_needed(preedit_attr4.area_needed.width,
00986                          preedit_attr4.area_needed.height);
00987   }
00988 
00989   if (mask & XIMP_PRE_SPOTL_MASK3) {
00990     preedit_attr4.spot_location.x = preedit_attr3.spot_location.x;
00991     preedit_attr4.spot_location.y = preedit_attr3.spot_location.y;
00992     set_preedit_spot_location(preedit_attr4.spot_location.x,
00993                            preedit_attr4.spot_location.y);
00994   }
00995 
00996   if (mask & XIMP_PRE_COLORMAP_MASK3) {
00997     preedit_attr4.colormap = preedit_attr3.colormap;
00998     set_preedit_colormap(preedit_attr4.colormap);
00999   }
01000 
01001   if (mask & XIMP_PRE_FG_MASK3) {
01002     preedit_attr4.foreground = preedit_attr3.foreground;
01003     set_preedit_fg(preedit_attr4.foreground);
01004   }
01005 
01006   if (mask & XIMP_PRE_BG_MASK3) {
01007     preedit_attr4.background = preedit_attr3.background;
01008     set_preedit_bg(preedit_attr4.background);
01009   }
01010 
01011   if (mask & XIMP_PRE_BGPIXMAP_MASK3) {
01012     preedit_attr4.bg_pixmap = preedit_attr3.bg_pixmap;
01013     set_preedit_bg_pixmap(preedit_attr4.bg_pixmap);
01014   }
01015 
01016   if (mask & XIMP_PRE_LINESP_MASK3) {
01017     preedit_attr4.line_spacing = preedit_attr3.line_spacing;
01018     set_preedit_line_spacing(preedit_attr4.line_spacing);
01019   }
01020 
01021   if (mask & XIMP_PRE_CURSOR_MASK3) {
01022     preedit_attr4.cursor = preedit_attr3.cursor;
01023     set_preedit_cursor(preedit_attr4.cursor);
01024   }
01025 
01026   return True;
01027 }
01028 
01029 Bool
01030 XIMPInputContext::
01031 get_status3(unsigned long mask) {
01032   Ximp_StatusPropRec3 status_attr3;
01033   if (!ximp_protocol->get_status3(client_win,
01034                               status_attr3)) {
01035     return False;
01036   }
01037   if (mask & XIMP_STS_AREA_MASK3) {
01038     status_attr4.area.x = status_attr3.area.x;
01039     status_attr4.area.y = status_attr3.area.y;
01040     status_attr4.area.width = status_attr3.area.width;
01041     status_attr4.area.height = status_attr3.area.height;
01042     set_status_area(status_attr4.area.x, status_attr4.area.y,
01043                   status_attr4.area.width, status_attr4.area.height);
01044   }
01045 
01046   if (mask & XIMP_STS_AREANEED_MASK3) {
01047     status_attr4.area_needed.width = status_attr3.area_needed.width;
01048     status_attr4.area_needed.height = status_attr3.area_needed.height;
01049     set_status_area_needed(status_attr4.area_needed.width,
01050                         status_attr4.area_needed.height);
01051   }
01052 
01053   if (mask & XIMP_STS_COLORMAP_MASK3) {
01054     status_attr4.colormap = status_attr3.colormap;
01055     set_status_colormap(status_attr4.colormap);
01056   }
01057 
01058   if (mask & XIMP_STS_FG_MASK3) {
01059     status_attr4.foreground = status_attr3.foreground;
01060     set_status_fg(status_attr3.foreground);
01061   }
01062 
01063   if (mask & XIMP_STS_BG_MASK3) {
01064     status_attr4.background = status_attr3.background;
01065     set_status_bg(status_attr3.background);
01066   }
01067 
01068   if (mask & XIMP_STS_BGPIXMAP_MASK3) {
01069     status_attr4.bg_pixmap = status_attr3.bg_pixmap;
01070     set_status_bg_pixmap(status_attr4.bg_pixmap);
01071   }
01072 
01073   if (mask & XIMP_STS_LINESP_MASK3) {
01074     status_attr4.line_spacing = status_attr3.line_spacing;
01075     set_status_line_spacing(status_attr4.line_spacing);
01076   }
01077 
01078   if (mask & XIMP_STS_CURSOR_MASK3) {
01079     status_attr4.cursor = status_attr3.cursor;
01080     set_status_cursor(status_attr4.cursor);
01081   }
01082   return True;
01083 }
01084 
01085 Bool
01086 XIMPInputContext::
01087 set_xicvalues(unsigned long &u_mask) {
01088 
01089   long mask = (long)u_mask;
01090   if (is_version_40()) {
01091     if (mask & XIMP_FOCUS_WIN_MASK4) {
01092       if (set_focus_win())
01093        attr_mask |= XIMP_FOCUS_WIN_MASK4;
01094       else
01095        return False;
01096     }
01097     if (mask & XIMP_PRE_FONT_MASK4) {
01098       if (set_preedit_font())
01099        attr_mask |= XIMP_PRE_FONT_MASK4;
01100       else
01101        return False;
01102     }
01103     if (mask & XIMP_STS_FONT_MASK4) {
01104       if (set_status_font())
01105        attr_mask |= XIMP_STS_FONT_MASK4;
01106       else
01107        return False;
01108     }
01109     if (mask & PREEDIT_MASK4) {
01110       if (set_preedit4())
01111        attr_mask |= mask & PREEDIT_MASK4;
01112       else
01113        return False;
01114     }
01115     if (mask & STATUS_MASK4) {
01116       if (set_status4())
01117        attr_mask |= mask & STATUS_MASK4;
01118       else
01119        return False;
01120     }
01121     if (mask & XIMP_SERVERTYPE_MASK4) {
01122       if (set_server_type4())
01123        attr_mask |= mask & XIMP_SERVERTYPE_MASK4;
01124       else
01125        return False;
01126     }
01127   } else {
01128     if (mask & XIMP_FOCUS_WIN_MASK3) {
01129       if (set_focus_win())
01130        attr_mask |= XIMP_FOCUS_WIN_MASK3;
01131       else
01132        return False;
01133     }
01134     if (mask & XIMP_PRE_FONT_MASK3) {
01135       if (set_preedit_font())
01136        attr_mask |= XIMP_PRE_FONT_MASK3;
01137       else
01138        return False;
01139     }
01140     if (mask & XIMP_STS_FONT_MASK3) {
01141       if (set_status_font())
01142        attr_mask |= XIMP_STS_FONT_MASK3;
01143       else
01144        return False;
01145     }
01146     if (mask & PREEDIT_MASK3) {
01147       if (set_preedit3())
01148        attr_mask |= mask & PREEDIT_MASK3;
01149       else
01150        return False;
01151     }
01152     if (mask & STATUS_MASK3) {
01153       if (set_status3())
01154        attr_mask |= mask & STATUS_MASK3;
01155       else
01156        return False;
01157     }
01158   }
01159   return True;
01160 }
01161 
01162 Bool
01163 XIMPInputContext::set_focus_win() {
01164   if (!ximp_protocol->set_focus_window(client_win,
01165                                    focus_win)) {
01166     return False;
01167   }
01168   return True;
01169 }
01170 
01171 Bool
01172 XIMPInputContext::set_preedit_font() {
01173   if (!ximp_protocol->set_preedit_font(client_win,
01174                                    preedit_fontname)) {
01175     return False;
01176   }
01177   return True;
01178 }
01179 
01180 Bool
01181 XIMPInputContext::set_status_font() {
01182   if (!ximp_protocol->set_status_font(client_win,
01183                                   status_fontname)) {
01184     return False;
01185   }
01186   return True;
01187 }
01188 
01189 Bool
01190 XIMPInputContext::set_preedit4() {
01191   // check area needed width/height to see if 0
01192 #if 0
01193   const int MIN_PREEDIT_CHARNUM = 20;
01194 #endif
01195   if (!ximp_protocol->set_preedit4(client_win,
01196                                preedit_attr4)) {
01197     return False;
01198   }
01199   return True;
01200 }
01201 
01202 Bool
01203 XIMPInputContext::set_status4() {
01204   // check area needed width/height to see if 0
01205   if (!ximp_protocol->set_status4(client_win,
01206                               status_attr4)) {
01207     return False;
01208   }
01209   return True;
01210 }
01211 
01212 Bool
01213 XIMPInputContext::set_server_type4() {
01214   if (!ximp_protocol->set_server_type4(client_win,
01215                                    ev_flow_type)) {
01216     return False;
01217   }
01218   return True;
01219 }
01220 
01221 Bool
01222 XIMPInputContext::set_preedit3() {
01223   // check area needed width/height to see if 0
01224 #if 0
01225   const int MIN_PREEDIT_CHARNUM = 20; 
01226 #endif
01227   Ximp_PreeditPropRec3 preedit_attr3;
01228   preedit_attr3.area.x = preedit_attr4.area.x;
01229   preedit_attr3.area.y = preedit_attr4.area.y;
01230   preedit_attr3.area.width = preedit_attr4.area.width;
01231   preedit_attr3.area.height = preedit_attr4.area.height;
01232   preedit_attr3.area_needed.width = preedit_attr4.area_needed.width;
01233   preedit_attr3.area_needed.height = preedit_attr4.area_needed.height;
01234   preedit_attr3.spot_location.x = preedit_attr4.spot_location.x;
01235   preedit_attr3.spot_location.y = preedit_attr4.spot_location.y;
01236   preedit_attr3.colormap = preedit_attr4.colormap;
01237   preedit_attr3.foreground = preedit_attr4.foreground;
01238   preedit_attr3.background = preedit_attr4.background;
01239   preedit_attr3.bg_pixmap = preedit_attr4.bg_pixmap;
01240   preedit_attr3.line_spacing = preedit_attr4.line_spacing;
01241   preedit_attr3.cursor = preedit_attr4.cursor;
01242   if (!ximp_protocol->set_preedit3(client_win,
01243                                preedit_attr3)) {
01244     return False;
01245   }
01246   return True;
01247 }
01248 
01249 Bool
01250 XIMPInputContext::set_status3() {
01251   // check area needed width/height to see if 0
01252   Ximp_StatusPropRec3 status_attr3;
01253   status_attr3.area.x = status_attr4.area.x;
01254   status_attr3.area.y = status_attr4.area.y;
01255   status_attr3.area.width = status_attr4.area.width;
01256   status_attr3.area.height = status_attr4.area.height;
01257   status_attr3.area_needed.width = status_attr4.area_needed.width;
01258   status_attr3.area_needed.height = status_attr4.area_needed.height;
01259   status_attr3.colormap = status_attr4.colormap;
01260   status_attr3.foreground = status_attr4.foreground;
01261   status_attr3.background = status_attr4.background;
01262   status_attr3.bg_pixmap = status_attr4.bg_pixmap;
01263   status_attr3.line_spacing = status_attr4.line_spacing;
01264   status_attr3.cursor = status_attr4.cursor;
01265   if (!ximp_protocol->set_status3(client_win,
01266                               status_attr3)) {
01267     return False;
01268   }
01269   return True;
01270 }
01271 
01272 Bool
01273 XIMPInputContext::destroy_clientwin_filter(Display *display,
01274                                       Window win, XEvent *ev,
01275                                       XPointer client_data) {
01276   XIMPInputContext *ic = (XIMPInputContext*)client_data;
01277   ic->unregister_clientwin_destroy_filter();
01278   // client_window is destroyed, so xic is no longer valid
01279   if (ic->xic) {
01280     ic->destroy_xic();
01281     return True;
01282   }
01283   return False;
01284 }
01285 
01286 void
01287 XIMPInputContext::register_clientwin_destroy_filter() {
01288 #if 0
01289   XFactory::register_filter(dpy, client_win,
01290                          DestroyNotify, DestroyNotify,
01291                          destroy_clientwin_filter, (XPointer)this);
01292 #endif
01293 }
01294 void
01295 XIMPInputContext::unregister_clientwin_destroy_filter() {
01296 #if 0
01297   XFactory::unregister_filter(dpy, client_win,
01298                            destroy_clientwin_filter, (XPointer)this);
01299 #endif
01300 }
01301 
01302 void
01303 XIMPInputContext::unselect_destroy_emask() {
01304   if (filters & FLT_DESTROY) {
01305     ximp_protocol->unselect_destroy_emask(focus_win);
01306     filters &= ~FLT_DESTROY;
01307   }
01308 }
01309 
01310 void
01311 XIMPInputContext::unselect_destroy_clientwin_emask() {
01312   if (filters & FLT_DESTROY) {
01313     ximp_protocol->unselect_destroy_emask(client_win);
01314     filters &= ~FLT_DESTROY;
01315   }
01316 }
01317 
01318 void
01319 XIMPInputContext::unselect_keypress_emask() {
01320   if (filters & FLT_KEYPRESS) {
01321     ximp_protocol->unselect_keypress_emask(focus_win);
01322     filters &= ~FLT_KEYPRESS;
01323   }
01324 }
01325 void
01326 XIMPInputContext::unselect_keyrelease_emask() {
01327   if (filters & FLT_KEYRELEASE) {
01328     ximp_protocol->unselect_keyrelease_emask(focus_win);
01329     filters &= ~FLT_KEYRELEASE;
01330   }
01331 }
01332 
01333 void
01334 XIMPInputContext::select_destroy_emask() {
01335   if (!(filters & FLT_DESTROY)) {
01336     ximp_protocol->select_destroy_emask(focus_win);
01337     filters |= FLT_DESTROY;
01338   }
01339 }
01340 
01341 void
01342 XIMPInputContext::select_destroy_clientwin_emask() {
01343   if (!(filters & FLT_DESTROY)) {
01344     ximp_protocol->select_destroy_emask(client_win);
01345     filters |= FLT_DESTROY;
01346   }
01347 }
01348 
01349 void
01350 XIMPInputContext::select_keypress_emask() {
01351   if (!(filters & FLT_KEYPRESS)) {
01352     ximp_protocol->select_keypress_emask(focus_win);
01353     filters |= FLT_KEYPRESS;
01354   }
01355 }
01356 void
01357 XIMPInputContext::select_keyrelease_emask() {
01358   if (!(filters & FLT_KEYRELEASE)) {
01359     ximp_protocol->select_keyrelease_emask(focus_win);
01360     filters |= FLT_KEYRELEASE;
01361   }
01362 }
01363 
01364 // backward compativility
01365 int
01366 XIMPInputContext::forward_xevent(XEvent *event) {
01367   int input_context_id = ximp_protocol->getICID(this);
01368   switch (event->type) {
01369   case KeyPress:
01370     ximp_protocol->send_client_message(focus_win,
01371                                    (is_version_40() ?
01372                                    XIMProtocol::XIMP_KEYPRESS4 :
01373                                    XIMProtocol::XIMP_KEYPRESS3),
01374                                    input_context_id,
01375                                    event->xkey.keycode,
01376                                    event->xkey.state,
01377                                    (is_version_40() ?
01378                                    event->xkey.time : 0));
01379     if (is_version_40()) {
01380       set_match(event->xkey.keycode, event->xkey.state);
01381     }
01382     break;
01383   case KeyRelease:
01384     if (process_match(event->xkey.keycode, event->xkey.state)) {
01385       ximp_protocol->send_client_message(focus_win,
01386                              XIMProtocol::XIMP_KEYRELEASE4,
01387                              input_context_id,
01388                              event->xkey.keycode,
01389                              event->xkey.state,
01390                              event->xkey.time);
01391     }
01392     break;
01393   }
01394   return True;
01395 }
01396 
01397 int
01398 XIMPInputContext::commit_string(char *text) {
01399   int input_context_id = ximp_protocol->getICID(this);
01400   int length = strlen(text);
01401 
01402   if (length > 20) {
01403     Atom atom = ximp_protocol->set_ctext_property((unsigned char*)text ,
01404                                             length, True);
01405     ximp_protocol->send_client_message(focus_win,
01406                                    (is_version_40() ?
01407                                    XIMProtocol::XIMP_READPROP4 :
01408                                    XIMProtocol::XIMP_READPROP3),
01409                                    input_context_id,
01410                                    atom, 0, 0);
01411   } else {
01412     ximp_protocol->commit_by_client_message(focus_win,
01413                                        input_context_id,
01414                                        text, length);
01415   }
01416   return True;
01417 }
01418 
01419 int
01420 XIMPInputContext::preedit_draw(XIMPreeditDrawCallbackStruct *draw) {
01421   int input_context_id = ximp_protocol->getICID(this);
01422   int length;
01423 
01424   if (!(inputstyle & XIMPreeditCallbacks)) {
01425     return True;
01426   }
01427   
01428   if (draw->text) {
01429     length = strlen((char*)draw->text->string.multi_byte);
01430   } else {
01431     length = 0;
01432   }
01433 
01434   if (length <= COMMIT_CMSG_MAX) {
01435     /* send by client message */
01436     preedit_draw_by_cm(draw);
01437   } else {
01438     Atom atom1, atom2, atom3;
01439     CARD32 l[3];
01440     char *ctext;
01441     CARD32 *feedback;
01442     int n;
01443 
01444     l[0] = draw->caret; l[1] = draw->chg_first; l[2] = draw->chg_length;
01445     atom1 = ximp_protocol->set_preedit_draw_data_property((unsigned char*)l,
01446                                                    3);
01447 
01448     if (draw->text) {
01449       ctext = draw->text->string.multi_byte;
01450       atom2 = ximp_protocol->set_ctext_property((unsigned char*)ctext,
01451                                           length);
01452     } else {
01453       atom2 = ximp_protocol->set_ctext_property((unsigned char*)0,
01454                                           0);
01455     }
01456 
01457     if (draw->text) {
01458       feedback = draw->text->feedback;
01459       for (n = 0; (feedback[n] != 0) && (n < draw->text->length); n++) ;
01460       atom3 = ximp_protocol->set_feedback_property((unsigned char*)feedback,
01461                                              n);
01462     } else {
01463       atom3 = ximp_protocol->set_feedback_property((unsigned char*)0, 0);
01464     }
01465     ximp_protocol->send_client_message(focus_win,
01466                                    (is_version_40() ?
01467                                    XIMProtocol::XIMP_PREEDITDRAW4 :
01468                                    XIMProtocol::XIMP_PREEDITDRAW3),
01469                                    input_context_id,
01470                                    atom1, atom2, atom3);
01471   }
01472   return True;
01473 }
01474 
01475 int
01476 XIMPInputContext::preedit_draw_feedback(XIMPreeditDrawCallbackStruct *draw) {
01477   CARD32 l[5];
01478   int count;
01479   int length = draw->text->length;
01480   int chg_first = draw->chg_first;
01481   XIMFeedback *feedback = draw->text->feedback;
01482   XIMFeedback  first_feedback;
01483   int input_context_id = ximp_protocol->getICID(this);
01484 
01485   first_feedback = *feedback;
01486   l[0] = XIMProtocol::XIMP_PREEDITDRAW_CM_FEEDBACK4;
01487   l[1] = input_context_id;
01488   l[2] = chg_first << 24;
01489   l[3] = (unsigned long)first_feedback;
01490   for (count = 0; ((count < length ) && (*feedback == first_feedback));
01491        count++, chg_first++, feedback++)
01492     ;
01493 
01494   l[2] |= count << 16;
01495   if (count < length) {
01496     l[2] |= chg_first << 8;
01497     l[2] |= length - count;
01498     l[4] = (unsigned long)*feedback;
01499   } else {
01500     l[2] |= 0xffff;
01501   }
01502   ximp_protocol->send_client_message(focus_win,
01503                                  l[0], l[1], l[2], l[3], l[4]);
01504   return True;
01505 }
01506 
01507 int
01508 XIMPInputContext::preedit_draw_tiny(XIMPreeditDrawCallbackStruct *draw) {
01509   CARD32 l[5];
01510   char *text = (char *)&l[3];
01511   int ct_length = strlen(draw->text->string.multi_byte);
01512   int input_context_id = ximp_protocol->getICID(this);
01513 
01514   l[0] = XIMProtocol::XIMP_PREEDITDRAW_CM_TINY4;
01515   l[1] = input_context_id;
01516   l[2] = ct_length;
01517   l[2] |= draw->chg_length << 8;
01518   l[2] |= draw->chg_first << 16;
01519   memmove(text, draw->text->string.multi_byte, ct_length); // l[3]-l[4]
01520   ximp_protocol->send_client_message(focus_win,
01521                                  l[0], l[1], l[2], l[3], l[4]);
01522   return True;
01523 }
01524 
01525 int
01526 XIMPInputContext::preedit_caret(XIMPreeditCaretCallbackStruct *caret) {
01527   int input_context_id = ximp_protocol->getICID(this);
01528 
01529   ximp_protocol->send_client_message(focus_win,
01530                                  (is_version_40() ?
01531                                   XIMProtocol::XIMP_PREEDITCARET4 :
01532                                   XIMProtocol::XIMP_PREEDITCARET3),
01533                                  input_context_id,
01534                                  caret->position,
01535                                  caret->direction,
01536                                  caret->style);
01537   return True;
01538 }
01539 
01540 int
01541 XIMPInputContext::status_draw(XIMStatusDrawCallbackStruct *draw) {
01542   int input_context_id = ximp_protocol->getICID(this);
01543   Atom atom1, atom2;
01544   char *ctext;
01545   CARD32 *feedback;
01546   int len;
01547   int n;
01548 
01549   switch (draw->type) {
01550   case XIMTextType:
01551     ctext = draw->data.text->string.multi_byte;
01552     len = strlen(draw->data.text->string.multi_byte);
01553     atom1 = ximp_protocol->set_ctext_property((unsigned char*)ctext, len);
01554 
01555     feedback = draw->data.text->feedback;
01556     for (n = 0;
01557         draw->data.text->feedback[n] != 0 && n < draw->data.text->length;
01558         n++) ;
01559     atom2 = ximp_protocol->set_feedback_property((unsigned char*)feedback,
01560                                            n);
01561 
01562     ximp_protocol->send_client_message(focus_win,
01563                                    (is_version_40() ?
01564                                    XIMProtocol::XIMP_STATUSDRAW4 :
01565                                    XIMProtocol::XIMP_STATUSDRAW3),
01566                                    input_context_id,
01567                                    XIMTextType, atom1, atom2);
01568     break;
01569   case XIMBitmapType:
01570     ximp_protocol->send_client_message(focus_win,
01571                                    (is_version_40() ?
01572                                    XIMProtocol::XIMP_STATUSDRAW4 :
01573                                    XIMProtocol::XIMP_STATUSDRAW3),
01574                                    input_context_id,
01575                                    XIMBitmapType,
01576                                    (CARD32)draw->data.bitmap, 0);
01577     break;
01578   }
01579   return True;
01580 }
01581 
01582 int
01583 XIMPInputContext::preedit_draw_by_cm(XIMPreeditDrawCallbackStruct *draw) {
01584   CARD32 l[5];
01585   int chg_count;
01586   int chg_first = draw->chg_first;
01587   int chg_length = draw->chg_length;
01588   int i;
01589   int input_context_id = ximp_protocol->getICID(this);
01590   XIMFeedback first_feedback;
01591   XIMFeedback *feedback;
01592   int size;
01593 
01594   l[0] = (is_version_40() ?
01595          XIMProtocol::XIMP_PREEDITDRAW_CM4 :
01596          XIMProtocol::XIMP_PREEDITDRAW_CM3);
01597   l[1] = input_context_id;
01598   l[2] = (unsigned long)draw->caret;
01599 
01600   if (!draw->text) {
01601     l[2] |= (XIMP_PDCBSTATUS_NOTEXT | XIMP_PDCBSTATUS_NOFEEDBACK) << 16;
01602     l[3] = chg_length;
01603     l[3] |= chg_first << 16;
01604     l[4]  = 0;
01605   } else if (!draw->text->feedback) {
01606 #ifdef USE_PREEDITDRAW_TINY
01607     cont int PREEDITDRAW_TINY_SIZE = 8;
01608     if (draw->text->length < PREEDITDRAW_TINY_SIZE) {
01609       return preedit_draw_tiny(draw);
01610     }
01611 #endif /* USE_PREEDITDRAW_TINY */
01612     l[2] |= XIMP_PDCBSTATUS_NOFEEDBACK << 16;
01613     l[3]  = chg_length;
01614     l[3] |= chg_first << 16;
01615     l[4]  = 0;
01616   } else if (!draw->text->string.wide_char) {
01617 #ifdef USE_PREEDITDRAW_FEEDBACK
01618     chg_count = 0;
01619     first_feedback = *draw->text->feedback;
01620     for (i = 0, feedback = draw->text->feedback;
01621         i < draw->text->length; i++, feedback++) {
01622       if (first_feedback != *feedback) {
01623        chg_count++;
01624        first_feedback = *feedback;
01625       }
01626     }
01627 #endif /* USE_PREEDITDRAW_FEEDBACK */
01628     if (is_version_40()) {
01629 #ifdef USE_PREEDITDRAW_FEEDBACK
01630       if (chg_count < 2) {
01631        return preedit_draw_feedback(draw);
01632       } else {
01633 #endif /* USE_PREEDITDRAW_FEEDBACK */
01634        l[2] |= (XIMP_PDCBSTATUS_FEEDBACKS_VIA_PROP
01635                | XIMP_PDCBSTATUS_NOTEXT ) << 16;
01636        l[3] = chg_length;
01637        l[3] |= chg_first << 16;
01638        l[4] = ximp_protocol->replace_prop_pool((unsigned char *)draw->text->feedback,
01639                                           draw->text->length);
01640 #ifdef USE_PREEDITDRAW_FEEDBACK
01641       }
01642 #endif /* USE_PREEDITDRAW_FEEDBACK */
01643     } else {
01644       l[2] |= XIMP_PDCBSTATUS_NOTEXT << 16;
01645       l[3] = chg_length;
01646       l[3] |= chg_first << 16;
01647       l[4] = *draw->text->feedback;
01648     }
01649   } else {
01650     chg_count = 0;
01651     first_feedback = *draw->text->feedback;
01652     for (i = 0, feedback = draw->text->feedback;
01653         i < (int)draw->text->length; i++, feedback++ ) {
01654       if (first_feedback != *feedback) {
01655        chg_count++;
01656        first_feedback = *feedback;
01657       }
01658     }
01659     if (chg_count == 0) {
01660       l[3] = chg_length;
01661       l[3] |= chg_first << 16;
01662       l[4] = *draw->text->feedback;
01663     } else if (is_version_40()) {
01664       l[2] |= XIMP_PDCBSTATUS_FEEDBACKS_VIA_PROP << 16;
01665       l[3] = chg_length;
01666       l[3] |= chg_first << 16;
01667       l[4] = ximp_protocol->replace_prop_pool((unsigned char *)draw->text->feedback,
01668                                          draw->text->length);
01669     } else {
01670       int first_chg_first = chg_first;
01671       first_feedback = *draw->text->feedback;
01672       size = 0;
01673       for (i = 0, feedback = draw->text->feedback;
01674           i < (int)draw->text->length;
01675           i++, size++, feedback++, chg_first++) {
01676        if (first_feedback != *feedback) {
01677          l[3] = chg_length;
01678          l[3] |= first_chg_first << 16;
01679          l[4] = first_feedback;
01680          first_chg_first = chg_first;
01681          first_feedback = *feedback;
01682          ximp_protocol->send_client_message(focus_win,
01683                                         l[0], l[1], l[2], l[3], l[4]);
01684          const char *text = draw->text->string.multi_byte;
01685          ximp_protocol->commit_by_client_message(focus_win,
01686                                             input_context_id,
01687                                             text, strlen(text));
01688          chg_length = 0;
01689        }
01690       }
01691       l[3]  = chg_length;
01692       l[3] |= first_chg_first << 16;
01693       l[4]  = first_feedback;
01694       first_feedback = *feedback;
01695       ximp_protocol->send_client_message(focus_win,
01696                                     l[0], l[1], l[2], l[3], l[4]);
01697       const char *text = draw->text->string.multi_byte;
01698       ximp_protocol->commit_by_client_message(focus_win,
01699                                          input_context_id,
01700                                          text, strlen(text));
01701       return True;
01702     }
01703   }
01704   ximp_protocol->send_client_message(focus_win,
01705                                  l[0], l[1], l[2], l[3], l[4]);
01706   if (draw->text != NULL && draw->text->string.multi_byte != NULL) {
01707     const char *text = draw->text->string.multi_byte;
01708     ximp_protocol->commit_by_client_message(focus_win,
01709                                        input_context_id,
01710                                        text, strlen(text));
01711   }
01712   return True;
01713 }
01714 
01715 char*
01716 XIMPInputContext::get_commit_string() {
01717   being_reset = False;
01718   return (char*)reset_text;
01719 }
01720 
01721 char*
01722 XIMPInputContext::reset_xic() {
01723   char *ret = NULL;
01724   being_reset = True;
01725   reset_text = "";
01726   if (!xic) DelayBind();
01727   if (xic) 
01728     ret = XmbResetIC(xic);
01729   return ret;
01730 }
01731 void
01732 XIMPInputContext::destroy_xic() {
01733   unregister_clientwin_destroy_filter();
01734   if (xic) XDestroyIC(xic);
01735   xic = 0;
01736 }
01737 void
01738 XIMPInputContext::set_xicfocus() {
01739   if (!xic) DelayBind();
01740   if (xic) XSetICFocus(xic);
01741 }
01742 void
01743 XIMPInputContext::unset_xicfocus() {
01744   if (!xic) DelayBind();
01745   if (xic) XUnsetICFocus(xic);
01746 }
01747 
01748 Bool
01749 XIMPInputContext::is_sync() {
01750   return (ev_flow_type & XIMProtocol::XIMP_SYNC);
01751 }
01752 
01753 int
01754 XIMPInputContext::focus_window(Window &ret) const {
01755   if (!(attr_mask & XIMP_FOCUS_WIN_MASK4)) return False;
01756   ret = focus_win;
01757   return True;
01758 }
01759 
01760 int
01761 XIMPInputContext::client_window(Window &ret) const {
01762   ret = client_win;
01763   return client_win != 0;
01764 }
01765 
01766 Bool
01767 XIMPInputContext::checkAltKey(XClientMessageEvent *ev) {
01768   unsigned int kcode = ev->data.l[2];
01769   unsigned int kstate = ev->data.l[3];
01770 
01771   if (is_version_40()) {
01772     switch (ev_flow_type) {
01773     case XIMProtocol::XIMP_SYNC_BE_TYPE2: // Solaris XIMP support this
01774       return ximp_protocol->isConversionKey(kcode, kstate, is_conv_on);
01775     case XIMProtocol::XIMP_FE_TYPE1:      // Solaris XIMP support this
01776     default:
01777       return False;
01778     }
01779   } else {
01780     return ximp_protocol->isConversionKey(kcode, kstate, is_conv_on);
01781   }
01782 }