Back to index

im-sdk  12.3.91
codeinput.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 "xiiimp.h"
00044 #include "guiIM.h"
00045 #include "composeIM.h"
00046 #include <X11/keysym.h>
00047 #include "lookup.h"
00048 #include "codeinput.h"
00049 #include "iiimpIM.h"
00050 
00051 #define PREEDIT_STRLEN 15
00052 
00053 static Bool
00054 setup_local_preedit_ext(XicCommon ic)
00055 {
00056   LocalPreeditExt *hook = (LocalPreeditExt *)(ic->local_icpart->preedit_ext);
00057 
00058   if (hook) return (True);
00059 
00060   hook = (LocalPreeditExt *)Xmalloc(sizeof(LocalPreeditExt));
00061   if(!hook)
00062     return (False);
00063   memset(hook, 0, sizeof(LocalPreeditExt));
00064 
00065   hook->preedit_text = Xmalloc(sizeof(char) * PREEDIT_STRLEN);
00066   if(!hook->preedit_text) {
00067     Xfree(hook);
00068     return (False);
00069   }
00070   hook->preedit_alloc_len = PREEDIT_STRLEN;
00071   hook->preedit_len = 0;
00072   ic->local_icpart->preedit_ext = (void *)hook;
00073   return(True);
00074 }
00075 
00076 /* public */
00077 void
00078 Ximp_Local_Preedit_Create(XicCommon ic) {
00079   setup_local_preedit_ext(ic);
00080   return;
00081 }
00082 
00083 void
00084 Ximp_Local_Preedit_Start(XicCommon ic) {
00085   LocalPreeditExt *hook = (LocalPreeditExt *)(ic->local_icpart->preedit_ext);
00086 
00087   if (!hook) {
00088     if (!setup_local_preedit_ext(ic))
00089       return;
00090     hook = (LocalPreeditExt *)(ic->local_icpart->preedit_ext);
00091   }
00092   {
00093     XIMCallback *cb = &ic->core.preedit_attr.start_callback;
00094     int max_len = -1;
00095     if (cb->callback &&
00096        ic->core.input_style & XIMPreeditCallbacks)
00097       max_len = (*(int(*)())cb->callback)(ic, cb->client_data, NULL);
00098     else
00099       XIC_GUI(ic, change_preedit)((XIC)ic, PREEDIT_START, NULL);
00100   }
00101 }
00102 
00103 Bool
00104 Ximp_Local_Preedit_Draw(XicCommon ic, KeySym keysym)
00105 {
00106   XIMText cbtext;
00107   XIMPreeditDrawCallbackStruct call_data;
00108   XIMDrawTextStruct preedit_draw;
00109   LocalIMState *state = (LocalIMState *)(ic->local_icpart->imstate);
00110   LocalPreeditExt *hook = (LocalPreeditExt *)(ic->local_icpart->preedit_ext);
00111   int max_len;
00112   InputType mode;
00113   if (!state || !state->attr) return False;
00114 
00115   if (!hook) {
00116     Ximp_Local_Preedit_Start(ic);
00117     hook = (LocalPreeditExt *)(ic->local_icpart->preedit_ext);
00118     if (!hook) return False;
00119   }
00120 
00121   mode = state->attr->_attr_u.CIstruct.type_of_input;
00122   max_len = state->attr->_attr_u.CIstruct.max_input_len;
00123 
00124   memset(&call_data, 0, sizeof(XIMPreeditDrawCallbackStruct));
00125   memset(&cbtext, 0, sizeof(XIMText));
00126 
00127   if ( (keysym >= XK_0 && keysym <= XK_9) ||     /* 0 - 9 */
00128        (keysym >= XK_A && keysym <= XK_F) ||     /* A - F */
00129        (keysym >= XK_a && keysym <= XK_f) ) {    /* a - f */
00130     char *str = XKeysymToString(keysym);
00131     if (str &&
00132        (((mode == HEX) && strspn(str, "0123456789abcdefABCDEF")) ||
00133         ((mode == OCTET) && strspn(str, "01234567")))) {
00134       XIMFeedback *p;
00135       /* append */
00136       size_t len = strlen(str);
00137       cbtext.length = len;
00138       cbtext.encoding_is_wchar = 0;
00139       cbtext.string.multi_byte = strdup(str);
00140 
00141       cbtext.feedback = (XIMFeedback*)Xmalloc(sizeof(XIMFeedback) * len);
00142       if (cbtext.feedback) {
00143        for (p = cbtext.feedback; p < &cbtext.feedback[len]; p++) {
00144          *p = XIMReverse;
00145        }
00146       } else {
00147        return False;
00148       }
00149       call_data.caret = hook->preedit_len + len;
00150       call_data.chg_first = hook->preedit_len;
00151       call_data.chg_length = 0;
00152       call_data.text = &cbtext;
00153 
00154       if (hook->preedit_alloc_len < hook->preedit_len + len) {
00155        hook->preedit_alloc_len += 20;
00156        hook->preedit_text = Xrealloc(hook->preedit_text,
00157                                   sizeof(char) * hook->preedit_alloc_len);
00158        if (!hook->preedit_text) return False;
00159       }
00160       if (hook->preedit_len) 
00161        strcat(hook->preedit_text, str);
00162       else
00163        strcpy(hook->preedit_text, str);
00164       hook->preedit_len += len;
00165     }
00166   } else if ((keysym == XK_Delete || keysym == XK_BackSpace) ) {
00167     /* delete 1 char */
00168     if (hook->preedit_len == 0) return False;
00169 
00170     hook->preedit_len--;
00171     call_data.caret = hook->preedit_len;
00172     call_data.chg_first = hook->preedit_len;
00173     call_data.chg_length = 1;
00174     call_data.text = 0;
00175     hook->preedit_text[hook->preedit_len] = '\0';
00176   }
00177   preedit_draw.call_data = (XPointer)&call_data;
00178   preedit_draw.feedback_list = 0;
00179 
00180   {
00181     XIMCallback *cb;
00182     cb = &ic->core.preedit_attr.draw_callback;
00183     if (cb->callback &&
00184        ic->core.input_style & XIMPreeditCallbacks)
00185       (*cb->callback)((XIC)ic, cb->client_data, (XPointer)&call_data);
00186     else
00187       XIC_GUI(ic, change_preedit)((XIC)ic, PREEDIT_DRAW,
00188                               (XPointer)&preedit_draw);
00189   }
00190   if (cbtext.feedback) Xfree(cbtext.feedback);
00191   if (cbtext.string.multi_byte) Xfree(cbtext.string.multi_byte);
00192   return True;
00193 }
00194 
00195 void
00196 Ximp_Local_Preedit_Done(XicCommon ic) {
00197   LocalPreeditExt *hook = (LocalPreeditExt *)(ic->local_icpart->preedit_ext);
00198 
00199   if (!hook) return;
00200 
00201   /* delete preedit chars if any */
00202   if (hook->preedit_len) {
00203     XIMPreeditDrawCallbackStruct call_data;
00204     XIMDrawTextStruct preedit_draw;
00205     call_data.caret = 0;
00206     call_data.chg_first = 0;
00207     call_data.chg_length = hook->preedit_len;
00208     call_data.text = 0;
00209     preedit_draw.call_data = (XPointer)&call_data;
00210     preedit_draw.feedback_list = 0;
00211 
00212     {
00213       XIMCallback *cb;
00214       cb = &ic->core.preedit_attr.draw_callback;
00215       if (cb->callback &&
00216          ic->core.input_style & XIMPreeditCallbacks)
00217        (*cb->callback)((XIC)ic, cb->client_data, (XPointer)&call_data);
00218       else
00219        XIC_GUI(ic, change_preedit)((XIC)ic, PREEDIT_DRAW,
00220                                 (XPointer)&preedit_draw);
00221     }
00222   }
00223   {
00224     XIMCallback *cb;
00225     cb = &ic->core.preedit_attr.done_callback;
00226     if (cb->callback &&
00227        ic->core.input_style & XIMPreeditCallbacks)
00228       (*cb->callback)((XIC)ic, cb->client_data, NULL);
00229     else
00230       XIC_GUI(ic, change_preedit)((XIC)ic, PREEDIT_DONE, NULL);
00231   }
00232 
00233   Ximp_Local_Lookup_Done(ic);
00234 
00235   if (hook->preedit_text) Xfree(hook->preedit_text);
00236   hook->preedit_text = 0;
00237   hook->preedit_len = 0;
00238   hook->preedit_alloc_len = 0;
00239   Xfree(hook);
00240   ic->local_icpart->preedit_ext = 0;
00241   return;
00242 }
00243 
00244 #define LOCAL_MB_BUFSIZE 128
00245 
00246 /* convert current input(code sequence) and commit */
00247 void
00248 Ximp_Local_Preedit_Conv(XicCommon ic, XEvent *ev) {
00249   LocalIMState *state = (LocalIMState *)(ic->local_icpart->imstate);
00250   LocalPreeditExt *hook = (LocalPreeditExt *)(ic->local_icpart->preedit_ext);
00251   char tmpstr[80], *ret;
00252   int twc[2];
00253   char local_mb_buf[LOCAL_MB_BUFSIZE];
00254   extern int errno;
00255   size_t len;
00256   InputType mode;
00257   Display *display = ic->core.im->core.display;
00258   XimCommon im = (XimCommon)ic->core.im;
00259   Bool useUnicode;
00260 
00261   if (!hook || !display || !state || !state->attr) return;
00262 
00263   mode = state->attr->_attr_u.CIstruct.type_of_input;
00264 
00265   if (mode == HEX)
00266     sprintf(tmpstr, "0X%s", hook->preedit_text);
00267   else
00268     sprintf(tmpstr, "0%s", hook->preedit_text);
00269 
00270   Ximp_Local_Preedit_Done(ic);
00271 
00272   twc[0] = (wchar_t)strtol(tmpstr, &ret, 0);
00273   if (twc[0] == 0 && errno == EINVAL) return;
00274 
00275   while (0xffff0000 &twc[0]) {
00276     if (HEX == mode) {
00277       twc[0] >>= 4;
00278     } else {
00279       twc[0] >>= 3;
00280     }
00281   }
00282 
00283   twc[1] = L'\0';
00284 
00285   useUnicode = (XIM_USE_UNICODE(im) &&
00286               NULL != ic->commit_string_callback.callback);
00287 
00288   /* private XIC extension */
00289   if (useUnicode) {
00290     XIMCallback *cb = &ic->commit_string_callback;
00291     XIMUnicodeText cbtext;
00292     memset(&cbtext, 0, sizeof(XIMUnicodeText));
00293     cbtext.string.utf16_char = (unsigned short*)&twc[0];
00294     cbtext.length = 1;
00295     (*cb->callback)((XIC)ic,
00296                   cb->client_data,
00297                   (XPointer)&cbtext);
00298   } else {
00299     len = IIimpWcstoMbs(im, (wchar_t*)twc, 1,
00300                      local_mb_buf, LOCAL_MB_BUFSIZE - 1, NULL);
00301     if (len < 1) return;
00302     if (len <= LOCAL_MB_BUFSIZE) local_mb_buf[len] = '\0';
00303 
00304     if (ic->local_icpart->composed != (DefTree *)NULL) {
00305       if (ic->local_icpart->composed->mb != NULL) {
00306        Xfree(ic->local_icpart->composed->mb);
00307        ic->local_icpart->composed->mb = NULL;
00308       }
00309       XFree(ic->local_icpart->composed);
00310       ic->local_icpart->composed = (DefTree *)NULL;
00311     }
00312     if ((ic->local_icpart->composed = (DefTree *)Xmalloc(sizeof(DefTree))) == NULL)
00313       return;
00314 
00315     memset(ic->local_icpart->composed, 0, sizeof(DefTree));
00316 
00317     if ((ic->local_icpart->composed->mb =
00318         (char *)Xmalloc((len + 1) * sizeof(char))) == (char *)NULL) {
00319       XFree(ic->local_icpart->composed);
00320       ic->local_icpart->composed = (DefTree *)NULL;
00321       return;
00322     }
00323     memset(ic->local_icpart->composed->mb, 0, len+1);
00324     bcopy(local_mb_buf, ic->local_icpart->composed->mb,
00325          (len + 1) * sizeof(char));
00326     ic->local_icpart->composed->keysym_return = NoSymbol;
00327 
00328     /* return back to client KeyPressEvent keycode == 0 */
00329     ev->xkey.keycode = XIM_COMPOSE_KEYCODE;
00330     XPutBackEvent(display, ev);
00331   }
00332   return;
00333 }
00334 
00335 /* get candidates for current input(code sequence) */
00336 void
00337 Ximp_Local_Preedit_Lookup(XicCommon ic, XEvent *ev) {
00338   LocalIMState *state = (LocalIMState *)(ic->local_icpart->imstate);
00339   LocalPreeditExt *hook = (LocalPreeditExt *)(ic->local_icpart->preedit_ext);
00340   int chindex, zeropad;
00341   char tmpstr[80], format[80], *ret;
00342   int max_len;
00343   InputType mode;
00344 
00345   if (!hook || !state || !state->attr) return;
00346 
00347   mode = state->attr->_attr_u.CIstruct.type_of_input;
00348   max_len = state->attr->_attr_u.CIstruct.max_input_len;
00349 
00350   zeropad = max_len - strlen(hook->preedit_text);
00351   if (mode == HEX)
00352     sprintf(format, "0X%%s%%0%dd", zeropad);
00353   else
00354     sprintf(format, "0%%s%%0%dd", zeropad);
00355 
00356   sprintf(tmpstr, format, hook->preedit_text, 0);
00357   chindex = (int)strtol(tmpstr, &ret, 0);
00358 
00359   while (0xffff0000 & chindex) {
00360     if (HEX == mode) {
00361       chindex >>= 4;
00362     } else {
00363       chindex >>= 3;
00364     }
00365   }
00366 
00367   Ximp_Local_Lookup_Start(ic);
00368 
00369   if (chindex != -1 ) {
00370     LocalLookupExt *hook2 = (LocalLookupExt*)(ic->local_icpart->lookup_ext);
00371     if (!hook2) return;
00372     hook2->startindex = chindex;
00373     hook2->begin_range = chindex;
00374     hook2->crange = -1;
00375     hook2->end_range = -1;
00376     Ximp_Local_Lookup_Draw(ic);
00377   }
00378   return;
00379 }
00380 
00381 void
00382 Ximp_Local_Preedit_Destroy(XicCommon ic) {
00383   LocalPreeditExt *hook = (LocalPreeditExt *)(ic->local_icpart->preedit_ext);
00384 
00385   if (!hook) return;
00386 
00387   if (hook->preedit_text) Xfree(hook->preedit_text);
00388   hook->preedit_text = 0;
00389   Xfree(hook);
00390   ic->local_icpart->preedit_ext = 0;
00391   return;
00392 }