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