Back to index

im-sdk  12.3.91
XInputContext.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 "XInputContext.hh"
00043 #include "XIMPublic.hh"
00044 #include "Xfactory.hh"
00045 #include <string.h>
00046 #include <stdio.h>
00047 #include <stdlib.h>
00048 
00049 extern "C" {
00050   extern int _Xi18nPreeditStartCallback(XIMS, X11R6IMProtocol);
00051   extern int _Xi18nPreeditDrawCallback(XIMS, X11R6IMProtocol);
00052   extern int _Xi18nPreeditCaretCallback(XIMS, X11R6IMProtocol);
00053   extern int _Xi18nPreeditDoneCallback(XIMS, X11R6IMProtocol);
00054   extern int _Xi18nStatusStartCallback(XIMS, X11R6IMProtocol);
00055   extern int _Xi18nStatusDrawCallback(XIMS, X11R6IMProtocol);
00056   extern int _Xi18nStatusDoneCallback(XIMS, X11R6IMProtocol);
00057           }
00058 
00059 XInputContext::XInputContext(XIMPublic *ximp, CARD16 imid,
00060                           int style) {
00061   XIM xim = ximp->getXIM();
00062   client_win = focus_win = 0;
00063   ev_masks = 0;
00064   attr_mask = 0;
00065   is_conv_on = 0;
00066   connect_id = imid;
00067   inputstyle = style;
00068   filters = 0;
00069 
00070   focused = False;
00071 
00072   // for XIMProtocol::reset() can return reset text
00073   being_reset = False;
00074   reset_text = "";
00075 
00076   ximp_protocol = ximp;
00077 
00078   dpy = ximp_protocol->getDisplay();
00079 
00080   if (xim)
00081     xic = XCreateIC(xim,
00082                   XNInputStyle, inputstyle,
00083                   0);
00084   else
00085     abort();
00086 
00087   state_notify_cb = new XIMCallback2;
00088   state_notify_cb->client_data = (char*)this;
00089   state_notify_cb->callback = state_notify_cbproc;
00090 
00091   commit_string_cb = new XIMCallback2;
00092   commit_string_cb->client_data = (char*)this;
00093   commit_string_cb->callback = commit_string_cbproc;
00094 
00095   forward_event_cb = new XIMCallback2;
00096   forward_event_cb->client_data = (char*)this;
00097   forward_event_cb->callback = forward_event_cbproc;
00098 
00099   SetExtensionCallbacks();
00100 
00101   // callback styles?
00102   if (inputstyle & XIMPreeditCallbacks) {
00103     preedit_start_cb = new XIMCallback1;
00104     preedit_start_cb->client_data = (char*)this;
00105     preedit_start_cb->callback = preedit_start_cbproc;
00106 
00107     preedit_draw_cb = new XIMCallback2;
00108     preedit_draw_cb->client_data = (char*)this;
00109     preedit_draw_cb->callback = preedit_draw_cbproc;
00110 
00111     preedit_caret_cb = new XIMCallback2;
00112     preedit_caret_cb->client_data = (char*)this;
00113     preedit_caret_cb->callback = preedit_caret_cbproc;
00114 
00115     preedit_done_cb = new XIMCallback2;
00116     preedit_done_cb->client_data = (char*)this;
00117     preedit_done_cb->callback = preedit_done_cbproc;
00118 
00119     SetPreeditCallbacks();
00120   }
00121   if (inputstyle & XIMStatusCallbacks) {
00122     status_start_cb = new XIMCallback2;
00123     status_start_cb->client_data = (char*)this;
00124     status_start_cb->callback = status_start_cbproc;
00125 
00126     status_draw_cb = new XIMCallback2;
00127     status_draw_cb->client_data = (char*)this;
00128     status_draw_cb->callback = status_draw_cbproc;
00129 
00130     status_done_cb = new XIMCallback2;
00131     status_done_cb->client_data = (char*)this;
00132     status_done_cb->callback = status_done_cbproc;
00133 
00134     SetStatusCallbacks();
00135   }
00136 
00137 }
00138 
00139 XInputContext::~XInputContext() {
00140   delete state_notify_cb;
00141   delete commit_string_cb;
00142   delete forward_event_cb;
00143 
00144   if (inputstyle & XIMPreeditCallbacks) {
00145     delete preedit_start_cb;
00146     delete preedit_draw_cb;
00147     delete preedit_caret_cb;
00148     delete preedit_done_cb;
00149   }
00150   if (inputstyle & XIMStatusCallbacks) {
00151     delete status_start_cb;
00152     delete status_draw_cb;
00153     delete status_done_cb;
00154     delete state_notify_cb;
00155   }
00156 }
00157 
00158 
00159 void
00160 XInputContext::
00161 SetPreeditCallbacks() {
00162   if (xic) {
00163     XVaNestedList preedit_attr = XVaCreateNestedList(0,
00164                           XNPreeditStartCallback, preedit_start_cb,
00165                           XNPreeditDrawCallback, preedit_draw_cb,
00166                           XNPreeditCaretCallback, preedit_caret_cb,
00167                           XNPreeditDoneCallback, preedit_done_cb,
00168                           0);
00169     XSetICValues(xic,
00170                XNPreeditAttributes, preedit_attr,
00171                0);
00172     XFree(preedit_attr);
00173   }
00174   return;
00175 }
00176 
00177 void
00178 XInputContext::
00179 SetStatusCallbacks() {
00180   if (xic) {
00181     XVaNestedList status_attr = XVaCreateNestedList(0,
00182                          XNStatusStartCallback, status_start_cb,
00183                          XNStatusDrawCallback, status_draw_cb,
00184                          XNStatusDoneCallback, status_done_cb,
00185                          0);
00186     XSetICValues(xic,
00187                XNStatusAttributes, status_attr,
00188                0);
00189     XFree(status_attr);
00190   }
00191 }
00192 
00193 void
00194 XInputContext::
00195 SetExtensionCallbacks() {
00196   if (xic)
00197     XSetICValues(xic,
00198                XNPreeditStateNotifyCallback, state_notify_cb,
00199                // private XIC attribute
00200                "commitStringCallback", commit_string_cb,
00201                "forwardEventCallback", forward_event_cb,
00202                0);
00203   return;
00204 }
00205 
00206 // set IC attributes
00207 void
00208 XInputContext::set_client_window(Window new_win) {
00209   if (client_win != new_win) {
00210     filters &= ~FLT_DESTROY;
00211     unselect_destroy_clientwin_emask();
00212     unregister_clientwin_destroy_filter();
00213     client_win = new_win;
00214     if (xic) {
00215       // client_win might have been set already, but even for
00216       // such cases, we allow to set client_win again.
00217       XSetICValues(xic,
00218                  XNClientWindow, client_win,
00219                  0);
00220       filters &= ~FLT_DESTROY;
00221       select_destroy_clientwin_emask();
00222       register_clientwin_destroy_filter();
00223     }
00224   }
00225   return;
00226 }
00227 
00228 Bool
00229 XInputContext::destroy_clientwin_filter(Display *display,
00230                                    Window win, XEvent *ev,
00231                                    XPointer client_data) {
00232   XInputContext *ic = (XInputContext*)client_data;
00233   ic->unregister_clientwin_destroy_filter();
00234   // client_window is destroyed, so xic is no longer valid
00235   if (ic->xic) {
00236     ic->destroy();
00237     return True;
00238   }
00239   return False;
00240 }
00241 
00242 void
00243 XInputContext::register_clientwin_destroy_filter() {
00244   XFactory::register_filter(dpy, client_win,
00245                          DestroyNotify, DestroyNotify,
00246                          destroy_clientwin_filter, (XPointer)this);
00247 }
00248 void
00249 XInputContext::unregister_clientwin_destroy_filter() {
00250   XFactory::unregister_filter(dpy, client_win,
00251                            destroy_clientwin_filter, (XPointer)this);
00252 }
00253 
00254 void
00255 XInputContext::select_destroy_emask() {
00256   if (!(filters & FLT_DESTROY)) {
00257     ximp_protocol->select_destroy_emask(focus_win);
00258     filters |= FLT_DESTROY;
00259   }
00260 }
00261 
00262 void
00263 XInputContext::set_focus_window(Window new_win) {
00264   if (focus_win != new_win) {
00265     filters &= ~FLT_KEYPRESS;
00266     filters &= ~FLT_KEYRELEASE;
00267     filters &= ~FLT_DESTROY;
00268     focus_win = new_win;
00269     select_destroy_emask();
00270 
00271     attr_mask |= XIMP_FOCUS_WIN_MASK4;
00272     // as XIM client
00273     if (xic)
00274       XSetICValues(xic,
00275                  XNFocusWindow, focus_win,
00276                  0);
00277   }
00278   return;
00279 }
00280 
00281 void
00282 XInputContext::select_destroy_clientwin_emask() {
00283   if (!(filters & FLT_DESTROY)) {
00284     ximp_protocol->select_destroy_emask(client_win);
00285     filters |= FLT_DESTROY;
00286   }
00287 }
00288 
00289 void
00290 XInputContext::unselect_destroy_clientwin_emask() {
00291   if (filters & FLT_DESTROY) {
00292     ximp_protocol->unselect_destroy_emask(client_win);
00293     filters &= ~FLT_DESTROY;
00294   }
00295 }
00296 
00297 
00298 void
00299 XInputContext::set_fwin_select_mask(long mask) {
00300   ev_masks = mask;
00301   return;
00302 }
00303 
00304 void
00305 XInputContext::set_focus() {
00306   if (xic) {
00307     XSetICFocus(xic);
00308   }
00309   focused = True;
00310 }
00311 
00312 void
00313 XInputContext::unset_focus() {
00314   if (xic) {
00315     XUnsetICFocus(xic);
00316   }
00317   focused = False;
00318 }
00319 
00320 void
00321 XInputContext::destroy() {
00322   if (xic) {
00323     XDestroyIC(xic);
00324     xic = 0;
00325   }
00326 }
00327 
00328 void
00329 XInputContext::filter_event(XEvent *event) {
00330   /* Forward event doesn't work after commit on kedit */
00331   /*  sometimes focus_win isn't get jusst after Qt start up */
00332   if(focus_win == 0){
00333         focus_win = client_win;
00334         set_focus_window(focus_win);
00335   }
00336   if (event->type == KeyPress || event->type == KeyRelease) {
00337     event->xkey.window = focus_win;
00338   }
00339   if (!XFilterEvent(event, 0)) {
00340     forward_event_cbproc(xic, (XPointer)this, (XPointer)event);
00341   }
00342   return;
00343 }
00344 
00345 char*
00346 XInputContext::reset() {
00347   being_reset = True;
00348   reset_text = "";
00349   if (xic) {
00350     char *mb = XmbResetIC(xic);
00351     if (mb) return mb;
00352   }
00353   if(reset_text) {
00354     return reset_text;
00355   }
00356   return 0;
00357 }
00358 
00359 void
00360 XInputContext::conversion_start(Bool reply_back) {
00361   if (reply_back && xic) {
00362     XSetICValues(xic,
00363                XNPreeditState, XIMPreeditEnable,
00364                0);
00365   }
00366   is_conv_on = 1;
00367 }
00368 
00369 void
00370 XInputContext::conversion_end(Bool reply_back) {
00371   if (reply_back && xic) {
00372     XSetICValues(xic,
00373                XNPreeditState, XIMPreeditDisable,
00374                0);
00375   }
00376   is_conv_on = 0;
00377 }
00378                   
00379 void
00380 XInputContext::set_preedit_spot_location(long x, long y) {
00381   attr_mask |= XIMP_PRE_SPOTL_MASK4;
00382 
00383   preedit_attr4.spot_location.x = x;
00384   preedit_attr4.spot_location.y = y;
00385 
00386   // as XIM client
00387   XVaNestedList preedit_attr;
00388   XPoint spot;
00389   spot.x = x; spot.y = y;
00390   preedit_attr = XVaCreateNestedList(0,
00391                                  XNSpotLocation, &spot,
00392                                  NULL);
00393   if (xic)
00394     XSetICValues(xic,
00395                XNPreeditAttributes, preedit_attr,
00396                0);
00397   XFree(preedit_attr);
00398   return;
00399 }
00400 void
00401 XInputContext::set_preedit_area(long x, long y, unsigned long width,
00402                             unsigned long height) {
00403   attr_mask |= XIMP_PRE_AREA_MASK4;
00404 
00405   preedit_attr4.area.x = x;
00406   preedit_attr4.area.y = y;
00407   preedit_attr4.area.width = width;
00408   preedit_attr4.area.height = height;
00409 
00410   // as XIM client
00411   XVaNestedList preedit_attr;
00412   XRectangle area;
00413   area.x = x; area.y = y; area.width = width; area.height = height;
00414   preedit_attr = XVaCreateNestedList(0,
00415                                  XNArea, &area,
00416                                  NULL);
00417   if (xic)
00418     XSetICValues(xic,
00419                XNPreeditAttributes, preedit_attr,
00420                0);
00421   XFree(preedit_attr);
00422   return;
00423 }
00424 void
00425 XInputContext::set_preedit_area_needed(unsigned long width,
00426                                      unsigned long height) {
00427   attr_mask |= XIMP_PRE_AREANEED_MASK4;
00428 
00429   preedit_attr4.area_needed.width = width;
00430   preedit_attr4.area_needed.height = height;
00431 
00432   // as XIM client
00433   XVaNestedList preedit_attr;
00434   XRectangle area;
00435   area.x = 0; area.y = 0; area.width = width; area.height = height;
00436   preedit_attr = XVaCreateNestedList(0,
00437                                  XNAreaNeeded, &area,
00438                                  NULL);
00439   if (xic)
00440     XSetICValues(xic,
00441                XNPreeditAttributes, preedit_attr,
00442                0);
00443   XFree(preedit_attr);
00444   if (width == 0 || height == 0) {
00445     // do geometry negotiation
00446     XRectangle *area2 = (XRectangle*)0;
00447     preedit_attr = XVaCreateNestedList(0,
00448                                    XNAreaNeeded, &area2,
00449                                    NULL);
00450     if (xic)
00451       XGetICValues(xic,
00452                  XNPreeditAttributes, preedit_attr,
00453                  0);
00454     XFree(preedit_attr);
00455     if (area2) {
00456       if (width == 0) {
00457        preedit_attr4.area_needed.width = area2->width;
00458       }
00459       if (height == 0) {
00460        preedit_attr4.area_needed.height = area2->height;
00461       }
00462       XFree(area2);
00463     }
00464     // fallback to avoid setting 0
00465     if (preedit_attr4.area_needed.width == 0) {
00466       XFontSet font_set = XFactory::create_fontset(dpy, preedit_fontname);
00467       XFontSetExtents *fsx = XExtentsOfFontSet(font_set);
00468       preedit_attr4.area_needed.width = fsx->max_logical_extent.width *10;
00469       XFactory::free_fontset(dpy, font_set);
00470     }
00471     if (preedit_attr4.area_needed.height == 0) {
00472       XFontSet font_set = XFactory::create_fontset(dpy, preedit_fontname);
00473       XFontSetExtents *fsx = XExtentsOfFontSet(font_set);
00474       preedit_attr4.area_needed.height = fsx->max_logical_extent.height;
00475       XFactory::free_fontset(dpy, font_set);
00476     }
00477   }
00478   return;
00479 }
00480 void
00481 XInputContext::set_preedit_colormap(Colormap colormap) {
00482   attr_mask |= XIMP_PRE_COLORMAP_MASK4;
00483 
00484   preedit_attr4.colormap = colormap;
00485 
00486   // as XIM client
00487   XVaNestedList preedit_attr;
00488   preedit_attr = XVaCreateNestedList(0,
00489                                  XNColormap, colormap,
00490                                  NULL);
00491   if (xic)
00492     XSetICValues(xic,
00493                XNPreeditAttributes, preedit_attr,
00494                0);
00495   XFree(preedit_attr);
00496   return;
00497 }
00498 void
00499 XInputContext::set_preedit_bg_pixmap(Pixmap bg_pixmap) {
00500   attr_mask |= XIMP_PRE_BGPIXMAP_MASK4;
00501 
00502   preedit_attr4.bg_pixmap = bg_pixmap;
00503 
00504   // as XIM client
00505   XVaNestedList preedit_attr;
00506   preedit_attr = XVaCreateNestedList(0,
00507                                  XNBackgroundPixmap, bg_pixmap,
00508                                  NULL);
00509   if (xic)
00510     XSetICValues(xic,
00511                XNPreeditAttributes, preedit_attr,
00512                0);
00513   XFree(preedit_attr);
00514 }
00515 void
00516 XInputContext::set_preedit_line_spacing(long line_spacing) {
00517   attr_mask |= XIMP_PRE_LINESP_MASK4;
00518 
00519   preedit_attr4.line_spacing = line_spacing;
00520 
00521   // as XIM client
00522   XVaNestedList preedit_attr;
00523   preedit_attr = XVaCreateNestedList(0,
00524                                  XNLineSpace, line_spacing,
00525                                  NULL);
00526   if (xic)
00527     XSetICValues(xic,
00528                XNPreeditAttributes, preedit_attr,
00529                0);
00530   XFree(preedit_attr);
00531 }
00532 void
00533 XInputContext::set_preedit_cursor(Cursor cursor) {
00534   attr_mask |= XIMP_PRE_CURSOR_MASK4;
00535 
00536   preedit_attr4.cursor = cursor;
00537 
00538   // as XIM client
00539   XVaNestedList preedit_attr;
00540   preedit_attr = XVaCreateNestedList(0,
00541                                  XNCursor, cursor,
00542                                  NULL);
00543   if (xic)
00544     XSetICValues(xic,
00545                XNPreeditAttributes, preedit_attr,
00546                0);
00547   XFree(preedit_attr);
00548 }
00549 void
00550 XInputContext::set_preedit_bg(unsigned long bg) {
00551   attr_mask |= XIMP_PRE_BG_MASK4;
00552 
00553   preedit_attr4.background = bg;
00554 
00555   // as XIM client
00556   XVaNestedList preedit_attr;
00557   preedit_attr = XVaCreateNestedList(0,
00558                                  XNBackground, bg,
00559                                  NULL);
00560   if (xic)
00561     XSetICValues(xic,
00562                XNPreeditAttributes, preedit_attr,
00563                0);
00564   XFree(preedit_attr);
00565 }
00566 void
00567 XInputContext::set_preedit_fg(unsigned long fg) {
00568   attr_mask |= XIMP_PRE_FG_MASK4;
00569 
00570   preedit_attr4.foreground = fg;
00571 
00572   XVaNestedList preedit_attr;
00573   preedit_attr = XVaCreateNestedList(0,
00574                                  XNForeground, fg,
00575                                  NULL);
00576   if (xic)
00577     XSetICValues(xic,
00578                XNPreeditAttributes, preedit_attr,
00579                0);
00580   XFree(preedit_attr);
00581 }
00582 void
00583 XInputContext::set_preedit_fontset(char *fontname) {
00584   attr_mask |= XIMP_PRE_FONT_MASK4;
00585 
00586   preedit_fontname = fontname;
00587 
00588   XVaNestedList preedit_attr;
00589   XFontSet font_set = XFactory::create_fontset(dpy, preedit_fontname);
00590   preedit_attr = XVaCreateNestedList(0,
00591                                  XNFontSet, font_set,
00592                                  NULL);
00593   if (xic)
00594     XSetICValues(xic,
00595                XNPreeditAttributes, preedit_attr,
00596                0);
00597   XFree(preedit_attr);
00598 }
00599 
00600 void
00601 XInputContext::set_status_area(long x, long y, unsigned long width,
00602                               unsigned long height) {
00603   attr_mask |= XIMP_STS_AREA_MASK4;
00604 
00605   status_attr4.area.x = x;
00606   status_attr4.area.y = y;
00607   status_attr4.area.width = width;;
00608   status_attr4.area.height = height;
00609 
00610   // as XIM client
00611   XVaNestedList status_attr;
00612   XRectangle area;
00613   area.x = x; area.y = y; area.width = width; area.height = height;
00614   status_attr = XVaCreateNestedList(0,
00615                                 XNArea, &area,
00616                                 NULL);
00617   if (xic)
00618     XSetICValues(xic,
00619                XNStatusAttributes, status_attr,
00620                0);
00621   XFree(status_attr);
00622   return;
00623 }
00624 void
00625 XInputContext::set_status_area_needed(unsigned long width,
00626                                   unsigned long height) {
00627   attr_mask |= XIMP_STS_AREANEED_MASK4;
00628 
00629   status_attr4.area_needed.width = width;;
00630   status_attr4.area_needed.height = height;
00631 
00632   // as XIM client
00633   XVaNestedList status_attr;
00634   XRectangle area;
00635   area.x = 0; area.y = 0; area.width = width; area.height = height;
00636   status_attr = XVaCreateNestedList(0,
00637                                 XNAreaNeeded, &area,
00638                                 NULL);
00639   if (xic)
00640     XSetICValues(xic,
00641                XNStatusAttributes, status_attr,
00642                0);
00643   XFree(status_attr);
00644   if (width == 0 || height == 0) {
00645     // do geometry negotiation
00646     XRectangle *area2 = (XRectangle*)0;
00647     status_attr = XVaCreateNestedList(0,
00648                                   XNAreaNeeded, &area2,
00649                                   NULL);
00650     if (xic)
00651       XGetICValues(xic,
00652                  XNStatusAttributes, status_attr,
00653                  0);
00654     XFree(status_attr);
00655     if (area2) {
00656       if (width == 0 ||
00657          inputstyle & XIMPreeditArea) {
00658        status_attr4.area_needed.width = area2->width;
00659       }
00660       if (height == 0) {
00661        status_attr4.area_needed.height = area2->height;
00662       }
00663       XFree(area2);
00664     }
00665     // fallback to avoid setting 0
00666     if (status_attr4.area_needed.width == 0) {
00667       XFontSet font_set = XFactory::create_fontset(dpy, status_fontname);
00668       XFontSetExtents *fsx = XExtentsOfFontSet(font_set);
00669       status_attr4.area_needed.width = fsx->max_logical_extent.width *10;
00670       XFactory::free_fontset(dpy, font_set);
00671     }
00672     if (status_attr4.area_needed.height == 0) {
00673       XFontSet font_set = XFactory::create_fontset(dpy, status_fontname);
00674       XFontSetExtents *fsx = XExtentsOfFontSet(font_set);
00675       status_attr4.area_needed.height = fsx->max_logical_extent.height;
00676       XFactory::free_fontset(dpy, font_set);
00677     }
00678   }
00679   return;
00680 }
00681 
00682 void
00683 XInputContext::set_status_colormap(Colormap colormap) {
00684   attr_mask |= XIMP_STS_COLORMAP_MASK4;
00685 
00686   status_attr4.colormap = colormap;
00687 
00688   // as XIM client
00689   XVaNestedList status_attr;
00690   status_attr = XVaCreateNestedList(0,
00691                                 XNColormap, colormap,
00692                                 NULL);
00693   if (xic)
00694     XSetICValues(xic,
00695                XNStatusAttributes, status_attr,
00696                0);
00697   XFree(status_attr);
00698   return;
00699 }
00700 void
00701 XInputContext::set_status_bg(unsigned long bg) {
00702   attr_mask |= XIMP_STS_BG_MASK4;
00703 
00704   status_attr4.background = bg;
00705 
00706   // as XIM client
00707   XVaNestedList status_attr;
00708   status_attr = XVaCreateNestedList(0,
00709                                 XNBackground, bg,
00710                                 NULL);
00711   if (xic)
00712     XSetICValues(xic,
00713                XNStatusAttributes, status_attr,
00714                0);
00715   XFree(status_attr);
00716 }
00717 void
00718 XInputContext::set_status_fg(unsigned long fg) {
00719   attr_mask |= XIMP_STS_FG_MASK4;
00720 
00721   status_attr4.foreground = fg;
00722 
00723   // as XIM client
00724   XVaNestedList status_attr;
00725   status_attr = XVaCreateNestedList(0,
00726                                 XNForeground, fg,
00727                                 NULL);
00728   if (xic)
00729     XSetICValues(xic,
00730                XNStatusAttributes, status_attr,
00731                0);
00732   XFree(status_attr);
00733 }
00734 void
00735 XInputContext::set_status_bg_pixmap(Pixmap bg_pixmap) {
00736   attr_mask |= XIMP_STS_BGPIXMAP_MASK4;
00737 
00738   status_attr4.bg_pixmap = bg_pixmap;
00739 
00740   // as XIM client
00741   XVaNestedList status_attr;
00742   status_attr = XVaCreateNestedList(0,
00743                                 XNBackgroundPixmap, bg_pixmap,
00744                                 NULL);
00745   if (xic)
00746     XSetICValues(xic,
00747                XNStatusAttributes, status_attr,
00748                0);
00749   XFree(status_attr);
00750 }
00751 void
00752 XInputContext::set_status_line_spacing(long line_spacing) {
00753   attr_mask |= XIMP_STS_LINESP_MASK4;
00754 
00755   status_attr4.line_spacing = line_spacing;
00756 
00757   // as XIM client
00758   XVaNestedList status_attr;
00759   status_attr = XVaCreateNestedList(0,
00760                                 XNLineSpace, line_spacing,
00761                                 NULL);
00762   if (xic)
00763     XSetICValues(xic,
00764                XNStatusAttributes, status_attr,
00765                0);
00766   XFree(status_attr);
00767 }
00768 void
00769 XInputContext::set_status_cursor(Cursor cursor) {
00770   attr_mask |= XIMP_STS_CURSOR_MASK4;
00771 
00772   status_attr4.cursor = cursor;
00773 
00774   // as XIM client
00775   XVaNestedList status_attr;
00776   status_attr = XVaCreateNestedList(0,
00777                                 XNCursor, cursor,
00778                                 NULL);
00779   if (xic)
00780     XSetICValues(xic,
00781                XNStatusAttributes, status_attr,
00782                0);
00783   XFree(status_attr);
00784 }
00785 void
00786 XInputContext::set_status_fontset(char *fontname) {
00787   attr_mask |= XIMP_STS_FONT_MASK4;
00788 
00789   status_fontname = fontname;
00790 
00791   XVaNestedList status_attr;
00792   XFontSet font_set = XFactory::create_fontset(dpy, status_fontname);
00793   status_attr = XVaCreateNestedList(0,
00794                                 XNFontSet, font_set,
00795                                 NULL);
00796   if (xic)
00797     XSetICValues(xic,
00798                XNStatusAttributes, status_attr,
00799                0);
00800   XFree(status_attr);
00801 }
00802 
00803 // XIM callbacks
00804 int
00805 XInputContext::preedit_start_cbproc(XIC xic, XPointer client_data,
00806                                 XPointer call_data) {
00807   XInputContext *ic = (XInputContext*)client_data;
00808   XIMPublic *ximp_protocol = ic->ximp_protocol;
00809 
00810   XIMS ims = ((R6IMProtocol*)ximp_protocol)->getXIMS();
00811   int icid = R6IMProtocol::getICID(ic);
00812   IMPreeditCBStruct data;
00813   memset(&data, 0, sizeof(IMPreeditCBStruct));
00814   data.icid = icid;
00815   data.connect_id = ic->connect_id;
00816   _Xi18nPreeditStartCallback(ims, (X11R6IMProtocol)&data);
00817 
00818   return -1;
00819 }
00820 
00821 void
00822 XInputContext::preedit_draw_cbproc(XIC xic, XPointer client_data,
00823                                XPointer call_data_p) {
00824   XInputContext *ic = (XInputContext*)client_data;
00825   XIMPreeditDrawCallbackStruct preedit_cb;
00826   XIMPreeditDrawCallbackStruct *call_data =
00827     (XIMPreeditDrawCallbackStruct*)call_data_p;
00828   XTextProperty prop;
00829 
00830   // follow kinput2, it seems that PREEDIT_DRAW will be invoked while
00831   // destroying an IC just after RESET_IC is called
00832   if (ic->being_reset) {
00833        return;
00834   }
00835 
00836   memmove(&preedit_cb, call_data, sizeof(XIMPreeditDrawCallbackStruct));
00837 
00838   prop.value = 0;
00839   if (call_data->text) {
00840     // call_data is native encoding, so need to convert to CT
00841     char *mb_data = call_data->text->string.multi_byte;
00842     XmbTextListToTextProperty(ic->dpy, &mb_data,
00843                            1, XCompoundTextStyle, &prop);
00844     preedit_cb.text = new XIMText;
00845     preedit_cb.text->length = call_data->text->length;
00846     preedit_cb.text->feedback = call_data->text->feedback;
00847     preedit_cb.text->encoding_is_wchar =
00848       call_data->text->encoding_is_wchar;
00849     preedit_cb.text->string.multi_byte = (char*)prop.value;
00850   }
00851 
00852   XIMPublic *ximp_protocol = ic->ximp_protocol;
00853   XIMS ims = ((R6IMProtocol*)ximp_protocol)->getXIMS();
00854   int icid = R6IMProtocol::getICID(ic);
00855   IMPreeditCBStruct data;
00856   memset(&data, 0, sizeof(IMPreeditCBStruct));
00857   data.icid = icid;
00858   data.connect_id = ic->connect_id;
00859   data.todo.draw = preedit_cb;
00860 
00861   _Xi18nPreeditDrawCallback(ims, (X11R6IMProtocol)&data);
00862 
00863   if (prop.value) XFree(prop.value);
00864   delete preedit_cb.text;
00865 
00866   return;
00867 }
00868 void
00869 XInputContext::preedit_caret_cbproc(XIC xic, XPointer client_data,
00870                                 XPointer call_data_p) {
00871   XInputContext *ic = (XInputContext*)client_data;
00872   XIMPreeditCaretCallbackStruct *call_data =
00873     (XIMPreeditCaretCallbackStruct*)call_data_p;
00874 
00875   // follow kinput2, it seems that PREEDIT_DRAW will be invoked while
00876   // destroying an IC just after RESET_IC is called
00877   if (ic->being_reset) {
00878        return;
00879   }
00880 
00881   XIMPublic *ximp_protocol = ic->ximp_protocol;
00882   XIMS ims = ((R6IMProtocol*)ximp_protocol)->getXIMS();
00883   int icid = R6IMProtocol::getICID(ic);
00884   IMPreeditCBStruct data;
00885   memset(&data, 0, sizeof(IMPreeditCBStruct));
00886   data.icid = icid;
00887   data.connect_id = ic->connect_id;
00888   data.todo.caret = *call_data;
00889 
00890   _Xi18nPreeditCaretCallback(ims, (X11R6IMProtocol)&data);
00891 
00892   return;
00893 }
00894 void
00895 XInputContext::preedit_done_cbproc(XIC xic, XPointer client_data,
00896                                XPointer call_data) {
00897   XInputContext *ic = (XInputContext*)client_data;
00898 
00899   XIMPublic *ximp_protocol = ic->ximp_protocol;
00900   XIMS ims = ((R6IMProtocol*)ximp_protocol)->getXIMS();
00901   int icid = R6IMProtocol::getICID(ic);
00902   IMPreeditCBStruct data;
00903   memset(&data, 0, sizeof(IMPreeditCBStruct));
00904   data.icid = icid;
00905   data.connect_id = ic->connect_id;
00906 
00907   _Xi18nPreeditDoneCallback(ims, (X11R6IMProtocol)&data);
00908 
00909   return;
00910 }
00911 void
00912 XInputContext::status_start_cbproc(XIC xic, XPointer client_data,
00913                                XPointer call_data) {
00914   XInputContext *ic = (XInputContext*)client_data;
00915 
00916   XIMPublic *ximp_protocol = ic->ximp_protocol;
00917   XIMS ims = ((R6IMProtocol*)ximp_protocol)->getXIMS();
00918   int icid = R6IMProtocol::getICID(ic);
00919   IMStatusCBStruct data;
00920   memset(&data, 0, sizeof(IMStatusCBStruct));
00921   data.icid = icid;
00922   data.connect_id = ic->connect_id;
00923 
00924   _Xi18nStatusStartCallback(ims, (X11R6IMProtocol)&data);
00925 
00926   return;
00927 }
00928 
00929 void
00930 XInputContext::status_draw_cbproc(XIC xic, XPointer client_data,
00931                               XPointer call_data_p) {
00932   XInputContext *ic = (XInputContext*)client_data;
00933   XIMStatusDrawCallbackStruct status_cb;
00934   XIMStatusDrawCallbackStruct *call_data = 
00935     (XIMStatusDrawCallbackStruct*)call_data_p;
00936   XTextProperty prop;
00937 
00938   memmove(&status_cb, call_data, sizeof(XIMStatusDrawCallbackStruct));
00939 
00940   prop.value = 0;
00941   if (call_data->data.text) {
00942     // call_data is native encoding, so need to convert to CT
00943     char *mb_data = call_data->data.text->string.multi_byte;
00944     XmbTextListToTextProperty(ic->dpy, &mb_data,
00945                            1, XCompoundTextStyle, &prop);
00946     status_cb.data.text = new XIMText;
00947     status_cb.data.text->length = call_data->data.text->length;
00948     status_cb.data.text->feedback = call_data->data.text->feedback;
00949     status_cb.data.text->encoding_is_wchar =
00950       call_data->data.text->encoding_is_wchar;
00951     status_cb.data.text->string.multi_byte = (char*)prop.value;
00952   }
00953 
00954   XIMPublic *ximp_protocol = ic->ximp_protocol;
00955   XIMS ims = ((R6IMProtocol*)ximp_protocol)->getXIMS();
00956   int icid = R6IMProtocol::getICID(ic);
00957   IMStatusCBStruct data;
00958   memset(&data, 0, sizeof(IMStatusCBStruct));
00959   data.icid = icid;
00960   data.connect_id = ic->connect_id;
00961   data.todo.draw = status_cb;
00962 
00963   _Xi18nStatusDrawCallback(ims, (X11R6IMProtocol)&data);
00964 
00965   if (prop.value) XFree(prop.value);
00966   delete status_cb.data.text;
00967 
00968   return;
00969 }
00970 void
00971 XInputContext::status_done_cbproc(XIC xic, XPointer client_data,
00972                               XPointer call_data) {
00973   XInputContext *ic = (XInputContext*)client_data;
00974 
00975   XIMPublic *ximp_protocol = ic->ximp_protocol;
00976   XIMS ims = ((R6IMProtocol*)ximp_protocol)->getXIMS();
00977   int icid = R6IMProtocol::getICID(ic);
00978   IMStatusCBStruct data;
00979   memset(&data, 0, sizeof(IMStatusCBStruct));
00980   data.icid = icid;
00981   data.connect_id = ic->connect_id;
00982 
00983   _Xi18nStatusDoneCallback(ims, (X11R6IMProtocol)&data);
00984 
00985   return;
00986 }
00987 
00988 
00989 void
00990 XInputContext::commit_string_cbproc(XIC xic, XPointer client_data,
00991                                    XPointer call_data_p) {
00992   XIMText *cbtext = (XIMText*)call_data_p;
00993   char *mb_data = (char*)cbtext->string.multi_byte;
00994   XInputContext *ic = (XInputContext*)client_data;
00995 
00996   if (mb_data == 0 || *mb_data == 0) return;
00997 
00998   // mb_data is native encoding, so need to convert to CT
00999   XTextProperty prop;
01000   XmbTextListToTextProperty(ic->dpy, &mb_data,
01001                          1, XCompoundTextStyle, &prop);
01002   char *ret = (char *)prop.value;
01003   if (ic->being_reset)
01004     // XmbTextListToTextProperty() will be performed in ResetICMessageProc()
01005     ic->reset_text = mb_data;
01006   else {
01007     XIMPublic *ximp_protocol = ic->ximp_protocol;
01008     XIMS ims = ((R6IMProtocol*)ximp_protocol)->getXIMS();
01009     int icid = R6IMProtocol::getICID(ic);
01010     IMCommitEventStruct data;
01011     memset(&data, 0, sizeof(IMCommitEventStruct));
01012     data.icid = icid;
01013     data.connect_id = ic->connect_id;
01014     data.flag = XimLookupChars;
01015     data.commit_string = ret;
01016     ims->methods->commitString(ims, &data);
01017   }
01018 
01019   if (prop.value) XFree(prop.value);
01020   return;
01021 }
01022 
01023 void
01024 XInputContext::forward_event_cbproc(XIC xic, XPointer client_data,
01025                                 XPointer call_data_p) {
01026   XEvent *call_data = (XEvent*)call_data_p;
01027   XInputContext *ic = (XInputContext*)client_data;
01028 
01029   XIMPublic *ximp_protocol = ic->ximp_protocol;
01030   XIMS ims = ((R6IMProtocol*)ximp_protocol)->getXIMS();
01031   int icid = R6IMProtocol::getICID(ic);
01032   IMForwardEventStruct data;
01033   memset(&data, 0, sizeof(IMForwardEventStruct));
01034   data.icid = icid;
01035   data.connect_id = ic->connect_id;
01036   data.event = *call_data;
01037 
01038   ims->methods->forwardEvent(ims, &data);
01039 
01040   return;
01041 }
01042 
01043 void
01044 XInputContext::state_notify_cbproc(XIC xic, XPointer client_data,
01045                                    XPointer call_data_p) {
01046   XIMPreeditStateNotifyCallbackStruct *call_data =
01047     (XIMPreeditStateNotifyCallbackStruct *)call_data_p;
01048   XInputContext *ic = (XInputContext*)client_data;
01049 
01050   XIMPublic *ximp_protocol = ic->ximp_protocol;
01051   XIMS ims = ((R6IMProtocol*)ximp_protocol)->getXIMS();
01052   int icid = R6IMProtocol::getICID(ic);
01053   IMPreeditStateStruct data;
01054   memset(&data, 0, sizeof(IMPreeditStateStruct));
01055   data.icid = icid;
01056   data.connect_id = ic->connect_id;
01057 
01058   if (call_data->state == XIMPreeditDisable) {
01059     ic->conversion_end(False);
01060     ims->methods->preeditEnd(ims, (X11R6IMProtocol)&data);
01061   }
01062   if (call_data->state == XIMPreeditEnable) {
01063     ic->conversion_start(False);
01064     ims->methods->preeditStart(ims, (X11R6IMProtocol)&data);
01065   }
01066   return;
01067 }