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