Back to index

im-sdk  12.3.91
tableinput.c
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 "xiiimp.h"
00043 #include "guiIM.h"
00044 #include "composeIM.h"
00045 #include "tableinput.h"
00046 #include "lookup.h"
00047 #include "xfactory.h"
00048 
00049 static int
00050 findLUIndex(LuRange *range, int size, int ch) {
00051   int i;
00052 
00053   for (i = 0; i < size; i++) {
00054     if (range[i].RangeName[0] == ch) {
00055       return(i);
00056     }
00057   }
00058   return -1;
00059 }
00060 
00061 static Bool
00062 selectLURange(XicCommon ic, int idx) {
00063   LocalTableExt *hook = (LocalTableExt *)(ic->local_icpart->table_ext);
00064   LocalLookupExt *hook2;
00065 
00066   if (idx < 0 || idx > hook->nrange) return False;
00067 
00068   Ximp_Local_Lookup_Start(ic);
00069   hook2 = (LocalLookupExt*)(ic->local_icpart->lookup_ext);
00070   hook2->range = hook->range;
00071   hook2->begin_range = hook->range[idx].start_range;
00072   hook2->startindex = hook->range[idx].start_range;
00073   hook2->end_range = hook->range[idx].end_range;
00074   hook2->crange = idx;
00075   hook2->currentindex = 0;
00076   Ximp_Local_Lookup_Draw(ic);
00077 
00078   XUnmapWindow(ic->core.im->core.display, hook->window);
00079   return True;
00080 }
00081 
00082 static Bool
00083 FilterKeyPress(Display *d, Window w, XEvent *ev, XPointer client_data) {
00084   XicCommon ic = (XicCommon)client_data;
00085   LocalTableExt *hook = (LocalTableExt *)(ic->local_icpart->table_ext);
00086   KeySym ks;
00087   int idx;
00088 
00089   if (ev->type != KeyPress) return False;
00090   if (!hook || !hook->window ||
00091       !hook->range || !hook->fontset || !hook->gc) return False;
00092   
00093   ks = XKeycodeToKeysym(d, ev->xkey.keycode, 0);
00094   idx = findLUIndex(hook->range, hook->nrange, (int)ks);
00095 
00096   return selectLURange(ic, idx);
00097 }
00098 static Bool
00099 RepaintTable(Display *d, Window w, XEvent *ev, XPointer client_data) {
00100   XicCommon ic = (XicCommon)client_data;
00101   LocalTableExt *hook = (LocalTableExt *)(ic->local_icpart->table_ext);
00102   int i, ypos;
00103 
00104   if (!hook || !hook->range || !hook->fontset || !hook->gc) return False;
00105 
00106   for (i = 0; i < hook->nrange; i++) {
00107     ypos = (i+1) * hook->theight;
00108     XmbDrawString(d, w, hook->fontset, hook->gc, 0, ypos,
00109                 hook->range[i].RangeName,
00110                 strlen(hook->range[i].RangeName));
00111   }
00112   return(True);
00113 }
00114 
00115 #define xMargin 4
00116 #define yMargin 4
00117 static Bool
00118 FilterMotionNotify(Display *d, Window w, XEvent *ev, XPointer client_data) {
00119   XicCommon ic = (XicCommon)client_data;
00120   LocalTableExt *hook = (LocalTableExt *)(ic->local_icpart->table_ext);
00121   int y;
00122   static int oy = -1;
00123 
00124   if (ev->type != MotionNotify) return False;
00125 
00126   if (!hook || !hook->window ||
00127       !hook->range || !hook->fontset || !hook->gc) return False;
00128 
00129   y = (int)((int)(ev->xmotion.y/hook->theight)*hook->theight);
00130   if (y != oy) {
00131     if (oy != -1) {
00132       y += yMargin;
00133       XDrawRectangle(d, w, hook->rgc, 0, oy, hook->rect.width, hook->theight);
00134     }
00135     XDrawRectangle(d, w, hook->gc, 0, y, hook->rect.width, hook->theight);
00136     oy = y;
00137   }
00138   return True;
00139 }
00140 
00141 static Bool
00142 FilterButtonRelease(Display *d, Window w, XEvent *ev, XPointer client_data) {
00143   XicCommon ic = (XicCommon)client_data;
00144   LocalTableExt *hook = (LocalTableExt *)(ic->local_icpart->table_ext);
00145   int idx;
00146 
00147   if (ev->type != ButtonRelease) return False;
00148 
00149   if (!hook || !hook->window ||
00150       !hook->range || !hook->fontset || !hook->gc) return False;
00151 
00152   if (ev->xbutton.x < 0 || ev->xbutton.x > hook->rect.width ||
00153       ev->xbutton.y < 0 || ev->xbutton.y > hook->rect.height)
00154     return False;
00155 
00156   idx = (int)(ev->xbutton.y/hook->theight);
00157 
00158   return selectLURange(ic, idx);
00159 }
00160 
00161 static Window
00162 setup_table_window(XicCommon ic) {
00163   LocalTableExt *hook = (LocalTableExt *)(ic->local_icpart->table_ext);
00164   XWindowAttributes attr;
00165   Display *display = ic->core.im->core.display;
00166   Window parent, win;
00167   unsigned long fg, bg;
00168   unsigned long val_mask;
00169   XGCValues gcval;
00170   XIMFilterRec filters[4];
00171   short x, y;
00172   unsigned short width, height;
00173 
00174   XGetWindowAttributes(display, 
00175                      ic->core.client_window,
00176                      &attr);
00177   parent = RootWindow(display, XScreenNumberOfScreen(attr.screen));
00178 
00179   if (XIMP_CHK_PREBGMASK(ic)) 
00180     bg = ic->core.preedit_attr.background;
00181   else
00182     bg = WhitePixel(display, XScreenNumberOfScreen(attr.screen));
00183 
00184   if (XIMP_CHK_PREFGMASK(ic))
00185     fg = ic->core.preedit_attr.foreground;
00186   else
00187     fg = BlackPixel(display, XScreenNumberOfScreen(attr.screen));
00188 
00189   filters[0].type = KeyPress;
00190   filters[0].filter = FilterKeyPress;
00191   filters[0].client_data = (XPointer)ic;
00192   filters[1].type = Expose;
00193   filters[1].filter = RepaintTable;
00194   filters[1].client_data = (XPointer)ic;
00195   filters[2].type = MotionNotify;
00196   filters[2].filter = FilterMotionNotify;
00197   filters[2].client_data = (XPointer)ic;
00198   filters[3].type = ButtonRelease;
00199   filters[3].filter = FilterButtonRelease;
00200   filters[3].client_data = (XPointer)ic;
00201 
00202   x = y = 0;                /* default position */
00203   width = height = 10;             /* default size */
00204   win = XFactoryCreateIMWindow(display, parent,
00205                             ic->core.client_window,
00206                             x, y, width, height,
00207                             bg,
00208                             KeyPressMask|ExposureMask|
00209                             ButtonPressMask |PointerMotionMask|
00210                             ButtonReleaseMask |
00211                             StructureNotifyMask,
00212                             filters, 4);
00213   if (!win) return 0;
00214 
00215   val_mask = GCForeground | GCBackground;
00216   gcval.foreground = fg;
00217   gcval.background = bg;
00218   hook->gc = XCreateGC(display, win, val_mask, &gcval);
00219   gcval.foreground = bg;
00220   gcval.background = fg;
00221   hook->rgc = XCreateGC(display, win, val_mask, &gcval);
00222 
00223   /* fontset */
00224   hook->need_free_fontset = False;
00225   if (ic->core.status_attr.fontset) {
00226     hook->fontset = ic->core.status_attr.fontset;
00227   }
00228   if (ic->core.preedit_attr.fontset) {
00229     hook->fontset = ic->core.preedit_attr.fontset;
00230   }
00231   if (!hook->fontset) {
00232     char *base_font_name = DEFAULT_FONT_NAME;
00233     char **missing_list;
00234     int missing_count;
00235     char *def_string;
00236     hook->fontset = XCreateFontSet(display,
00237                                base_font_name, &missing_list,
00238                                &missing_count, &def_string);
00239     hook->need_free_fontset = True;
00240   }
00241   return win;
00242 }
00243 
00244 static void
00245 move_table_window(XicCommon ic) {
00246   LocalTableExt *hook = (LocalTableExt *)(ic->local_icpart->table_ext);
00247   XPoint point;
00248   int x = 0, y = 0;  /* default */
00249 
00250   point.x = point.y = 0;    /* default */
00251   if (XIMP_CHK_PREAREAMASK(ic)) {
00252     x = ic->core.preedit_attr.area.x;
00253     y = ic->core.preedit_attr.area.y;
00254     XFactoryGetLocationOnScreen(ic->core.im->core.display,
00255                             ic->core.client_window, x, y, &point);
00256   }
00257   if (XIMP_CHK_PRESPOTLMASK(ic)) {
00258     point.x = -1;
00259     point.y = -1;
00260     if ((-1 == point.x) && (-1 == point.y)) {
00261       XFontSetExtents *fse;
00262       fse = XExtentsOfFontSet(hook->fontset);
00263 
00264       x = ic->core.preedit_attr.spot_location.x;
00265       y = ic->core.preedit_attr.spot_location.y;
00266       y += (fse->max_logical_extent.height + fse->max_logical_extent.y);
00267       y += yMargin;
00268     
00269       XFactoryGetLocationOnScreen(ic->core.im->core.display,
00270                               ic->core.focus_window, x, y, &point);
00271     }
00272   }
00273 
00274 #if 0
00275   if (hook->fontset) {
00276     XFontSetExtents *fse;
00277     fse = XExtentsOfFontSet(hook->fontset);
00278     if (fse) {
00279       int height = fse->max_logical_extent.height;
00280       hook->column_height = height;
00281     }
00282   }
00283 #endif
00284   x = point.x;
00285   y = point.y;
00286   XFactoryAdjustPlacementInsideScreen(ic->core.im->core.display,
00287                                   hook->window,
00288                                   point.x, point.y,
00289                                   hook->rect.width + (2 * xMargin),
00290                                   hook->rect.height + (2 * yMargin),
00291                                   &x, &y);
00292   XMoveWindow(ic->core.im->core.display, hook->window, x, y);
00293   hook->rect.x = point.x;
00294   hook->rect.y = point.y;
00295   return;
00296 }
00297 
00298 static void
00299 set_table_window_size(XicCommon ic) {
00300   LocalTableExt *hook = (LocalTableExt *)(ic->local_icpart->table_ext);
00301   int i, slen, sheight;
00302   XRectangle ink, logic;
00303 
00304   slen = 0;
00305   sheight = 0;
00306   for (i = 0; i < hook->nrange; i++) {
00307     XmbTextExtents(hook->fontset,
00308                  hook->range[i].RangeName,
00309                  strlen(hook->range[i].RangeName),
00310                  &ink, &logic);
00311     if (slen < logic.width) slen = logic.width;
00312     if (sheight < logic.height) sheight = logic.height;
00313   }
00314   hook->rect.width = slen;
00315   hook->rect.height = sheight * hook->nrange + yMargin;
00316   hook->theight = sheight;
00317   return;
00318 }
00319 
00320 static Bool
00321 setup_local_table_ext(XicCommon ic) {
00322   LocalIMState *state = (LocalIMState *)(ic->local_icpart->imstate);
00323   LocalTableExt *hook = (LocalTableExt *)(ic->local_icpart->table_ext);
00324 
00325   if (hook) return (True);
00326 
00327   hook = (LocalTableExt *)Xmalloc(sizeof(LocalTableExt));
00328   if (!hook)
00329     return (False);
00330   memset(hook, 0, sizeof(LocalTableExt));
00331 
00332   hook->range = (LuRange*)Xmalloc(sizeof(LuRange) * state->attr->_attr_u.LUstruct.nrange);
00333   memcpy(hook->range, state->attr->_attr_u.LUstruct.range,
00334         sizeof(LuRange)*state->attr->_attr_u.LUstruct.nrange);
00335   hook->nrange = state->attr->_attr_u.LUstruct.nrange;
00336 
00337   ic->local_icpart->table_ext = (void *)hook;
00338   return(True);
00339 }
00340 
00341 /* public */
00342 void
00343 Ximp_Local_Table_Create(XicCommon ic) {
00344   LocalIMState *state = (LocalIMState *)(ic->local_icpart->imstate);
00345   LocalTableExt *hook = (LocalTableExt *)(ic->local_icpart->table_ext);
00346   Display *display = ic->core.im->core.display;
00347 
00348   if (!display || !state || !state->attr) return;
00349 
00350   if (!(XIMP_CHK_FOCUSWINMASK(ic))) {
00351     return;  /* Client's not ready, Let's do it later */
00352   }
00353   if (!hook) {
00354     if (!setup_local_table_ext(ic))
00355       return;
00356     hook = (LocalTableExt *)(ic->local_icpart->table_ext);
00357   }
00358   if (!hook->window) {
00359     hook->window = setup_table_window(ic);
00360     if (!hook->window) return;
00361     set_table_window_size(ic);
00362   }
00363   return;
00364 }
00365 
00366 void
00367 Ximp_Local_Table_Start(XicCommon ic) {
00368   LocalTableExt *hook = (LocalTableExt *)(ic->local_icpart->table_ext);
00369   Display *display = ic->core.im->core.display;
00370   XSizeHints hints;
00371 
00372   if (!hook) {
00373     Ximp_Local_Table_Create(ic);
00374     hook = (LocalTableExt *)(ic->local_icpart->table_ext);
00375     if (!hook) return;
00376   }
00377   hints.flags = PSize | PMinSize | PMaxSize;
00378   hints.width = hook->rect.x;
00379   hints.min_width = hook->rect.width;
00380   hints.max_width = hook->rect.width;
00381   hints.height = hook->rect.height;
00382   hints.min_height = hook->rect.height;
00383   hints.max_height = hook->rect.height;
00384   XSetWMNormalHints(display, hook->window, &hints);
00385   move_table_window(ic);
00386   XMapWindow(display, hook->window);
00387   return;
00388 }
00389 
00390 void
00391 Ximp_Local_Table_Draw(XicCommon ic) {
00392 }
00393 
00394 void
00395 Ximp_Local_Table_Done(XicCommon ic) {
00396   LocalTableExt *hook = (LocalTableExt *)(ic->local_icpart->table_ext);
00397   Display *display = ic->core.im->core.display;
00398   Ximp_Local_Lookup_Done(ic);
00399   if (hook && display)
00400     XUnmapWindow(display, hook->window);
00401   return;
00402 }
00403 
00404 void
00405 Ximp_Local_Table_Destroy(XicCommon ic) {
00406   LocalTableExt *hook = (LocalTableExt *)(ic->local_icpart->table_ext);
00407   Display *display = ic->core.im->core.display;
00408   if (!hook || !display) return;
00409 
00410   if (hook->window) {
00411     XDestroyWindow(display, hook->window);
00412     _XUnregisterFilter(display, hook->window,
00413                      RepaintTable, (XPointer)ic);
00414     _XUnregisterFilter(display, hook->window,
00415                      FilterKeyPress, (XPointer)ic);
00416     _XUnregisterFilter(display, hook->window,
00417                      FilterMotionNotify, (XPointer)ic);
00418     _XUnregisterFilter(display, hook->window,
00419                      FilterButtonRelease, (XPointer)ic);
00420     hook->window = 0;
00421   }
00422   if (hook->gc) XFreeGC(display, hook->gc);
00423   if (hook->rgc) XFreeGC(display, hook->rgc);
00424 
00425   if (hook->need_free_fontset && hook->fontset) {
00426     XFreeFontSet(display, hook->fontset);
00427     hook->need_free_fontset = False;
00428   }
00429   if (hook->range) Xfree(hook->range);
00430   Xfree(hook);
00431   
00432   ic->local_icpart->table_ext = 0;
00433 }