1 /*
2  * Motif
3  *
4  * Copyright (c) 1987-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /*
24  * HISTORY
25  */
26 #ifdef HAVE_CONFIG_H
27 #include <config.h>
28 #endif
29 
30 
31 #ifdef REV_INFO
32 #ifndef lint
33 static char rcsid[] = "$TOG: XmIm.c /main/28 1997/10/13 14:57:31 cshi $"
34 #endif
35 #endif
36 
37 #include <stdio.h>
38 #include <Xm/DisplayP.h>
39 #include <Xm/DrawP.h>
40 #include <Xm/PrimitiveP.h>
41 #include <Xm/VendorSEP.h>
42 #include <Xm/VendorSP.h>
43 #include <Xm/XmosP.h>		/* for bzero */
44 #include "BaseClassI.h"
45 #include "MessagesI.h"
46 #include "XmI.h"
47 #include "XmImI.h"
48 #include <X11/Xlib.h>
49 
50 #define FIX_1534
51 
52 # include <stdarg.h>
53 # define Va_start(a,b) va_start(a,b)
54 
55 #define FIX_1510
56 #define FIX_1129
57 #define FIX_1196
58 
59 #ifdef NO_XICPROC
60 typedef Bool (*XICProc)( XIC, XPointer, XPointer);
61 #endif
62 
63 /* Data structures:
64  *	While multiple XIMs are not currently supported, some thought
65  * was given to how they might be implemented.  Currently both
66  * XmImDisplayInfo and XmImShellInfo contain per-XIM fields.  Also the
67  * locale and XmNinputMethod are implicit in the XmImDisplayInfo.
68  * The back-pointer for the original source of shared XICs is perhaps
69  * overly general, but will ease XmPER_MANAGER sharing if implemented.
70  *
71  * If an XIC is shared among several widgets, all will reference a
72  * single XmImXICInfo.
73  */
74 
75 typedef struct _XmImRefRec {
76   Cardinal	num_refs;	/* Number of referencing widgets. */
77   Cardinal	max_refs;	/* Maximum length of refs array. */
78   Widget*	refs;		/* Array of referencing widgets. */
79   XtPointer     **callbacks;
80 } XmImRefRec, *XmImRefInfo;
81 
82 typedef struct _PreeditBufferRec {
83   unsigned short length;
84   wchar_t 	 *text;
85   XIMFeedback  	 *feedback;
86   int 		 caret;
87   XIMCaretStyle	 style;
88 } PreeditBufferRec, *PreeditBuffer;
89 
90 typedef struct _XmImXICRec {
91   struct _XmImXICRec *next;	/* Links all have the same XIM. */
92   XIC		xic;		/* The XIC. */
93   Window	focus_window;	/* Cached information about the XIC. */
94   XIMStyle	input_style;	/* ...ditto... */
95   int		status_width;	/* ...ditto... */
96   int		preedit_width;	/* ...ditto... */
97   int		sp_height;	/* ...ditto... */
98   Boolean	has_focus;	/* Does this XIC have keyboard focus. */
99   Boolean	anonymous;	/* Do we have exclusive rights to this XIC. */
100   XmImRefRec	widget_refs;	/* Widgets referencing this XIC. */
101   struct _XmImXICRec **source; /* Original source of shared XICs. */
102   PreeditBuffer preedit_buffer;
103 } XmImXICRec, *XmImXICInfo;
104 
105 typedef struct _XmImShellRec {
106   /* per-Shell fields. */
107   Widget 	im_widget;	/* Dummy widget to make intrinsics behave. */
108   Widget	current_widget;	/* Widget whose visual we're matching. */
109 
110   /* per <Shell,XIM> fields. */
111   XmImXICInfo	shell_xic;	/* For PER_SHELL sharing policy. */
112   XmImXICInfo	iclist;		/* All known XICs for this <XIM,Shell>. */
113 } XmImShellRec, *XmImShellInfo;
114 
115 typedef struct {
116   /* per-Display fields. */
117   XContext	current_xics;	/* Map widget -> current XmImXICInfo. */
118 
119   /* per-XIM fields. */
120   XIM		xim;		/* The XIM. */
121   XIMStyles	*styles;	/* XNQueryInputStyle result. */
122   XmImRefRec	shell_refs;	/* Shells referencing this XIM. */
123 } XmImDisplayRec, *XmImDisplayInfo;
124 
125 
126 /*
127  * Although the current implementation of XVaNestedList is similar
128  * to an Xt ArgList, this is not guaranteed by the spec.  The only
129  * approved interface for creating XVaNestedLists takes pairs of
130  * (char*, XPointer) paramters.
131  */
132 typedef struct {
133   char    *name;
134   XPointer value;
135 } VaArg;
136 
137 typedef struct {
138   Cardinal count;
139   Cardinal max;
140   VaArg   *args;
141 } VaArgListRec, *VaArgList;
142 
143 
144 /********    Static Function Declarations    ********/
145 
146 static int add_sp(String name,
147 		  XPointer value,
148 		  VaArgList slp,
149 		  VaArgList plp,
150 		  VaArgList vlp);
151 static int add_p(String name,
152 		 XPointer value,
153 		 VaArgList slp,
154 		 VaArgList plp,
155 		 VaArgList vlp);
156 static int add_fs(String name,
157 		  XPointer value,
158 		  VaArgList slp,
159 		  VaArgList plp,
160 		  VaArgList vlp);
161 static int add_bgpxmp(String name,
162 		      XPointer value,
163 		      VaArgList slp,
164 		      VaArgList plp,
165 		      VaArgList vlp);
166 
167 static XIMStyle check_style(XIMStyles *styles,
168 			    XIMStyle preedit_style,
169 			    XIMStyle status_style);
170 static int ImGetGeo(Widget vw,
171 		    XmImXICInfo this_icp );
172 static void ImSetGeo(Widget vw,
173 		     XmImXICInfo this_icp );
174 static void ImGeoReq(Widget vw);
175 static XFontSet extract_fontset(XmFontList fl);
176 static XmImDisplayInfo get_xim_info(Widget w);
177 static XtPointer* get_im_info_ptr(Widget w,
178 				  Boolean create);
179 static XmImShellInfo get_im_info(Widget w,
180 				 Boolean create);
181 static void draw_separator(Widget vw);
182 static void null_proc(Widget w,
183 		      XtPointer ptr,
184 		      XEvent *ev,
185 		      Boolean *b);
186 static void ImCountVaList(va_list var,
187 			  int *total_count);
188 static ArgList ImCreateArgList(va_list var,
189 			       int total_count);
190 
191 static XmImXICInfo create_xic_info(Widget	   shell,
192 				   XmImDisplayInfo xim_info,
193 				   XmImShellInfo   im_info,
194 #if NeedWidePrototypes
195 				   unsigned int    input_policy);
196 #else
197                                    XmInputPolicy   input_policy);
198 #endif /*NeedWidePrototypes*/
199 static XmImXICInfo recreate_xic_info(XIC		xic,
200                                      Widget		shell,
201 				     XmImDisplayInfo xim_info,
202 				     XmImShellInfo   im_info);
203 static void set_values(Widget w,
204 		       ArgList args,
205 		       Cardinal num_args,
206 #if NeedWidePrototypes
207 		       unsigned int  policy);
208 #else
209                        XmInputPolicy policy);
210 #endif /*NeedWidePrototypes*/
211 
212 static XmImXICInfo get_current_xic(XmImDisplayInfo xim_info,
213 				   Widget 	   widget);
214 static void set_current_xic(XmImXICInfo     xic_info,
215 			    XmImDisplayInfo xim_info,
216 			    Widget 	    widget);
217 static void unset_current_xic(XmImXICInfo     xic_info,
218 			      XmImShellInfo   im_info,
219 			      XmImDisplayInfo xim_info,
220 			      Widget 	      widget);
221 
222 static Cardinal add_ref(XmImRefInfo refs,
223 			Widget      widget);
224 static Cardinal remove_ref(XmImRefInfo refs,
225 			   Widget      widget);
226 
227 static XVaNestedList VaCopy(VaArgList   list);
228 static void VaSetArg(VaArgList   list,
229 		     char       *name,
230 		     XPointer    value);
231 
232 static int ImPreeditStartCallback(XIC xic,
233 				  XPointer client_data,
234 				  XPointer call_data);
235 static void ImPreeditDoneCallback(XIC xic,
236 				  XPointer client_data,
237 				  XPointer call_data);
238 static void ImPreeditDrawCallback(XIC xic,
239 				  XPointer client_data,
240 				  XPointer call_data);
241 static void ImPreeditCaretCallback(XIC xic,
242 				   XPointer client_data,
243 				   XPointer call_data);
244 static void ImFreePreeditBuffer(PreeditBuffer pb);
245 static void set_callback_values(Widget w,
246                     String name,
247                     XIMCallback *value,
248                     VaArgList vlp,
249                     XmInputPolicy input_policy);
250 static void regist_real_callback(Widget w,
251                      XIMProc call,
252                      int swc);
253 static XICProc get_real_callback(Widget w,
254                   int swc,
255 		  Widget *real_widget);
256 static void move_preedit_string(XmImXICInfo icp,
257 			  Widget wfrom,
258 			  Widget wto);
259 
260      /********    End Static Function Declarations    ********/
261 
262 
263 typedef int (*XmImResLProc)(String, XPointer,
264 			   VaArgList, VaArgList, VaArgList);
265 
266 
267 typedef struct {
268   String xmstring;
269   String xstring;
270   XrmName xrmname;
271   XmImResLProc proc;
272 } XmImResListRec;
273 
274 static XmImResListRec XmImResList[] = {
275   {XmNbackground,       XNBackground,       NULLQUARK, add_sp},
276   {XmNforeground,       XNForeground,       NULLQUARK, add_sp},
277   {XmNbackgroundPixmap, XNBackgroundPixmap, NULLQUARK, add_bgpxmp},
278   {XmNspotLocation,     XNSpotLocation,     NULLQUARK, add_p},
279   {XmNfontList,         XNFontSet,          NULLQUARK, add_fs},
280   {XmNrenderTable,      XNFontSet,          NULLQUARK, add_fs},
281   {XmNlineSpace,        XNLineSpace,        NULLQUARK, add_sp},
282   {XmNarea,             XNArea,             NULLQUARK, add_p},
283   {XmNpreeditStartCallback, XNPreeditStartCallback, NULLQUARK, NULL},
284   {XmNpreeditDoneCallback,  XNPreeditDoneCallback,  NULLQUARK, NULL},
285   {XmNpreeditDrawCallback,  XNPreeditDrawCallback,  NULLQUARK, NULL},
286   {XmNpreeditCaretCallback, XNPreeditCaretCallback, NULLQUARK, NULL},
287 };
288 
289 #define OVERTHESPOT	"overthespot"
290 #define OFFTHESPOT	"offthespot"
291 #define ROOT		"root"
292 #define ONTHESPOT	"onthespot"
293 
294 #define PREEDIT_START   0
295 #define PREEDIT_DONE    1
296 #define PREEDIT_DRAW    2
297 #define PREEDIT_CARET   3
298 
299 #define SEPARATOR_HEIGHT 2
300 
301 #define GEO_CHG 0x1
302 #define BG_CHG  0x2
303 
304 #define MSG1	_XmMMsgXmIm_0000
305 
306 /*ARGSUSED*/
307 void
XmImRegister(Widget w,unsigned int reserved)308 XmImRegister(Widget w,
309 	     unsigned int reserved) /* unused */
310 {
311   Widget p;
312   XmImShellInfo im_info;
313   XmImDisplayInfo xim_info;
314   XmInputPolicy input_policy = XmINHERIT_POLICY;
315 
316   _XmWidgetToAppContext(w);
317 
318   _XmAppLock(app);
319   /* Find the enclosing shell. */
320   p = XtParent(w);
321   while (!XtIsShell(p))
322     p = XtParent(p);
323 
324   /* Lookup or create per-shell IM info and an XIM. */
325   if (((xim_info = get_xim_info(p)) == NULL) ||
326       (xim_info->xim == NULL)) {
327     _XmAppUnlock(app);
328     return;
329   }
330   if ((im_info = get_im_info(p, True)) == NULL) {
331     _XmAppUnlock(app);
332     return;
333   }
334 
335   /* Check that this widget doesn't already have a current XIC. */
336   if (get_current_xic(xim_info, w) != NULL) {
337     _XmAppUnlock(app);
338     return;
339   }
340 
341   /* See if this widget will be sharing an existing XIC. */
342   XtVaGetValues(p, XmNinputPolicy, &input_policy, NULL);
343   switch (input_policy)
344     {
345     case XmPER_SHELL:
346       if (im_info->shell_xic == NULL)
347 	(void) create_xic_info(p, xim_info, im_info, input_policy);
348       set_current_xic(im_info->shell_xic, xim_info, w);
349       break;
350 
351     case XmPER_WIDGET:
352       set_current_xic(create_xic_info(p, xim_info, im_info, input_policy),
353 		      xim_info, w);
354       break;
355 
356     case XmINHERIT_POLICY:
357       break;
358 
359     default:
360       assert(False);
361     }
362   _XmAppUnlock(app);
363 }
364 
365 void
XmImUnregister(Widget w)366 XmImUnregister(Widget w)
367 {
368   register XmImDisplayInfo xim_info;
369   register XmImShellInfo im_info;
370   register XmImXICInfo xic_info;
371   XtAppContext app;
372 
373   /* Punt if insufficient information was provided. */
374   if (w == NULL)
375     return;
376 
377   app = XtWidgetToApplicationContext(w);
378   _XmAppLock(app);
379   /* Locate this record. */
380   xim_info = get_xim_info(w);
381   if ((xic_info = get_current_xic(xim_info, w)) == NULL) {
382     _XmAppUnlock(app);
383     return;
384   }
385   if ((im_info = get_im_info(w, False)) == NULL) {
386     _XmAppUnlock(app);
387     return;
388   }
389 
390   /* Unregister this record. */
391   unset_current_xic(xic_info, im_info, xim_info, w);
392 
393   if (im_info->iclist == NULL) {
394     Widget vw = XtParent(w);
395     while (!XtIsShell(vw)) vw = XtParent(vw);
396     ImGeoReq(vw);
397   }
398   _XmAppUnlock(app);
399 }
400 
401 void
XmImSetFocusValues(Widget w,ArgList args,Cardinal num_args)402 XmImSetFocusValues(Widget w,
403 		   ArgList args,
404 		   Cardinal num_args)
405 {
406   register XmImXICInfo xic_info;
407   Widget p;
408   Pixel fg, bg;
409   XmFontList fl=NULL;
410   XFontSet fs=NULL;
411   XmVendorShellExtObject ve;
412   XmWidgetExtData extData;
413   XmImShellInfo im_info;
414   XVaNestedList list;
415   Window wind;
416   XmInputPolicy input_policy;
417   _XmWidgetToAppContext(w);
418 
419   _XmAppLock(app);
420   p = w;
421   while (!XtIsShell(p))
422     p = XtParent(p);
423 
424   if ((xic_info = get_current_xic(get_xim_info(p), w)) == NULL) {
425     _XmAppUnlock(app);
426     return;
427   }
428 
429   wind = xic_info->focus_window;
430   xic_info->focus_window = XtWindow(w);
431 
432   set_values(w, args, num_args, XmINHERIT_POLICY);
433 
434   if (wind != XtWindow(w)) {
435     /* Safe, since we have a window - so it's no gadget */
436     XtVaGetValues(w, XmNbackground, &bg, NULL);
437     XtVaGetValues(w, XmNforeground, &fg, NULL);
438     XtVaGetValues(w, XmNfontList, &fl, NULL);
439     if (fl) fs = extract_fontset(fl);
440     if (fs)
441       list = XVaCreateNestedList(0,
442 				 XNBackground, bg,
443 				 XNForeground, fg,
444 				 XNFontSet,    fs, NULL);
445     else
446       list = XVaCreateNestedList(0,
447 				 XNBackground, bg,
448 				 XNForeground, fg, NULL);
449     XSetICValues(xic_info->xic,
450 		 XNFocusWindow, XtWindow(w),
451 		 XNStatusAttributes,  list,
452 		 XNPreeditAttributes, list,
453 		 NULL);
454     XFree(list);
455 
456     if (xic_info->input_style & XIMPreeditCallbacks) {
457       XtVaGetValues(p, XmNinputPolicy, &input_policy, NULL);
458       if (input_policy == XmPER_SHELL && wind)
459 	move_preedit_string(xic_info,
460 			XtWindowToWidget(XtDisplay(w), wind), w);
461     }
462   }
463   XSetICFocus(xic_info->xic);
464   xic_info->has_focus = True;
465 
466   extData = _XmGetWidgetExtData((Widget)p, XmSHELL_EXTENSION);
467   if (extData)
468     {
469       ve = (XmVendorShellExtObject) extData->widget;
470 
471       if (ve->vendor.im_height)
472         {
473           im_info = (XmImShellInfo)ve->vendor.im_info;
474           im_info->current_widget = w;
475           XtVaGetValues(w, XmNbackground, &bg, NULL);
476           XtVaSetValues(p, XmNbackground, bg, NULL);
477 #ifdef FIX_1129
478           ImGeoReq(p);
479 #endif
480           draw_separator(p);
481         }
482     }
483   _XmAppUnlock(app);
484 }
485 
486 void
XmImSetValues(Widget w,ArgList args,Cardinal num_args)487 XmImSetValues(Widget w,
488 	      ArgList args,
489 	      Cardinal num_args )
490 {
491   _XmWidgetToAppContext(w);
492   _XmAppLock(app);
493   set_values(w, args, num_args, XmINHERIT_POLICY);
494   _XmAppUnlock(app);
495 }
496 
497 void
XmImUnsetFocus(Widget w)498 XmImUnsetFocus(Widget w)
499 {
500   register XmImXICInfo xic_info;
501   _XmWidgetToAppContext(w);
502 
503   _XmAppLock(app);
504   if ((xic_info = get_current_xic(get_xim_info(w), w)) == NULL) {
505     _XmAppUnlock(app);
506     return;
507   }
508 
509   if (xic_info->xic)
510     XUnsetICFocus(xic_info->xic);
511   xic_info->has_focus = False;
512   _XmAppUnlock(app);
513 }
514 
515 XIM
XmImGetXIM(Widget w)516 XmImGetXIM(Widget w)
517 {
518   XmImDisplayInfo xim_info;
519   _XmWidgetToAppContext(w);
520 
521   _XmAppLock(app);
522   xim_info = get_xim_info(w);
523   if (xim_info != NULL) {
524     _XmAppUnlock(app);
525     return xim_info->xim;
526   }
527   else {
528     _XmAppUnlock(app);
529     return NULL;
530   }
531 }
532 
533 void
XmImCloseXIM(Widget w)534 XmImCloseXIM(Widget w)
535 {
536   XmDisplay xmDisplay;
537   XmImDisplayInfo xim_info;
538   Widget shell;
539   XmVendorShellExtObject ve;
540   XmWidgetExtData extData;
541   int height, base_height;
542   Arg args[1];
543   XtWidgetGeometry my_request;
544   _XmWidgetToAppContext(w);
545 
546   _XmAppLock(app);
547   /* Allow (xim_info->xim == NULL) so we can reset the "failed" flag. */
548   if ((xim_info = get_xim_info(w)) == NULL) {
549     _XmAppUnlock(app);
550     return;
551   }
552 
553   /* Remove all references to all XICs */
554   while (xim_info->shell_refs.refs != NULL)
555     {
556       shell = xim_info->shell_refs.refs[0];
557       _XmImFreeShellData(shell, get_im_info_ptr(shell, False));
558       assert((xim_info->shell_refs.refs == NULL) ||
559 	     (xim_info->shell_refs.refs[0] != shell));
560     }
561 
562   shell = w;
563   while (!XtIsShell(shell))
564     shell = XtParent(shell);
565 
566   extData = _XmGetWidgetExtData((Widget)shell, XmSHELL_EXTENSION);
567   if (extData) {
568     ve = (XmVendorShellExtObject) extData->widget;
569     height = ve->vendor.im_height;
570 
571     if (height != 0){
572       XtSetArg(args[0], XtNbaseHeight, &base_height);
573       XtGetValues(shell, args, 1);
574       if (base_height > 0){
575 	base_height -= height;
576 	XtSetArg(args[0], XtNbaseHeight, base_height);
577 	XtSetValues(shell, args, 1);
578       }
579       if(!(XtIsRealized(shell)))
580 	shell->core.height -= height;
581       else {
582 	my_request.height = shell->core.height - height;
583 	my_request.request_mode = CWHeight;
584 	XtMakeGeometryRequest(shell, &my_request, NULL);
585       }
586       ve->vendor.im_height = 0;
587     }
588   }
589 
590   /* Close the XIM. */
591   if (xim_info->xim != NULL)
592     {
593       XCloseIM(xim_info->xim);
594       xim_info->xim = NULL;
595     }
596 
597   XFree(xim_info->styles);
598   xim_info->styles = NULL;
599 
600   xmDisplay = (XmDisplay) XmGetXmDisplay(XtDisplay(w));
601   xmDisplay->display.xmim_info = NULL;
602   XtFree((char *) xim_info);
603   _XmAppUnlock(app);
604 }
605 
606 int
XmImMbLookupString(Widget w,XKeyPressedEvent * event,char * buf,int nbytes,KeySym * keysym,int * status)607 XmImMbLookupString(Widget w,
608 		   XKeyPressedEvent *event,
609 		   char *buf,
610 		   int nbytes,
611 		   KeySym *keysym,
612 		   int *status )
613 {
614   register XmImXICInfo icp;
615   int ret_val;
616   _XmWidgetToAppContext(w);
617 
618   _XmAppLock(app);
619   if ((icp = get_current_xic(get_xim_info(w), w)) == NULL ||
620       icp->xic == NULL)
621     {
622       if (status)
623 	*status = XLookupBoth;
624       ret_val = XLookupString(event, buf, nbytes, keysym, 0);
625       _XmAppUnlock(app);
626       return ret_val;
627     }
628 
629   ret_val = XmbLookupString( icp->xic, event, buf, nbytes,
630 				keysym, status );
631   _XmAppUnlock(app);
632   return ret_val;
633 }
634 
635 XIC
XmImGetXIC(Widget w,unsigned int input_policy,ArgList args,Cardinal num_args)636 XmImGetXIC(Widget 	 w,
637 #if NeedWidePrototypes
638 	   unsigned int  input_policy,
639 #else
640 	   XmInputPolicy input_policy,
641 #endif /*NeedWidePrototypes*/
642 	   ArgList 	 args,
643 	   Cardinal 	 num_args)
644 {
645   XmImDisplayInfo xim_info;
646   XmImShellInfo im_info;
647   XmImXICInfo xic_info;
648   Widget shell;
649   _XmWidgetToAppContext(w);
650 
651   _XmAppLock(app);
652   xim_info = get_xim_info(w);
653   im_info = get_im_info(w, True);
654   xic_info = get_current_xic(xim_info, w);
655 
656   if ((xim_info == NULL) || (xim_info->xim == NULL)) {
657     _XmAppUnlock(app);
658     return NULL;
659   }
660 
661   /* Find the enclosing shell. */
662   shell = w;
663   while (!XtIsShell(shell))
664     shell = XtParent(shell);
665 
666   /* Resolve the true input policy. */
667   if (input_policy == XmINHERIT_POLICY)
668     XtVaGetValues(shell, XmNinputPolicy, &input_policy, NULL);
669 
670   /* If there is already a current XIC, we may want to unregister it. */
671   switch (input_policy)
672     {
673     case XmPER_SHELL:
674       if ((xic_info != NULL) && (im_info->shell_xic != xic_info))
675 	{
676 	  unset_current_xic(xic_info, im_info, xim_info, w);
677 	  xic_info = NULL;
678 	}
679       break;
680 
681     case XmPER_WIDGET:
682       if (xic_info != NULL)
683 	{
684 	  unset_current_xic(xic_info, im_info, xim_info, w);
685 	  xic_info = NULL;
686 	}
687       break;
688 
689     default:
690       assert(False);
691     }
692 
693   /* Register an XIC with the desired input policy. */
694   if (xic_info == NULL)
695     {
696       xic_info = create_xic_info(shell, xim_info, im_info, input_policy);
697       set_current_xic(xic_info, xim_info, w);
698     }
699 
700   /* Set the values, which creates an XIC. */
701   set_values(w, args, num_args, input_policy);
702 
703   /* Return the current XIC. */
704   if (xic_info != NULL) {
705     _XmAppUnlock(app);
706     return xic_info->xic;
707   }
708   _XmAppUnlock(app);
709   return NULL;
710 }
711 
712 XIC
XmImSetXIC(Widget widget,XIC xic)713 XmImSetXIC(Widget widget,
714 	   XIC    xic)
715 {
716   XmImDisplayInfo xim_info;
717   XmImShellInfo im_info;
718   XmImXICInfo xic_info;
719   Widget shell;
720   _XmWidgetToAppContext(widget);
721 
722   _XmAppLock(app);
723   xim_info = get_xim_info(widget);
724   im_info = get_im_info(widget, True);
725   xic_info = get_current_xic(xim_info, widget);
726   if ((xim_info == NULL) || (xim_info->xim == NULL)) {
727     _XmAppUnlock(app);
728     return NULL;
729   }
730 
731   /* This may be a simple query. */
732   if (xic == NULL)
733     {
734       /* No XIC is registered for this widget. */
735       if (xic_info == NULL) {
736 	_XmAppUnlock(app);
737 	return NULL;
738       }
739 
740       /* Force creation of the XIC. */
741       if (xic_info->xic == NULL)
742 	set_values(widget, NULL, 0, XmINHERIT_POLICY);
743 
744       _XmAppUnlock(app);
745       return xic_info->xic;
746     }
747 
748   /* We don't support multiple IMs. */
749   if (XIMOfIC(xic) != xim_info->xim) {
750     _XmAppUnlock(app);
751     return NULL;
752   }
753 
754   /* Unregister the current XIC. */
755   if (xic_info != NULL)
756     {
757       /* Setting the current XIC to itself is a no-op. */
758       if (xic_info->xic == xic) {
759 	_XmAppUnlock(app);
760 	return xic;
761       }
762 
763       unset_current_xic(xic_info, im_info, xim_info, widget);
764       xic_info = NULL;
765     }
766 
767   /* Find the enclosing shell. */
768   shell = widget;
769   while (!XtIsShell(shell))
770     shell = XtParent(shell);
771 
772   /* Get or create xic_info for this xic. */
773   xic_info = recreate_xic_info(xic, shell, xim_info, im_info);
774 
775   /* Make this the current XIC for this widget. */
776   set_current_xic(xic_info, xim_info, widget);
777 
778   _XmAppUnlock(app);
779   return xic;
780 }
781 
782 void
XmImFreeXIC(Widget w,XIC context)783 XmImFreeXIC(Widget w,
784 	    XIC    context)
785 {
786   register int index;
787   register XmImDisplayInfo xim_info;
788   register XmImShellInfo im_info;
789   register XmImXICInfo xic_info;
790   XtAppContext app;
791 
792   /* Punt if insufficient information was provided. */
793   if (w == NULL)
794     return;
795 
796   app = XtWidgetToApplicationContext(w);
797   _XmAppLock(app);
798   /* Locate this record. */
799   xim_info = get_xim_info(w);
800   if ((xic_info = get_current_xic(xim_info, w)) == NULL) {
801     _XmAppUnlock(app);
802     return;
803   }
804   if ((im_info = get_im_info(w, False)) == NULL) {
805     _XmAppUnlock(app);
806     return;
807   }
808   if ((context != NULL) && (xic_info->xic != context)) {
809     _XmAppUnlock(app);
810     return;
811   }
812 
813   /* Remove all references. */
814   index = xic_info->widget_refs.num_refs;
815   while (--index >= 0)
816     unset_current_xic(xic_info, im_info, xim_info,
817 		      xic_info->widget_refs.refs[index]);
818   _XmAppUnlock(app);
819 }
820 
821 /*********************
822  * Private Functions *
823  *********************/
824 
825 /* Free a VendorShellExt's im_info field. */
826 void
_XmImFreeShellData(Widget widget,XtPointer * data)827 _XmImFreeShellData(Widget     widget,
828 		   XtPointer* data)
829 {
830   XmImShellInfo   im_info;
831   XmImDisplayInfo xim_info;
832   XmImXICInfo	  xic_info;
833   Widget	  reference;
834 
835   if ((data == NULL) ||
836       (im_info = (XmImShellInfo) *data) == NULL)
837     return;
838 
839   /* Ignore (xim_info->xim == NULL), since it is immaterial here. */
840   xim_info = get_xim_info(widget);
841   if (xim_info == NULL)
842     return;
843 
844   /* Remove any dangling references. */
845   while (im_info->iclist != NULL)
846     {
847       xic_info = im_info->iclist;
848       reference = xic_info->widget_refs.refs[0];
849       unset_current_xic(xic_info, im_info, xim_info, reference);
850       assert((xic_info != im_info->iclist) ||
851 	     (reference != xic_info->widget_refs.refs[0]));
852     }
853   assert(im_info->shell_xic == NULL);
854 
855   /* Delete the dummy widget. */
856 #ifdef FIX_1534
857   if (im_info->im_widget != NULL &&
858       !widget->core.being_destroyed)
859 #else
860   if (im_info->im_widget != NULL)
861 #endif
862     {
863       XtDestroyWidget(im_info->im_widget);
864       im_info->im_widget = NULL;
865     }
866 
867   /* Remove this shell as a reference to the XIM. */
868   (void) remove_ref(&xim_info->shell_refs, widget);
869 
870   /* Delete the data. */
871   XtFree((char *) im_info);
872   *data = NULL;
873 }
874 
875 void
_XmImChangeManaged(Widget vw)876 _XmImChangeManaged(
877 		   Widget vw )
878 {
879   XmVendorShellExtObject ve;
880   XmWidgetExtData extData;
881   register int height, old_height;
882 
883   extData = _XmGetWidgetExtData((Widget)vw, XmSHELL_EXTENSION);
884   if (extData) {
885     ve = (XmVendorShellExtObject) extData->widget;
886 
887     old_height = ve->vendor.im_height;
888 
889     height = ImGetGeo(vw, NULL);
890     if (!ve->vendor.im_vs_height_set) {
891       Arg args[1];
892       int base_height;
893       XtSetArg(args[0], XtNbaseHeight, &base_height);
894       XtGetValues(vw, args, 1);
895       if (base_height > 0) {
896         base_height += (height - old_height);
897         XtSetArg(args[0], XtNbaseHeight, base_height);
898         XtSetValues(vw, args, 1);
899       }
900       vw->core.height += (height - old_height);
901     }
902   }
903 }
904 
905 void
_XmImRealize(Widget vw)906 _XmImRealize(
907 	     Widget vw )
908 {
909   XmImXICInfo icp;
910   Pixel bg;
911   XmVendorShellExtObject ve;
912   XmWidgetExtData extData;
913   XmImShellInfo im_info;
914   XmImDisplayInfo xim_info;
915 
916   xim_info = get_xim_info(vw);
917   im_info = get_im_info(vw, False);
918 
919   if ((xim_info == NULL) ||
920       (im_info == NULL) ||
921       (im_info->iclist == NULL))
922     return;
923 
924   /* We need to synchronize here to make sure the server has created
925    * the client window before the input server attempts to reparent
926    * any windows to it
927    */
928   XSync(XtDisplay(vw), False);
929 
930   for (icp = im_info->iclist; icp != NULL; icp = icp->next)
931     {
932       if (!icp->xic) continue;
933       XSetICValues(icp->xic, XNClientWindow, XtWindow(vw), NULL);
934     }
935 
936   extData = _XmGetWidgetExtData((Widget)vw, XmSHELL_EXTENSION);
937   if (extData)
938     ve = (XmVendorShellExtObject) extData->widget;
939   else
940     ve = NULL;
941   if (ve && ve->vendor.im_height == 0) {
942     ShellWidget shell = (ShellWidget)(vw);
943     Boolean resize = shell->shell.allow_shell_resize;
944 
945     if (!resize) shell->shell.allow_shell_resize = True;
946     ImGeoReq(vw);
947     if (!resize) shell->shell.allow_shell_resize = False;
948   } else
949     ImSetGeo(vw, NULL);
950 
951   /* For some reason we need to wait till now before we set the
952    * initial background pixmap.
953    */
954   if (ve && ve->vendor.im_height && im_info->current_widget)
955     {
956       XtVaGetValues(im_info->current_widget, XmNbackground, &bg, NULL);
957       XtVaSetValues(vw, XmNbackground, bg, NULL);
958     }
959 }
960 
961 void
_XmImResize(Widget vw)962 _XmImResize(
963 	    Widget vw )
964 {
965   ImGetGeo(vw, NULL);
966   ImSetGeo(vw, NULL);
967 }
968 
969 void
_XmImRedisplay(Widget vw)970 _XmImRedisplay(
971 	       Widget vw )
972 {
973   XmVendorShellExtObject ve;
974   XmWidgetExtData extData;
975 
976   if ((extData = _XmGetWidgetExtData((Widget)vw, XmSHELL_EXTENSION)) == NULL)
977     return;
978 
979   ve = (XmVendorShellExtObject) extData->widget;
980 
981   if (ve->vendor.im_height == 0)
982     return;
983 
984   draw_separator(vw);
985 }
986 
987 /********************
988  * Static functions *
989  ********************/
990 
991 /* Locate an XmImXICInfo struct for an existing XIC. */
992 static XmImXICInfo
recreate_xic_info(XIC xic,Widget shell,XmImDisplayInfo xim_info,XmImShellInfo im_info)993 recreate_xic_info(XIC		  xic,
994 		  Widget	  shell,
995 		  XmImDisplayInfo xim_info,
996 		  XmImShellInfo   im_info)
997 {
998   Cardinal index;
999   XmImXICInfo xic_info;
1000   assert(xic != NULL);
1001 
1002   /* Search for an existing record in this shell's im_info. */
1003   for (xic_info = im_info->iclist;
1004        xic_info != NULL;
1005        xic_info = xic_info->next)
1006     {
1007       if (xic_info->xic == xic)
1008 	return xic_info;
1009     }
1010 
1011   /* Search for an existing record in another shell's im_info? */
1012   for (index = 0; index < xim_info->shell_refs.num_refs; index++)
1013     if (shell != xim_info->shell_refs.refs[index])
1014       {
1015 	XmImShellInfo tmp_info =
1016 	  get_im_info(xim_info->shell_refs.refs[index], False);
1017 	assert(tmp_info != NULL);
1018 
1019 	for (xic_info = tmp_info->iclist;
1020 	     xic_info != NULL;
1021 	     xic_info = xic_info->next)
1022 	  {
1023 	    if (xic_info->xic == xic)
1024 	      return xic_info;
1025 	  }
1026       }
1027 
1028   /* This XIC must have been created by the application directly. */
1029   xic_info = XtNew(XmImXICRec);
1030   bzero((char*) xic_info, sizeof(XmImXICRec));
1031   (void) XGetICValues(xic, XNInputStyle, &xic_info->input_style, NULL);
1032   xic_info->next = im_info->iclist;
1033   im_info->iclist = xic_info;
1034 
1035   if (XtIsRealized (shell))
1036     {
1037       /* If client_window hasn't been set already, set it now. */
1038       (void) XSetICValues(xic, XNClientWindow, XtWindow(shell), NULL);
1039 
1040       /* Update cached geometry fields */
1041       ImGetGeo(shell, xic_info);
1042       ImSetGeo(shell, xic_info);
1043     }
1044 
1045   return xic_info;
1046 }
1047 
1048 /* Attempt to create an XmImXICInfo struct.  Return it or NULL. */
1049 static XmImXICInfo
create_xic_info(Widget shell,XmImDisplayInfo xim_info,XmImShellInfo im_info,unsigned int input_policy)1050 create_xic_info(Widget		shell,
1051 		XmImDisplayInfo xim_info,
1052 		XmImShellInfo   im_info,
1053 #if NeedWidePrototypes
1054 		unsigned int 	input_policy)
1055 #else
1056                 XmInputPolicy	input_policy)
1057 #endif /*NeedWidePrototypes*/
1058 {
1059   XIMStyle style = 0;
1060   char tmp[BUFSIZ];
1061   char *cp = NULL;
1062   char *tp = NULL;
1063   char *cpend = NULL;
1064   register XIMStyles *styles;
1065   XmImXICInfo xic_info;
1066 
1067   /* Determine the input style to be used for this XIC. */
1068   styles = xim_info->styles;
1069   XtVaGetValues(shell, XmNpreeditType, &cp, NULL);
1070 
1071   if (cp != NULL)
1072     {
1073       /* Parse for the successive commas */
1074       cp = strcpy(tmp,cp);
1075       cpend = &tmp[strlen(tmp)];
1076       assert(strlen(tmp) < BUFSIZ);
1077       while((style == 0) && (cp < cpend))
1078         {
1079           tp = strchr(cp,',');
1080           if (tp)
1081             *tp = 0;
1082           else
1083             tp = cpend;
1084 
1085           /* Look for an acceptable supported style. */
1086           if (XmeNamesAreEqual(cp, OVERTHESPOT))
1087             style = check_style(styles, XIMPreeditPosition,
1088                                 XIMStatusArea|XIMStatusNothing|XIMStatusNone);
1089           else if (XmeNamesAreEqual(cp, OFFTHESPOT))
1090             style = check_style(styles, XIMPreeditArea,
1091                                 XIMStatusArea|XIMStatusNothing|XIMStatusNone);
1092           else if (XmeNamesAreEqual(cp, ROOT))
1093             style = check_style(styles, XIMPreeditNothing,
1094                                 XIMStatusNothing|XIMStatusNone);
1095           else if (XmeNamesAreEqual(cp, ONTHESPOT))
1096             style = check_style(styles, XIMPreeditCallbacks,
1097                                 XIMStatusArea|XIMStatusNothing|XIMStatusNone);
1098 
1099           cp = tp+1;
1100         }
1101     }
1102   if (style == 0)
1103     {
1104       /* Try for a fallback style, or give up and use XLookupString. */
1105       if ((style = check_style(styles, XIMPreeditNone, XIMStatusNone)) == 0)
1106         return NULL;
1107     }
1108 
1109   /* We need to create this widget whenever there is a non-simple
1110    * input method in order to stop the intrinsics from calling
1111    * XMapSubwindows, thereby improperly mapping input method
1112    * windows which have been made children of the client or
1113    * focus windows.
1114    */
1115   if ((im_info->im_widget == NULL) &&
1116       (style & (XIMStatusArea | XIMPreeditArea | XIMPreeditPosition)))
1117     im_info->im_widget =
1118       XtVaCreateWidget("xmim_wrapper", coreWidgetClass,
1119 		       shell, XmNwidth, 10, XmNheight, 10, NULL);
1120 
1121   /* Create the XIC info record. */
1122   xic_info = XtNew(XmImXICRec);
1123   bzero((char*) xic_info, sizeof(XmImXICRec));
1124   xic_info->input_style = style;
1125   xic_info->anonymous = True;
1126   xic_info->preedit_buffer = XtNew(PreeditBufferRec);
1127   bzero((char *) xic_info->preedit_buffer, sizeof(PreeditBufferRec));
1128 
1129   xic_info->next = im_info->iclist;
1130   im_info->iclist = xic_info;
1131 
1132   /* Setup sharing for this XIC. */
1133   switch (input_policy)
1134     {
1135     case XmPER_SHELL:
1136       assert (im_info->shell_xic == NULL);
1137       im_info->shell_xic = xic_info;
1138       im_info->shell_xic->source = &im_info->shell_xic;
1139       break;
1140 
1141     case XmPER_WIDGET:
1142       break;
1143 
1144     case XmINHERIT_POLICY:
1145       break;
1146 
1147     default:
1148       assert(False);
1149     }
1150 
1151   return xic_info;
1152 }
1153 
1154 
1155 #define IsCallback(name) \
1156   if (name == XrmStringToName(XmNpreeditStartCallback) || \
1157       name == XrmStringToName(XmNpreeditDoneCallback) || \
1158       name == XrmStringToName(XmNpreeditDrawCallback) || \
1159       name == XrmStringToName(XmNpreeditCaretCallback))
1160 
1161 
1162 static void
set_values(Widget w,ArgList args,Cardinal num_args,unsigned int input_policy)1163 set_values(Widget w,
1164 	   ArgList args,
1165 	   Cardinal num_args,
1166 #if NeedWidePrototypes
1167 	   unsigned int  input_policy )
1168 #else
1169            XmInputPolicy input_policy )
1170 #endif /*NeedWidePrototypes*/
1171 {
1172   register XmImXICInfo icp;
1173   XmImDisplayInfo xim_info;
1174   XmImResListRec *rlp;
1175   register int i, j;
1176   register ArgList argp = args;
1177   VaArgListRec status_vlist, preedit_vlist, xic_vlist;
1178   XVaNestedList va_slist, va_plist, va_vlist;
1179   XrmName name, area_name = XrmStringToName(XmNarea);
1180   Widget p;
1181   XmImShellInfo im_info;
1182   int flags = 0;
1183   Pixel bg;
1184   char *ret;
1185   unsigned long mask = 0;
1186   Boolean unrecognized = False;
1187 
1188   p = w;
1189   while (!XtIsShell(p))
1190     p = XtParent(p);
1191 
1192   xim_info = get_xim_info(p);
1193   if ((icp = get_current_xic(xim_info, w)) == NULL)
1194     return;
1195 
1196   im_info = get_im_info(p, False);
1197   assert(im_info != NULL);
1198 
1199   if (!XtIsRealized(p)) {
1200     /* If vendor widget not realized, then the current info
1201      * is that for the last widget to set values.
1202      */
1203     im_info->current_widget = w;
1204   }
1205 
1206   if (icp->xic &&
1207       icp->focus_window && icp->focus_window != XtWindow(w))
1208     return;
1209 
1210   bzero((char*) &status_vlist, sizeof(VaArgListRec));
1211   bzero((char*) &preedit_vlist, sizeof(VaArgListRec));
1212   bzero((char*) &xic_vlist, sizeof(VaArgListRec));
1213   for (i = num_args; i > 0; i--, argp++) {
1214     name = XrmStringToName(argp->name);
1215     if (name == area_name && !(icp->input_style & XIMPreeditPosition))
1216       continue;
1217 
1218     IsCallback(name){
1219       if (icp->input_style & XIMPreeditCallbacks){
1220         set_callback_values(w, argp->name, (XIMCallback *)(argp->value),
1221                                                 &preedit_vlist, input_policy);
1222         continue;
1223       } else
1224         continue;
1225     }
1226 
1227     _XmProcessLock();
1228     for (rlp = XmImResList, j = XtNumber(XmImResList); j != 0; j--, rlp++) {
1229       if (rlp->xrmname == name)	{
1230 	flags |= (*rlp->proc)(rlp->xstring, (XPointer) argp->value,
1231 			 &status_vlist, &preedit_vlist, &xic_vlist);
1232 	break;
1233       }
1234     }
1235     _XmProcessUnlock();
1236     if (j == 0) {
1237       /* Simply pass unrecognized values along */
1238       VaSetArg(&xic_vlist, argp->name, (XPointer) argp->value);
1239       unrecognized = True;
1240     }
1241   }
1242 
1243   /* We do not create the IC until the initial data is ready to be passed */
1244   assert(xim_info != NULL);
1245   if (icp->xic == NULL) {
1246     if (XtIsRealized(p)) {
1247       XSync(XtDisplay(p), False);
1248       VaSetArg(&xic_vlist, XNClientWindow, (XPointer) XtWindow(p));
1249     }
1250     if (icp->focus_window) {
1251       VaSetArg(&xic_vlist, XNFocusWindow, (XPointer) icp->focus_window);
1252     }
1253     VaSetArg(&xic_vlist, XNInputStyle, (XPointer) icp->input_style);
1254 
1255     va_plist = VaCopy(&preedit_vlist);
1256     if (va_plist)
1257       VaSetArg(&xic_vlist, XNPreeditAttributes, (XPointer)va_plist);
1258     va_slist = VaCopy(&status_vlist);
1259     if (va_slist)
1260       VaSetArg(&xic_vlist, XNStatusAttributes, (XPointer)va_slist);
1261     va_vlist = VaCopy(&xic_vlist);
1262 
1263     if (va_vlist)
1264     {
1265       icp->xic = XCreateIC(xim_info->xim, XNVaNestedList, va_vlist, NULL);
1266 #ifdef FIX_1510
1267       if (icp->xic == NULL)
1268       {
1269         icp->input_style = XIMPreeditNothing | XIMStatusNothing;
1270         icp->xic = XCreateIC(xim_info->xim, XNInputStyle, icp->input_style,
1271             XNClientWindow, XtWindow(p), XNFocusWindow, XtWindow(p), NULL);
1272       }
1273 #endif
1274     }
1275     else
1276       icp->xic = XCreateIC(xim_info->xim, NULL);
1277 
1278     if (va_vlist) XFree(va_vlist);
1279     if (va_plist) XFree(va_plist);
1280     if (va_slist) XFree(va_slist);
1281     if (preedit_vlist.args) XtFree((char *)preedit_vlist.args);
1282     if (status_vlist.args) XtFree((char *)status_vlist.args);
1283     if (xic_vlist.args) XtFree((char *)xic_vlist.args);
1284 
1285     if (icp->xic == NULL) {
1286       unset_current_xic(icp, im_info, xim_info, w);
1287       return;
1288     }
1289     XGetICValues(icp->xic, XNFilterEvents, &mask, NULL);
1290     if (mask) {
1291       XtAddEventHandler(p, (EventMask)mask, False, null_proc, NULL);
1292     }
1293     if (XtIsRealized(p)) {
1294 #ifdef FIX_1129
1295       im_info->current_widget = w;
1296 #endif
1297       if (XmIsDialogShell(p)) {
1298 	for (i = 0;
1299 	     i < ((CompositeWidget)p)->composite.num_children;
1300 	     i++)
1301 	  if (XtIsManaged(((CompositeWidget)p)->composite.children[i])) {
1302 	    ImGeoReq(p);
1303 	    break;
1304 	  }
1305       } else
1306 	ImGeoReq(p);
1307 #ifndef FIX_1129
1308       im_info->current_widget = w;
1309 #endif
1310     }
1311     /* Is this new XIC supposed to be shared? */
1312     switch (input_policy)
1313       {
1314       case XmPER_SHELL:
1315 	assert(im_info->shell_xic == NULL);
1316 	im_info->shell_xic = icp;
1317 	break;
1318 
1319       case XmPER_WIDGET:
1320 	break;
1321       default:
1322 	assert(False);
1323       }
1324   } else {
1325     /* Try to modify the existing XIC. */
1326     va_plist = VaCopy(&preedit_vlist);
1327     if (va_plist)
1328       VaSetArg(&xic_vlist, XNPreeditAttributes, (XPointer)va_plist);
1329     va_slist = VaCopy(&status_vlist);
1330     if (va_slist)
1331       VaSetArg(&xic_vlist, XNStatusAttributes, (XPointer)va_slist);
1332     va_vlist = VaCopy(&xic_vlist);
1333 
1334     if (va_vlist)
1335       ret = XSetICValues(icp->xic, XNVaNestedList, va_vlist, NULL);
1336     else
1337       ret = NULL;
1338 
1339     if (va_vlist) XFree(va_vlist);
1340     if (va_plist) XFree(va_plist);
1341     if (va_slist) XFree(va_slist);
1342     if (preedit_vlist.args) XtFree((char *)preedit_vlist.args);
1343     if (status_vlist.args) XtFree((char *)status_vlist.args);
1344     if (xic_vlist.args) XtFree((char *)xic_vlist.args);
1345 
1346     /* ??? Both a write-once and an unrecognized arg might be present. */
1347     if ((ret != NULL) && unrecognized)	{
1348       unsigned long status_bg, status_fg;
1349       unsigned long preedit_bg, preedit_fg;
1350 
1351       /* ??? This code assumes that the XIM hasn't changed. */
1352       assert(XIMOfIC(icp->xic) == xim_info->xim);
1353 
1354       /* We do this in case an input method does not support
1355        * change of some value, but does allow it to be set on
1356        * create.  If however the value is not one of the
1357        * standard values, this im may not support it so we
1358        * should ignore it.
1359        */
1360 
1361       va_slist = XVaCreateNestedList(0,
1362 				     XNBackground, &status_bg,
1363 				     XNForeground, &status_fg,
1364 				     NULL);
1365       va_plist = XVaCreateNestedList(0,
1366 				     XNBackground, &preedit_bg,
1367 				     XNForeground, &preedit_fg,
1368 				     NULL);
1369       XGetICValues(icp->xic,
1370 		   XNStatusAttributes,  va_slist,
1371 		   XNPreeditAttributes, va_plist,
1372 		   NULL);
1373       XFree(va_slist);
1374       XFree(va_plist);
1375 
1376       if (icp->anonymous)
1377 	XDestroyIC(icp->xic);
1378       icp->anonymous = TRUE;
1379       icp->xic = NULL;
1380 
1381       VaSetArg(&status_vlist, XNBackground, (XPointer) status_bg);
1382       VaSetArg(&status_vlist, XNForeground, (XPointer) status_fg);
1383 
1384       VaSetArg(&preedit_vlist, XNBackground, (XPointer) preedit_bg);
1385       VaSetArg(&preedit_vlist, XNForeground, (XPointer) preedit_fg);
1386 
1387       if (XtIsRealized(p)) {
1388 	XSync(XtDisplay(p), False);
1389 	VaSetArg(&xic_vlist, XNClientWindow, (XPointer) XtWindow(p));
1390       }
1391       if (icp->focus_window) {
1392 	VaSetArg(&xic_vlist, XNFocusWindow, (XPointer)icp->focus_window);
1393       }
1394       VaSetArg(&xic_vlist, XNInputStyle, (XPointer) icp->input_style);
1395 
1396       va_plist = VaCopy(&preedit_vlist);
1397       if (va_plist)
1398 	VaSetArg(&xic_vlist, XNPreeditAttributes, (XPointer)va_plist);
1399       va_slist = VaCopy(&status_vlist);
1400       if (va_slist)
1401 	VaSetArg(&xic_vlist, XNStatusAttributes, (XPointer)va_slist);
1402       va_vlist = VaCopy(&xic_vlist);
1403 
1404       if (va_vlist)
1405       {
1406 	icp->xic = XCreateIC(xim_info->xim, XNVaNestedList, va_vlist, NULL);
1407 #ifdef FIX_1510
1408         if (icp->xic == NULL)
1409         {
1410           icp->input_style = XIMPreeditNothing | XIMStatusNothing;
1411           icp->xic = XCreateIC(xim_info->xim, XNInputStyle, icp->input_style,
1412               XNClientWindow, XtWindow(p), XNFocusWindow, XtWindow(p), NULL);
1413         }
1414 #endif
1415       }
1416       else
1417 	icp->xic = XCreateIC(xim_info->xim, NULL);
1418 
1419       if (va_vlist) XFree(va_vlist);
1420       if (va_plist) XFree(va_plist);
1421       if (va_slist) XFree(va_slist);
1422       if (preedit_vlist.args) XtFree((char *)preedit_vlist.args);
1423       if (status_vlist.args) XtFree((char *)status_vlist.args);
1424       if (xic_vlist.args) XtFree((char *)xic_vlist.args);
1425 
1426       if (icp->xic == NULL) {
1427 	unset_current_xic(icp, im_info, xim_info, w);
1428 	return;
1429       }
1430       ImGeoReq(p);
1431       if (icp->has_focus)
1432 	XSetICFocus(icp->xic);
1433       return;
1434     }
1435     if (flags & GEO_CHG) {
1436       ImGeoReq(p);
1437       if (icp->has_focus)
1438 	XSetICFocus(icp->xic);
1439     }
1440   }
1441 
1442   /* Since we do not know whether a set values may have been done
1443    * on top shadow or bottom shadow (used for the separator), we
1444    * will redraw the separator in order to keep the visuals in sync
1445    * with the current text widget. Also repaint background if needed.
1446    */
1447   if ((im_info->current_widget == w) && (flags & BG_CHG)) {
1448     XtVaGetValues(w, XmNbackground, &bg, NULL);
1449     XtVaSetValues(p, XmNbackground, bg, NULL);
1450   }
1451 }
1452 
1453 
1454 static void
ImFreePreeditBuffer(PreeditBuffer pb)1455 ImFreePreeditBuffer(PreeditBuffer pb)
1456 {
1457   if (pb->text) XtFree((char *)pb->text);
1458   if (pb->feedback) XtFree((char *)pb->feedback);
1459   XtFree((char *)pb);
1460 }
1461 
1462 
1463 static int
ImPreeditStartCallback(XIC xic,XPointer client_data,XPointer call_data)1464 ImPreeditStartCallback(XIC xic,
1465 		       XPointer client_data,
1466 		       XPointer call_data)
1467 {
1468   XICProc proc;
1469   Widget real = NULL;
1470 
1471   if (!client_data){
1472     assert(False);
1473   }
1474 
1475   proc = get_real_callback((Widget)client_data, PREEDIT_START, &real);
1476   if (proc)
1477     (*proc)(xic, (XPointer)real, call_data);
1478 
1479   return (-1);
1480 }
1481 
1482 static void
ImPreeditDoneCallback(XIC xic,XPointer client_data,XPointer call_data)1483 ImPreeditDoneCallback(XIC xic,
1484 		      XPointer client_data,
1485 		      XPointer call_data)
1486 {
1487   XICProc proc;
1488   Widget w = (Widget)client_data;
1489   XmImShellInfo im_info;
1490   XmImXICInfo icp;
1491   Widget real = NULL;
1492 
1493   if (!client_data){
1494     assert(False);
1495   }
1496 
1497   if ((im_info = get_im_info(w, False)) == NULL)
1498     return;
1499   if ((icp = im_info->shell_xic) == NULL)
1500     return;
1501 
1502   proc = get_real_callback((Widget)client_data, PREEDIT_DONE, &real);
1503   if (proc)
1504     (*proc)(xic, (XPointer)real, call_data);
1505 
1506   if (icp->preedit_buffer->text)
1507     XtFree((char *)icp->preedit_buffer->text);
1508   if (icp->preedit_buffer->feedback)
1509     XtFree((char *)icp->preedit_buffer->feedback);
1510   bzero((char *)icp->preedit_buffer, sizeof(PreeditBufferRec));
1511 }
1512 
1513 static void
ImPreeditDrawCallback(XIC xic,XPointer client_data,XPointer call_data)1514 ImPreeditDrawCallback(XIC xic,
1515 		      XPointer client_data,
1516 		      XPointer call_data)
1517 {
1518   XICProc proc;
1519   Widget w = (Widget)client_data;
1520   XmImShellInfo im_info;
1521   XmImXICInfo icp;
1522   PreeditBuffer pb;
1523   XIMText *text;
1524   XIMPreeditDrawCallbackStruct *data =
1525 		(XIMPreeditDrawCallbackStruct *) call_data;
1526   int from=0, to=0, ml=0;
1527   wchar_t *wchar;
1528   Widget real = NULL;
1529 
1530   if (!client_data){
1531     assert(False);
1532   }
1533 
1534   /* update the preedit buffer */
1535   if ((im_info = get_im_info(w, False)) == NULL)
1536     return;
1537   if ((icp = im_info->shell_xic) == NULL)
1538     return;
1539 
1540   pb = icp->preedit_buffer;
1541   pb->caret = data->caret;
1542   text = data->text;
1543 
1544   if ((int)data->chg_length > (int)pb->length)
1545     data->chg_length = pb->length;
1546 
1547   if (data->text) { /* text field is non-NULL */
1548 
1549     if (data->chg_length > 0) { /* replace */
1550 	if ((int)text->length > (int)data->chg_length) {
1551 	  pb->text = (wchar_t *)
1552 	    XtRealloc((char *)pb->text, (pb->length - data->chg_length +
1553 			text->length + 1) * sizeof(wchar_t));
1554 	  pb->feedback = (XIMFeedback *)
1555 	    XtRealloc((char *)pb->feedback, (pb->length - data->chg_length +
1556 			 text->length + 1) *sizeof(XIMFeedback));
1557 	}
1558 	from = data->chg_first + data->chg_length;
1559 	to = data->chg_first + text->length;
1560  	ml = pb->length - from;
1561     }
1562     else if (data->chg_length == 0) { /* insert */
1563       /* do we really need to change anything? */
1564       if (data->text->length) {
1565         pb->text = (wchar_t *)
1566 	  XtRealloc((char *)pb->text, (pb->length + text->length +1)
1567 		    * sizeof(wchar_t));
1568 	pb->feedback = (XIMFeedback *)
1569 	  XtRealloc((char *)pb->feedback, (pb->length + text->length +1)
1570 		    * sizeof(XIMFeedback));
1571 	from = data->chg_first;
1572 	to = data->chg_first + text->length;
1573 	ml = pb->length - from;
1574       }
1575     }
1576 
1577     /*
1578     ** if preedit buffer changed, then we munge it,
1579     ** otherwise we just leave it alone
1580     */
1581     if (from || to || ml) {
1582 
1583       /* convert multibyte to wide char */
1584       wchar = (wchar_t *)XtMalloc ((text->length +1) * sizeof(wchar_t));
1585       if (text->encoding_is_wchar)
1586         memcpy(wchar, text->string.wide_char, text->length * sizeof(wchar_t));
1587       else
1588         mbstowcs(wchar, text->string.multi_byte, text->length + 1);
1589 
1590       /* make change */
1591       memmove((char *)pb->text + to * sizeof(wchar_t),
1592 	      (char *)pb->text + from * sizeof(wchar_t),
1593 	      ml * sizeof(wchar_t));
1594       memmove((char *)pb->feedback + to * sizeof(XIMFeedback),
1595 	      (char *)pb->feedback + from * sizeof(XIMFeedback),
1596 	      ml * sizeof(XIMFeedback));
1597 
1598       memmove((char *)pb->text + data->chg_first * sizeof(wchar_t),
1599 	      (char *)wchar,
1600 	      text->length * sizeof(wchar_t));
1601 
1602       /* feedback may be NULL, check for it */
1603       if (text->feedback)
1604 	memmove((char *)pb->feedback + data->chg_first * sizeof(XIMFeedback),
1605 		(char *)text->feedback,
1606 		text->length * sizeof(XIMFeedback));
1607 
1608       pb->length = pb->length + text->length - data->chg_length;
1609       bzero((char *)pb->text + pb->length * sizeof(wchar_t),
1610 	    sizeof(wchar_t));
1611       bzero((char *)pb->feedback + pb->length * sizeof(XIMFeedback),
1612 	    sizeof(XIMFeedback));
1613 
1614       XtFree((char *) wchar);
1615     }
1616   }
1617   else { /* text field is NULL, delete */
1618     from = data->chg_first + data->chg_length;
1619     to = data->chg_first;
1620     ml = pb->length - from;
1621     memmove((char *)pb->text + to * sizeof(wchar_t),
1622 	    (char *)pb->text + from * sizeof(wchar_t),
1623 	    ml * sizeof(wchar_t));
1624     memmove((char *)pb->feedback + to * sizeof(XIMFeedback),
1625 	    (char *)pb->feedback + from * sizeof(XIMFeedback),
1626 	    ml * sizeof(XIMFeedback));
1627 
1628     pb->length = pb->length - data->chg_length;
1629     bzero((char *)pb->text + pb->length * sizeof(wchar_t),
1630 	  data->chg_length * sizeof(wchar_t));
1631     bzero((char *)pb->feedback + pb->length * sizeof(XIMFeedback),
1632 	  data->chg_length * sizeof(XIMFeedback));
1633   }
1634 
1635   proc = get_real_callback((Widget)client_data, PREEDIT_DRAW, &real);
1636   if (proc)
1637     (*proc)(xic, (XPointer)real, call_data);
1638 }
1639 
1640 static void
ImPreeditCaretCallback(XIC xic,XPointer client_data,XPointer call_data)1641 ImPreeditCaretCallback(XIC xic,
1642 		       XPointer client_data,
1643 		       XPointer call_data)
1644 {
1645   XICProc proc;
1646   Widget w = (Widget)client_data;
1647   XmImShellInfo im_info;
1648   XmImXICInfo icp;
1649   PreeditBuffer pb;
1650   XIMPreeditCaretCallbackStruct *data =
1651 		(XIMPreeditCaretCallbackStruct *) call_data;
1652   Widget real = NULL;
1653 
1654   if (!client_data){
1655     assert(False);
1656   }
1657 
1658 /* update the preedit buffer */
1659   if ((im_info = get_im_info(w, False)) == NULL)
1660         return;
1661   if ((icp = im_info->shell_xic) == NULL)
1662         return;
1663 
1664   pb = icp->preedit_buffer;
1665   pb->style = data->style;
1666 
1667   switch (data->direction) {
1668     case XIMForwardChar:
1669 	pb->caret = pb->caret + 1;
1670 	break;
1671     case XIMBackwardChar:
1672 	pb->caret = pb->caret - 1;
1673 	break;
1674     case XIMAbsolutePosition:
1675 	pb->caret = data->position;
1676 	break;
1677     default:
1678 	break;
1679   }
1680 
1681   proc = get_real_callback((Widget)client_data, PREEDIT_CARET, &real);
1682   if (proc)
1683     (*proc)(xic, (XPointer)real, call_data);
1684 }
1685 
1686 static XICProc
get_real_callback(Widget w,int swc,Widget * real_widget)1687 get_real_callback(Widget w,
1688                   int swc,
1689 		  Widget *real_widget)
1690 {
1691   XmImShellInfo im_info;
1692   XmImXICInfo icp;
1693   int i, target;
1694   XmImRefRec refs;
1695 
1696   if ((im_info = get_im_info(w, False)) == NULL)
1697         return (XICProc)NULL;
1698   if ((icp = im_info->shell_xic) == NULL)
1699         return (XICProc)NULL;
1700 
1701   if (*real_widget == NULL)
1702     *real_widget = XtWindowToWidget(XtDisplay(w), icp->focus_window);
1703 
1704   refs = icp->widget_refs;
1705   target = refs.num_refs;
1706   for (i = 0; i < refs.num_refs; i++){
1707     if (refs.refs[i] == *real_widget){
1708       target = i;
1709       break;
1710     }
1711   }
1712   if (target == refs.num_refs){
1713     assert(False);
1714   }
1715 
1716   if (refs.callbacks[target])
1717     return (XICProc)refs.callbacks[target][swc];
1718   else
1719     return (XICProc)NULL;
1720 }
1721 
1722 static void
regist_real_callback(Widget w,XIMProc call,int swc)1723 regist_real_callback(Widget w,
1724                      XIMProc call,
1725                      int swc)
1726 {
1727   Widget p;
1728   register XmImXICInfo icp;
1729   XmImDisplayInfo xim_info;
1730   XmImRefRec refs;
1731   int i, target = 0;
1732 
1733   p = w;
1734   while (!XtIsShell(p))
1735   {
1736     p = XtParent(p);
1737   }
1738 
1739   xim_info = get_xim_info(p);
1740   if ((icp = get_current_xic(xim_info, w)) == NULL)
1741   {
1742     return;
1743   }
1744 
1745   refs = icp->widget_refs;
1746 
1747   for (i = 0; i < refs.num_refs; i++)
1748   {
1749     if (refs.refs[i] == w)
1750     {
1751       target = i;
1752       break;
1753     }
1754   }
1755 
1756   if (!refs.callbacks[target])
1757     refs.callbacks[target] = (XtPointer *)XtMalloc(4 * sizeof(XtPointer));
1758 
1759   refs.callbacks[target][swc] = (XtPointer)call;
1760 }
1761 
1762 static int
NameToSwitch(String name)1763 NameToSwitch(String name)
1764 {
1765 
1766   if (!strcmp(name, XmNpreeditStartCallback))
1767     return PREEDIT_START;
1768   if (!strcmp(name, XmNpreeditDoneCallback))
1769     return PREEDIT_DONE;
1770   if (!strcmp(name, XmNpreeditDrawCallback))
1771     return PREEDIT_DRAW;
1772   if (!strcmp(name, XmNpreeditCaretCallback))
1773     return PREEDIT_CARET;
1774 
1775   return 100;
1776 }
1777 
1778 static void
set_callback_values(Widget w,String name,XIMCallback * value,VaArgList vlp,XmInputPolicy input_policy)1779 set_callback_values(Widget w,
1780                     String name,
1781                     XIMCallback *value,
1782                     VaArgList vlp,
1783                     XmInputPolicy input_policy)
1784 {
1785   XIMProc call = value->callback;
1786   int s = NameToSwitch(name);
1787   XmInputPolicy ip = input_policy;
1788   Widget p =NULL;
1789 
1790   if (input_policy == XmINHERIT_POLICY){
1791     p = w;
1792     while (!XtIsShell(p))
1793       p = XtParent(p);
1794     XtVaGetValues(p, XmNinputPolicy, &ip, NULL);
1795   }
1796 
1797   switch (s) {
1798     case PREEDIT_START :
1799       if (ip == XmPER_SHELL){
1800         call = value->callback;
1801         regist_real_callback(w, call, s);
1802 	value->client_data = (XPointer)p;
1803         value->callback = (XIMProc) ImPreeditStartCallback;
1804         VaSetArg(vlp, XNPreeditStartCallback, (XPointer)value);
1805       } else
1806         VaSetArg(vlp, XNPreeditStartCallback, (XPointer)value);
1807       break;
1808 
1809     case PREEDIT_DONE :
1810       if (ip == XmPER_SHELL){
1811         call = value->callback;
1812         regist_real_callback(w, call, s);
1813 	value->client_data = (XPointer)p;
1814         value->callback = (XIMProc) ImPreeditDoneCallback;
1815         VaSetArg(vlp, XNPreeditDoneCallback, (XPointer)value);
1816       } else
1817         VaSetArg(vlp, XNPreeditDoneCallback, (XPointer)value);
1818       break;
1819 
1820     case PREEDIT_DRAW :
1821       if (ip == XmPER_SHELL){
1822         call = value->callback;
1823         regist_real_callback(w, call, s);
1824 	value->client_data = (XPointer)p;
1825         value->callback = (XIMProc) ImPreeditDrawCallback;
1826         VaSetArg(vlp, XNPreeditDrawCallback, (XPointer)value);
1827       } else
1828         VaSetArg(vlp, XNPreeditDrawCallback, (XPointer)value);
1829       break;
1830 
1831     case PREEDIT_CARET :
1832       if (ip == XmPER_SHELL){
1833         call = value->callback;
1834         regist_real_callback(w, call, s);
1835 	value->client_data = (XPointer)p;
1836         value->callback = (XIMProc) ImPreeditCaretCallback;
1837         VaSetArg(vlp, XNPreeditCaretCallback, (XPointer)value);
1838       } else
1839         VaSetArg(vlp, XNPreeditCaretCallback, (XPointer)value);
1840       break;
1841 
1842     default :
1843       assert(False);
1844   }
1845 }
1846 
1847 
1848 static void
move_preedit_string(XmImXICInfo icp,Widget wfrom,Widget wto)1849 move_preedit_string(XmImXICInfo icp,
1850 		    Widget wfrom,
1851 		    Widget wto)
1852 {
1853   PreeditBuffer pb = icp->preedit_buffer;
1854   XIMPreeditDrawCallbackStruct draw_data;
1855   XIMText text;
1856   XICProc proc;
1857 
1858   proc = get_real_callback(wfrom, PREEDIT_DONE, &wfrom);
1859   if (proc)
1860     (*proc)(icp->xic, (XPointer)wfrom, NULL);
1861 
1862   proc = get_real_callback(wto, PREEDIT_START, &wto);
1863   if (proc)
1864     (*proc)(icp->xic, (XPointer)wto, NULL);
1865 
1866   if (pb->length == 0)
1867     return;
1868 
1869   draw_data.caret = pb->caret;
1870   draw_data.chg_first = 0;
1871   draw_data.chg_length = 0;
1872   text.length = pb->length;
1873   text.feedback = pb->feedback;
1874   text.encoding_is_wchar = True;
1875   text.string.wide_char = pb->text;
1876   draw_data.text = &text;
1877   proc = get_real_callback(wto, PREEDIT_DRAW, &wto);
1878   if (proc)
1879     (*proc)(icp->xic, (XPointer)wto, (XPointer)&draw_data);
1880 }
1881 
1882 
1883 
1884 /*ARGSUSED*/
1885 static int
add_sp(String name,XPointer value,VaArgList slp,VaArgList plp,VaArgList vlp)1886 add_sp(String name,
1887        XPointer value,
1888        VaArgList slp,
1889        VaArgList plp,
1890        VaArgList vlp )		/* unused */
1891 {
1892   VaSetArg(slp, name, value);
1893   VaSetArg(plp, name, value);
1894 
1895   return BG_CHG;
1896 }
1897 
1898 /*ARGSUSED*/
1899 static int
add_p(String name,XPointer value,VaArgList slp,VaArgList plp,VaArgList vlp)1900 add_p(String name,
1901       XPointer value,
1902       VaArgList slp,		/* unused */
1903       VaArgList plp,
1904       VaArgList vlp )		/* unused */
1905 {
1906   VaSetArg(plp, name, value);
1907 
1908   return 0;
1909 }
1910 
1911 
1912 /*ARGSUSED*/
1913 static int
add_fs(String name,XPointer value,VaArgList slp,VaArgList plp,VaArgList vlp)1914 add_fs(String name,
1915        XPointer value,
1916        VaArgList slp,
1917        VaArgList plp,
1918        VaArgList vlp )		/* unused */
1919 {
1920   XFontSet fs;
1921 
1922   if ( (fs = extract_fontset((XmFontList)value)) == NULL)
1923     return 0;
1924 
1925   VaSetArg(slp, name, (XPointer) fs);
1926   VaSetArg(plp, name, (XPointer) fs);
1927 
1928   return GEO_CHG;
1929 }
1930 
1931 static int
add_bgpxmp(String name,XPointer value,VaArgList slp,VaArgList plp,VaArgList vlp)1932 add_bgpxmp(String name,
1933 	   XPointer value,
1934 	   VaArgList slp,
1935 	   VaArgList plp,
1936 	   VaArgList vlp )
1937 {
1938   if ( (Pixmap)value == XtUnspecifiedPixmap )
1939     return 0;
1940 
1941   return add_sp( name, value, slp, plp, vlp );
1942 }
1943 
1944 static XIMStyle
check_style(XIMStyles * styles,XIMStyle preedit_style,XIMStyle status_style)1945 check_style(XIMStyles *styles,
1946 	    XIMStyle preedit_style,
1947 	    XIMStyle status_style )
1948 {
1949   register int i;
1950 
1951   /* Is this preedit & status style combination supported? */
1952   for (i=0; i < (int) styles->count_styles; i++)
1953     {
1954       if ((styles->supported_styles[i] & preedit_style) &&
1955 	  (styles->supported_styles[i] & status_style))
1956 	return styles->supported_styles[i];
1957     }
1958   return 0;
1959 }
1960 
1961 
1962 /* if this_icp is non-null, operations will only be performed on the
1963    corresponding IC. (Basically disables looping) */
1964 
1965 static int
ImGetGeo(Widget vw,XmImXICInfo this_icp)1966 ImGetGeo(Widget  vw,
1967 	 XmImXICInfo this_icp )
1968 {
1969   XmImXICInfo icp;
1970   XmVendorShellExtObject ve;
1971   XmWidgetExtData extData;
1972   int height = 0;
1973   XRectangle rect;
1974   XRectangle *rp;
1975   XmImShellInfo im_info;
1976   XVaNestedList set_list, get_list;
1977 
1978   extData = _XmGetWidgetExtData((Widget)vw, XmSHELL_EXTENSION);
1979   if (extData)
1980     ve = (XmVendorShellExtObject) extData->widget;
1981   else
1982     ve = NULL;
1983 
1984   im_info = get_im_info(vw, False);
1985 
1986   if (ve && ((im_info == NULL) || (im_info->iclist == NULL))) {
1987     ve->vendor.im_height = 0;
1988     return 0;
1989   }
1990 
1991   set_list = XVaCreateNestedList(0, XNAreaNeeded, (XPointer) &rect, NULL);
1992   get_list = XVaCreateNestedList(0, XNAreaNeeded, (XPointer) &rp, NULL);
1993 
1994   for (icp = this_icp ? this_icp : im_info->iclist;
1995        icp != NULL;
1996        icp = icp->next) {
1997     if (icp->xic) {
1998       if (icp->input_style & XIMStatusArea) {
1999 	rect.width = vw->core.width;
2000 	rect.height = 0;
2001 
2002 	XSetICValues(icp->xic, XNStatusAttributes, set_list, NULL);
2003 	XGetICValues(icp->xic, XNStatusAttributes, get_list, NULL);
2004 
2005 	if ((int) rp->height > height)
2006 	  height = rp->height;
2007 
2008 	icp->status_width = MIN(rp->width, vw->core.width);
2009 	icp->sp_height = rp->height;
2010 	  XFree(rp);
2011       }
2012       if (icp->input_style & XIMPreeditArea) {
2013 	rect.width = vw->core.width;
2014 	rect.height = 0;
2015 
2016 	XSetICValues(icp->xic, XNPreeditAttributes, set_list, NULL);
2017 	XGetICValues(icp->xic, XNPreeditAttributes, get_list, NULL);
2018 
2019 	if ((int) rp->height > height)
2020 	  height = rp->height;
2021 
2022 	icp->preedit_width = MIN((int) rp->width,
2023 				 (int) (vw->core.width - icp->status_width));
2024 	if (icp->sp_height < (int) rp->height)
2025 	  icp->sp_height = rp->height;
2026 	XFree(rp);
2027       }
2028     }
2029 
2030     if (this_icp)
2031       break;
2032   }
2033 
2034   XFree(set_list);
2035   XFree(get_list);
2036 
2037   if (height)
2038     height += SEPARATOR_HEIGHT;
2039 
2040   if (ve)
2041     ve->vendor.im_height = height;
2042   return height;
2043 }
2044 
2045 
2046 /* if this_icp is non-null, operations will only be performed on the
2047    corresponding IC. (Basically disables looping) */
2048 
2049 static void
ImSetGeo(Widget vw,XmImXICInfo this_icp)2050 ImSetGeo(Widget  vw,
2051 	 XmImXICInfo this_icp )
2052 {
2053   XmVendorShellExtObject ve;
2054   XmWidgetExtData extData;
2055   register XmImXICInfo icp;
2056   XRectangle rect_status;
2057   XRectangle rect_preedit;
2058   XmImShellInfo im_info;
2059   XVaNestedList va_slist, va_plist;
2060   unsigned long use_slist, use_plist;
2061 
2062   im_info = get_im_info(vw, False);
2063   if ((im_info == NULL) || (im_info->iclist == NULL))
2064     return;
2065 
2066   extData = _XmGetWidgetExtData((Widget)vw, XmSHELL_EXTENSION);
2067   if (!extData) return;
2068   ve = (XmVendorShellExtObject) extData->widget;
2069 
2070   if (ve->vendor.im_height == 0)
2071     return;
2072 
2073   va_slist = XVaCreateNestedList(0, XNArea, &rect_status, NULL);
2074   va_plist = XVaCreateNestedList(0, XNArea, &rect_preedit, NULL);
2075 
2076   for (icp = this_icp ? this_icp : im_info->iclist;
2077        icp != NULL;
2078        icp = icp->next)
2079     {
2080       if ((use_slist = (icp->input_style & XIMStatusArea)) != 0)
2081 	{
2082 	  rect_status.x = 0;
2083 	  rect_status.y = vw->core.height - icp->sp_height;
2084 	  rect_status.width = icp->status_width;
2085 	  rect_status.height = icp->sp_height;
2086 	}
2087 
2088       if ((use_plist = (icp->input_style & XIMPreeditArea)) != 0)
2089 	{
2090 	  rect_preedit.x = icp->status_width;
2091 	  rect_preedit.y = vw->core.height - icp->sp_height;
2092 	  rect_preedit.width = icp->preedit_width;
2093 	  rect_preedit.height = icp->sp_height;
2094         } else if ((use_plist = (icp->input_style & XIMPreeditPosition)) != 0)
2095         {
2096           unsigned int  margin;
2097 #ifdef FIX_1129
2098         /*
2099          * im_info->current_widget can contains NULL,
2100          * for example, when widget having XIC focus is disposed.
2101          * Thus, we should check this and avoid dereferencing NULL pointer.
2102          */
2103           if (im_info->current_widget == NULL)
2104             break;
2105 #endif
2106           margin = ((XmPrimitiveWidget)im_info->current_widget)
2107                   ->primitive.shadow_thickness
2108               + ((XmPrimitiveWidget)im_info->current_widget)
2109                   ->primitive.highlight_thickness;
2110 
2111             rect_preedit.width = MIN(icp->preedit_width,
2112                   XtWidth(im_info->current_widget) - 2*margin);
2113             rect_preedit.height = MIN(icp->sp_height,
2114                   XtHeight(im_info->current_widget) - 2*margin);
2115 	}
2116 
2117       if (use_slist && use_plist)
2118 	XSetICValues(icp->xic,
2119 		     XNStatusAttributes,  va_slist,
2120 		     XNPreeditAttributes, va_plist,
2121 		     NULL);
2122       else if (use_slist)
2123 	XSetICValues(icp->xic,
2124 		     XNStatusAttributes,  va_slist,
2125 		     NULL);
2126       else if (use_plist)
2127 	XSetICValues(icp->xic,
2128 		     XNPreeditAttributes, va_plist,
2129 		     NULL);
2130 
2131       if (this_icp)
2132 	break;
2133     }
2134 
2135   XFree(va_slist);
2136   XFree(va_plist);
2137 }
2138 
2139 static void
ImGeoReq(Widget vw)2140 ImGeoReq(Widget vw )
2141 {
2142   XmVendorShellExtObject ve;
2143   XmWidgetExtData extData;
2144   XtWidgetGeometry my_request;
2145   int old_height;
2146   int delta_height;
2147   ShellWidget shell = (ShellWidget)(vw);
2148 
2149   if (!(shell->shell.allow_shell_resize) && XtIsRealized(vw))
2150     return;
2151 
2152   extData = _XmGetWidgetExtData(vw, XmSHELL_EXTENSION);
2153   if (!extData) return;
2154   ve = (XmVendorShellExtObject) extData->widget;
2155 
2156   old_height = ve->vendor.im_height;
2157   ImGetGeo(vw, NULL);
2158   if ((delta_height = ve->vendor.im_height - old_height) != 0)
2159     {
2160       int base_height;
2161       Arg args[1];
2162       XtSetArg(args[0], XtNbaseHeight, &base_height);
2163       XtGetValues(vw, args, 1);
2164       if (base_height > 0) {
2165 	base_height += delta_height;
2166 	XtSetArg(args[0], XtNbaseHeight, base_height);
2167 	XtSetValues(vw, args, 1);
2168       }
2169       my_request.height = vw->core.height + delta_height;
2170       my_request.request_mode = CWHeight;
2171       XtMakeGeometryRequest(vw, &my_request, NULL);
2172     }
2173   ImSetGeo(vw, NULL);
2174 }
2175 
2176 static XFontSet
extract_fontset(XmFontList fl)2177 extract_fontset(
2178 		XmFontList fl )
2179 {
2180   XmFontContext context;
2181   XmFontListEntry next_entry;
2182   XmFontType type_return;
2183   XtPointer tmp_font;
2184   XFontSet first_fs = NULL;
2185   char *font_tag = NULL;
2186 
2187   if (!XmFontListInitFontContext(&context, fl))
2188     return NULL;
2189 
2190   do {
2191     next_entry = XmFontListNextEntry(context);
2192     if (next_entry)
2193       {
2194 	tmp_font = XmFontListEntryGetFont(next_entry, &type_return);
2195 	if (type_return == XmFONT_IS_FONTSET)
2196 	  {
2197 	    font_tag = XmFontListEntryGetTag(next_entry);
2198 	    if (!strcmp(font_tag, XmFONTLIST_DEFAULT_TAG))
2199 	      {
2200 		XmFontListFreeFontContext(context);
2201 		if (font_tag) XtFree(font_tag);
2202 		return (XFontSet)tmp_font;
2203 	      }
2204 	    if (font_tag) XtFree(font_tag);
2205 	    if (first_fs == NULL)
2206 	      first_fs = (XFontSet)tmp_font;
2207 	  }
2208       }
2209   } while (next_entry);
2210 
2211   XmFontListFreeFontContext(context);
2212   return first_fs;
2213 }
2214 
2215 /* Fetch (creating if necessary) the Display's xmim_info. */
2216 static XmImDisplayInfo
get_xim_info(Widget widget)2217 get_xim_info(Widget  widget)
2218 {
2219   XmDisplay xmDisplay;
2220   char tmp[BUFSIZ];
2221   char *cp = NULL;
2222   XmImDisplayInfo xim_info;
2223   String name, w_class;
2224   Display *dpy;
2225   Widget shell;
2226 
2227   if (widget == NULL)
2228     return NULL;
2229 
2230   /* Find the parent shell. */
2231   shell = widget;
2232   while (!XtIsShell(shell))
2233     shell = XtParent(shell);
2234 
2235   dpy = XtDisplay(shell);
2236   xmDisplay = (XmDisplay) XmGetXmDisplay(dpy);
2237   xim_info = (XmImDisplayInfo)xmDisplay->display.xmim_info;
2238 
2239   /* If this is a simple lookup we're done. */
2240   if (xim_info != NULL)
2241     return xim_info;
2242 
2243   /* Create a record so that we only try XOpenIM() once. */
2244   xim_info = XtNew(XmImDisplayRec);
2245   bzero((char*) xim_info, sizeof(XmImDisplayRec));
2246   xmDisplay->display.xmim_info = (XtPointer)xim_info;
2247 
2248   /* Setup any specified locale modifiers. */
2249   XtVaGetValues(shell, XmNinputMethod, &cp, NULL);
2250   if (cp != NULL)
2251     {
2252       strcpy(tmp,"@im=");
2253       strcat(tmp,cp);
2254       assert(strlen(tmp) < BUFSIZ);
2255       XSetLocaleModifiers(tmp);
2256     }
2257 
2258   XtGetApplicationNameAndClass(dpy, &name, &w_class);
2259 
2260   /* Try to open the input method. */
2261   xim_info->xim = XOpenIM(dpy, XtDatabase(dpy), name, w_class);
2262   if (xim_info->xim == NULL)
2263     {
2264 #ifdef XOPENIM_WARNING
2265       /* Generate a warning if XOpenIM was supposed to work. */
2266       /* Use the WMShell's XmNtitleEncoding as a shibboleth. */
2267       Atom encoding = (Atom) 0;
2268       XtVaGetValues(shell, XmNtitleEncoding, &encoding, NULL);
2269       if (encoding != XA_STRING)
2270 	XmeWarning ((Widget)widget, MSG1);
2271 #endif
2272 
2273       /* Leave the null xim_info attached to the display so we only */
2274       /* print the warning message once. */
2275       return xim_info;
2276     }
2277 
2278   /* Lookup the styles this input method supports. */
2279   if (XGetIMValues(xim_info->xim,
2280 		   XNQueryInputStyle, &xim_info->styles, NULL) != NULL)
2281     {
2282       XCloseIM(xim_info->xim);
2283       xim_info->xim = NULL;
2284       XmeWarning ((Widget)widget, MSG1);
2285       return xim_info;
2286     }
2287 
2288   /* Initialize the list of xrm names */
2289   {
2290     XmImResListRec *rlp;
2291     register int i;
2292 
2293     _XmProcessLock();
2294     for (rlp = XmImResList, i = XtNumber(XmImResList);
2295 	 i != 0;
2296 	 i--, rlp++)
2297       rlp->xrmname = XrmStringToName(rlp->xmstring);
2298     _XmProcessUnlock();
2299   }
2300 
2301   return xim_info;
2302 }
2303 
2304 static XtPointer*
get_im_info_ptr(Widget w,Boolean create)2305 get_im_info_ptr(Widget  w,
2306 		Boolean create)
2307 {
2308   Widget p;
2309   XmVendorShellExtObject ve;
2310   XmWidgetExtData extData;
2311   XmImShellInfo im_info;
2312   XmImDisplayInfo xim_info;
2313 
2314   if (w == NULL)
2315     return NULL;
2316 
2317   p = w;
2318   while (!XtIsShell(p))
2319     p = XtParent(p);
2320 
2321   /* Check extension data since app could be attempting to create
2322    * a text widget as child of menu shell.  This is illegal, and will
2323    * be detected later, but check here so we don't core dump.
2324    */
2325   if ((extData = _XmGetWidgetExtData((Widget)p, XmSHELL_EXTENSION)) == NULL)
2326     return NULL;
2327 
2328   ve = (XmVendorShellExtObject) extData->widget;
2329 
2330   if ((ve->vendor.im_info == NULL) && create)
2331     {
2332       im_info = XtNew(XmImShellRec);
2333       bzero((char*) im_info, sizeof(XmImShellRec));
2334       ve->vendor.im_info = (XtPointer)im_info;
2335 
2336       xim_info = get_xim_info(p);
2337       (void) add_ref(&xim_info->shell_refs, p);
2338     }
2339 
2340   return &ve->vendor.im_info;
2341 }
2342 
2343 static XmImShellInfo
get_im_info(Widget w,Boolean create)2344 get_im_info(Widget w,
2345 	    Boolean create)
2346 {
2347   XmImShellInfo* ptr = (XmImShellInfo *) get_im_info_ptr(w, create);
2348   if (ptr != NULL)
2349     return *ptr;
2350   else
2351     return NULL;
2352 }
2353 
2354 static void
draw_separator(Widget vw)2355 draw_separator(Widget vw )
2356 {
2357   XmPrimitiveWidget pw;
2358   XmVendorShellExtObject ve;
2359   XmWidgetExtData extData;
2360   XmImShellInfo im_info;
2361 
2362   extData = _XmGetWidgetExtData((Widget)vw, XmSHELL_EXTENSION);
2363   if (!extData) return;
2364   ve = (XmVendorShellExtObject) extData->widget;
2365   if ((im_info = (XmImShellInfo)ve->vendor.im_info) == NULL)
2366     return;
2367   pw = (XmPrimitiveWidget)im_info->current_widget;
2368   if (!pw || !XmIsPrimitive(pw))
2369     return;
2370 
2371   XmeDrawSeparator(XtDisplay(vw), XtWindow(vw),
2372 		   pw->primitive.top_shadow_GC,
2373 		   pw->primitive.bottom_shadow_GC,
2374 		   0,
2375 		   0,
2376 		   vw->core.height - ve->vendor.im_height,
2377 		   vw->core.width,
2378 		   SEPARATOR_HEIGHT,
2379 		   SEPARATOR_HEIGHT,
2380 		   0, 			/* separator.margin */
2381 		   XmHORIZONTAL,		/* separator.orientation */
2382 		   XmSHADOW_ETCHED_IN); /* separator.separator_type */
2383 }
2384 
2385 /*ARGSUSED*/
2386 static void
null_proc(Widget w,XtPointer ptr,XEvent * ev,Boolean * b)2387 null_proc(Widget w,		/* unused */
2388 	  XtPointer ptr,		/* unused */
2389 	  XEvent *ev,		/* unused */
2390 	  Boolean *b )		/* unused */
2391 {
2392   /* This function does nothing.  It is only there to allow the
2393    * event mask required by the input method to be added to
2394    * the client window.
2395    */
2396 }
2397 
2398 /* The following section contains the varargs functions */
2399 
2400 
2401 /*VARARGS*/
2402 void
XmImVaSetFocusValues(Widget w,...)2403 XmImVaSetFocusValues(Widget w,
2404 		     ... )
2405 {
2406   va_list	var;
2407   int	    	total_count;
2408   ArgList     args;
2409   _XmWidgetToAppContext(w);
2410 
2411   _XmAppLock(app);
2412   Va_start(var,w);
2413   ImCountVaList(var, &total_count);
2414   va_end(var);
2415 
2416   Va_start(var,w);
2417   args  = ImCreateArgList(var, total_count);
2418   va_end(var);
2419 
2420   XmImSetFocusValues(w, args, total_count);
2421   XtFree((char *)args);
2422   _XmAppUnlock(app);
2423 }
2424 
2425 /*VARARGS*/
2426 void
XmImVaSetValues(Widget w,...)2427   XmImVaSetValues(Widget w,
2428 		  ... )
2429 {
2430   va_list	var;
2431   int	    	total_count;
2432   ArgList     args;
2433   _XmWidgetToAppContext(w);
2434 
2435   _XmAppLock(app);
2436   Va_start(var,w);
2437   ImCountVaList(var, &total_count);
2438   va_end(var);
2439 
2440   Va_start(var,w);
2441   args  = ImCreateArgList(var, total_count);
2442   va_end(var);
2443 
2444   XmImSetValues(w, args, total_count);
2445   XtFree((char *)args);
2446   _XmAppUnlock(app);
2447 }
2448 
2449 
2450 static void
ImCountVaList(va_list var,int * total_count)2451 ImCountVaList(va_list var,
2452 	      int *total_count )
2453 {
2454   String          attr;
2455 
2456   *total_count = 0;
2457 
2458   for(attr = va_arg(var, String); attr != NULL; attr = va_arg(var, String))
2459     {
2460       (void) va_arg(var, XPointer);
2461       ++(*total_count);
2462     }
2463 }
2464 
2465 static ArgList
ImCreateArgList(va_list var,int total_count)2466 ImCreateArgList(va_list var,
2467 		int total_count )
2468 {
2469   ArgList args = (ArgList)XtCalloc(total_count, sizeof(Arg));
2470   register int i;
2471 
2472   assert(args || (total_count == 0));
2473   for (i = 0; i < total_count; i++)
2474     {
2475       args[i].name = va_arg(var,String);
2476       args[i].value = (XtArgVal)va_arg(var,XPointer);
2477     }
2478 
2479   return args;
2480 }
2481 
2482 /* Return the current xic info for a widget, or NULL. */
2483 static XmImXICInfo
get_current_xic(XmImDisplayInfo xim_info,Widget widget)2484 get_current_xic(XmImDisplayInfo xim_info,
2485 		Widget          widget)
2486 {
2487   XmImXICInfo xic_info;
2488 
2489   if ((xim_info == NULL) ||
2490       (xim_info->current_xics == (XContext) 0))
2491     return NULL;
2492 
2493   if (XFindContext(XtDisplay(widget), (XID) widget,
2494 		   xim_info->current_xics, (XPointer*) &xic_info) != 0)
2495     return NULL;
2496   else
2497     return xic_info;
2498 }
2499 
2500 /* Set the current XIC for an unregistered widget. */
2501 static void
set_current_xic(XmImXICInfo xic_info,XmImDisplayInfo xim_info,Widget widget)2502 set_current_xic(XmImXICInfo 	xic_info,
2503 		XmImDisplayInfo	xim_info,
2504 		Widget		widget)
2505 {
2506   if (xic_info == NULL)
2507     return;
2508 
2509   /* Record this widget as a reference to this XIC. */
2510   (void) add_ref(&xic_info->widget_refs, widget);
2511 
2512   /* Set the current XIC for this widget. */
2513   if (xim_info->current_xics == (XContext) NULL)
2514     xim_info->current_xics = XUniqueContext();
2515   (void) XSaveContext(XtDisplay(widget), (XID) widget,
2516 		      xim_info->current_xics, (XPointer) xic_info);
2517 }
2518 
2519 /* Unset the current XIC for a widget, freeing data as necesary. */
2520 static void
unset_current_xic(XmImXICInfo xic_info,XmImShellInfo im_info,XmImDisplayInfo xim_info,Widget widget)2521 unset_current_xic(XmImXICInfo	  xic_info,
2522 		  XmImShellInfo   im_info,
2523 		  XmImDisplayInfo xim_info,
2524 		  Widget 	  widget)
2525 {
2526   /* Remove the current xic for this widget. */
2527   assert(xim_info->current_xics != (XContext) 0);
2528   (void) XDeleteContext(XtDisplay(widget), (XID) widget,
2529 			xim_info->current_xics);
2530 #ifdef FIX_1196
2531   if (im_info->current_widget == widget)
2532     im_info->current_widget = NULL;
2533 #endif
2534   /* Remove this widget as a reference to this XIC. */
2535   if (remove_ref(&xic_info->widget_refs, widget) == 0)
2536     {
2537       /* Remove this xic_info from the master list. */
2538       XmImXICInfo *ptr;
2539       for (ptr = &(im_info->iclist); *ptr != NULL; ptr = &((*ptr)->next))
2540 	if (*ptr == xic_info)
2541 	  {
2542 	    *ptr = xic_info->next;
2543 	    break;
2544 	  }
2545 #ifndef FIX_1196
2546       if (im_info->current_widget == widget)
2547 	im_info->current_widget = NULL;
2548 #endif
2549       /* Don't let anyone share this XIC. */
2550       if (xic_info->source != NULL)
2551 	*(xic_info->source) = NULL;
2552 
2553       /* Destroy the XIC */
2554       if ((xic_info->anonymous) && (xic_info->xic != NULL))
2555 	XDestroyIC(xic_info->xic);
2556 
2557       ImFreePreeditBuffer (xic_info->preedit_buffer);
2558       XtFree((char *) xic_info);
2559     }
2560 }
2561 
2562 /* Add a widget to a list of references. */
2563 static Cardinal
add_ref(XmImRefInfo refs,Widget widget)2564 add_ref(XmImRefInfo refs,
2565 	Widget	    widget)
2566 {
2567 #ifdef DEBUG
2568   /* Verify that we don't already have a reference. */
2569   register Cardinal index;
2570   for (index = 0; index < refs->num_refs; index++)
2571     assert(refs->refs[index] != widget);
2572 #endif
2573 
2574   /* Make room in the array. */
2575   if (refs->num_refs == refs->max_refs)
2576     {
2577       if (refs->max_refs == 0)
2578 	refs->max_refs = 10;
2579       else
2580 	refs->max_refs += (refs->max_refs / 2);
2581 
2582       refs->refs = (Widget*) XtRealloc((char *) refs->refs,
2583 				       refs->max_refs * sizeof(Widget));
2584       refs->callbacks = (XtPointer **) XtRealloc((char *) refs->callbacks,
2585                                        refs->max_refs * sizeof(XtPointer *));
2586     }
2587   assert(refs->num_refs < refs->max_refs);
2588 
2589   refs->callbacks[refs->num_refs] = NULL;
2590 
2591   /* Insert this reference. */
2592   refs->refs[refs->num_refs++] = widget;
2593 
2594   return refs->num_refs;
2595 }
2596 
2597 /* Remove a widget from a list of references. */
2598 static Cardinal
remove_ref(XmImRefInfo refs,Widget widget)2599 remove_ref(XmImRefInfo refs,
2600 	   Widget      widget)
2601 {
2602   /* Is this the last reference? */
2603   refs->num_refs--;
2604   if (refs->num_refs > 0)
2605     {
2606       /* Just remove this reference. */
2607       int index = 0;
2608       while (index <= refs->num_refs) {
2609 	if (refs->refs[index] == widget)
2610 	  {
2611 	    refs->refs[index] = refs->refs[refs->num_refs];
2612 	    refs->refs[refs->num_refs] = NULL;
2613             XtFree((char *)refs->callbacks[index]);
2614             refs->callbacks[index] = refs->callbacks[refs->num_refs];
2615             refs->callbacks[refs->num_refs] = NULL;
2616 
2617 	    break;
2618 	  }
2619 	index++;
2620       }
2621 
2622       /* Free some storage from the array? */
2623       if ((refs->num_refs * 3 < refs->max_refs) &&
2624 	  (refs->max_refs >= 20))
2625 	{
2626 	  refs->max_refs /= 2;
2627 	  refs->refs = (Widget*) XtRealloc((char *) refs->refs,
2628 					   refs->max_refs * sizeof(Widget));
2629           refs->callbacks = (XtPointer **) XtRealloc((char *) refs->callbacks,
2630                                    refs->max_refs * sizeof(XtPointer *));
2631 	}
2632     }
2633   else
2634     {
2635       /* Free the references array. */
2636       XtFree((char *) refs->refs);
2637       refs->refs = NULL;
2638       XtFree((char *) refs->callbacks[0]);
2639       XtFree((char *) refs->callbacks);
2640       refs->callbacks = NULL;
2641       refs->max_refs = 0;
2642     }
2643 
2644   return refs->num_refs;
2645 }
2646 
2647 /* Convert a VaArgList into a true XVaNestedList. */
2648 static XVaNestedList
VaCopy(VaArgList list)2649 VaCopy(VaArgList list)
2650 {
2651   /* This is ugly, but it's a legal way to construct a nested */
2652   /* list whose length is unknown at compile time.  If MAXARGS is */
2653   /* increased more parameter pairs should be added below.   A */
2654   /* recursive approach would leak memory. */
2655   register Cardinal count = list->count;
2656   register VaArg *args = list->args;
2657 
2658 #define VA_NAME(index)	(index < count ? args[index].name : NULL)
2659 #define VA_VALUE(index)	(index < count ? args[index].value : NULL)
2660 
2661   assert(count <= 10);
2662   return XVaCreateNestedList(0,
2663 			     VA_NAME(0), VA_VALUE(0),
2664 			     VA_NAME(1), VA_VALUE(1),
2665 			     VA_NAME(2), VA_VALUE(2),
2666 			     VA_NAME(3), VA_VALUE(3),
2667 			     VA_NAME(4), VA_VALUE(4),
2668 			     VA_NAME(5), VA_VALUE(5),
2669 			     VA_NAME(6), VA_VALUE(6),
2670 			     VA_NAME(7), VA_VALUE(7),
2671 			     VA_NAME(8), VA_VALUE(8),
2672 			     VA_NAME(9), VA_VALUE(9),
2673 			     NULL);
2674 
2675 #undef VA_NAME
2676 #undef VA_VALUE
2677 }
2678 
2679 static void
VaSetArg(VaArgList list,char * name,XPointer value)2680 VaSetArg(VaArgList list,
2681 	 char     *name,
2682 	 XPointer  value)
2683 {
2684   if (list->max <= list->count)
2685     {
2686       list->max += 10;
2687       list->args = (VaArg*) XtRealloc((char*) list->args,
2688 				      list->max * sizeof(VaArg));
2689     }
2690 
2691   list->args[list->count].name = name;
2692   list->args[list->count].value = value;
2693   list->count++;
2694 }
2695 
2696 
2697 void
XmImMbResetIC(Widget w,char ** mb)2698 XmImMbResetIC(
2699     Widget w,
2700     char **mb)
2701 {
2702     register XmImXICInfo icp;
2703     _XmWidgetToAppContext(w);
2704 
2705     _XmAppLock(app);
2706 
2707     *mb = NULL;
2708 
2709     if ((icp = get_current_xic(get_xim_info(w), w)) == NULL ||
2710 	icp->xic == NULL) {
2711 	_XmAppUnlock(app);
2712         return;
2713     }
2714 
2715     if (!(icp->input_style & XIMPreeditCallbacks)) {
2716 	_XmAppUnlock(app);
2717 	return;
2718     }
2719 
2720     *mb = XmbResetIC(icp->xic);
2721     _XmAppUnlock(app);
2722 }
2723 
2724 XIMResetState
XmImGetXICResetState(Widget w)2725 XmImGetXICResetState(Widget w)
2726 {
2727     XmImXICInfo icp;
2728     XIMResetState state = XIMInitialState;
2729     icp = get_current_xic(get_xim_info(w), w);
2730     if (icp != NULL && icp->xic != NULL)
2731         XGetICValues(icp->xic, XNResetState, &state, NULL);
2732     return state;
2733 }
2734