XawIm.c revision ab902922
1/* $Xorg: XawIm.c,v 1.6 2001/02/09 02:03:47 xorgcvs Exp $ */
2
3/*
4 * Copyright 1991 by OMRON Corporation
5 *
6 * Permission to use, copy, modify, distribute, and sell this software and its
7 * documentation for any purpose is hereby granted without fee, provided that
8 * the above copyright notice appear in all copies and that both that
9 * copyright notice and this permission notice appear in supporting
10 * documentation, and that the name of OMRON not be used in advertising or
11 * publicity pertaining to distribution of the software without specific,
12 * written prior permission.  OMRON makes no representations about the
13 * suitability of this software for any purpose.  It is provided "as is"
14 * without express or implied warranty.
15 *
16 * OMRON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
17 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
18 * OMRON BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
19 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
20 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTUOUS ACTION,
21 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
22 * SOFTWARE.
23 *
24 *	Author:	Seiji Kuwari	OMRON Corporation
25 *				kuwa@omron.co.jp
26 *				kuwa%omron.co.jp@uunet.uu.net
27 */
28
29
30/*
31
32Copyright 1994, 1998  The Open Group
33
34Permission to use, copy, modify, distribute, and sell this software and its
35documentation for any purpose is hereby granted without fee, provided that
36the above copyright notice appear in all copies and that both that
37copyright notice and this permission notice appear in supporting
38documentation.
39
40The above copyright notice and this permission notice shall be included in
41all copies or substantial portions of the Software.
42
43THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
44IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
45FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
46OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
47AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
48CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
49
50Except as contained in this notice, the name of The Open Group shall not be
51used in advertising or otherwise to promote the sale, use or other dealings
52in this Software without prior written authorization from The Open Group.
53
54*/
55/* $XFree86: xc/lib/Xaw/XawIm.c,v 1.14tsi Exp $ */
56
57#ifdef HAVE_CONFIG_H
58#include <config.h>
59#endif
60#include <X11/IntrinsicP.h>
61#include <X11/StringDefs.h>
62#include <X11/Xos.h>
63#include <X11/Xfuncs.h>
64#include <X11/ShellP.h>
65#include <X11/Xaw/TextP.h>
66#include <X11/Xaw/MultiSrc.h>
67#include <X11/Xaw/MultiSinkP.h>
68#include <X11/Xaw/XawImP.h>
69#include <X11/Xaw/VendorEP.h>
70#include "XawI18n.h"
71#include <ctype.h>
72
73#include <stdarg.h>
74
75#define maxAscentOfFontSet(fontset)     \
76        ( - (XExtentsOfFontSet((fontset)))->max_logical_extent.y)
77
78#define maxHeightOfFontSet(fontset) \
79        ((XExtentsOfFontSet((fontset)))->max_logical_extent.height)
80
81#define maxDescentOfFontSet(fontset) \
82        (maxHeightOfFontSet(fontset) - maxAscentOfFontSet(fontset))
83
84#define Offset(field) (XtOffsetOf(XawIcTablePart, field))
85
86/*****************************************************
87 *
88 * Forward reference prototypes
89 *
90 *****************************************************/
91
92/*
93 * Prototypes
94 */
95static void AllCreateIC(XawVendorShellExtPart*);
96static void CloseIM(XawVendorShellExtPart*);
97static void CompileResourceList(XtResourceList, unsigned int);
98static void ConfigureCB(Widget, XtPointer, XEvent*, Boolean*);
99static void CreateIC(Widget, XawVendorShellExtPart*);
100static XawIcTableList CreateIcTable(Widget, XawVendorShellExtPart*);
101static XawIcTableList CurrentSharedIcTable(XawVendorShellExtPart*);
102static void Destroy(Widget, XawVendorShellExtPart*);
103static void DestroyAllIM(XawVendorShellExtPart*);
104static void DestroyIC(Widget, XawVendorShellExtPart*);
105static void FreeAllDataOfVendorShell(XawVendorShellExtPart*,
106				     VendorShellWidget);
107static XawVendorShellExtPart *GetExtPart(VendorShellWidget);
108static XawIcTableList GetIcTable(Widget, XawVendorShellExtPart*);
109static XawIcTableList GetIcTableShared(Widget, XawVendorShellExtPart*);
110static XIMStyle GetInputStyleOfIC(XawVendorShellExtPart*);
111static Bool Initialize(VendorShellWidget, XawVendorShellExtPart*);
112static Bool IsCreatedIC(Widget, XawVendorShellExtPart*);
113static Bool IsRegistered(Widget, XawVendorShellExtPart*);
114static Bool IsSharedIC(XawVendorShellExtPart*);
115static Bool NoRegistered(XawVendorShellExtPart*);
116static void OpenIM(XawVendorShellExtPart*);
117static void Reconnect(XawVendorShellExtPart*);
118static void Register(Widget, XawVendorShellExtPart*);
119static Bool RegisterToVendorShell(Widget, XawVendorShellExtPart*);
120static void ResizeVendorShell(VendorShellWidget, XawVendorShellExtPart*);
121static Bool ResizeVendorShell_Core(VendorShellWidget, XawVendorShellExtPart*,
122				   XawIcTableList);
123static VendorShellWidget SearchVendorShell(Widget);
124static Widget SetErrCnxt(Widget, XIM);
125static XawVendorShellExtPart *SetExtPart(VendorShellWidget,
126					 XawVendorShellExtWidget);
127static void SetFocus(Widget, XawVendorShellExtPart*);
128static void SetFocusValues(Widget, ArgList, Cardinal, Bool);
129static void SetICFocus(Widget, XawVendorShellExtPart*);
130static void SetICValues(Widget, XawVendorShellExtPart*, Bool);
131static void SetICValuesShared(Widget, XawVendorShellExtPart*, XawIcTableList,
132			      Bool);
133static void SetValues(Widget, XawVendorShellExtPart*, ArgList, Cardinal);
134static unsigned int SetVendorShellHeight(XawVendorShellExtPart*,
135					 unsigned int);
136static void SharedICChangeFocusWindow(Widget, XawVendorShellExtPart*,
137				      XawIcTableList);
138static void SizeNegotiation(XawIcTableList, unsigned int, unsigned int);
139static void Unregister(Widget, XawVendorShellExtPart*);
140static void UnregisterFromVendorShell(Widget, XawVendorShellExtPart*);
141static void UnsetFocus(Widget);
142static void UnsetICFocus(Widget, XawVendorShellExtPart*);
143static void VendorShellDestroyed(Widget, XtPointer, XtPointer);
144
145/*
146 * From Vendor.c
147 */
148void XawVendorShellExtResize(Widget);
149void XawVendorStructureNotifyHandler(Widget, XtPointer, XEvent*, Boolean*);
150
151
152/*
153 * From Xt/Resources.c
154 */
155void _XtCopyFromArg(XtArgVal src, char*, unsigned int);
156
157static XtResource resources[] =
158{
159    {
160	XtNfontSet, XtCFontSet, XtRFontSet, sizeof(XFontSet),
161	Offset (font_set), XtRString, XtDefaultFontSet
162    },
163    {
164	XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
165	Offset (foreground), XtRString, (XtPointer)"XtDefaultForeground"
166    },
167    {
168	XtNbackground, XtCBackground, XtRPixel, sizeof(Pixel),
169	Offset (background), XtRString, (XtPointer)"XtDefaultBackground"
170    },
171    {
172	XtNbackgroundPixmap, XtCPixmap, XtRPixmap, sizeof(Pixmap),
173	Offset (bg_pixmap), XtRImmediate, (XtPointer) XtUnspecifiedPixmap
174    },
175    {
176	XtNinsertPosition, XtCTextPosition, XtRInt, sizeof (XawTextPosition),
177	Offset (cursor_position), XtRImmediate, (XtPointer) 0
178    }
179};
180#undef Offset
181
182
183static VendorShellWidget SearchVendorShell(Widget w)
184{
185    while(w && !XtIsShell(w)) w = XtParent(w);
186    if (w && XtIsVendorShell(w)) return((VendorShellWidget)w);
187    return(NULL);
188}
189
190static XContext extContext = (XContext)NULL;
191
192static XawVendorShellExtPart *
193SetExtPart(VendorShellWidget w, XawVendorShellExtWidget vew)
194{
195    contextDataRec *contextData;
196
197    if (extContext == (XContext)NULL) extContext = XUniqueContext();
198
199    contextData = XtNew(contextDataRec);
200    contextData->parent = (Widget)w;
201    contextData->ve = (Widget)vew;
202    if (XSaveContext(XtDisplay(w), (Window)w, extContext, (char *)contextData)) {
203	return(NULL);
204    }
205    return(&(vew->vendor_ext));
206}
207
208static XawVendorShellExtPart *
209GetExtPart(VendorShellWidget w)
210{
211    contextDataRec *contextData;
212    XawVendorShellExtWidget vew;
213
214    if (XFindContext(XtDisplay(w), (Window)w, extContext,
215		      (XPointer*)&contextData)) {
216	return(NULL);
217    }
218    vew = (XawVendorShellExtWidget)contextData->ve;
219    return(&(vew->vendor_ext));
220}
221
222static Bool
223IsSharedIC(XawVendorShellExtPart * ve)
224{
225    return( ve->ic.shared_ic );
226}
227
228static XawIcTableList
229GetIcTableShared(Widget w, XawVendorShellExtPart *ve)
230{
231    XawIcTableList	p;
232
233    for (p = ve->ic.ic_table; p; p = p->next) {
234	if (p->widget == w) {
235	    if (IsSharedIC(ve)) {
236		return(ve->ic.shared_ic_table);
237	    } else {
238		return(p);
239	    }
240	}
241    }
242    return(NULL);
243}
244
245static XawIcTableList
246GetIcTable(Widget w, XawVendorShellExtPart *ve)
247{
248    XawIcTableList	p;
249
250    for (p = ve->ic.ic_table; p; p = p->next) {
251	if (p->widget == w) {
252	    return(p);
253	}
254    }
255    return(NULL);
256}
257
258static XIMStyle
259GetInputStyleOfIC(XawVendorShellExtPart *ve)
260{
261
262    if (!ve) return((XIMStyle)0);
263    return(ve->ic.input_style);
264}
265
266/*ARGSUSED*/
267static void
268ConfigureCB(Widget w, XtPointer closure, XEvent *event, Boolean *unused)
269{
270    XawIcTableList		p;
271    XawVendorShellExtPart	*ve;
272    VendorShellWidget		vw;
273    XVaNestedList		pe_attr;
274    XRectangle			pe_area;
275    XawTextMargin		*margin;
276
277    if (event->type != ConfigureNotify) return;
278
279    if ((vw = SearchVendorShell(w)) == NULL) return;
280
281    if ((ve = GetExtPart(vw)) != NULL) {
282        if (IsSharedIC(ve)) return;
283	if ((ve->im.xim == NULL) ||
284	    ((p = GetIcTableShared(w, ve)) == NULL) ||
285	    (p->xic == NULL) || !(p->input_style & XIMPreeditPosition)) return;
286	pe_area.x = 0;
287        pe_area.y = 0;
288        pe_area.width = w->core.width;
289        pe_area.height = w->core.height;
290	margin = &(((TextWidget)w)->text.margin);
291	pe_area.x += margin->left;
292	pe_area.y += margin->top;
293	pe_area.width -= (margin->left + margin->right - 1);
294	pe_area.height -= (margin->top + margin->bottom - 1);
295
296	pe_attr = XVaCreateNestedList(0, XNArea, &pe_area, NULL);
297	XSetICValues(p->xic, XNPreeditAttributes, pe_attr, NULL);
298	XtFree(pe_attr);
299    }
300}
301
302static XContext errContext = (XContext)NULL;
303
304static Widget SetErrCnxt(Widget w, XIM xim)
305{
306    contextErrDataRec *contextErrData;
307
308    if (errContext == (XContext)NULL) errContext = XUniqueContext();
309
310    contextErrData = XtNew(contextErrDataRec);
311    contextErrData->widget = w;
312    contextErrData->xim = xim;
313    if (XSaveContext(XtDisplay(w), (Window)xim, errContext,
314	(char *)contextErrData)) {
315	return(NULL);
316    }
317    return(contextErrData->widget);
318}
319
320#if 0
321static Widget
322GetErrCnxt(XIM error_im)
323{
324    contextErrDataRec *contextErrData;
325
326    if (XFindContext(XDisplayOfIM(error_im), (Window)error_im, errContext,
327		      (XPointer*)&contextErrData)) {
328	return(NULL);
329    }
330    return(contextErrData->widget);
331}
332#endif
333
334static void
335CloseIM(XawVendorShellExtPart *ve)
336{
337    if (ve->im.xim)
338	XCloseIM(ve->im.xim);
339}
340
341static unsigned int
342SetVendorShellHeight(XawVendorShellExtPart* ve, unsigned int height)
343{
344    Arg			args[2];
345    Cardinal		i = 0;
346
347   if (ve->im.area_height < height || height == 0) {
348       XtSetArg(args[i], XtNheight,
349		(ve->parent->core.height + height - ve->im.area_height));
350       ve->im.area_height = height;
351       XtSetValues(ve->parent, args, 1);
352   }
353   return(ve->im.area_height);
354}
355
356static void
357DestroyAllIM(XawVendorShellExtPart *ve)
358{
359    XawIcTableList	p;
360    contextErrDataRec *contextErrData;
361
362    /*
363     * Destory all ICs
364     */
365    if (IsSharedIC(ve)) {
366        if ((p = ve->ic.shared_ic_table) && p->xic) {
367            DestroyIC(p->widget, ve);
368            p->xic = NULL;
369            p->ic_focused = FALSE;
370        }
371    } else {
372	for (p = ve->ic.ic_table; p; p = p->next) {
373	    if (p->xic == NULL) continue;
374	    DestroyIC(p->widget, ve);
375	    p->xic = NULL;
376	    p->ic_focused = FALSE;
377	}
378    }
379    if (!ve->im.xim) return;
380    /*
381     * Close Input Method
382     */
383    if (!XFindContext(XDisplayOfIM(ve->im.xim), (Window)ve->im.xim, errContext,
384		      (XPointer*)&contextErrData)) {
385	if (contextErrData) XtFree((char *)contextErrData);
386    }
387    XDeleteContext(XDisplayOfIM(ve->im.xim), (Window)ve->im.xim, errContext);
388    CloseIM(ve);
389    ve->im.xim = NULL;
390
391    /*
392     * resize vendor shell to core size
393     */
394    (void) SetVendorShellHeight(ve, 0);
395    /*
396    XawVendorShellExtResize(vw);
397    */
398    return;
399}
400
401static void
402FreeAllDataOfVendorShell(XawVendorShellExtPart *ve, VendorShellWidget vw)
403{
404    XawIcTableList       p, next;
405    contextErrDataRec *contextErrData;
406
407    if (!XFindContext(XtDisplay(vw), (Window)vw, extContext,
408		      (XPointer*)&contextErrData)) {
409	if (contextErrData) XtFree((char *)contextErrData);
410    }
411    XDeleteContext(XtDisplay(vw), (Window)vw, extContext);
412    if (ve->ic.shared_ic_table)
413        XtFree((char *)ve->ic.shared_ic_table);
414    if (ve->im.resources) XtFree((char *)ve->im.resources);
415    for (p = ve->ic.ic_table; p; p = next) {
416        next = p->next;
417        XtFree((char *)p);
418    }
419}
420
421static void
422VendorShellDestroyed(Widget w, XtPointer cl_data, XtPointer ca_data)
423{
424    XawVendorShellExtPart	*ve;
425
426    if ( ( ve = GetExtPart( (VendorShellWidget) w ) ) == NULL ) return;
427    DestroyAllIM( ve );
428    FreeAllDataOfVendorShell( ve, (VendorShellWidget) w );
429    return;
430}
431
432#if 0
433static int
434IOErrorHandler(XIM error_im)
435{
436    VendorShellWidget vw;
437    XawVendorShellExtPart * ve;
438
439    if ((vw = (VendorShellWidget)GetErrCnxt(error_im)) == NULL
440	|| (ve = GetExtPart(vw)) == NULL) return(0);
441
442    DestroyAllIM(ve);
443    return(0);
444}
445#endif
446
447/*
448 * Attempt to open an input method
449 */
450
451static void
452OpenIM(XawVendorShellExtPart *ve)
453{
454    int		i;
455    char	*p, *s, *ns, *end, *pbuf, buf[32];
456    XIM		xim = NULL;
457    XIMStyles	*xim_styles;
458    XIMStyle	input_style = 0;
459    Boolean	found;
460
461    if (ve->im.open_im == False) return;
462    ve->im.xim = NULL;
463    if (ve->im.input_method == NULL) {
464	if ((p = XSetLocaleModifiers("@im=none")) != NULL && *p)
465	    xim = XOpenIM(XtDisplay(ve->parent), NULL, NULL, NULL);
466    } else {
467	/* no fragment can be longer than the whole string */
468	Cardinal len = strlen (ve->im.input_method) + 5;
469
470	if (len < sizeof buf) pbuf = buf;
471	else pbuf = XtMalloc (len);
472
473	if (pbuf == NULL) return;
474
475	for(ns=s=ve->im.input_method; ns && *s;) {
476	    /* skip any leading blanks */
477	    while (*s && isspace(*s)) s++;
478	    if (!*s) break;
479	    if ((ns = end = strchr(s, ',')) == NULL)
480		end = s + strlen(s);
481	    /* If there is a spurious comma end can be the same as s */
482	    if (end > s) {
483		/* strip any trailing blanks */
484		while (isspace(*(end - 1))) end--;
485
486		strcpy (pbuf, "@im=");
487		strncat (pbuf, s, end - s);
488		pbuf[end - s + 4] = '\0';
489	    }
490
491	    if ((p = XSetLocaleModifiers(pbuf)) != NULL && *p
492		&& (xim = XOpenIM(XtDisplay(ve->parent), NULL, NULL, NULL)) != NULL)
493		break;
494
495	    s = ns + 1;
496	}
497
498	if (pbuf != buf) XtFree (pbuf);
499    }
500    if (xim == NULL) {
501	if ((p = XSetLocaleModifiers("")) != NULL) {
502	    xim = XOpenIM(XtDisplay(ve->parent), NULL, NULL, NULL);
503	}
504    }
505    if (xim == NULL) {
506	XtAppWarning(XtWidgetToApplicationContext(ve->parent),
507	    "Input Method Open Failed");
508	return;
509    }
510    if (XGetIMValues(xim, XNQueryInputStyle, &xim_styles, NULL)
511	|| !xim_styles) {
512	XtAppWarning(XtWidgetToApplicationContext(ve->parent),
513	    "input method doesn't support any style");
514	XCloseIM(xim);
515	return;
516    }
517    found = False;
518    for(ns = s = ve->im.preedit_type; s && !found;) {
519	while (*s && isspace(*s)) s++;
520	if (!*s) break;
521	if ((ns = end = strchr(s, ',')) == NULL)
522	    end = s + strlen(s);
523	else
524	    ns++;
525	if (end > s)
526	    while (isspace(*(end - 1))) end--;
527
528	if (!strncmp(s, "OverTheSpot", end - s)) {
529	    input_style = (XIMPreeditPosition | XIMStatusArea);
530	} else if (!strncmp(s, "OffTheSpot", end - s)) {
531	    input_style = (XIMPreeditArea | XIMStatusArea);
532	} else if (!strncmp(s, "Root", end - s)) {
533	    input_style = (XIMPreeditNothing | XIMStatusNothing);
534	}
535	for (i = 0; (unsigned short)i < xim_styles->count_styles; i++)
536	    if (input_style == xim_styles->supported_styles[i]) {
537		ve->ic.input_style = input_style;
538		SetErrCnxt(ve->parent, xim);
539		ve->im.xim = xim;
540		found = True;
541		break;
542	    }
543
544	s = ns;
545    }
546    XFree(xim_styles);
547
548    if (!found) {
549	XCloseIM(xim);
550	XtAppWarning(XtWidgetToApplicationContext(ve->parent),
551		     "input method doesn't support my input style");
552    }
553}
554
555static Bool
556ResizeVendorShell_Core(VendorShellWidget vw, XawVendorShellExtPart *ve,
557		       XawIcTableList p)
558{
559    XVaNestedList		pe_attr, st_attr;
560    XRectangle			pe_area, st_area;
561    XRectangle			*get_pe_area = NULL, *get_st_area = NULL;
562
563    st_area.width = 0;
564    if (p->input_style & XIMStatusArea) {
565	st_attr = XVaCreateNestedList(0, XNArea, &get_st_area, NULL);
566	XGetICValues(p->xic, XNStatusAttributes, st_attr, NULL);
567	XFree(st_attr);
568	if (p->xic == NULL) {
569	    return(FALSE);
570	}
571	st_area.x = 0;
572	st_area.y = vw->core.height - ve->im.area_height;
573	st_area.width = get_st_area->width;
574	st_area.height = get_st_area->height;
575	XFree(get_st_area);
576	st_attr = XVaCreateNestedList(0, XNArea, &st_area, NULL);
577	XSetICValues(p->xic, XNStatusAttributes, st_attr, NULL);
578	XFree(st_attr);
579	if (p->xic == NULL) {
580	    return(FALSE);
581	}
582    }
583    if (p->input_style & XIMPreeditArea) {
584	pe_attr = XVaCreateNestedList(0, XNArea, &get_pe_area, NULL);
585	XGetICValues(p->xic, XNPreeditAttributes, pe_attr, NULL);
586	XFree(pe_attr);
587	if (p->xic == NULL) {
588	    return(FALSE);
589	}
590	pe_area.x = st_area.width;
591	pe_area.y = vw->core.height - ve->im.area_height;
592	pe_area.width = vw->core.width;
593	pe_area.height = get_pe_area->height;
594	if (p->input_style & XIMStatusArea) {
595	    pe_area.width -= st_area.width;
596	}
597	XFree(get_pe_area);
598	pe_attr = XVaCreateNestedList(0, XNArea, &pe_area, NULL);
599	XSetICValues(p->xic, XNPreeditAttributes, pe_attr, NULL);
600	XFree(pe_attr);
601    }
602    return(TRUE);
603}
604
605static void
606ResizeVendorShell(VendorShellWidget vw, XawVendorShellExtPart *ve)
607{
608    XawIcTableList               p;
609
610    if (IsSharedIC(ve)) {
611	p = ve->ic.shared_ic_table;
612	if (p->xic == NULL) return;
613	ResizeVendorShell_Core(vw, ve, p);
614	return;
615    }
616    for (p = ve->ic.ic_table; p; p = p->next) {
617	if (p->xic == NULL) continue;
618	if (ResizeVendorShell_Core(vw, ve, p) == FALSE) return;
619    }
620}
621
622static XawIcTableList
623CreateIcTable(Widget w, XawVendorShellExtPart *ve)
624{
625    XawIcTableList	table;
626
627    table = (XawIcTableList) XtMalloc(sizeof(XawIcTablePart));
628    if (table == NULL) return(NULL);
629    table->widget = w;
630    table->xic = NULL;
631    table->flg = table->prev_flg = 0;
632    table->font_set = NULL;
633    table->foreground = table->background = 0xffffffff;
634    table->bg_pixmap = 0;
635    table->cursor_position = 0xffff;
636    table->line_spacing = 0;
637    table->ic_focused = FALSE;
638    table->openic_error = FALSE;
639    return(table);
640}
641
642static Bool
643RegisterToVendorShell(Widget w, XawVendorShellExtPart *ve)
644{
645    XawIcTableList	table;
646
647    if ((table = CreateIcTable(w, ve)) == NULL) return(FALSE);
648    table->next = ve->ic.ic_table;
649    ve->ic.ic_table = table;
650    return(TRUE);
651}
652
653static void
654UnregisterFromVendorShell(Widget w, XawVendorShellExtPart *ve)
655{
656    XawIcTableList	*prev, p;
657
658    for (prev = &ve->ic.ic_table; (p = *prev) != NULL; prev = &p->next) {
659	if (p->widget == w) {
660	    *prev = p->next;
661	    XtFree((char *)p);
662	    break;
663	}
664    }
665    return;
666}
667
668static void
669SetICValuesShared(Widget w, XawVendorShellExtPart *ve,
670		  XawIcTableList p, Bool check)
671{
672    XawIcTableList	pp;
673
674    if ((pp = GetIcTable(w, ve)) == NULL) return;
675    if (check == TRUE && CurrentSharedIcTable(ve) != pp) return;
676
677    if (pp->prev_flg & CICursorP && p->cursor_position != pp->cursor_position) {
678	p->cursor_position = pp->cursor_position;
679	p->flg |= CICursorP;
680    }
681    if (pp->prev_flg & CIFontSet && p->font_set != pp->font_set) {
682	p->font_set = pp->font_set;
683	p->flg |= (CIFontSet|CICursorP);
684    }
685    if (pp->prev_flg & CIFg && p->foreground != pp->foreground) {
686	p->foreground = pp->foreground;
687	p->flg |= CIFg;
688    }
689    if (pp->prev_flg & CIBg && p->background != pp->background) {
690	p->background = pp->background;
691	p->flg |= CIBg;
692    }
693    if (pp->prev_flg & CIBgPixmap && p->bg_pixmap != pp->bg_pixmap) {
694	p->bg_pixmap = pp->bg_pixmap;
695	p->flg |= CIBgPixmap;
696    }
697    if (pp->prev_flg & CILineS && p->line_spacing != pp->line_spacing) {
698	p->line_spacing = pp->line_spacing;
699	p->flg |= CILineS;
700    }
701}
702
703static Bool
704IsCreatedIC(Widget w, XawVendorShellExtPart *ve)
705{
706    XawIcTableList	p;
707
708    if (ve->im.xim == NULL) return(FALSE);
709    if ((p = GetIcTableShared(w, ve)) == NULL) return(FALSE);
710    if (p->xic == NULL) return(FALSE);
711    return(TRUE);
712}
713
714static void
715SizeNegotiation(XawIcTableList p, unsigned int width, unsigned int height)
716{
717    XRectangle		pe_area, st_area;
718    XVaNestedList	pe_attr = NULL, st_attr = NULL;
719    int			ic_cnt = 0;
720    XRectangle		*pe_area_needed = NULL, *st_area_needed = NULL;
721    XPointer		ic_a[5];
722
723    if (p->input_style & XIMPreeditArea) {
724	pe_attr = XVaCreateNestedList(0, XNAreaNeeded, &pe_area_needed, NULL);
725	ic_a[ic_cnt] = (XPointer) XNPreeditAttributes; ic_cnt++;
726	ic_a[ic_cnt] = (XPointer) pe_attr; ic_cnt++;
727    }
728    if (p->input_style & XIMStatusArea) {
729	st_attr = XVaCreateNestedList(0, XNAreaNeeded, &st_area_needed, NULL);
730	ic_a[ic_cnt] = (XPointer) XNStatusAttributes; ic_cnt++;
731	ic_a[ic_cnt] = (XPointer) st_attr; ic_cnt++;
732    }
733    ic_a[ic_cnt] = (XPointer) NULL;
734
735    if (ic_cnt > 0) {
736	XGetICValues(p->xic, ic_a[0], ic_a[1], ic_a[2], ic_a[3], NULL);
737	if (pe_attr) XFree(pe_attr);
738	if (st_attr) XFree(st_attr);
739	if (p->xic == NULL) {
740	    p->openic_error = True;
741	    return;
742	}
743	pe_attr = st_attr = NULL;
744	ic_cnt = 0;
745	if (p->input_style & XIMStatusArea) {
746	    st_area.height = st_area_needed->height;
747	    st_area.x = 0;
748	    st_area.y = height - st_area.height;
749	    if (p->input_style & XIMPreeditArea) {
750		st_area.width = st_area_needed->width;
751	    } else {
752		st_area.width = width;
753	    }
754
755	    XFree(st_area_needed);
756	    st_attr = XVaCreateNestedList(0, XNArea, &st_area, NULL);
757	    ic_a[ic_cnt] = (XPointer) XNStatusAttributes; ic_cnt++;
758	    ic_a[ic_cnt] = (XPointer) st_attr; ic_cnt++;
759	}
760	if (p->input_style & XIMPreeditArea) {
761	    if (p->input_style & XIMStatusArea) {
762		pe_area.x = st_area.width;
763		pe_area.width = width - st_area.width;
764	    } else {
765		pe_area.x = 0;
766		pe_area.width = width;
767	    }
768	    pe_area.height = pe_area_needed->height;
769	    XFree(pe_area_needed);
770	    pe_area.y = height - pe_area.height;
771	    pe_attr = XVaCreateNestedList(0, XNArea, &pe_area, NULL);
772	    ic_a[ic_cnt] = (XPointer) XNPreeditAttributes; ic_cnt++;
773	    ic_a[ic_cnt] = (XPointer) pe_attr; ic_cnt++;
774	}
775	ic_a[ic_cnt] = (XPointer) NULL;
776	XSetICValues(p->xic, ic_a[0], ic_a[1], ic_a[2], ic_a[3], NULL);
777	if (pe_attr) XFree(pe_attr);
778	if (st_attr) XFree(st_attr);
779	if (p->xic == NULL) {
780	    p->openic_error = True;
781	    return;
782	}
783    }
784}
785
786static void
787CreateIC(Widget w, XawVendorShellExtPart *ve)
788{
789    XawIcTableList	p;
790    XPoint		position;
791    XRectangle		pe_area, st_area;
792    XVaNestedList	pe_attr = NULL, st_attr = NULL;
793    XPointer		ic_a[20], pe_a[20], st_a[20];
794    Dimension		height = 0;
795    int			ic_cnt = 0, pe_cnt = 0, st_cnt = 0;
796    XawTextMargin	*margin;
797
798    if (!XtIsRealized(w)) return;
799    if (((ve->im.xim == NULL) || (p = GetIcTableShared(w, ve)) == NULL) ||
800	p->xic || (p->openic_error != FALSE)) return;
801
802    p->input_style = GetInputStyleOfIC(ve);
803
804    if (IsSharedIC(ve)) SetICValuesShared(w, ve, p, FALSE);
805    XFlush(XtDisplay(w));
806
807    if (p->input_style & (XIMPreeditArea|XIMPreeditPosition|XIMStatusArea)) {
808	if (p->flg & CIFontSet) {
809	    pe_a[pe_cnt] = (XPointer) XNFontSet; pe_cnt++;
810	    pe_a[pe_cnt] = (XPointer) p->font_set; pe_cnt++;
811	    st_a[st_cnt] = (XPointer) XNFontSet; st_cnt++;
812	    st_a[st_cnt] = (XPointer) p->font_set; st_cnt++;
813	    if (p->font_set) {
814		height = maxAscentOfFontSet(p->font_set)
815		    + maxDescentOfFontSet(p->font_set);
816	    }
817	    height = SetVendorShellHeight(ve, height);
818	}
819	if (p->flg & CIFg) {
820	    pe_a[pe_cnt] = (XPointer) XNForeground; pe_cnt++;
821	    pe_a[pe_cnt] = (XPointer) p->foreground; pe_cnt++;
822	    st_a[st_cnt] = (XPointer) XNForeground; st_cnt++;
823	    st_a[st_cnt] = (XPointer) p->foreground; st_cnt++;
824	}
825	if (p->flg & CIBg) {
826	    pe_a[pe_cnt] = (XPointer) XNBackground; pe_cnt++;
827	    pe_a[pe_cnt] = (XPointer) p->background; pe_cnt++;
828	    st_a[st_cnt] = (XPointer) XNBackground; st_cnt++;
829	    st_a[st_cnt] = (XPointer) p->background; st_cnt++;
830	}
831	if (p->flg & CIBgPixmap) {
832	    pe_a[pe_cnt] = (XPointer) XNBackgroundPixmap; pe_cnt++;
833	    pe_a[pe_cnt] = (XPointer) p->bg_pixmap; pe_cnt++;
834	    st_a[st_cnt] = (XPointer) XNBackgroundPixmap; st_cnt++;
835	    st_a[st_cnt] = (XPointer) p->bg_pixmap; st_cnt++;
836	}
837	if (p->flg & CILineS) {
838	    pe_a[pe_cnt] = (XPointer) XNLineSpace; pe_cnt++;
839	    pe_a[pe_cnt] = (XPointer) p->line_spacing; pe_cnt++;
840	    st_a[st_cnt] = (XPointer) XNLineSpace; st_cnt++;
841	    st_a[st_cnt] = (XPointer) p->line_spacing; st_cnt++;
842	}
843    }
844    if (p->input_style & XIMPreeditArea) {
845	pe_area.x = 0;
846	pe_area.y = ve->parent->core.height - height;
847	pe_area.width = ve->parent->core.width;
848	pe_area.height = height;
849	pe_a[pe_cnt] = (XPointer) XNArea; pe_cnt++;
850	pe_a[pe_cnt] = (XPointer) &pe_area; pe_cnt++;
851    }
852    if (p->input_style & XIMPreeditPosition) {
853	pe_area.x = 0;
854	pe_area.y = 0;
855	pe_area.width = w->core.width;
856	pe_area.height = w->core.height;
857	margin = &(((TextWidget)w)->text.margin);
858	pe_area.x += margin->left;
859	pe_area.y += margin->top;
860	pe_area.width -= (margin->left + margin->right - 1);
861	pe_area.height -= (margin->top + margin->bottom - 1);
862	pe_a[pe_cnt] = (XPointer) XNArea; pe_cnt++;
863	pe_a[pe_cnt] = (XPointer) &pe_area; pe_cnt++;
864	if (p->flg & CICursorP) {
865	    _XawMultiSinkPosToXY(w, p->cursor_position, &position.x, &position.y);
866	} else {
867	    position.x = position.y = 0;
868	}
869	pe_a[pe_cnt] = (XPointer) XNSpotLocation; pe_cnt++;
870	pe_a[pe_cnt] = (XPointer) &position; pe_cnt++;
871    }
872    if (p->input_style & XIMStatusArea) {
873	st_area.x = 0;
874	st_area.y = ve->parent->core.height - height;
875	st_area.width = ve->parent->core.width;
876	st_area.height = height;
877	st_a[st_cnt] = (XPointer) XNArea; st_cnt++;
878	st_a[st_cnt] = (XPointer) &st_area; st_cnt++;
879    }
880
881    ic_a[ic_cnt] = (XPointer) XNInputStyle; ic_cnt++;
882    ic_a[ic_cnt] = (XPointer) p->input_style; ic_cnt++;
883    ic_a[ic_cnt] = (XPointer) XNClientWindow; ic_cnt++;
884    ic_a[ic_cnt] = (XPointer) XtWindow(ve->parent); ic_cnt++;
885    ic_a[ic_cnt] = (XPointer) XNFocusWindow; ic_cnt++;
886    ic_a[ic_cnt] = (XPointer) XtWindow(w); ic_cnt++;
887
888    if (pe_cnt > 0) {
889	pe_a[pe_cnt] = (XPointer) NULL;
890	pe_attr = XVaCreateNestedList(0, pe_a[0], pe_a[1], pe_a[2], pe_a[3],
891				   pe_a[4], pe_a[5], pe_a[6], pe_a[7], pe_a[8],
892				   pe_a[9], pe_a[10], pe_a[11], pe_a[12],
893				   pe_a[13], pe_a[14], pe_a[15], pe_a[16],
894				   pe_a[17], pe_a[18],  NULL);
895	ic_a[ic_cnt] = (XPointer) XNPreeditAttributes; ic_cnt++;
896	ic_a[ic_cnt] = (XPointer) pe_attr; ic_cnt++;
897    }
898
899    if (st_cnt > 0) {
900	st_a[st_cnt] = (XPointer) NULL;
901	st_attr = XVaCreateNestedList(0, st_a[0], st_a[1], st_a[2], st_a[3],
902				   st_a[4], st_a[5], st_a[6], st_a[7], st_a[8],
903				   st_a[9], st_a[10], st_a[11], st_a[12],
904				   st_a[13], st_a[14], st_a[15], st_a[16],
905				   st_a[17], st_a[18],  NULL);
906	ic_a[ic_cnt] = (XPointer) XNStatusAttributes; ic_cnt++;
907	ic_a[ic_cnt] = (XPointer) st_attr; ic_cnt++;
908    }
909    ic_a[ic_cnt] = (XPointer) NULL;
910
911    p->xic = XCreateIC(ve->im.xim, ic_a[0], ic_a[1], ic_a[2], ic_a[3],
912		       ic_a[4], ic_a[5], ic_a[6], ic_a[7], ic_a[8], ic_a[9],
913		       ic_a[10], ic_a[11], ic_a[12], ic_a[13], ic_a[14],
914		       ic_a[15], ic_a[16], ic_a[17], ic_a[18], NULL);
915    if (pe_attr) XtFree(pe_attr);
916    if (st_attr) XtFree(st_attr);
917
918    if (p->xic == NULL) {
919	p->openic_error = True;
920	return;
921    }
922
923    SizeNegotiation(p, ve->parent->core.width, ve->parent->core.height);
924
925    p->flg &= ~(CIFontSet | CIFg | CIBg | CIBgPixmap | CICursorP | CILineS);
926
927    if (!IsSharedIC(ve)) {
928	if (p->input_style & XIMPreeditPosition) {
929	    XtAddEventHandler(w, (EventMask)StructureNotifyMask, FALSE,
930			      (XtEventHandler)ConfigureCB, (Opaque)NULL);
931	}
932    }
933}
934
935static void
936SetICValues(Widget w, XawVendorShellExtPart *ve, Bool focus)
937{
938    XawIcTableList	p;
939    XPoint		position;
940    XRectangle		pe_area;
941    XVaNestedList	pe_attr = NULL, st_attr = NULL;
942    XPointer		ic_a[20], pe_a[20], st_a[20];
943    int			ic_cnt = 0, pe_cnt = 0, st_cnt = 0;
944    XawTextMargin	*margin;
945    int			height = 0;
946
947    if ((ve->im.xim == NULL) || ((p = GetIcTableShared(w, ve)) == NULL) ||
948	(p->xic == NULL)) return;
949
950    if (IsSharedIC(ve)) SetICValuesShared(w, ve, p, TRUE);
951    XFlush(XtDisplay(w));
952    if (focus == FALSE &&
953	!(p->flg & (CIFontSet | CIFg | CIBg |
954		    CIBgPixmap | CICursorP | CILineS))) return;
955#ifdef SPOT
956    if ((p->input_style & XIMPreeditPosition)
957	&& ((!IsSharedIC(ve) && ((p->flg & ~CIICFocus) == CICursorP))
958	    || (IsSharedIC(ve) && p->flg == CICursorP))) {
959	_XawMultiSinkPosToXY(w, p->cursor_position, &position.x, &position.y);
960	_XipChangeSpot(p->xic, position.x, position.y);
961	p->flg &= ~CICursorP;
962	return;
963    }
964#endif
965
966    if (p->input_style & (XIMPreeditArea|XIMPreeditPosition|XIMStatusArea)) {
967	if (p->flg & CIFontSet) {
968	    pe_a[pe_cnt] = (XPointer) XNFontSet; pe_cnt++;
969	    pe_a[pe_cnt] = (XPointer) p->font_set; pe_cnt++;
970	    st_a[st_cnt] = (XPointer) XNFontSet; st_cnt++;
971	    st_a[st_cnt] = (XPointer) p->font_set; st_cnt++;
972	    if (p->font_set) {
973		height = maxAscentOfFontSet(p->font_set)
974		    + maxDescentOfFontSet(p->font_set);
975	    }
976	    height = SetVendorShellHeight(ve, height);
977	}
978	if (p->flg & CIFg) {
979	    pe_a[pe_cnt] = (XPointer) XNForeground; pe_cnt++;
980	    pe_a[pe_cnt] = (XPointer) p->foreground; pe_cnt++;
981	    st_a[st_cnt] = (XPointer) XNForeground; st_cnt++;
982	    st_a[st_cnt] = (XPointer) p->foreground; st_cnt++;
983	}
984	if (p->flg & CIBg) {
985	    pe_a[pe_cnt] = (XPointer) XNBackground; pe_cnt++;
986	    pe_a[pe_cnt] = (XPointer) p->background; pe_cnt++;
987	    st_a[st_cnt] = (XPointer) XNBackground; st_cnt++;
988	    st_a[st_cnt] = (XPointer) p->background; st_cnt++;
989	}
990	if (p->flg & CIBgPixmap) {
991	    pe_a[pe_cnt] = (XPointer) XNBackgroundPixmap; pe_cnt++;
992	    pe_a[pe_cnt] = (XPointer) p->bg_pixmap; pe_cnt++;
993	    st_a[st_cnt] = (XPointer) XNBackgroundPixmap; st_cnt++;
994	    st_a[st_cnt] = (XPointer) p->bg_pixmap; st_cnt++;
995	}
996	if (p->flg & CILineS) {
997	    pe_a[pe_cnt] = (XPointer) XNLineSpace; pe_cnt++;
998	    pe_a[pe_cnt] = (XPointer) p->line_spacing; pe_cnt++;
999	    st_a[st_cnt] = (XPointer) XNLineSpace; st_cnt++;
1000	    st_a[st_cnt] = (XPointer) p->line_spacing; st_cnt++;
1001	}
1002    }
1003    if (p->input_style & XIMPreeditPosition) {
1004	if (p->flg & CICursorP) {
1005	    _XawMultiSinkPosToXY(w, p->cursor_position, &position.x, &position.y);
1006	    pe_a[pe_cnt] = (XPointer) XNSpotLocation; pe_cnt++;
1007	    pe_a[pe_cnt] = (XPointer) &position; pe_cnt++;
1008	}
1009    }
1010    if (IsSharedIC(ve)) {
1011	if (p->input_style & XIMPreeditPosition) {
1012	    pe_area.x = 0;
1013	    pe_area.y = 0;
1014	    pe_area.width = w->core.width;
1015	    pe_area.height = w->core.height;
1016	    margin = &(((TextWidget)w)->text.margin);
1017	    pe_area.x += margin->left;
1018	    pe_area.y += margin->top;
1019	    pe_area.width -= (margin->left + margin->right - 1);
1020	    pe_area.height -= (margin->top + margin->bottom - 1);
1021	    pe_a[pe_cnt] = (XPointer) XNArea; pe_cnt++;
1022	    pe_a[pe_cnt] = (XPointer) &pe_area; pe_cnt++;
1023	}
1024    }
1025
1026    if (pe_cnt > 0) {
1027	pe_a[pe_cnt] = (XPointer) NULL;
1028	pe_attr = XVaCreateNestedList(0, pe_a[0], pe_a[1], pe_a[2], pe_a[3],
1029				      pe_a[4], pe_a[5], pe_a[6], pe_a[7],
1030				      pe_a[8], pe_a[9], pe_a[10], pe_a[11],
1031				      pe_a[12], pe_a[13], pe_a[14], pe_a[15],
1032				      pe_a[16], pe_a[17], pe_a[18],  NULL);
1033	ic_a[ic_cnt] = (XPointer) XNPreeditAttributes; ic_cnt++;
1034	ic_a[ic_cnt] = (XPointer) pe_attr; ic_cnt++;
1035    }
1036    if (st_cnt > 0) {
1037	st_a[st_cnt] = (XPointer) NULL;
1038	st_attr = XVaCreateNestedList(0, st_a[0], st_a[1], st_a[2], st_a[3],
1039				      st_a[4], st_a[5], st_a[6], st_a[7],
1040				      st_a[8], st_a[9], st_a[10], st_a[11],
1041				      st_a[12], st_a[13], st_a[14], st_a[15],
1042				      st_a[16], st_a[17], st_a[18],  NULL);
1043	ic_a[ic_cnt] = (XPointer) XNStatusAttributes; ic_cnt++;
1044	ic_a[ic_cnt] = (XPointer) st_attr; ic_cnt++;
1045    }
1046    if (focus == TRUE) {
1047	ic_a[ic_cnt] = (XPointer) XNFocusWindow; ic_cnt++;
1048	ic_a[ic_cnt] = (XPointer) XtWindow(w); ic_cnt++;
1049    }
1050    if (ic_cnt > 0) {
1051	ic_a[ic_cnt] = (XPointer) NULL;
1052	XSetICValues(p->xic, ic_a[0], ic_a[1], ic_a[2], ic_a[3], ic_a[4],
1053		     ic_a[5], ic_a[6], ic_a[7], ic_a[8], ic_a[9], ic_a[10],
1054		     ic_a[11], ic_a[12], ic_a[13], ic_a[14], ic_a[15],
1055		     ic_a[16], ic_a[17], ic_a[18], NULL);
1056	if (pe_attr) XtFree(pe_attr);
1057	if (st_attr) XtFree(st_attr);
1058    }
1059
1060    if (IsSharedIC(ve) && p->flg & CIFontSet)
1061	SizeNegotiation(p, ve->parent->core.width, ve->parent->core.height);
1062
1063    p->flg &= ~(CIFontSet | CIFg | CIBg | CIBgPixmap | CICursorP | CILineS);
1064}
1065
1066static void
1067SharedICChangeFocusWindow(Widget w, XawVendorShellExtPart *ve,
1068			  XawIcTableList p)
1069{
1070    XawIcTableList	pp;
1071
1072    if (w == NULL) {
1073	ve->ic.current_ic_table = NULL;
1074	return;
1075    }
1076    if ((pp = GetIcTable(w, ve)) == NULL) return;
1077    ve->ic.current_ic_table = pp;
1078    SetICValues(w, ve, TRUE);
1079}
1080
1081static XawIcTableList
1082CurrentSharedIcTable(XawVendorShellExtPart *ve)
1083{
1084    return(ve->ic.current_ic_table);
1085}
1086
1087static void
1088SetICFocus(Widget w, XawVendorShellExtPart *ve)
1089{
1090    XawIcTableList	p, pp;
1091
1092    if ((ve->im.xim == NULL) || ((p = GetIcTableShared(w, ve)) == NULL) ||
1093	(p->xic == NULL)) return;
1094
1095    if (IsSharedIC(ve)) {
1096	pp = CurrentSharedIcTable(ve);
1097	if (pp == NULL || pp->widget != w) {
1098	    SharedICChangeFocusWindow(w, ve, p);
1099	}
1100    }
1101    if (p->flg & CIICFocus && p->ic_focused == FALSE) {
1102	p->ic_focused = TRUE;
1103	XSetICFocus(p->xic);
1104    }
1105    p->flg &= ~CIICFocus;
1106}
1107
1108static void
1109UnsetICFocus(Widget w, XawVendorShellExtPart *ve)
1110{
1111    XawIcTableList	p, pp;
1112
1113    if ((ve->im.xim == NULL) || ((p = GetIcTableShared(w, ve)) == NULL) ||
1114	(p->xic == NULL)) return;
1115
1116    if (IsSharedIC(ve) && (pp = CurrentSharedIcTable(ve))) {
1117	if (pp->widget != w) {
1118	    return;
1119	}
1120	SharedICChangeFocusWindow(NULL, ve, p);
1121    }
1122    if (p->ic_focused == TRUE) {
1123	XUnsetICFocus(p->xic);
1124	p->ic_focused = FALSE;
1125    }
1126}
1127
1128static void
1129SetValues(Widget w, XawVendorShellExtPart *ve,
1130	  ArgList args, Cardinal num_args)
1131{
1132    ArgList	arg;
1133
1134    XrmName	argName;
1135    XrmResourceList	xrmres;
1136    Cardinal	i;
1137    XawIcTablePart	*p, save_tbl;
1138
1139    if ((p = GetIcTable(w, ve)) == NULL) return;
1140
1141    memcpy(&save_tbl, p, sizeof(XawIcTablePart));
1142
1143    for (arg = args ; num_args != 0; num_args--, arg++) {
1144	argName = XrmStringToName(arg->name);
1145	for (xrmres = (XrmResourceList)ve->im.resources, i = 0;
1146	     i < ve->im.num_resources; i++, xrmres++) {
1147            if (argName == xrmres->xrm_name) {
1148                _XtCopyFromArg(arg->value,
1149			       (char *)p - xrmres->xrm_offset - 1,
1150			       xrmres->xrm_size);
1151                break;
1152            }
1153        }
1154    }
1155    if (p->font_set != save_tbl.font_set) {
1156	p->flg |= CIFontSet;
1157    }
1158    if (p->foreground != save_tbl.foreground) {
1159	p->flg |= CIFg;
1160    }
1161    if (p->background !=save_tbl.background) {
1162	p->flg |= CIBg;
1163    }
1164    if (p->bg_pixmap != save_tbl.bg_pixmap) {
1165	p->flg |= CIBgPixmap;
1166    }
1167    if (p->cursor_position != save_tbl.cursor_position) {
1168	p->flg |= CICursorP;
1169    }
1170    if (p->line_spacing != save_tbl.line_spacing) {
1171	p->flg |= CILineS;
1172    }
1173    p->prev_flg |= p->flg;
1174}
1175
1176static void
1177SetFocus(Widget w, XawVendorShellExtPart *ve)
1178{
1179    XawIcTableList	p;
1180    if ((p = GetIcTableShared(w, ve)) == NULL) return;
1181
1182    if ( p->ic_focused == FALSE || IsSharedIC(ve)) {
1183	p->flg |= CIICFocus;
1184    }
1185    p->prev_flg |= p->flg;
1186}
1187
1188static void
1189DestroyIC(Widget w, XawVendorShellExtPart *ve)
1190{
1191    XawIcTableList	p;
1192
1193    if ((ve->im.xim == NULL) || ((p = GetIcTableShared(w, ve)) == NULL) ||
1194	(p->xic == NULL)) return;
1195    if (IsSharedIC(ve)) {
1196	if (GetIcTable(w, ve) == ve->ic.current_ic_table) {
1197	    UnsetICFocus(w, ve);
1198	}
1199        return;
1200    }
1201    XDestroyIC(p->xic);
1202    if (!IsSharedIC(ve)) {
1203	if (p->input_style & XIMPreeditPosition) {
1204	    XtRemoveEventHandler(w, (EventMask)StructureNotifyMask, FALSE,
1205				 (XtEventHandler)ConfigureCB, (Opaque)NULL);
1206	}
1207    }
1208}
1209
1210static void
1211SetFocusValues(Widget inwidg, ArgList args, Cardinal num_args, Bool focus)
1212{
1213    XawVendorShellExtPart	*ve;
1214    VendorShellWidget		vw;
1215
1216    if ((vw = SearchVendorShell(inwidg)) == NULL) return;
1217    if ((ve = GetExtPart(vw)) != NULL) {
1218	if (num_args > 0) SetValues(inwidg, ve, args, num_args);
1219	if (focus) SetFocus(inwidg, ve);
1220	if (XtIsRealized((Widget)vw) && ve->im.xim) {
1221	    if (IsCreatedIC(inwidg, ve)) {
1222		SetICValues(inwidg, ve, FALSE);
1223		if (focus) SetICFocus(inwidg, ve);
1224	    } else {
1225		CreateIC(inwidg, ve);
1226	    	SetICFocus(inwidg, ve);
1227	    }
1228	}
1229    }
1230}
1231
1232static void
1233UnsetFocus(Widget inwidg)
1234{
1235    XawVendorShellExtPart	*ve;
1236    VendorShellWidget		vw;
1237    XawIcTableList		p;
1238
1239    if ((vw = SearchVendorShell(inwidg)) == NULL) return;
1240    if ((ve = GetExtPart(vw)) != NULL) {
1241	if ((p = GetIcTableShared(inwidg, ve)) == NULL) return;
1242	if (p->flg & CIICFocus) {
1243	    p->flg &= ~CIICFocus;
1244	}
1245	p->prev_flg &= ~CIICFocus;
1246	if (ve->im.xim && XtIsRealized((Widget)vw) && p->xic) {
1247	    UnsetICFocus(inwidg, ve);
1248	}
1249    }
1250}
1251
1252static Bool
1253IsRegistered(Widget w, XawVendorShellExtPart* ve)
1254{
1255    XawIcTableList	p;
1256
1257    for (p = ve->ic.ic_table; p; p = p->next)
1258	{
1259	    if (p->widget == w) return(TRUE);
1260	}
1261    return(FALSE);
1262}
1263
1264static void
1265Register(Widget inwidg, XawVendorShellExtPart* ve)
1266{
1267    if (ve->im.xim == NULL)
1268	{
1269	    OpenIM(ve);
1270	}
1271
1272    if (IsRegistered(inwidg, ve)) return;
1273
1274    if (RegisterToVendorShell(inwidg, ve) == FALSE) return;
1275
1276    if (ve->im.xim == NULL) return;
1277
1278    if (XtIsRealized(ve->parent))
1279	{
1280	    CreateIC(inwidg, ve);
1281	    SetICFocus(inwidg, ve);
1282	}
1283}
1284
1285static Bool
1286NoRegistered(XawVendorShellExtPart* ve)
1287{
1288    if (ve->ic.ic_table == NULL) return(TRUE);
1289    return(FALSE);
1290}
1291
1292static void
1293Unregister(Widget inwidg, XawVendorShellExtPart *ve)
1294{
1295    if (!IsRegistered(inwidg, ve)) return;
1296
1297    DestroyIC(inwidg, ve);
1298
1299    UnregisterFromVendorShell(inwidg, ve);
1300
1301    if (NoRegistered(ve))
1302	{
1303	    CloseIM(ve);
1304	    ve->im.xim = NULL;
1305	    /*
1306	     * resize vendor shell to core size
1307	    */
1308	    (void) SetVendorShellHeight(ve, 0);
1309	}
1310}
1311
1312static void
1313AllCreateIC(XawVendorShellExtPart *ve)
1314{
1315    XawIcTableList p;
1316
1317    if (ve->im.xim == NULL) return;
1318    if (IsSharedIC(ve) && ve->ic.ic_table[0].widget) {
1319	p = ve->ic.shared_ic_table;
1320	if (p->xic == NULL)
1321	    CreateIC(ve->ic.ic_table[0].widget, ve);
1322	SetICFocus(ve->ic.ic_table[0].widget, ve);
1323	return;
1324    }
1325    for (p = ve->ic.ic_table; p; p = p->next) {
1326	if (p->xic == NULL)
1327	    CreateIC(p->widget, ve);
1328    }
1329    for (p = ve->ic.ic_table; p; p = p->next) {
1330	SetICFocus(p->widget, ve);
1331    }
1332}
1333
1334
1335static void
1336Reconnect(XawVendorShellExtPart *ve)
1337{
1338    XawIcTableList	p;
1339
1340    ve->im.open_im = True;
1341    if (ve->im.xim == NULL) {
1342	OpenIM(ve);
1343    }
1344    if (ve->im.xim == NULL) return;
1345
1346    if (IsSharedIC(ve)) {
1347	p = ve->ic.shared_ic_table;
1348	p->flg = p->prev_flg;
1349	p->openic_error = FALSE;
1350    } else {
1351	for (p = ve->ic.ic_table; p; p = p->next) {
1352	    p->flg = p->prev_flg;
1353	    p->openic_error = FALSE;
1354	}
1355    }
1356    AllCreateIC(ve);
1357}
1358
1359
1360static void
1361CompileResourceList(XtResourceList res, unsigned int num_res)
1362{
1363    unsigned int count;
1364
1365#define xrmres	((XrmResourceList) res)
1366    for (count = 0; count < num_res; res++, count++) {
1367	xrmres->xrm_name         = XrmPermStringToQuark(res->resource_name);
1368	xrmres->xrm_class        = XrmPermStringToQuark(res->resource_class);
1369	xrmres->xrm_type         = XrmPermStringToQuark(res->resource_type);
1370	xrmres->xrm_offset	= -res->resource_offset - 1;
1371	xrmres->xrm_default_type = XrmPermStringToQuark(res->default_type);
1372    }
1373#undef xrmres
1374}
1375
1376static Bool
1377Initialize(VendorShellWidget vw, XawVendorShellExtPart *ve)
1378{
1379    if (!XtIsVendorShell((Widget)vw)) return(FALSE);
1380    ve->parent = (Widget)vw;
1381    ve->im.xim = NULL;
1382    ve->im.area_height = 0;
1383    ve->im.resources = (XrmResourceList)XtMalloc(sizeof(resources));
1384    if (ve->im.resources == NULL) return(FALSE);
1385    memcpy((char *)ve->im.resources, (char *)resources, sizeof(resources));
1386    ve->im.num_resources = XtNumber(resources);
1387    CompileResourceList( (XtResourceList) ve->im.resources,
1388			   ve->im.num_resources );
1389    if ((ve->ic.shared_ic_table = CreateIcTable( (Widget)vw, ve)) == NULL)
1390	return(FALSE);
1391    ve->ic.current_ic_table = NULL;
1392    ve->ic.ic_table = NULL;
1393    return(TRUE);
1394}
1395
1396
1397/* Destroy()
1398 *
1399 * This frees all (most?) of the resources malloced by XawIm.
1400 * It is called by _XawImDestroy, which is called by Vendor.c's
1401 * VendorExt's Destroy method.           Sheeran, Omron KK, 93/08/05 */
1402
1403static void
1404Destroy(Widget w, XawVendorShellExtPart *ve)
1405{
1406    contextDataRec *contextData;
1407    contextErrDataRec *contextErrData;
1408
1409    if (!XtIsVendorShell( w ) )
1410	return;
1411    XtFree( (char*) ve->im.resources );
1412
1413    if (extContext != (XContext)NULL &&
1414	!XFindContext (XtDisplay (w), (Window)w,
1415		       extContext, (XPointer*)&contextData))
1416        XtFree( (char*) contextData );
1417
1418    if (errContext != (XContext)NULL &&
1419	!XFindContext (XDisplayOfIM( ve->im.xim ), (Window) ve->im.xim,
1420		       errContext, (XPointer*) &contextErrData))
1421        XtFree( (char*) contextErrData );
1422}
1423
1424/*********************************************
1425 *
1426 * SEMI-PRIVATE FUNCTIONS
1427 * For use by other Xaw modules
1428 *
1429 ********************************************/
1430
1431void
1432_XawImResizeVendorShell(Widget w)
1433{
1434    XawVendorShellExtPart *ve;
1435
1436    if ( ( ve = GetExtPart( (VendorShellWidget) w ) ) && ve->im.xim ) {
1437	ResizeVendorShell( (VendorShellWidget) w, ve );
1438    }
1439}
1440
1441
1442Dimension
1443_XawImGetShellHeight(Widget w)
1444{
1445    XawVendorShellExtPart *ve;
1446
1447    if (!XtIsVendorShell( w ) ) return( w->core.height );
1448    if ( (ve = GetExtPart( (VendorShellWidget) w )) != NULL ) {
1449	return( w->core.height - ve->im.area_height );
1450    }
1451    return( w->core.height );
1452}
1453
1454void
1455_XawImRealize(Widget w)
1456{
1457    XawVendorShellExtPart	*ve;
1458
1459    if ( !XtIsRealized( w ) || !XtIsVendorShell( w ) ) return;
1460    if ( (ve = GetExtPart( (VendorShellWidget) w )) != NULL ) {
1461	XtAddEventHandler( w, (EventMask)StructureNotifyMask, FALSE,
1462			  XawVendorStructureNotifyHandler, (XtPointer)NULL );
1463	AllCreateIC(ve);
1464    }
1465}
1466
1467void
1468_XawImInitialize(Widget w, Widget ext)
1469{
1470    XawVendorShellExtPart	*ve;
1471
1472    if ( !XtIsVendorShell( w ) ) return;
1473    if ( (ve = SetExtPart( (VendorShellWidget) w, (XawVendorShellExtWidget)ext )) != NULL ) {
1474	if ( Initialize( (VendorShellWidget) w, ve ) == FALSE ) return;
1475	XtAddCallback( w, XtNdestroyCallback, VendorShellDestroyed,
1476		      (XtPointer) NULL );
1477    }
1478}
1479
1480void
1481_XawImReconnect(Widget inwidg)
1482{
1483    XawVendorShellExtPart	*ve;
1484    VendorShellWidget		vw;
1485
1486    if ((vw = SearchVendorShell(inwidg)) == NULL) return;
1487    if ((ve = GetExtPart(vw)) != NULL) {
1488	Reconnect(ve);
1489    }
1490}
1491
1492void
1493_XawImRegister(Widget inwidg)
1494{
1495    XawVendorShellExtPart	*ve;
1496    VendorShellWidget		vw;
1497
1498    if ((vw = SearchVendorShell(inwidg)) == NULL) return;
1499    if ((ve = GetExtPart(vw)) != NULL) {
1500	Register(inwidg, ve);
1501    }
1502}
1503
1504void
1505_XawImUnregister(Widget inwidg)
1506{
1507    XawVendorShellExtPart	*ve;
1508    VendorShellWidget		vw;
1509
1510    if ((vw = SearchVendorShell(inwidg)) == NULL) return;
1511    if ((ve = GetExtPart(vw)) != NULL) {
1512	Unregister(inwidg, ve);
1513    }
1514}
1515
1516void
1517_XawImSetValues(Widget inwidg, ArgList args, Cardinal num_args)
1518{
1519    SetFocusValues( inwidg, args, num_args, FALSE );
1520}
1521
1522void
1523_XawImSetFocusValues(Widget inwidg, ArgList args, Cardinal num_args)
1524{
1525    SetFocusValues(inwidg, args, num_args, TRUE);
1526}
1527
1528void
1529_XawImUnsetFocus(Widget inwidg)
1530{
1531    UnsetFocus(inwidg);
1532}
1533
1534int
1535_XawImWcLookupString(Widget inwidg, XKeyPressedEvent *event,
1536		     wchar_t* buffer_return, int bytes_buffer,
1537		     KeySym *keysym_return)
1538{
1539    XawVendorShellExtPart*	ve;
1540    VendorShellWidget		vw;
1541    XawIcTableList		p;
1542    int				i, ret;
1543    char			tmp_buf[64], *tmp_p;
1544    wchar_t*			buf_p;
1545
1546    if ((vw = SearchVendorShell(inwidg)) && (ve = GetExtPart(vw)) &&
1547	ve->im.xim && (p = GetIcTableShared(inwidg, ve)) && p->xic) {
1548	  return(XwcLookupString(p->xic, event, buffer_return, bytes_buffer/sizeof(wchar_t),
1549				 keysym_return, NULL));
1550    }
1551    ret = XLookupString( event, tmp_buf, sizeof(tmp_buf), keysym_return,
1552		         NULL );
1553    for ( i = 0, tmp_p = tmp_buf, buf_p = buffer_return; i < ret; i++ ) {
1554	*buf_p++ = _Xaw_atowc(*tmp_p++);
1555    }
1556    return( ret );
1557}
1558
1559int
1560_XawLookupString(Widget w, XKeyEvent *event, char *buffer_return, int buffer_size,
1561		 KeySym *keysym_return)
1562{
1563    XawVendorShellExtPart *ve;
1564    VendorShellWidget vw;
1565    XawIcTableList p;
1566
1567    if ((vw = SearchVendorShell(w)) && (ve = GetExtPart(vw))
1568	&& ve->im.xim && (p = GetIcTableShared(w, ve)) && p->xic)
1569	return (XmbLookupString(p->xic, event, buffer_return, buffer_size,
1570				keysym_return, NULL));
1571
1572    return (XLookupString(event, buffer_return, buffer_size,
1573			  keysym_return, NULL));
1574}
1575
1576int
1577_XawImGetImAreaHeight(Widget w)
1578{
1579    XawVendorShellExtPart	*ve;
1580    VendorShellWidget		vw;
1581
1582    if ((vw = SearchVendorShell(w)) && (ve = GetExtPart(vw))) {
1583	return(ve->im.area_height);
1584    }
1585    return(0);
1586}
1587
1588void
1589_XawImCallVendorShellExtResize(Widget w)
1590{
1591    VendorShellWidget		vw;
1592
1593    if ((vw = SearchVendorShell(w)) && GetExtPart(vw)) {
1594	XawVendorShellExtResize((Widget)vw);
1595    }
1596}
1597
1598
1599/* _XawImDestroy()
1600 *
1601 * This should be called by the VendorExt from its
1602 * core Destroy method.  Sheeran, Omron KK 93/08/05 */
1603
1604void
1605_XawImDestroy(Widget w, Widget ext)
1606{
1607    XawVendorShellExtPart        *ve;
1608
1609    if ( !XtIsVendorShell( w ) ) return;
1610    if ( (ve = GetExtPart( (VendorShellWidget) w )) != NULL )
1611        Destroy( w, ve );
1612}
1613