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