Back to index

im-sdk  12.3.91
lookup.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 <stdio.h>
00043 #include <X11/keysym.h>
00044 #include "xiiimp.h"
00045 #include "iiimpIM.h"
00046 #include "guiIM.h"
00047 #include "composeIM.h"
00048 #include "codeinput.h"
00049 #include "lookup.h"
00050 
00051 #define MAX_LABEL_SIZE 0x5e
00052 #define LABEL_OFF 0x21
00053 
00054 static XIMFeedback no_feedback[] = {
00055   0, 0
00056 };
00057 
00058 static Bool
00059 DefillLookup(LocalLookupExt *luext, int start_index, int n_choices) {
00060   XIMText *p;
00061   XIMChoiceObject2 *LUTable = (XIMChoiceObject2*)luext->LUTable;
00062   int i;
00063   if (!LUTable) return True;
00064 
00065   p = LUTable->label;
00066   if (!p) return True;
00067   for (i = 0; p < &LUTable->label[n_choices]; p++, i++) {
00068     if (p->string.multi_byte) {
00069       Xfree(p->string.multi_byte);
00070       p->string.multi_byte = NULL;
00071     } else
00072       break;
00073   }
00074   if (LUTable->label) {
00075     Xfree(LUTable->label);
00076     LUTable->label = 0;
00077   }
00078   p = LUTable->value;
00079   if (!p) return True;
00080   for (i = 0; p < &LUTable->value[n_choices]; p++, i++) {
00081     if (p->string.multi_byte) {
00082       Xfree(p->string.multi_byte);
00083       p->string.multi_byte = NULL;
00084     } else
00085       break;
00086   }
00087   if (LUTable->value) {
00088     Xfree(LUTable->value);
00089     LUTable->value = 0;
00090   }
00091   return True;
00092 }
00093 
00094 static Bool
00095 FillLookup(XicCommon ic, LocalLookupExt *luext,
00096           int start_index, int n_choices) {
00097   XIMChoiceObject2 *LUTable;
00098   XIMText *p;
00099   int i;
00100   wchar_t wstr[2];
00101   XimCommon im = (XimCommon)ic->core.im;
00102   size_t mb_len;
00103 
00104   if (!luext->LUTable) {
00105     LUTable = Xmalloc(sizeof(XIMChoiceObject2));
00106     memset(LUTable, 0, sizeof(XIMChoiceObject2));
00107   } else {
00108     LUTable = (XIMChoiceObject2*)luext->LUTable;
00109   }
00110   if (!LUTable) return False;
00111 
00112   LUTable->label_decoration = BRACKET_DECORATION;
00113 
00114   LUTable->label = Xmalloc(sizeof(XIMText) * n_choices);
00115   LUTable->value = Xmalloc(sizeof(XIMText) * n_choices);
00116 
00117   if (!LUTable->label || !LUTable->value) {
00118     /* something is wrong */
00119     return False;
00120   }
00121   memset(LUTable->label, 0, sizeof(XIMText) * n_choices);
00122   memset(LUTable->value, 0, sizeof(XIMText) * n_choices);
00123 
00124   p = LUTable->label;
00125   for (i = 0; p < &LUTable->label[n_choices]; p++, i++) {
00126     p->length = 1;
00127     p->feedback = no_feedback;
00128     p->encoding_is_wchar = False;
00129 
00130     wstr[0] = (wchar_t)(i + LABEL_OFF);
00131     wstr[1] = (wchar_t)0;
00132 
00133     mb_len = XLC_PUBLIC(im->core.lcd, mb_cur_max);
00134     p->string.multi_byte = Xmalloc(mb_len + 1);
00135     if (p->string.multi_byte) {
00136       if ((mb_len = IIimpWcstoMbs(im, wstr, 1,
00137                               p->string.multi_byte, mb_len, NULL)) < 0) {
00138        return False;
00139       }
00140       p->string.multi_byte[mb_len] = 0;
00141     } else {
00142       goto error;
00143     }
00144   }
00145   p = LUTable->value;
00146   for (i = 0; p < &LUTable->value[n_choices]; p++, i++) {
00147     p->length = 1;
00148     p->feedback = no_feedback;
00149     p->encoding_is_wchar = False;
00150 
00151     wstr[0] = (wchar_t)(start_index + i);
00152     wstr[1] = (wchar_t)0;
00153 
00154     mb_len = XLC_PUBLIC(im->core.lcd, mb_cur_max);
00155     p->string.multi_byte = Xmalloc(mb_len + 1);
00156     if (p->string.multi_byte) {
00157       if ((mb_len = IIimpWcstoMbs(im, wstr, 1,
00158                               p->string.multi_byte, mb_len, NULL)) < 0) {
00159        return False;
00160       }
00161       p->string.multi_byte[mb_len] = 0;
00162     } else {
00163       goto error;
00164     }
00165   }
00166   luext->LUTable = (XPointer)LUTable;
00167   return True;
00168  error:
00169   /* memory clean up */
00170   DefillLookup(luext, start_index, n_choices);
00171   return False;
00172 }
00173 
00174 static Bool
00175 setup_local_lookup_ext(XicCommon ic) {
00176   LocalLookupExt *hook = (LocalLookupExt*)(ic->local_icpart->lookup_ext);
00177 
00178   if (hook) return False;
00179 
00180   hook = (LocalLookupExt *)Xmalloc(sizeof(LocalLookupExt));
00181   if (!hook) return False;
00182 
00183   memset(hook, 0, sizeof(LocalLookupExt));
00184   ic->local_icpart->lookup_ext = hook;
00185   return True;
00186 }
00187 
00188 #define XIMIsMaster 1
00189 
00190 /* public */
00191 void
00192 Ximp_Local_Lookup_Create(XicCommon ic) {
00193   setup_local_lookup_ext(ic);
00194   return;
00195 }
00196 
00197 void
00198 Ximp_Local_Lookup_Start(XicCommon ic) {
00199   LocalLookupExt *hook = (LocalLookupExt*)(ic->local_icpart->lookup_ext);
00200   LocalIMState *state = (LocalIMState *)(ic->local_icpart->imstate);
00201   XIMLookupStartCallbackStruct2 cbdata;
00202 
00203   if (!hook) {
00204     if (!setup_local_lookup_ext(ic))
00205       return;
00206     hook = (LocalLookupExt*)(ic->local_icpart->lookup_ext);
00207     if (!hook) return;
00208   }
00209 
00210   memset(&cbdata, 0, sizeof(XIMLookupStartCallbackStruct2));
00211   cbdata.which_is_master = XIMIsMaster;
00212   if (state->attr && state->type == LookupState) {
00213     cbdata.nrows = state->attr->_attr_u.LUstruct.num_of_rows;
00214     cbdata.ncolumns = state->attr->_attr_u.LUstruct.num_of_cols;
00215     cbdata.choice_per_window = state->attr->_attr_u.LUstruct.num_of_cands;
00216   } else {
00217     cbdata.nrows = 6;
00218     cbdata.ncolumns = 16;
00219     cbdata.choice_per_window = 80;
00220   }
00221   hook->choice_per_window = cbdata.choice_per_window; /* for drawing */
00222   hook->nrows = cbdata.nrows; /* for drawing */
00223   hook->ncolumns = cbdata.ncolumns; /* for drawing */
00224   cbdata.who_owns_label = XIMOwnsLabel;
00225 
00226   XIC_GUI(ic, change_lookup)((XIC)ic, LOOKUP_START,
00227                           (XPointer)&cbdata);
00228   return;
00229 }
00230 
00231 void
00232 Ximp_Local_Lookup_Draw(XicCommon ic) {
00233   LocalLookupExt *hook = (LocalLookupExt*)(ic->local_icpart->lookup_ext);
00234   XIMLookupDrawCallbackStruct2 cbdata;
00235   XIMText title_text;
00236   char stitle[80];
00237   size_t tlen;
00238   int startindex, endindex;
00239 
00240   if (!hook) {
00241     Ximp_Local_Lookup_Start(ic);
00242     hook = (LocalLookupExt *)(ic->local_icpart->lookup_ext);
00243     if (!hook) return;
00244   }
00245   DefillLookup(hook, hook->startindex, hook->n_choices);
00246 
00247   startindex = hook->startindex;
00248 
00249   endindex = startindex + ((hook->end_range == -1) ? 
00250                         hook->choice_per_window : hook->end_range);
00251 
00252   if (endindex < startindex) return;
00253 
00254   if (0xffff0000 & endindex) {
00255     endindex = 0x0000ffff;
00256   }
00257 
00258   memset(&cbdata, 0, sizeof(XIMLookupDrawCallbackStruct2));
00259   cbdata.n_choices =
00260     ((endindex - startindex) + 1 > hook->choice_per_window) ?
00261     hook->choice_per_window : (endindex - startindex) + 1;
00262   hook->n_choices = cbdata.n_choices;
00263   cbdata.first_index = 0;
00264   cbdata.current_index = hook->currentindex;
00265   cbdata.last_index = cbdata.n_choices - 1;
00266 
00267   if (!FillLookup(ic, hook, startindex, cbdata.n_choices)) return;
00268 
00269   cbdata.choices = (XIMChoiceObject2*)hook->LUTable;
00270 
00271   if (hook->crange != -1) {
00272     sprintf(stitle, "%s:  0x%04x to 0x%04x",
00273            hook->range[hook->crange].RangeName+3, startindex, 
00274            (startindex + (cbdata.n_choices - 1)));
00275   } else {
00276     sprintf(stitle, "UNICODE Lookup:  0x%04x to 0x%04x",
00277            startindex, (startindex +(cbdata.n_choices - 1)));
00278   }
00279   tlen = strlen(stitle);
00280 
00281   cbdata.title = &title_text;
00282   memset((char *)cbdata.title, 0, sizeof(XIMText));
00283   cbdata.title->length = tlen;
00284   cbdata.title->feedback = (XIMFeedback*)Xmalloc(sizeof(XIMFeedback) * tlen);
00285   if (cbdata.title->feedback) {
00286     XIMFeedback *p;
00287     for (p = cbdata.title->feedback; p < &cbdata.title->feedback[tlen]; p++) {
00288       *p = 0;
00289     }
00290   } else {
00291     return;
00292   }
00293 
00294   cbdata.title->encoding_is_wchar = False;
00295   cbdata.title->string.multi_byte = stitle;
00296 
00297   XIC_GUI(ic, change_lookup)((XIC)ic, LOOKUP_DRAW, (XPointer)&cbdata);
00298   hook->mapped = LOOKUP_MAPPED;
00299 
00300   if (cbdata.title->feedback) {
00301     Xfree(cbdata.title->feedback);
00302   }
00303   return;
00304 }
00305 
00306 void
00307 Ximp_Local_Lookup_Done(XicCommon ic) {
00308   LocalLookupExt *hook = (LocalLookupExt*)(ic->local_icpart->lookup_ext);
00309   if (!hook) return;
00310   DefillLookup(hook, hook->startindex, hook->n_choices);
00311   XIC_GUI(ic, change_lookup)((XIC)ic, LOOKUP_DONE, NULL);
00312   hook->mapped = LOOKUP_UNMAPPED;
00313 }
00314 
00315 static void
00316 lookup_commit(XicCommon ic, char *mb, XEvent *ev) {
00317   Display *display = ic->core.im->core.display;
00318   size_t len = strlen(mb);
00319   XimCommon im = (XimCommon)ic->core.im;
00320   Bool useUnicode;
00321 
00322   if (!display) {
00323     return;
00324   }
00325 
00326   useUnicode = (XIM_USE_UNICODE(im) &&
00327               NULL != ic->commit_string_callback.callback);
00328   /* private XIC extension */
00329   if (useUnicode) {
00330     XIMCallback *cb = &ic->commit_string_callback;
00331     XIMUnicodeText cbtext;
00332     size_t len_utf16 = 256; /* enough */
00333     char buffer[256];
00334     memset(&cbtext, 0, sizeof(XIMUnicodeText));
00335     cbtext.string.multi_byte = buffer;
00336     cbtext.length = len_utf16;
00337     IMConvertFromUTF8ToUTF16(mb, len,
00338                           (char**)&cbtext.string.utf16_char,
00339                           &len_utf16);
00340     cbtext.length -= len_utf16;
00341     cbtext.length /= sizeof(unsigned short);
00342     (*cb->callback)((XIM)ic, cb->client_data, (XPointer)&cbtext);
00343   } else {
00344     if (ic->local_icpart->composed != (DefTree *)NULL ) {
00345       if (ic->local_icpart->composed->mb != NULL )
00346        Xfree(ic->local_icpart->composed->mb);
00347       ic->local_icpart->composed->mb = (char *)NULL;
00348       Xfree(ic->local_icpart->composed);
00349       ic->local_icpart->composed = (DefTree *)NULL;
00350     }
00351     if ((ic->local_icpart->composed =
00352         (DefTree *)Xmalloc(sizeof(DefTree))) == NULL)
00353       return;
00354     memset(ic->local_icpart->composed, 0, sizeof(DefTree));
00355 
00356     if ((ic->local_icpart->composed->mb = (char *)
00357         Xmalloc((len + 1) * sizeof(char))) == (char *)NULL) {
00358       return;
00359     }
00360     strncpy(ic->local_icpart->composed->mb, mb, len);
00361     ic->local_icpart->composed->mb[len] = 0;
00362     ic->local_icpart->composed->keysym_return = NoSymbol;
00363     /* return back to client KeyPressEvent keycode == 0 */
00364     ev->type = KeyPress;
00365     ev->xkey.keycode = XIM_COMPOSE_KEYCODE;
00366     ev->xkey.window = ic->core.focus_window;
00367     XPutBackEvent(display, ev);
00368   }
00369 
00370   Ximp_Local_Preedit_Done(ic);
00371 
00372   return;
00373 }
00374 
00375 Bool
00376 Ximp_Local_Lookup_Button_Filter(XicCommon ic,
00377                             int index, XEvent *ev) {
00378   LocalLookupExt *hook = (LocalLookupExt*)(ic->local_icpart->lookup_ext);
00379   XIMChoiceObject2 *LUTable;
00380   XIMText *p;
00381 
00382   if (!hook) return False;
00383   LUTable = (XIMChoiceObject2*)hook->LUTable;
00384   p = &LUTable->value[index];
00385   lookup_commit(ic, p->string.multi_byte, ev);
00386   return True;
00387 }
00388 
00389 Bool
00390 Ximp_Local_Lookup_Input_Filter(XicCommon ic, char *input, XEvent *ev) {
00391   LocalLookupExt *hook = (LocalLookupExt *)(ic->local_icpart->lookup_ext);
00392   int i;
00393   XIMChoiceObject2 *LUTable;
00394   XIMText *p;
00395   LUTable = (XIMChoiceObject2*)hook->LUTable;
00396   if (!LUTable) return False;
00397   p = LUTable->label;
00398   if (!p) return False;
00399   /* if given input matches to a label, commit it */
00400   for (i = 0; p < &LUTable->label[hook->n_choices]; p++, i++) {
00401     if (!strcmp(p->string.multi_byte, input)) {
00402       Ximp_Local_Lookup_Button_Filter(ic, i, ev);
00403       return True;          /* filtered */
00404     }
00405   }
00406   return False;                    /* not filtered */
00407 }
00408 
00409 Bool
00410 Ximp_Local_Lookup_Action_Filter(XicCommon ic, ActionType action,
00411                             XEvent *ev) {
00412   LocalLookupExt *hook = (LocalLookupExt*)(ic->local_icpart->lookup_ext);
00413   int startindex, endindex;
00414 
00415   if (!hook) return False;
00416   switch (action) {
00417   case TopPage:
00418     /* top page */
00419     startindex = hook->begin_range;
00420     if (hook->startindex == startindex) {
00421       /* already at top */
00422       return False;
00423     }
00424     hook->startindex = startindex;
00425     Ximp_Local_Lookup_Draw(ic);
00426     break;
00427   case LastPage:
00428     /* last page */
00429     endindex = hook->end_range == -1 ? 0xffff : hook->end_range;
00430     if (hook->startindex + hook->choice_per_window - 1 == endindex) {
00431       /* already at last */
00432       return False;
00433     }
00434     startindex = endindex - hook->choice_per_window + 1;
00435     hook->startindex = startindex;
00436     Ximp_Local_Lookup_Draw(ic);
00437     break;
00438   case NextPage:
00439     /* next page */
00440     endindex = hook->end_range == -1 ? 0xffff : hook->end_range;
00441     if (hook->startindex + hook->choice_per_window - 1 == endindex) {
00442       /* already at last */
00443       return False;
00444     }
00445     startindex = hook->startindex + hook->choice_per_window;
00446     if (startindex + hook->choice_per_window > endindex) {
00447       startindex = endindex - hook->choice_per_window + 1;
00448     }
00449     hook->startindex = startindex;
00450     Ximp_Local_Lookup_Draw(ic);
00451     break;
00452   case PrevPage:
00453     /* prev page */
00454     startindex = hook->begin_range;
00455     if (hook->startindex == startindex) {
00456       /* already at top */
00457       return False;
00458     }
00459     startindex = hook->startindex - hook->choice_per_window;
00460     if (startindex < hook->begin_range) {
00461       startindex = hook->begin_range;
00462     }
00463     hook->startindex = startindex;
00464     Ximp_Local_Lookup_Draw(ic);
00465     break;
00466   case NextCand:
00467     /* move focus to next cand */
00468     if (hook->currentindex == hook->choice_per_window - 1) {
00469       /* move to top */
00470       hook->currentindex = 0;
00471     } else {
00472       hook->currentindex++;
00473     }
00474     Ximp_Local_Lookup_Draw(ic);
00475     break;
00476   case PrevCand:
00477     /* move focus to prev cand */
00478     if (hook->currentindex == 0) {
00479       /* move to last */
00480       hook->currentindex = hook->choice_per_window - 1;
00481     } else {
00482       hook->currentindex--;
00483     }
00484     Ximp_Local_Lookup_Draw(ic);
00485     break;
00486   case UpCand:
00487     /* move focus to up cand */
00488     hook->currentindex -= hook->ncolumns;
00489     if (hook->currentindex < 0) {
00490       hook->currentindex += hook->choice_per_window;
00491     }
00492     Ximp_Local_Lookup_Draw(ic);
00493     break;
00494   case DownCand:
00495     /* move focus to down cand */
00496     hook->currentindex += hook->ncolumns;
00497     if (hook->currentindex >= hook->choice_per_window) {
00498       hook->currentindex -= hook->choice_per_window;
00499     }
00500     Ximp_Local_Lookup_Draw(ic);
00501     break;
00502   case SelectCand:
00503     {
00504       /* select cand at currentindex */
00505       XIMText *p;
00506       XIMChoiceObject2 *LUTable;
00507       LUTable = (XIMChoiceObject2*)hook->LUTable;
00508       p = &LUTable->value[hook->currentindex];
00509       lookup_commit(ic, p->string.multi_byte, ev);
00510     }
00511     break;
00512   default:
00513     break;
00514   }
00515   return True;
00516 }
00517 
00518 void
00519 Ximp_Local_Lookup_Destroy(XicCommon ic) {
00520   LocalLookupExt *hook = (LocalLookupExt *)(ic->local_icpart->lookup_ext);
00521 
00522   if (!hook) return;
00523 
00524   if (hook->LUTable) {
00525     DefillLookup(hook, hook->startindex, hook->n_choices);
00526     Xfree(hook->LUTable);
00527   }
00528   Xfree(hook);
00529   ic->local_icpart->lookup_ext = 0;
00530   return;
00531 }