Back to index

im-sdk  12.3.91
guiIMLookup.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 "iiimpIM.h"
00044 #include "iiimpColor.h"
00045 #include "composeIM.h"
00046 #include "guiIMLookup.h"
00047 #include "guiIMPre.h"
00048 #include "lookup.h"
00049 #include "XimpIm.h"
00050 #include "xfactory.h"
00051 #include <X11/keysym.h>
00052 #include "trace_message.h"
00053 #include <stdio.h>
00054 
00055 static void doneProc(XicCommon ic, XPointer p);
00056 
00057 static void DestroyLookup(XicCommon, XPointer);
00058 static void UpdateLookup(XicCommon);
00059 static void highlightCandidate(XicCommon ic, int, Bool highlight);
00060 
00061 static void
00062 DrawLookupString(Display *display, Window win, XFontSet fontset,
00063                GC gc, GC rgc, XIMFeedback feedback,
00064                int x, int y, char *str, int len) {
00065   if (fontset == NULL) return;
00066 
00067   if (feedback & XIMReverse) {
00068     XmbDrawImageString(display, win, fontset, rgc, 
00069                      x, y, str, len);
00070   } else {
00071     XmbDrawImageString(display, win, fontset, gc, 
00072                      x, y, str, len);
00073   }
00074   return;
00075 }
00076 
00077 static void
00078 DrawLookupString2(XicCommon ic,
00079                 Display *display, Window win, XFontSet fontset,
00080                 GC gc, GC rgc,
00081                 int x, int y, char *str, int str_len,
00082                 XIMChoiceObject2 *choice, int idx) {
00083   XIMText *label = &choice->label[idx];
00084   XIMText *value = &choice->value[idx];
00085   int i;
00086   int j;
00087   wchar_t *wcstr = 0, *wcstrp;
00088   size_t wc_len = 0;
00089   IMFeedbackList *pfeedback;
00090   int feedback_length;
00091   XimCommon im = (XimCommon)ic->core.im;
00092 
00093   if (fontset == NULL) return;
00094 
00095   /* label */
00096   str = label->string.multi_byte;
00097   str_len = (str) ? strlen(str) : 0;
00098 
00099   /* need to get wchar string */
00100   wc_len = str_len;
00101   if (!(wcstr = Xmalloc(sizeof(wchar_t) * (wc_len + 1)))) return;
00102 
00103   if (IIimpMbstoWcs(im, str, str_len, wcstr, wc_len, NULL) == 0) {
00104     Xfree(wcstr);
00105     goto error;
00106   }
00107 
00108   wcstrp = wcstr;
00109 
00110   pfeedback = choice->label_feedback[idx];
00111   feedback_length = label->length;
00112 
00113   for (i = 0; i < feedback_length; i++, pfeedback++) {
00114     /* set colors */
00115     if ((0 == i) || (False == SameIMFeedbackList(pfeedback - 1, pfeedback))) {
00116       SetIMColors(ic, display, win, gc, (GC)0, pfeedback, (XIMFeedback)0);
00117     }
00118     XwcDrawImageString(display, win, fontset, gc,
00119                      x, y, wcstrp, 1);
00120     x += XwcTextEscapement(fontset, wcstrp, 1); wcstrp++;
00121   }
00122   Xfree(wcstr);
00123 
00124   /* space */
00125   x += XmbTextEscapement(fontset, " ", 1);
00126   
00127   /* value */
00128   str = value->string.multi_byte;
00129   str_len = (str) ? strlen(str) : 0;
00130 
00131   /* need to get wchar string */
00132   wc_len = str_len;
00133   if (!(wcstr = Xmalloc(sizeof(wchar_t) * (wc_len + 1)))) return;
00134 
00135   if (IIimpMbstoWcs(im, str, str_len, wcstr, wc_len, NULL) == 0) {
00136     Xfree(wcstr);
00137     goto error;
00138   }
00139 
00140   wcstrp = wcstr;
00141 
00142   pfeedback = choice->value_feedback[idx];
00143   feedback_length = value->length;
00144   for (i = 0; i < feedback_length; pfeedback++) {
00145     /* set colors */
00146     for (j = 1; j < (feedback_length - i); j++, pfeedback++) {
00147       if (False == SameIMFeedbackList(pfeedback, pfeedback + 1)) {
00148        break;
00149       }
00150     }
00151     SetIMColors(ic, display, win, gc, (GC)0, pfeedback, (XIMFeedback)0);
00152     XwcDrawImageString(display, win, fontset, gc, x, y, wcstrp, j);
00153     x = XwcTextEscapement(fontset, wcstrp, j);
00154     wcstrp += j;
00155     i += j;
00156   }
00157   Xfree(wcstr);
00158 error:
00159   return;
00160 }
00161 
00162 #if 0
00163 #define xMargin 5
00164 #define yMargin 10
00165 #define cMargin 5
00166 #define bMargin 10
00167 #else /* !0 */
00168 #define xMargin 4
00169 #define yMargin 4
00170 #define cMargin 6
00171 #define bMargin 12
00172 #endif /* !0 */
00173 
00174 static int
00175 boundValue(int value, int lower, int upper)
00176 {
00177   if (value > upper)
00178     return upper;
00179   if (value < lower)
00180     return lower;
00181 
00182   return value;
00183 }
00184 
00185 static int
00186 getChoiceIndex(XicCommon ic, XEvent *event) {
00187   LookupWin lookup = (LookupWin)(ic->gui_icpart->lookup);
00188   int x = event->xbutton.x;
00189   int y = event->xbutton.y;
00190   int curColumns, curRows;
00191   int candW;
00192   int candH;
00193   int currentCol = 0;
00194   int currentRow = 0;
00195   int w, h;
00196   int idx;
00197 
00198   if (!lookup) return -1;
00199 
00200   x = (x < xMargin ? 0: x - xMargin);
00201   y = (y < yMargin ? 0: y - yMargin);
00202 
00203   if (lookup->nrows == 1) {
00204     int i;
00205     curColumns = 0;
00206     w = 0;
00207     for (i = 0; i < lookup->ncolumns; i++) {
00208       w += lookup->candWidth[i] + cMargin;
00209       if (w > x)
00210        break;
00211       currentCol++;
00212     }
00213   } else {
00214     curColumns = (lookup->width + cMargin) / (lookup->maxWidth + cMargin);
00215     candW = (int)((lookup->width) / curColumns);
00216 
00217     for (w = candW; w < lookup->width; w += candW) {
00218       if (w > x) {
00219        break;
00220       }
00221       currentCol++;
00222     }
00223     currentCol = boundValue(currentCol, 0, curColumns - 1);
00224   }
00225 
00226   curRows = (lookup->height + cMargin) / (lookup->column_height + cMargin);
00227   candH = (int)((lookup->height) / curRows); 
00228   for (h = candH; h < lookup->height; h += candH) {
00229     if (h > y) {
00230       break;
00231     }
00232     currentRow++;
00233   }
00234   currentRow = boundValue(currentRow, 0, curRows - 1);
00235 
00236   idx = currentRow * curColumns + currentCol;
00237   return idx;
00238 }
00239 
00240 static void
00241 selectCandidate(XicCommon ic, int idx) {
00242   LookupWin lookup = (LookupWin)(ic->gui_icpart->lookup);
00243   KeySym keysym;
00244   XEvent ev;
00245   char charValue;
00246 
00247   if (!XIM_IS_IIIMP(ic->core.im)) return;
00248 
00249   if (idx >= 0 && idx < lookup->length)
00250     charValue = lookup->labelArray[idx][0];
00251   else {
00252     fprintf(stderr,
00253            "ButtonPress: something is wrong with %d index\n",
00254            idx);
00255     return;
00256   }
00257 
00258   memset(&ev, 0, sizeof(XEvent));
00259 
00260   /* labelArray should be of 1 character length... */
00261   if (charValue >= 'a' && charValue <= 'z') {
00262     keysym = XK_a + charValue - 'a';
00263   } else if (charValue >= 'A' && charValue <= 'Z') {
00264     keysym = XK_A + charValue - 'A';
00265     ev.xkey.state |= ShiftMask;
00266 
00267   } else if (charValue >= '0' && charValue <= '9') {
00268     keysym = XK_0 + charValue - '0';
00269   } else {
00270       /* Index is neither alpabet nor number?, well let's assgin
00271         index + 1 to keysym value */
00272       keysym = XK_0 + idx + 1;
00273   }
00274          
00275   ev.xkey.x = 0;
00276   ev.xkey.y = 0;
00277   ev.xkey.x_root = 0;
00278   ev.xkey.y_root = 0;
00279   ev.xany.display = ic->core.im->core.display;
00280   ev.type = (int)KeyPress;
00281   ev.xkey.window = lookup->window;
00282   ev.xkey.keycode = XKeysymToKeycode(ev.xany.display,
00283                                  keysym);
00284 
00285   IMForwardEvent(ic, &ev);
00286   PutBackXKeyEvent(ic);
00287   return;
00288 }
00289 
00290 static Bool
00291 FilterButtonPress(Display *d, Window window,
00292                 XEvent *ev, XPointer client_data) {
00293   int idx;
00294   XicCommon ic = (XicCommon)client_data;
00295 
00296   idx = getChoiceIndex(ic, ev);
00297   if (idx == -1) return False;
00298 
00299   /* wait for button released */
00300   return True;
00301 }
00302 
00303 static Bool
00304 FilterButtonRelease(Display *d, Window window,
00305                   XEvent *ev, XPointer client_data) {
00306   int idx;
00307   XicCommon ic = (XicCommon)client_data;
00308   XimCommon im = (XimCommon)ic->core.im;
00309 
00310   idx = getChoiceIndex(ic, ev);
00311   if (idx == -1) return False;
00312 
00313   if (XIM_IS_COMPOSE(im) &&
00314       (XIC_COMPOSE(ic, imstate)->type == LookupState ||
00315        XIC_COMPOSE(ic, imstate)->type == CodeInputState)) {
00316     Ximp_Local_Lookup_Button_Filter(ic, idx, ev); /* in lookup.c */
00317     return True;
00318   } else {
00319     selectCandidate(ic, idx);
00320   }
00321   return True;
00322 }
00323 
00324 static Bool
00325 FilterMotionNotify(Display *d, Window w, XEvent *ev, XPointer client_data) {
00326   XicCommon ic = (XicCommon)client_data;
00327   int idx = getChoiceIndex(ic, ev);
00328   if (idx == -1) return False;
00329   highlightCandidate(ic, idx, True);
00330   return True;
00331 }
00332 
00333 static Bool
00334 FilterKeyPress(Display *d, Window w, XEvent *ev, XPointer client_data) {
00335   XicCommon ic = (XicCommon)client_data;
00336   XimCommon im = (XimCommon)ic->core.im;
00337   if (XIM_IS_COMPOSE(im) &&
00338       (XIC_COMPOSE(ic, imstate)->type == LookupState ||
00339        XIC_COMPOSE(ic, imstate)->type == CodeInputState)) {
00340     Bool returnflag;
00341     returnflag = Ximp_Local_KeyFilter(d, w, ev, (XPointer)ic); /* in localIM.c */
00342     if (!returnflag) {
00343       ev->xkey.window = ic->core.focus_window;
00344       XPutBackEvent(d, ev);
00345     }
00346     return True;
00347   } else {
00348     IMForwardEvent(ic, ev);
00349     PutBackXKeyEvent(ic);
00350   }
00351   return True;
00352 }
00353 
00354 static Bool
00355 RepaintLookup(Display *d, Window w, XEvent *ev, XPointer client_data) {
00356   LookupWin lookup;
00357   XicCommon ic = (XicCommon)client_data;
00358   lookup = (LookupWin)(ic->gui_icpart->lookup);
00359   if (!lookup) return False;
00360   UpdateLookup(ic);
00361   return True;
00362 }
00363 
00364 static void
00365 UpdateLookup(XicCommon ic) {
00366   LookupWin lookup = (LookupWin)(ic->gui_icpart->lookup);
00367   int current_columns = lookup->ncolumns;
00368   int currentC = 0;
00369   int i;
00370   int rows;
00371   int x = xMargin;
00372   int y = yMargin;
00373 
00374   if (lookup->fontset) {
00375     XFontSetExtents *fse;
00376     fse = XExtentsOfFontSet(lookup->fontset);
00377     TRACE_MESSAGE('l', ("UpdateLookup: ink = (%d %d %d %d) logical = (%d %d %d %d)\n",
00378                 fse->max_ink_extent.x,
00379                 fse->max_ink_extent.y,
00380                 fse->max_ink_extent.width,
00381                 fse->max_ink_extent.height,
00382                 fse->max_logical_extent.x,
00383                 fse->max_logical_extent.y,
00384                 fse->max_logical_extent.width,
00385                 fse->max_logical_extent.height));
00386     y -= (fse->max_logical_extent.height + fse->max_logical_extent.y);
00387     y -= cMargin;
00388   }
00389 
00390   if (lookup->candidates == NULL || lookup->length == 0)
00391     return;
00392 
00393   if (lookup->ncolumns > lookup->length)
00394     current_columns = lookup->length;
00395   rows = 0;
00396 
00397   if (lookup->redraw & CONTENTS) {
00398     XClearArea(ic->core.im->core.display, lookup->window, 0, 0, 0, 0, False);
00399   }
00400   for (i = 0; i < lookup->length; i++) {
00401     if (i % current_columns == 0) {
00402       currentC = 0;
00403       rows++;
00404       y += lookup->column_height + cMargin;
00405       x = xMargin;
00406     } else {
00407       if (lookup->nrows == 1)
00408        x += lookup->candWidth[i-1] + cMargin;
00409       else
00410        x += lookup->maxWidth + cMargin;
00411       currentC++;
00412     }
00413     if (lookup->candidates->label_feedback &&
00414        lookup->candidates->value_feedback &&
00415        lookup->candidates->label_feedback[i] &&
00416        lookup->candidates->value_feedback[i]) {
00417       DrawLookupString2(ic, ic->core.im->core.display, lookup->window,
00418                      lookup->fontset, lookup->gc, lookup->rgc,
00419                      x, y, lookup->candidateArray[i],
00420                      strlen(lookup->candidateArray[i]),
00421                      lookup->candidates, i);
00422     } else {
00423       if (lookup->redraw == DRAW_NOTHING &&
00424          i == lookup->previous) {
00425        DrawLookupString(ic->core.im->core.display, lookup->window,
00426                       lookup->fontset, lookup->gc, lookup->rgc, 0,
00427                       x, y, lookup->candidateArray[i],
00428                       strlen(lookup->candidateArray[i]));
00429        if (lookup->current != i) {
00430          continue;
00431        }
00432       }
00433       if (i == lookup->current) {
00434        DrawLookupString(ic->core.im->core.display, lookup->window,
00435                       lookup->fontset, lookup->gc, lookup->rgc,
00436                       XIMReverse,
00437                       x, y, lookup->candidateArray[i],
00438                       strlen(lookup->candidateArray[i]));
00439        continue;
00440       }
00441       if (lookup->redraw & CONTENTS) {
00442        DrawLookupString(ic->core.im->core.display, lookup->window,
00443                       lookup->fontset, lookup->gc, lookup->rgc, 0,
00444                       x, y, lookup->candidateArray[i],
00445                       strlen(lookup->candidateArray[i]));
00446       }
00447     }
00448   }
00449   lookup->redraw = DRAW_ALL;
00450   return;
00451 }
00452 
00453 static void
00454 highlightCandidate(XicCommon ic, int highlight_index, Bool highlight)
00455 { 
00456   LookupWin lookup = (LookupWin)(ic->gui_icpart->lookup);
00457   GC                  gc;
00458   int column;
00459   int row;
00460   int x;
00461   int y;
00462   int width;
00463   int height;
00464 
00465   if (highlight) {
00466     if (highlight_index == lookup->highlight_index) { /* nothing changed */
00467       return;
00468     } else { /* need to clear prior highlight */
00469       highlightCandidate(ic, lookup->highlight_index, False);
00470     }
00471   }
00472 
00473   if ((highlight_index < 0) || (lookup->length <= highlight_index)) {
00474          return;
00475   }
00476 
00477   if (highlight) {
00478     gc = lookup->gc;
00479   } else {
00480     gc = lookup->rgc;
00481   }
00482 
00483   column = (highlight_index % lookup->ncolumns);
00484   row = (highlight_index / lookup->ncolumns);
00485 
00486   if (lookup->nrows == 1) {
00487     int i;
00488     x = xMargin / 2 ;
00489     for (i = 0; i < column; i++)
00490       x += lookup->candWidth[i] + cMargin;
00491   } else
00492     x = (xMargin / 2) + ((lookup->maxWidth + cMargin) * column);
00493 
00494   y = (yMargin / 2) + ((lookup->column_height + cMargin) * row);
00495 
00496   if (lookup->nrows == 1)
00497     width = lookup->candWidth[column] + xMargin - 1;
00498   else
00499     width = lookup->maxWidth + xMargin - 1;
00500   height = lookup->column_height + yMargin - 1;
00501 
00502   TRACE_MESSAGE('l', 
00503               ("idx=%d column=%d row=%d x=%d y=%d width=%d height=%d\n",
00504                highlight_index, column, row, x, y, width, height));
00505 
00506   XDrawRectangle(ic->core.im->core.display, lookup->window, gc,
00507                x, y, width, height);
00508 
00509   if (highlight) {
00510     lookup->highlight_index = highlight_index;
00511   } else {
00512     lookup->highlight_index = -1;
00513   }
00514 
00515   return;
00516 }
00517 
00518 static Bool
00519 SetupLookupExt(XicCommon ic) {
00520   LookupWin lookup;
00521 
00522   if (!(ic->ximp_icpart->value_mask & XIMP_CLIENT_WIN)) return False;
00523 
00524   lookup = (LookupWin)Xmalloc(sizeof(LookupWinRec));
00525   if (!lookup) return False;
00526   memset((char *)lookup, 0, sizeof(LookupWinRec));
00527   lookup->title_width = -1;
00528   ic->gui_icpart->lookup = (void *)lookup;
00529   return True;
00530 }
00531 
00532 static Bool
00533 SetupLookupWindow(XicCommon ic) {
00534   Display *display = ic->core.im->core.display;
00535   Window parent, win;
00536   unsigned long fg, bg;
00537   unsigned long val_mask;
00538   XGCValues gcval;
00539   LookupWin lookup = (LookupWin)(ic->gui_icpart->lookup);
00540   XIMFilterRec filters[10];
00541   int  n;
00542   XClassHint class_hint;
00543 
00544   TRACE_MESSAGE('l', ("SetupLookupWindow: 0x%08x\n", lookup->window));
00545 
00546   if (lookup->window) return True; /* don't need to recreate a window */
00547 
00548   parent = RootWindow(display, XIC_GUI(ic, screen_number));
00549 
00550   lookup->x = lookup->y = 0;                     /* default position */
00551 
00552   lookup->width = lookup->height = 10;           /* default size */
00553 
00554   lookup->x_real = lookup->y_real = -1;
00555 
00556   if (NULL != lookup->title) {
00557     free(lookup->title);
00558     lookup->title = NULL;
00559     lookup->title_width = -1;
00560   }
00561 
00562   if (XIMP_CHK_PREBGMASK(ic)) 
00563     bg = ic->core.preedit_attr.background;
00564   else
00565     bg = WhitePixel(display, XIC_GUI(ic, screen_number));
00566 
00567   if (XIMP_CHK_PREFGMASK(ic))
00568     fg = ic->core.preedit_attr.foreground;
00569   else
00570     fg = BlackPixel(display, XIC_GUI(ic, screen_number));
00571 
00572   n = 0;
00573   filters[n].type = KeyPress;
00574   filters[n].filter = FilterKeyPress;
00575   filters[n].client_data = (XPointer)ic;
00576   n++;
00577   filters[n].type = Expose;
00578   filters[n].filter = RepaintLookup;
00579   filters[n].client_data = (XPointer)ic;
00580   n++;
00581   filters[n].type = MotionNotify;
00582   filters[n].filter = FilterMotionNotify;
00583   filters[n].client_data = (XPointer)ic;
00584   n++;
00585   filters[n].type = ButtonPress;
00586   filters[n].filter = FilterButtonPress;
00587   filters[n].client_data = (XPointer)ic;
00588   n++;
00589   filters[n].type = ButtonRelease;
00590   filters[n].filter = FilterButtonRelease;
00591   filters[n].client_data = (XPointer)ic;
00592   n++;
00593   
00594   win = XFactoryCreateIMWindow(display, parent,
00595                             (ic->core.client_window ? ic->core.client_window:parent),
00596                             lookup->x, lookup->y, lookup->width, lookup->height,
00597                             bg,
00598                             KeyPressMask|ExposureMask|
00599                             ButtonPressMask |PointerMotionMask|
00600                             ButtonReleaseMask |
00601                             StructureNotifyMask,
00602                             filters, n);
00603   if (!win) return False;
00604 
00605   class_hint.res_name = "iiimx-im-lookup";
00606   class_hint.res_class = "IiimxImLookup";
00607   XSetClassHint(display, win, &class_hint);
00608 
00609   lookup->window = win;
00610 
00611   val_mask = GCForeground | GCBackground;
00612   gcval.foreground = fg;
00613   gcval.background = bg;
00614   lookup->gc = XCreateGC(display, win, val_mask, &gcval);
00615   gcval.foreground = bg;
00616   gcval.background = fg;
00617   lookup->rgc = XCreateGC(display, win, val_mask, &gcval);
00618 
00619   /* fontset */
00620   lookup->need_free_fontset = False;
00621   if (ic->core.status_attr.fontset) {
00622     lookup->fontset = ic->core.status_attr.fontset;
00623   }
00624   if (ic->core.preedit_attr.fontset) {
00625     lookup->fontset = ic->core.preedit_attr.fontset;
00626   }
00627   if (!lookup->fontset) {
00628     lookup->fontset = XFactoryCreateDefaultFontSet(display,
00629                                              XIM_IIIMP(ic->core.im, default_font_name));
00630     lookup->need_free_fontset = True;
00631   }
00632 
00633   return True;
00634 }
00635 
00636 static void
00637 moveLookupWindow(XicCommon ic) { 
00638   LookupWin lookup = (LookupWin)(ic->gui_icpart->lookup);
00639   XPoint point;
00640   int x = 0, y = 0;  /* default */
00641 
00642   point.x = point.y = 0;    /* default */
00643   if (XIMP_CHK_PREAREAMASK(ic)) {
00644     x = ic->core.preedit_attr.area.x;
00645     y = ic->core.preedit_attr.area.y;
00646     XFactoryGetLocationOnScreen(ic->core.im->core.display,
00647                             ic->core.client_window, x, y, &point);
00648   } else if (XIMP_CHK_PRESPOTLMASK(ic)) {
00649     point.x = -1;
00650     point.y = -1;
00651     PreeditCaretPlacement(ic, &point);
00652     if ((-1 == point.x) && (-1 == point.y)) {
00653       XFontSetExtents *fse;
00654       fse = XExtentsOfFontSet(lookup->fontset);
00655 
00656       x = ic->core.preedit_attr.spot_location.x;
00657       y = ic->core.preedit_attr.spot_location.y;
00658       y += (fse->max_logical_extent.height + fse->max_logical_extent.y);
00659       y += yMargin;
00660     
00661       XFactoryGetLocationOnScreen(ic->core.im->core.display,
00662                               ic->core.focus_window, x, y, &point);
00663     } else {
00664       point.y += 4; /* offset */
00665     }
00666   } else {
00667       Window parent;
00668       Window root;
00669       int x_return,y_return;
00670       unsigned int width_return,height_return,border_width_return,depth_return;
00671       parent =  XFactoryGetFrameWindow (ic->core.im->core.display,
00672                     ic->core.focus_window);
00673       XGetGeometry (ic->core.im->core.display,
00674                     parent, &root,&x_return,&y_return,
00675                     &width_return,&height_return,&border_width_return, &depth_return);
00676       XFactoryGetLocationOnScreen(ic->core.im->core.display,
00677                     parent, 0, height_return, &point);
00678       point.x -= border_width_return;
00679       point.y += border_width_return;
00680   }
00681 
00682   if (lookup->fontset) {
00683     XFontSetExtents *fse;
00684     fse = XExtentsOfFontSet(lookup->fontset);
00685     if (fse) {
00686       int height = fse->max_logical_extent.height;
00687 #if 0
00688       point.y += height;
00689 #endif /* 0 */
00690       lookup->column_height = height;
00691     }
00692   }
00693 
00694   x = point.x;
00695   y = point.y;
00696   XFactoryAdjustPlacementInsideScreen(ic->core.im->core.display,
00697                                   lookup->window,
00698                                   point.x, point.y,
00699                                   lookup->width + (2 * xMargin),
00700                                   lookup->height + (2 * yMargin) + bMargin,
00701                                   &x, &y);
00702   lookup->x_real = point.x;
00703   lookup->y_real = point.y;
00704   if ((False == lookup->mapped) ||
00705       (x != lookup->x_real) || (y != lookup->y_real)) {
00706     XSizeHints hints;
00707     hints.flags = PPosition;
00708     hints.x = x;
00709     hints.y = y;
00710     XSetWMNormalHints (ic->core.im->core.display,
00711                      lookup->window, &hints);
00712     XMoveWindow(ic->core.im->core.display, lookup->window, x, y);
00713   }
00714   lookup->x = point.x;
00715   lookup->y = point.y;
00716   TRACE_MESSAGE('l', ("moveLookupWindow: point=(%d, %d) lookup=(%d %d) x=%d y=%d\n",
00717                     point.x, point.y, lookup->x, lookup->y, x, y));
00718   return;
00719 }
00720 
00721 static void
00722 resizeLookupWindow(XicCommon ic) {
00723   LookupWin lookup = (LookupWin)(ic->gui_icpart->lookup);
00724   int x;
00725   int y;
00726   int height;
00727   int width;
00728 
00729   width = lookup->width + (2 * xMargin);
00730   height = lookup->height + (2 * yMargin);
00731   XFactoryAdjustPlacementInsideScreen(ic->core.im->core.display,
00732                                   lookup->window,
00733                                   lookup->x, lookup->y,
00734                                   width, height + bMargin,
00735                                   &x, &y);
00736   if ((False == lookup->mapped) ||
00737       (x != lookup->x_real) || (y != lookup->y_real) ||
00738       (width != lookup->w_real) || (height != lookup->h_real)) {
00739     XMoveResizeWindow(ic->core.im->core.display, lookup->window,
00740                     x, y, width, height);
00741     lookup->x_real = x;
00742     lookup->y_real = y;
00743     lookup->w_real = width;
00744     lookup->h_real = height;
00745   }
00746   TRACE_MESSAGE('l', ("resizeLookupWindow %d %d %d %d %d %d %d %d\n",
00747                     lookup->x, lookup->y, x, y,
00748                     lookup->width, lookup->height, width, height));
00749 }
00750 
00751 static LUCUpdate
00752 CompareLookupData(XIMChoiceObject2 *lc1, int lc1_start,
00753                 XIMChoiceObject2 *lc2, int lc2_start,
00754                 int length) {
00755   int i, j;
00756 
00757   if (lc1 == NULL || lc2 == NULL)
00758     return DRAW_NOTHING;
00759         
00760   for (i = 0; i < length; i++) {
00761     char* lc1_value = lc1->value[lc1_start + i].string.multi_byte;
00762     char* lc2_value = lc2->value[lc2_start + i].string.multi_byte;
00763     if (lc1_value && lc2_value) {
00764       if (strcmp(lc1_value, lc2_value)) return CONTENTS;
00765     }
00766     else {
00767       return CONTENTS;
00768     }
00769   }
00770   if (lc1->value_feedback == 0 ||
00771       lc2->value_feedback == 0 ||
00772       lc1->value_feedback[lc1_start] == 0 ||
00773       lc2->value_feedback[lc2_start] == 0) {
00774     return DRAW_NOTHING;
00775   }
00776   for (i = 0; i < length; i++) {
00777     IMFeedbackList *p = lc1->value_feedback[lc1_start + i];
00778     IMFeedbackList *q = lc2->value_feedback[lc2_start + i];
00779     int feedback_len = lc1->value[lc1_start + i].length;
00780     if (p->count_feedbacks != q->count_feedbacks) return FEEDBACKS;
00781     for (j = 0; j < feedback_len; j++) {
00782       if (p->feedbacks[j].type != q->feedbacks[j].type ||
00783          p->feedbacks[j].value != q->feedbacks[j].value) {
00784        return FEEDBACKS;
00785       }
00786     }
00787   }
00788   return DRAW_NOTHING;
00789 }
00790 
00791 static void
00792 FreeLookupData(LookupWin lookup) {
00793   if (lookup->array_size == 0) return;
00794 
00795   if (lookup->n_choices && lookup->candidates) {
00796     XIMText *label = lookup->candidates->label;
00797     XIMText *value = lookup->candidates->value;
00798     int i;
00799 
00800     for (i = 0; i < lookup->n_choices; i++) {
00801       if (lookup->candidates->label_feedback)
00802        FreeFeedbackList(lookup->candidates->label_feedback[i],
00803                       label[i].length);
00804       if (lookup->candidates->value_feedback)
00805        FreeFeedbackList(lookup->candidates->value_feedback[i],
00806                       value[i].length);
00807       Xfree(lookup->candidateArray[i]);
00808       Xfree(lookup->labelArray[i]);
00809       Xfree(value[i].feedback);
00810       Xfree(label[i].feedback);
00811       Xfree(value[i].string.multi_byte);
00812       Xfree(label[i].string.multi_byte);
00813     }
00814     Xfree(value);
00815     Xfree(label);
00816     if (lookup->candidates->label_feedback)
00817       Xfree(lookup->candidates->label_feedback);
00818     if (lookup->candidates->value_feedback)
00819       Xfree(lookup->candidates->value_feedback);
00820   }
00821 }
00822 
00823 static void
00824 CopyFeedbackList(XicCommon ic, IMFeedbackList **to_flist,
00825                IMFeedbackList *from_flist,
00826                int len) {
00827   IMFeedbackList *from, *to, *top;
00828 
00829   if (!from_flist) {
00830     *to_flist = 0;
00831     return;
00832   }
00833   top = (IMFeedbackList*)Xmalloc(sizeof(IMFeedbackList) * len);
00834   if (!top) return;
00835 
00836   for (from = from_flist, to = top; to < &top[len]; from++, to++) {
00837     to->count_feedbacks = from->count_feedbacks;
00838     to->feedbacks = Xmalloc(sizeof(IMFeedback) * to->count_feedbacks);
00839     if (to->feedbacks) {
00840       IMFeedback *p, *q;
00841       for (p = to->feedbacks, q = from->feedbacks;
00842           p < &to->feedbacks[to->count_feedbacks];
00843           p++, q++) {
00844        p->type = q->type;
00845        p->value = q->value;
00846       }
00847     }
00848   }
00849   *to_flist = top;
00850   return;
00851 }
00852 
00853 static void
00854 CopyXIMText(XicCommon ic, XIMText *to, XIMText *from) {
00855   to->length = from->length;
00856   to->encoding_is_wchar = False;
00857 
00858   to->feedback = Xmalloc(sizeof(XIMFeedback) * to->length);
00859 
00860   if (from->encoding_is_wchar == False) {
00861     int len;
00862     if (from->string.multi_byte) {
00863       len = strlen(from->string.multi_byte);
00864       to->string.multi_byte = Xmalloc(len + 1);
00865       strcpy(to->string.multi_byte, from->string.multi_byte);
00866     }
00867     else {
00868       len = 0;
00869       to->string.multi_byte = NULL;
00870     }
00871   } else {
00872     XimCommon im = (XimCommon)ic->core.im;
00873     int len = from->length * XLC_PUBLIC(im->core.lcd, mb_cur_max);
00874     to->string.multi_byte = Xmalloc(len + 1);
00875     if ((len = IIimpWcstoMbs(im, from->string.wide_char, from->length,
00876                           to->string.multi_byte, len, NULL)) < 0) {
00877       return;
00878     }
00879     to->string.multi_byte[len] = 0;
00880   }
00881   (void)memmove((void *)(to->feedback), (void *)(from->feedback),
00882               sizeof(XIMFeedback) * to->length);
00883   return;
00884 }
00885 
00886 static Bool
00887 CopyLookupData(XicCommon ic, LookupWin lookup,
00888               XIMLookupDrawCallbackStruct2 *call_data) {
00889   int i;
00890   char *candidate;
00891   int len;
00892   int realRow = 0;
00893   int cand_width = 0;
00894   char *value_str, *label_str;
00895   XIMText *value;
00896   XIMText *label;
00897   IMFeedbackList **value_flist, **label_flist;
00898   int actual_width = 0;
00899 
00900   if (lookup->array_size == 0) {
00901     lookup->array_size = 26;       /* init size */
00902     lookup->candidateArray = Xmalloc(sizeof(char*) * lookup->array_size);
00903     lookup->labelArray = Xmalloc(sizeof(char*) * lookup->array_size);
00904     lookup->candWidth = Xmalloc(sizeof(int) * lookup->array_size);
00905     lookup->candidates = Xmalloc(sizeof(XIMChoiceObject2));
00906   }
00907   if (lookup->array_size < lookup->n_choices) {
00908     lookup->array_size = lookup->n_choices;
00909     lookup->candidateArray = Xrealloc(lookup->candidateArray,
00910                                 sizeof(char*) * lookup->array_size);
00911     lookup->labelArray = Xrealloc(lookup->labelArray,
00912                             sizeof(char*) * lookup->array_size);
00913     lookup->candWidth = Xrealloc(lookup->candWidth,
00914                              sizeof(int) * lookup->array_size);
00915   }
00916   if (!lookup->candidateArray || !lookup->labelArray ||
00917       !lookup->candidates) {
00918     /* something wrong */
00919     return False;
00920   }
00921 
00922   lookup->candidates->label = Xmalloc(sizeof(XIMText) * lookup->n_choices);
00923   lookup->candidates->value = Xmalloc(sizeof(XIMText) * lookup->n_choices);
00924 
00925   if (!lookup->candidates->label || !lookup->candidates->value) {
00926     /* something wrong */
00927     return False;
00928   }
00929   if (call_data->choices->label_feedback &&
00930       call_data->choices->value_feedback) {
00931     lookup->candidates->label_feedback =
00932       Xmalloc(sizeof(IMFeedbackList*) * lookup->n_choices);
00933     lookup->candidates->value_feedback =
00934       Xmalloc(sizeof(IMFeedbackList*) * lookup->n_choices);
00935     if(!lookup->candidates->label_feedback ||
00936        !lookup->candidates->value_feedback) {
00937       /* something wrong */
00938       return False;
00939     }
00940     memset(lookup->candidates->label_feedback, 0,
00941           sizeof(IMFeedbackList*) * lookup->n_choices);
00942     memset(lookup->candidates->value_feedback, 0,
00943           sizeof(IMFeedbackList*) * lookup->n_choices);
00944   } else {
00945     lookup->candidates->label_feedback = 0;    
00946     lookup->candidates->value_feedback = 0;    
00947   }
00948 
00949   label = lookup->candidates->label;
00950   value = lookup->candidates->value;
00951   label_flist = lookup->candidates->label_feedback;
00952   value_flist = lookup->candidates->value_feedback;
00953 
00954   lookup->maxWidth = 0;
00955   for (i = 0; i < lookup->n_choices; i++) {
00956     CopyXIMText(ic, &(label[i]), &(call_data->choices->label[i]));
00957     CopyXIMText(ic, &(value[i]), &(call_data->choices->value[i]));
00958     if (label_flist)
00959       CopyFeedbackList(ic, &(label_flist[i]),
00960                      call_data->choices->label_feedback[i],
00961                      label[i].length);
00962     if (value_flist)
00963       CopyFeedbackList(ic, &(value_flist[i]),
00964                      call_data->choices->value_feedback[i],
00965                      value[i].length);
00966 
00967     label_str = label[i].string.multi_byte;
00968     value_str = value[i].string.multi_byte;
00969     if (call_data->choices->label_decoration != NO_DECORATION) {
00970       len = (label_str ? strlen(label_str) : 0) +
00971        (value_str ? strlen(value_str) : 0) + 5;
00972     } else {
00973       len = (label_str ? strlen(label_str) : 0) +
00974        (value_str ? strlen(value_str) : 0) + 7;
00975     }
00976     candidate = Xmalloc(len);
00977     candidate[0] = 0;
00978     if (label_str) {
00979       switch (call_data->choices->label_decoration) {
00980       case BRACKET_DECORATION:
00981        strcpy(candidate, "(");
00982        strcat(candidate, label_str);
00983        strcat(candidate, ")");
00984        break;
00985       case NO_DECORATION:
00986       default:
00987        strcpy(candidate, label_str);
00988        break;
00989       }
00990       strcat(candidate, " ");
00991     }
00992     if (value_str) strcat(candidate, value_str);
00993     len = strlen(candidate);
00994     if (lookup->maxWidth < (cand_width = XmbTextEscapement(lookup->fontset,
00995                                                     candidate, len))) {
00996       lookup->maxWidth = cand_width;
00997     }
00998     actual_width += cand_width;
00999 
01000     lookup->candidateArray[i] = candidate;
01001     lookup->labelArray[i] = (char*)strdup((label_str ? label_str : ""));
01002     lookup->candWidth[i] = cand_width;
01003     if (i % lookup->ncolumns == 0) {
01004       realRow++;
01005     }
01006   }
01007 
01008   /* adjust maxWidth for displaying title */
01009   if ((lookup->maxWidth * lookup->ncolumns) < lookup->title_width) {
01010     lookup->maxWidth = (lookup->title_width / lookup->ncolumns);
01011   }
01012 
01013   if (lookup->nrows == 1)
01014     lookup->width = actual_width + cMargin * (lookup->length > lookup->ncolumns ?
01015                                          lookup->ncolumns : lookup->length); 
01016   else
01017     lookup->width = (lookup->maxWidth + cMargin) * (lookup->length > lookup->ncolumns ?
01018                                               lookup->ncolumns : lookup->length);
01019   lookup->height = (lookup->column_height + cMargin) * realRow;
01020   lookup->width -= cMargin;
01021   lookup->height -= cMargin;
01022 
01023   return True;
01024 }
01025 
01026 static void
01027 setCandidates(XicCommon ic, XPointer p) {
01028   XIMLookupDrawCallbackStruct2 *call_data = (XIMLookupDrawCallbackStruct2*)p;
01029   LookupWin lookup = (LookupWin)(ic->gui_icpart->lookup);
01030 
01031   lookup->redraw = DRAW_ALL;              /* default */
01032 
01033   if (lookup->length == (call_data->last_index - call_data->first_index + 1) &&
01034       DRAW_NOTHING == (lookup->redraw = CompareLookupData(lookup->candidates,
01035                                                    lookup->first,
01036                                                    call_data->choices,
01037                                                    call_data->first_index,
01038                                                    lookup->length))) {
01039     /* nothing to do */
01040   } else {
01041     FreeLookupData(lookup);
01042     lookup->n_choices = call_data->n_choices;
01043     lookup->first = call_data->first_index;
01044     lookup->last = call_data->last_index;
01045     lookup->length = lookup->last - lookup->first + 1;
01046 
01047     if (lookup->length != lookup->n_choices) 
01048       fprintf(stderr, "something is wrong?\n");
01049 
01050     if (!CopyLookupData(ic, lookup, call_data)) {
01051       DestroyLookup(ic, NULL);
01052       return;
01053     }
01054   }
01055   lookup->previous = lookup->current;
01056   lookup->current = call_data->current_index;
01057   return;
01058 }
01059 
01060 static void
01061 setTitle(XicCommon ic, XPointer p) {
01062   XIMLookupDrawCallbackStruct2 *call_data = (XIMLookupDrawCallbackStruct2*)p;
01063   LookupWin lookup = (LookupWin)(ic->gui_icpart->lookup);
01064   Display *display = ic->core.im->core.display;
01065   XTextProperty prop;
01066   char *title_string;
01067 
01068   title_string = NULL;
01069 
01070   if ((call_data->title != NULL) && 
01071       (call_data->title->length != 0)) {
01072     int title_width;
01073 
01074     title_string = call_data->title->string.multi_byte;
01075 
01076     if ((lookup->title_width <= 0) ||
01077        ((NULL != lookup->title) &&
01078         (0 != strcmp(lookup->title, title_string)))) {
01079       title_width = XmbTextEscapement(lookup->fontset,
01080                                   title_string,
01081                                   strlen(title_string));
01082       XFactoryRemoveDecorationExceptTitle(display, lookup->window);
01083       free(lookup->title);
01084       lookup->title = strdup(title_string);
01085       lookup->title_width = title_width;
01086     } else {
01087       title_width = lookup->title_width;
01088       title_string = NULL;
01089     }
01090     if (lookup->maxWidth * lookup->ncolumns < title_width) {
01091       lookup->maxWidth = title_width/lookup->ncolumns;
01092     }
01093   } else {
01094     if ((NULL != lookup->title) || (-1 == lookup->title_width)) {
01095       free(lookup->title);
01096       lookup->title = NULL;
01097       lookup->title_width = 0;
01098       XFactoryRemoveDecoration(display, lookup->window);
01099 #ifdef linux
01100       title_string = "iiimx IM Lookup";   /* XFactoryRemoveDecoration()
01101                                       will not work for some window
01102                                       manager */
01103 #else
01104       title_string = "";                  /* empty string */
01105 #endif
01106     }
01107   }
01108 
01109   if (NULL != title_string) {
01110     XmbTextListToTextProperty(display,
01111                            &title_string, 1,
01112                            XCompoundTextStyle, &prop);
01113     XSetWMName(display, lookup->window, &prop);
01114     XFree(prop.value);
01115   }
01116 
01117   return;
01118 }
01119 
01120 
01121 static void
01122 DestroyLookup(XicCommon ic, XPointer p) {
01123   LookupWin lookup = (LookupWin)(ic->gui_icpart->lookup);
01124 
01125   if (!lookup) return;
01126 
01127   if (lookup->fontset && lookup->need_free_fontset) {
01128     XFactoryFreeDefaultFontSet (ic->core.im->core.display);
01129     lookup->need_free_fontset = False;
01130   }
01131   XDestroyWindow(ic->core.im->core.display,
01132                lookup->window);
01133   _XUnregisterFilter(ic->core.im->core.display, lookup->window,
01134                    RepaintLookup, (XPointer)ic);
01135   _XUnregisterFilter(ic->core.im->core.display, lookup->window,
01136                    FilterKeyPress, (XPointer)ic);
01137   _XUnregisterFilter(ic->core.im->core.display, lookup->window,
01138                    FilterMotionNotify, (XPointer)ic);
01139   _XUnregisterFilter(ic->core.im->core.display, lookup->window,
01140                    FilterButtonPress, (XPointer)ic);
01141   _XUnregisterFilter(ic->core.im->core.display, lookup->window,
01142                    FilterButtonRelease, (XPointer)ic);
01143 
01144   if (lookup->gc) XFreeGC(ic->core.im->core.display, lookup->gc);
01145   if (lookup->rgc) XFreeGC(ic->core.im->core.display, lookup->rgc);
01146 
01147   if (lookup->candidateArray) Xfree(lookup->candidateArray);
01148   if (lookup->labelArray) Xfree(lookup->labelArray);
01149   if (lookup->candidates) Xfree(lookup->candidates);
01150   if (lookup->candWidth) Xfree(lookup->candWidth);
01151   Xfree(lookup);
01152   ic->gui_icpart->lookup = (LookupWin)NULL;
01153   return;
01154 }
01155 
01156 static void
01157 createProc(XicCommon ic, XPointer p) {
01158   /* nothing to do until startProc is called  */
01159   return;
01160 }
01161 
01162 static void
01163 startProc(XicCommon ic, XPointer p) {
01164   XIMLookupStartCallbackStruct2 *call_data = (XIMLookupStartCallbackStruct2*)p;
01165   LookupWin lookup = (LookupWin)(ic->gui_icpart->lookup);
01166 
01167   TRACE_MESSAGE('l', ("startProc\n"));
01168 
01169   if (!lookup) {
01170     SetupLookupExt(ic);
01171     lookup = ic->gui_icpart->lookup;
01172   }
01173   if (!lookup) return;
01174 
01175   SetupLookupWindow(ic);
01176 
01177   moveLookupWindow(ic);
01178 
01179   lookup->ncolumns = call_data->ncolumns;
01180   lookup->nrows = call_data->nrows;
01181   lookup->choice_per_window = call_data->choice_per_window;
01182   return;
01183 }
01184 
01185 static void
01186 drawProc(XicCommon ic, XPointer p) {
01187   LookupWin lookup = (LookupWin)(ic->gui_icpart->lookup);
01188 
01189   TRACE_MESSAGE('l', ("drawProc\n"));
01190 
01191   if (!lookup) return;
01192 
01193   setTitle(ic, p);
01194 
01195   setCandidates(ic, p);
01196 
01197   resizeLookupWindow(ic);
01198 
01199   if (IsIMLookupEnabled ()) {
01200     XMapRaised(ic->core.im->core.display, lookup->window);
01201 
01202     if (True == lookup->mapped) {
01203       UpdateLookup(ic);
01204     }
01205 
01206     lookup->mapped = True;
01207   }
01208 
01209   return;
01210 }
01211 
01212 static void
01213 processProc(XicCommon ic, XPointer p) {
01214   fprintf(stderr, "lookup process\n");
01215 }
01216 
01217 static void
01218 doneProc(XicCommon ic, XPointer p) {
01219   LookupWin lookup = (LookupWin)(ic->gui_icpart->lookup);
01220 
01221   TRACE_MESSAGE('l', ("doneProc\n"));
01222 
01223   if (!lookup) return;
01224 
01225   if (IsIMLookupEnabled () || lookup->mapped) {
01226     lookup->mapped = False;
01227     XUnmapWindow(ic->core.im->core.display,
01228                lookup->window);
01229   }
01230 
01231   FreeLookupData(lookup);
01232   lookup->n_choices = 0;
01233   lookup->first = 0;
01234   lookup->last = 0;
01235   lookup->length = 0;
01236 
01237   if (NULL != lookup->title) {
01238     free(lookup->title);
01239     lookup->title = NULL;
01240     lookup->title_width = -1;
01241   }
01242 
01243   return;
01244 }
01245 
01246 static void
01247 moveProc(XicCommon ic, XPointer p) {
01248   LookupWin lookup = (LookupWin)(ic->gui_icpart->lookup);
01249   Display *display = ic->core.im->core.display;
01250   XTextProperty prop;
01251 
01252   if (!lookup) return;
01253 
01254   /* if lookup window has a title, we don't move it */
01255   if (XGetWMName(display, lookup->window, &prop)) {
01256     if (prop.nitems == 0)
01257       /* we move lookup window if there is no title */
01258       moveLookupWindow(ic);
01259   }
01260   return;
01261 }
01262 
01263 static void
01264 setFocusLookup(XicCommon ic, XPointer p) {
01265   LookupWin lookup = (LookupWin)(ic->gui_icpart->lookup);
01266   Display *display = ic->core.im->core.display;
01267 
01268   if (!lookup) return;
01269   if (lookup->mapped)
01270      XRaiseWindow(display, lookup->window);
01271   return;
01272 }
01273 typedef void (*lookupCB)(XicCommon, XPointer);
01274 
01275 static lookupCB lookup_methods[] = {
01276   createProc,               /* LOOKUP_CREATE */
01277   startProc,                /* LOOKUP_START */
01278   drawProc,                 /* LOOKUP_DRAW */
01279   processProc,                     /* LOOKUP_PROCESS */
01280   doneProc,                 /* LOOKUP_DONE */
01281   moveProc,                 /* LOOKUP_MOVE */
01282   DestroyLookup,            /* LOOKUP_DESTROY */
01283   setFocusLookup            /* LOOKUP_SETFOCUS */
01284 };
01285 
01286 /* Public function */
01287 void
01288 ChangeLookup(XIC xic, LookupAttr reason, XPointer call_data) {
01289   XicCommon ic = (XicCommon)xic;
01290   if (reason > LOOKUP_SETFOCUS) return;
01291   lookup_methods[reason](ic, call_data);
01292   return;
01293 }