1 #ifndef lint
2 static char *rcsid = "$Id: ConvCtrl.c,v 1.54 2001/01/10 08:51:28 ishisone Exp $";
3 #endif
4 /*
5  * Copyright (c) 1990  Software Research Associates, Inc.
6  *
7  * Permission to use, copy, modify, and distribute this software and its
8  * documentation for any purpose and without fee is hereby granted, provided
9  * that the above copyright notice appear in all copies and that both that
10  * copyright notice and this permission notice appear in supporting
11  * documentation, and that the name of Software Research Associates not be
12  * used in advertising or publicity pertaining to distribution of the
13  * software without specific, written prior permission.  Software Research
14  * Associates makes no representations about the suitability of this software
15  * for any purpose.  It is provided "as is" without express or implied
16  * warranty.
17  *
18  * Author:  Makoto Ishisone, Software Research Associates, Inc., Japan
19  */
20 
21 #include <X11/IntrinsicP.h>
22 #include <X11/StringDefs.h>
23 #include <X11/Xmu/CharSet.h>
24 #include "ConvCtrlP.h"
25 #include "InputConv.h"
26 #include "ConvDisp.h"
27 #include "MyDispatch.h"
28 #include "AsyncErr.h"
29 
30 #define DEBUG_VAR debug_ConversionControl
31 #include "DebugPrint.h"
32 
33 static XtResource resources[] = {
34 #define offset(field) XtOffset(ConversionControlWidget, ccontrol.field)
35     { XtNinputObject, XtCInputObject, XtRWidget, sizeof(Widget),
36 	offset(inputobj), XtRImmediate, (XtPointer)NULL },
37     { XtNinputObjectClass, XtCInputObjectClass,
38 	XtRPointer, sizeof(WidgetClass),
39 	offset(inputobjclass), XtRImmediate, (XtPointer)NULL },
40     { XtNdisplayObjectClass, XtCDisplayObjectClass,
41 	XtRPointer, sizeof(WidgetClass),
42 	offset(displayobjclass), XtRImmediate, (XtPointer)NULL },
43     { XtNclientWindow, XtCWindow, XtRWindow, sizeof(Window),
44 	offset(clientwindow), XtRImmediate, (XtPointer)None },
45     { XtNfocusWindow, XtCWindow, XtRWindow, sizeof(Window),
46 	offset(focuswindow), XtRImmediate, (XtPointer)None },
47     { XtNcursor, XtCCursor, XtRCursor, sizeof(Cursor),
48 	offset(cursor), XtRImmediate, (XtPointer)None },
49     { XtNeventSelectMethod, XtCEventSelectMethod,
50 	XtREventSelectMethod, sizeof(EventSelectMethod),
51 	offset(eventselectmethod), XtRString, (XtPointer)"none" },
52     { XtNtextEncoding, XtCTextEncoding, XtRAtom, sizeof(Atom),
53 	offset(textencoding), XtRString, "COMPOUND_TEXT" },
54     { XtNtextCallback, XtCCallback, XtRCallback, sizeof(XtCallbackList),
55 	offset(textcallback), XtRCallback, (XtPointer)NULL },
56     { XtNnewTextCallback, XtCCallback, XtRCallback, sizeof(XtCallbackList),
57 	offset(newtextcallback), XtRCallback, (XtPointer)NULL },
58     { XtNendCallback, XtCCallback, XtRCallback, sizeof(XtCallbackList),
59 	offset(endcallback), XtRCallback, (XtPointer)NULL },
60     { XtNunusedEventCallback, XtCCallback, XtRCallback, sizeof(XtCallbackList),
61 	offset(unusedeventcallback), XtRCallback, (XtPointer)NULL },
62     { XtNsendbackKeyPress, XtCSendbackEvent, XtRBoolean, sizeof(Boolean),
63 	offset(sendbackKeyPress), XtRString, (XtPointer)"False" },
64     { XtNtitlebarHeight, XtCTitlebarHeight, XtRDimension, sizeof(Dimension),
65 	offset(titlebarheight), XtRImmediate, (XtPointer)0 },
66 #undef offset
67 };
68 
69 static void EventToInputObject();
70 
71 static XtActionsRec actions[] = {
72     {"to-inputobj",	EventToInputObject },
73 };
74 
75 static char translations[] = "<Key>: to-inputobj()";
76 
77 static void ClassInitialize();
78 static void StringToESM();
79 static void ClassPartInitialize();
80 static void Initialize(), Destroy();
81 static void Realize();
82 static void Resize();
83 static Boolean SetValues();
84 
85 static void ConversionStartup();
86 static void ConversionFinish();
87 static void ChangeAttributes();
88 static void ChangeFocus();
89 static void TextChange();
90 static void Fix();
91 static void ModeChange();
92 static void SelectionControl();
93 static void AuxControl();
94 
95 static void GetClientCoordinates();
96 
97 static Widget CreateInputObject();
98 
99 static Boolean ClassIsSubClassOf();
100 
101 static void CaptureClientDead();
102 static void InterceptClientKeyEvent();
103 static void SelectFocusKeyEvent();
104 static void UnselectFocusKeyEvent();
105 static void ClientKey();
106 static void ClientDead();
107 
108 static Boolean SafeGetWindowAttributes();
109 static void CheckAttributes();
110 static void CheckCoordinates();
111 static Boolean clipRectangle();
112 
113 static void FixCallback();
114 static void ConversionEndCallback();
115 static void TextChangeCallback();
116 static void ModeChangeCallback();
117 static void SelectionControlCallback();
118 static void AuxControlCallback();
119 
120 static void WidgetError(), WidgetWarning();
121 
122 static CompositeClassExtensionRec CompositeExtension = {
123     /* next_extension		*/	NULL,
124     /* record_type		*/	NULLQUARK,
125     /* version			*/	XtCompositeExtensionVersion,
126     /* record_size		*/	sizeof(CompositeClassExtensionRec),
127     /* accept_objects		*/	True,
128 };
129 
130 ConversionControlClassRec conversionControlClassRec = {
131   { /* core fields */
132     /* superclass		*/	(WidgetClass) &transientShellClassRec,
133     /* class_name		*/	"ConversionControl",
134     /* widget_size		*/	sizeof(ConversionControlRec),
135     /* class_initialize		*/	ClassInitialize,
136     /* class_part_initialize	*/	ClassPartInitialize,
137     /* class_inited		*/	FALSE,
138     /* initialize		*/	Initialize,
139     /* initialize_hook		*/	NULL,
140     /* realize			*/	Realize,
141     /* actions			*/	actions,
142     /* num_actions		*/	XtNumber(actions),
143     /* resources		*/	resources,
144     /* num_resources		*/	XtNumber(resources),
145     /* xrm_class		*/	NULLQUARK,
146     /* compress_motion		*/	TRUE,
147     /* compress_exposure	*/	TRUE,
148     /* compress_enterleave	*/	TRUE,
149     /* visible_interest		*/	FALSE,
150     /* destroy			*/	Destroy,
151     /* resize			*/	Resize,
152     /* expose			*/	NULL,
153     /* set_values		*/	SetValues,
154     /* set_values_hook		*/	NULL,
155     /* set_values_almost	*/	XtInheritSetValuesAlmost,
156     /* get_values_hook		*/	NULL,
157     /* accept_focus		*/	NULL,
158     /* version			*/	XtVersion,
159     /* callback_private		*/	NULL,
160     /* tm_table			*/	translations,
161     /* query_geometry		*/	XtInheritQueryGeometry,
162     /* display_accelerator	*/	XtInheritDisplayAccelerator,
163     /* extension		*/	NULL
164   },
165   { /* composite fields */
166     /* geometry_manager		*/	XtInheritGeometryManager,
167     /* change_managed		*/	XtInheritChangeManaged,
168     /* insert_child		*/	XtInheritInsertChild,
169     /* delete_child		*/	XtInheritDeleteChild,
170     /* extension		*/	(XtPointer)&CompositeExtension,
171   },
172   { /* shell fields */
173     /* extension		*/	NULL
174   },
175   { /* wm_shell fields */
176     /* extension		*/	NULL
177   },
178   { /* vendor_shell fields */
179     /* extension		*/	NULL
180   },
181   { /* transient_shell fields */
182     /* extension		*/	NULL
183   },
184   { /* conversionControl fields */
185     /* Startup			*/	ConversionStartup,
186     /* Finish			*/	ConversionFinish,
187     /* ChangeAttributes		*/	ChangeAttributes,
188     /* ChangeFocus		*/	ChangeFocus,
189     /* TextChange		*/	TextChange,
190     /* Fix			*/	Fix,
191     /* ModeChange		*/	ModeChange,
192     /* SelectionControl		*/	SelectionControl,
193     /* AuxControl		*/	AuxControl,
194   }
195 };
196 
197 WidgetClass conversionControlWidgetClass = (WidgetClass)&conversionControlClassRec;
198 
199 /* ARGSUSED */
200 static void
ClassInitialize()201 ClassInitialize()
202 {
203     /* add String -> EventSelectionMethod converter */
204     XtAddConverter(XtRString, XtREventSelectMethod, StringToESM,
205 		   (XtConvertArgList)NULL, (Cardinal)0);
206 }
207 
208 /* ARGSUSED */
209 static void
StringToESM(args,num_args,from,to)210 StringToESM(args, num_args, from, to)
211 XrmValue *args;
212 Cardinal *num_args;
213 XrmValue *from;
214 XrmValue *to;
215 {
216     char *s = (char *)from->addr;
217     static EventSelectMethod esm = ESMethodNone;
218 
219     if (!XmuCompareISOLatin1(s, "inputonly")) {
220 	esm = ESMethodInputOnly;
221     } else if (!XmuCompareISOLatin1(s, "selectfocus")) {
222 	esm = ESMethodSelectFocus;
223     } else if (!XmuCompareISOLatin1(s, "none")) {
224 	esm = ESMethodNone;
225     } else {
226 	XtStringConversionWarning(s, XtREventSelectMethod);
227     }
228 
229     to->size = sizeof(EventSelectMethod);
230     to->addr = (caddr_t)&esm;
231 }
232 
233 static void
ClassPartInitialize(cl)234 ClassPartInitialize(cl)
235 WidgetClass cl;
236 {
237     ConversionControlWidgetClass class = (ConversionControlWidgetClass)cl;
238     ConversionControlWidgetClass super = (ConversionControlWidgetClass)class->core_class.superclass;
239 
240 #define ccclass conversionControl_class
241     if (class->ccclass.Startup == XtInheritStartup) {
242 	class->ccclass.Startup = super->ccclass.Startup;
243     }
244     if (class->ccclass.Finish == XtInheritFinish) {
245 	class->ccclass.Finish = super->ccclass.Finish;
246     }
247     if (class->ccclass.ChangeAttributes == XtInheritChangeAttributes) {
248 	class->ccclass.ChangeAttributes = super->ccclass.ChangeAttributes;
249     }
250     if (class->ccclass.ChangeFocus == XtInheritChangeFocus) {
251 	class->ccclass.ChangeFocus = super->ccclass.ChangeFocus;
252     }
253     if (class->ccclass.TextChange == XtInheritTextChange) {
254 	class->ccclass.TextChange = super->ccclass.TextChange;
255     }
256     if (class->ccclass.Fix == XtInheritFix) {
257 	class->ccclass.Fix = super->ccclass.Fix;
258     }
259     if (class->ccclass.ModeChange == XtInheritModeChange) {
260 	class->ccclass.ModeChange = super->ccclass.ModeChange;
261     }
262     if (class->ccclass.SelectionControl == XtInheritSelectionControl) {
263 	class->ccclass.SelectionControl = super->ccclass.SelectionControl;
264     }
265     if (class->ccclass.AuxControl == XtInheritAuxControl) {
266 	class->ccclass.AuxControl = super->ccclass.AuxControl;
267     }
268 #undef ccclass
269 }
270 
271 /* ARGSUSED */
272 static void
Initialize(req,new,args,num_args)273 Initialize(req, new, args, num_args)
274 Widget req;
275 Widget new;
276 ArgList args;
277 Cardinal *num_args;
278 {
279     ConversionControlWidget ccw = (ConversionControlWidget)new;
280 
281     /*
282      * check inputobj/inputobjclass resource
283      */
284 
285     if (ccw->ccontrol.inputobj == NULL) {
286 	/* if inputobj not specified, inputobjclass must be specified */
287 	if (ccw->ccontrol.inputobjclass == NULL) {
288 	    WidgetError(new, "noResourceError", "inputObjectClass",
289 			"either inputObject or inputObjectClass must be specified at creation time");
290 	} else if (!ClassIsSubClassOf(ccw->ccontrol.inputobjclass,
291 				      inputConvObjectClass)) {
292 	    WidgetError(new, "classError", "inputObjectClass",
293 			"inputObjectClass must be subclass of inputConvObjectClass");
294 	}
295 	(void)CreateInputObject(ccw);
296 	ccw->ccontrol.createinputobj = True;
297 
298     } else if (!XtIsSubclass(ccw->ccontrol.inputobj, inputConvObjectClass)) {
299 	WidgetError(new, "classError", "inputObject",
300 		    "inputObject must be subclass of inputConvObjectClass");
301     }
302 
303     if (ccw->ccontrol.displayobjclass == NULL) {
304 	WidgetError(new, "noResourceError", "displayObjectClass",
305 		    "displayObjectClass must be specified");
306     } else if (!ClassIsSubClassOf(ccw->ccontrol.displayobjclass,
307 				  convDisplayObjectClass)) {
308 	WidgetError(new, "classError", "displayObjectClass",
309 		    "displayObjectClass must be subclass of convDisplayObjectClass");
310     }
311 
312     ccw->ccontrol.active = False;
313     ccw->ccontrol.oldclientwindow = None;
314     ccw->ccontrol.probewindow = None;
315 }
316 
317 static void
Destroy(w)318 Destroy(w)
319 Widget w;
320 {
321     ConversionControlWidget ccw = (ConversionControlWidget)w;
322     Display *dpy = XtDisplay(w);
323 
324     if (ccw->ccontrol.active == False) return;
325 
326     if (ccw->ccontrol.clientwindow != None) {
327 	MyRemoveAllEventHandler(dpy, ccw->ccontrol.clientwindow);
328     }
329 
330     if (ccw->ccontrol.probewindow != None) {
331 	MyRemoveAllEventHandler(dpy, ccw->ccontrol.probewindow);
332 	XDestroyWindow(dpy, ccw->ccontrol.probewindow);
333     }
334 }
335 
336 static void
Realize(w,maskp,attr)337 Realize(w, maskp, attr)
338 Widget w;
339 XtValueMask *maskp;
340 XSetWindowAttributes *attr;
341 {
342     ConversionControlWidget ccw = (ConversionControlWidget)w;
343 
344     if (ccw->ccontrol.cursor != None) {
345 	attr->cursor = ccw->ccontrol.cursor;
346 	*maskp |= CWCursor;
347     }
348 
349     /* call super class's realize function */
350     (*conversionControlWidgetClass->core_class.superclass->core_class.realize)(w, maskp, attr);
351 }
352 
353 static void
Resize(w)354 Resize(w)
355 Widget w;
356 {
357     ConversionControlWidget ccw = (ConversionControlWidget)w;
358     Widget child;
359     int i;
360 
361     TRACE(("ConversionControl:Resize()\n"));
362 
363     /* ignore non-widgets */
364     for (i = 0; i < ccw->composite.num_children; i++) {
365 	child = ccw->composite.children[i];
366 	if (XtIsWidget(child) && child->core.managed) {
367 	    XtResizeWidget(child, ccw->core.width, ccw->core.height,
368 			   child->core.border_width);
369 	}
370     }
371 }
372 
373 /* ARGSUSED */
374 static Boolean
SetValues(cur,req,wid,args,num_args)375 SetValues(cur, req, wid, args, num_args)
376 Widget cur;
377 Widget req;
378 Widget wid;
379 ArgList args;
380 Cardinal *num_args;
381 {
382     ConversionControlWidget old = (ConversionControlWidget)cur;
383     ConversionControlWidget new = (ConversionControlWidget)wid;
384 
385     if (new->ccontrol.active) {
386 	if (old->ccontrol.inputobj != new->ccontrol.inputobj) {
387 	    WidgetWarning(wid, "setValuesError", "inputObject",
388 			  "inputObject resource can't be changed during conversion");
389 	    new->ccontrol.inputobj = old->ccontrol.inputobj;	/* restore */
390 	}
391 	if (old->ccontrol.eventselectmethod != new->ccontrol.eventselectmethod) {
392 	    WidgetWarning(wid, "setValuesError", "eventSelectionMethod",
393 			  "eventSelectionMethod resource can't be changed during conversion");
394 	    new->ccontrol.eventselectmethod = old->ccontrol.eventselectmethod; /* restore */
395 	}
396     }
397 
398     if (new->ccontrol.clientwindow != old->ccontrol.clientwindow ||
399 	new->ccontrol.focuswindow != old->ccontrol.focuswindow) {
400 	WidgetWarning(wid, "setValuesError", "clientWindow",
401 		      "clientWindow and focusWindow resources are read-only");
402 	new->ccontrol.clientwindow = old->ccontrol.clientwindow; /* restore */
403 	new->ccontrol.focuswindow = old->ccontrol.focuswindow; /* restore */
404     }
405 
406     if (new->ccontrol.cursor != old->ccontrol.cursor && XtIsRealized(wid)) {
407 	XDefineCursor(XtDisplay(wid), XtWindow(wid), new->ccontrol.cursor);
408     }
409 
410     return False;
411 }
412 
413 /* ARGSUSED */
414 static void
ConversionStartup(w,mask,value)415 ConversionStartup(w, mask, value)
416 Widget w;
417 unsigned long mask;
418 ConversionAttributes *value;
419 {
420     /* do nothing */
421 }
422 
423 /* ARGSUSED */
424 static void
ConversionFinish(w)425 ConversionFinish(w)
426 Widget w;
427 {
428     /* do nothing */
429 }
430 
431 /* ARGSUSED */
432 static void
ChangeAttributes(w,mask,value)433 ChangeAttributes(w, mask, value)
434 Widget w;
435 unsigned long mask;
436 ConversionAttributes *value;
437 {
438     /* do nothing */
439 }
440 
441 /* ARGSUSED */
442 static void
ChangeFocus(w,set)443 ChangeFocus(w, set)
444 Widget w;
445 int set;
446 {
447     /* do nothing */
448 }
449 
450 /* ARGSUSED */
451 static void
TextChange(w)452 TextChange(w)
453 Widget w;
454 {
455     /* do nothing */
456 }
457 
458 /* ARGSUSED */
459 static void
Fix(w,arg)460 Fix(w, arg)
461 Widget w;
462 CCTextCallbackArg *arg;
463 {
464     ConversionControlWidget ccw = (ConversionControlWidget)w;
465 
466     XtCallCallbackList((Widget)ccw, ccw->ccontrol.textcallback,
467 		       (XtPointer)arg);
468 }
469 
470 /* ARGSUSED */
471 static void
ModeChange(w)472 ModeChange(w)
473 Widget w;
474 {
475     /* do nothing */
476 }
477 
478 /* ARGSUSED */
479 static void
SelectionControl(w,controlarg)480 SelectionControl(w, controlarg)
481 Widget w;
482 ICSelectionControlArg *controlarg;
483 {
484     /* do nothing */
485 }
486 
487 /* ARGSUSED */
488 static void
AuxControl(w,controlarg)489 AuxControl(w, controlarg)
490 Widget w;
491 ICAuxControlArg *controlarg;
492 {
493     /* do nothing */
494 }
495 
496 /*
497  * public functions
498  */
499 
500 void
CControlStartConversion(w,clientwindow,valuemask,value)501 CControlStartConversion(w, clientwindow, valuemask, value)
502 Widget w;
503 Window clientwindow;
504 unsigned long valuemask;
505 ConversionAttributes *value;
506 {
507     ConversionControlWidget ccw = (ConversionControlWidget)w;
508     ConversionControlWidgetClass class = (ConversionControlWidgetClass)w->core.widget_class;
509 
510     TRACE(("CControlStartConversion(clientwindow=%lx)\n", clientwindow));
511     if (ccw->ccontrol.active) {
512 	WidgetWarning(w, "busyError", "CControlStartConversion",
513 		      "is busy. can't start conversion");
514 	return;
515     }
516     if (clientwindow == None) {
517 	/* ouch */
518 	WidgetWarning(w, "dataError", "cControlStartConversion",
519 		     "clientWindow not specified. can't start conversion.");
520 	return;
521     }
522 
523     /* check clientWindow's existance */
524     if (!SafeGetWindowAttributes(XtDisplay(w), clientwindow,
525 				 &(ccw->ccontrol.client_attr))) {
526 	WidgetWarning(w, "badWindowError", "clientWindow",
527 		      "clientWindow does not exist. can't start conversion.");
528 	return;
529     }
530 
531     ICClearConversion(ccw->ccontrol.inputobj);
532     ccw->ccontrol.notext = ICNumSegments(ccw->ccontrol.inputobj) == 0;
533 
534     ccw->ccontrol.active = True;
535     ccw->ccontrol.clientwindow = clientwindow;
536 
537     /* check given attributes */
538     CheckAttributes(ccw, &valuemask, value);
539 
540     if (valuemask & CAFocusWindow) {
541 	ccw->ccontrol.focuswindow = value->focuswindow;
542     } else {
543 	ccw->ccontrol.focuswindow = clientwindow;
544 	ccw->ccontrol.focus_attr = ccw->ccontrol.client_attr;
545     }
546 
547     if (ccw->ccontrol.eventselectmethod == ESMethodInputOnly) {
548 	InterceptClientKeyEvent(ccw);
549     } else if (ccw->ccontrol.eventselectmethod == ESMethodSelectFocus) {
550 	SelectFocusKeyEvent(ccw);
551     }
552 
553     CheckCoordinates(ccw, &valuemask, value, 1);
554 
555     GetClientCoordinates(ccw);
556 
557     CaptureClientDead(ccw);
558 
559     XtAddCallback(ccw->ccontrol.inputobj,
560 		  XtNfixNotify, FixCallback, (XtPointer)ccw);
561     XtAddCallback(ccw->ccontrol.inputobj,
562 		  XtNendNotify, ConversionEndCallback, (XtPointer)ccw);
563     XtAddCallback(ccw->ccontrol.inputobj,
564 		  XtNtextChangeNotify, TextChangeCallback, (XtPointer)ccw);
565     XtAddCallback(ccw->ccontrol.inputobj,
566 		  XtNmodeChangeNotify, ModeChangeCallback, (XtPointer)ccw);
567     XtAddCallback(ccw->ccontrol.inputobj,
568 		  XtNselectionControl, SelectionControlCallback,
569 		  (XtPointer)ccw);
570     XtAddCallback(ccw->ccontrol.inputobj,
571 		  XtNauxControl, AuxControlCallback,
572 		  (XtPointer)ccw);
573 
574     /* call input style dependent startup */
575     (*class->conversionControl_class.Startup)(w, valuemask, value);
576 }
577 
578 void
CControlEndConversion(w)579 CControlEndConversion(w)
580 Widget w;
581 {
582     ConversionControlWidget ccw = (ConversionControlWidget)w;
583     ConversionControlWidgetClass class = (ConversionControlWidgetClass)w->core.widget_class;
584     Display *dpy = XtDisplay(w);
585 
586     if (!ccw->ccontrol.active) {
587 	WidgetWarning(w, "busyError", "cControlEndConversion",
588 		      "is not active. can't stop conversion");
589 	return;
590     }
591 
592     XtRemoveCallback(ccw->ccontrol.inputobj,
593 		     XtNfixNotify, FixCallback, (XtPointer)ccw);
594     XtRemoveCallback(ccw->ccontrol.inputobj,
595 		     XtNendNotify, ConversionEndCallback, (XtPointer)ccw);
596     XtRemoveCallback(ccw->ccontrol.inputobj,
597 		     XtNtextChangeNotify, TextChangeCallback, (XtPointer)ccw);
598     XtRemoveCallback(ccw->ccontrol.inputobj,
599 		     XtNmodeChangeNotify, ModeChangeCallback, (XtPointer)ccw);
600     XtRemoveCallback(ccw->ccontrol.inputobj,
601 		     XtNselectionControl, SelectionControlCallback,
602 		     (XtPointer)ccw);
603     XtRemoveCallback(ccw->ccontrol.inputobj,
604 		     XtNauxControl, AuxControlCallback,
605 		     (XtPointer)ccw);
606 
607     ICClearConversion(ccw->ccontrol.inputobj);
608 
609     MyRemoveEventHandler(dpy, ccw->ccontrol.clientwindow, DestroyNotify,
610 			 ClientDead, (XtPointer)ccw);
611 
612     if (ccw->ccontrol.probewindow != None) {
613 	MyRemoveAllEventHandler(dpy, ccw->ccontrol.probewindow);
614 	XDestroyWindow(dpy, ccw->ccontrol.probewindow);
615 	ccw->ccontrol.probewindow = None;
616     }
617 
618     /* unselect focuswindow events */
619     if (ccw->ccontrol.eventselectmethod == ESMethodSelectFocus) {
620 	UnselectFocusKeyEvent(ccw);
621     }
622 
623     ccw->ccontrol.active = False;
624 
625     /* call input style dependent finish */
626     (*class->conversionControl_class.Finish)(w);
627 
628     ccw->ccontrol.oldclientwindow = ccw->ccontrol.clientwindow;
629     ccw->ccontrol.clientwindow = None;
630 }
631 
632 void
CControlChangeAttributes(w,valuemask,value)633 CControlChangeAttributes(w, valuemask, value)
634 Widget w;
635 unsigned long valuemask;
636 ConversionAttributes *value;
637 {
638     ConversionControlWidget ccw = (ConversionControlWidget)w;
639     ConversionControlWidgetClass class = (ConversionControlWidgetClass)w->core.widget_class;
640 
641     if (!ccw->ccontrol.active) {
642 	WidgetWarning(w, "busyError", "cControlChangeAttributes",
643 		      "is not active. can't change attributes");
644 	return;
645     }
646 
647     CheckAttributes(ccw, &valuemask, value);
648     CheckCoordinates(ccw, &valuemask, value, 0);
649 
650     if (valuemask == 0L) return;
651 
652     if (valuemask & CAFocusWindow) {
653 	if (ccw->ccontrol.eventselectmethod == ESMethodSelectFocus) {
654 	    UnselectFocusKeyEvent(ccw);
655 	}
656 	ccw->ccontrol.focuswindow = value->focuswindow;
657 	if (ccw->ccontrol.eventselectmethod == ESMethodSelectFocus) {
658 	    SelectFocusKeyEvent(ccw);
659 	}
660     }
661 
662     (*class->conversionControl_class.ChangeAttributes)(w, valuemask, value);
663 }
664 
665 void
CControlChangeFocus(w,set)666 CControlChangeFocus(w, set)
667 Widget w;
668 int set;
669 {
670     ConversionControlWidget ccw = (ConversionControlWidget)w;
671     ConversionControlWidgetClass class = (ConversionControlWidgetClass)w->core.widget_class;
672 
673     if (!ccw->ccontrol.active) {
674 	WidgetWarning(w, "busyError", "cControlChangeFocus",
675 		      "is not active. can't change focus");
676 	return;
677     }
678 
679     (*class->conversionControl_class.ChangeFocus)(w, set);
680 }
681 
682 static Boolean
SafeGetWindowAttributes(dpy,w,attr)683 SafeGetWindowAttributes(dpy, w, attr)
684 Display *dpy;
685 Window w;
686 XWindowAttributes *attr;
687 {
688     XAEHandle h;
689     unsigned long errbits = 0;
690 
691     h = XAESetRecordErrors(dpy, &errbits);
692     (void)XGetWindowAttributes(dpy, w, attr);
693     XAEUnset(h);
694 
695     return (errbits == 0);
696 }
697 
698 static void
CheckAttributes(ccw,valuemaskp,value)699 CheckAttributes(ccw, valuemaskp, value)
700 ConversionControlWidget ccw;
701 unsigned long *valuemaskp;
702 ConversionAttributes *value;
703 {
704     Display *dpy = XtDisplay((Widget)ccw);
705     XAEHandle h;
706     unsigned long ebits = 0;
707 
708 #define CHECKATTRS (CAFocusWindow|CAColormap|CACursor|CABackgroundPixmap)
709     if ((*valuemaskp & CHECKATTRS) == 0) return;
710 #undef CHECKATTRS
711 
712 #define XERROR(e)	(ebits & (1 << (e)))
713 
714     h = XAESetRecordErrors(dpy, &ebits);
715 
716     if (*valuemaskp & (CAColormap|CACursor|CABackgroundPixmap)) {
717 	XSetWindowAttributes attr;
718 	Window w;
719 
720 	w = XCreateSimpleWindow(dpy, ccw->ccontrol.clientwindow,
721 				0, 0, 1, 1, 0, 0L, 0L);
722 
723 	if (*valuemaskp & CACursor) {
724 	    /* BadCursor */
725 	    attr.cursor = value->cursor;
726 	    XChangeWindowAttributes(dpy, w, CWCursor, &attr);
727 	}
728 	if (*valuemaskp & CAColormap) {
729 	    /* BadMatch or BadColormap */
730 	    attr.colormap = value->colormap;
731 	    XChangeWindowAttributes(dpy, w, CWColormap, &attr);
732 	}
733 	if (*valuemaskp & CABackgroundPixmap) {
734 	    /* BadMatch or BadPixmap */
735 	    attr.background_pixmap = value->background_pixmap;
736 	    XChangeWindowAttributes(dpy, w, CWBackPixmap, &attr);
737 	}
738 
739 	XDestroyWindow(dpy, w);
740     }
741     if (*valuemaskp & CAFocusWindow) {
742 	(void)XGetWindowAttributes(dpy, value->focuswindow,
743 				   &(ccw->ccontrol.focus_attr));
744     } else {
745 	XSync(dpy, False);
746     }
747     XAEUnset(h);
748 
749     if ((*valuemaskp & CAFocusWindow) && XERROR(BadWindow)) {
750 	WidgetWarning((Widget)ccw, "badWindowError", "focusWindow",
751 		      "focusWindow does not exist.");
752 	*valuemaskp &= ~CAFocusWindow;
753     }
754     if ((*valuemaskp & CAColormap) && XERROR(BadColor)) {
755 	WidgetWarning((Widget)ccw, "badColorError", "colormap",
756 		      "invalid colormap ID.");
757 	*valuemaskp &= ~CAColormap;
758     }
759     if ((*valuemaskp & CAColormap) && XERROR(BadMatch)) {
760 	WidgetWarning((Widget)ccw, "badMatchError", "colormap",
761 		      "invalid colormap.");
762 	*valuemaskp &= ~CAColormap;
763     }
764     if ((*valuemaskp & CABackgroundPixmap) && XERROR(BadPixmap)) {
765 	WidgetWarning((Widget)ccw, "badPixmapError", "backgroundPixmap",
766 		      "invalid pixmap ID.");
767 	*valuemaskp &= ~CABackgroundPixmap;
768     }
769     if ((*valuemaskp & CABackgroundPixmap) && XERROR(BadMatch)) {
770 	WidgetWarning((Widget)ccw, "badMatchError", "backgroundPixmap",
771 		      "invalid pixmap for background.");
772 	*valuemaskp &= ~CABackgroundPixmap;
773     }
774     if ((*valuemaskp & CACursor) && XERROR(BadCursor)) {
775 	WidgetWarning((Widget)ccw, "badCursorError", "cursor",
776 		      "invalid cursor ID.");
777 	*valuemaskp &= ~CACursor;
778     }
779 #undef XERROR
780 }
781 
782 static void
CheckCoordinates(ccw,valuemaskp,value,clip)783 CheckCoordinates(ccw, valuemaskp, value, clip)
784 ConversionControlWidget ccw;
785 unsigned long *valuemaskp;
786 ConversionAttributes *value;
787 int clip;
788 {
789 #define INVALIDRECT(r) (r.width == 0 || r.height == 0)
790     if ((*valuemaskp & CAClientArea) &&
791 	(INVALIDRECT(value->clientarea) ||
792 	 (clip && !clipRectangle(&value->clientarea, &ccw->ccontrol.client_attr)))) {
793 	DPRINT(("CheckCoordinates: invalid ClientArea\n"));
794 	*valuemaskp &= ~CAClientArea;
795     }
796     if ((*valuemaskp & CAStatusArea) &&
797 	(INVALIDRECT(value->statusarea) ||
798 	 (clip && !clipRectangle(&value->statusarea, &ccw->ccontrol.client_attr)))) {
799 	DPRINT(("CheckCoordinates: invalid StatusArea\n"));
800 	*valuemaskp &= ~CAStatusArea;
801     }
802 #undef INVALIDRECT
803 }
804 
805 static Boolean
clipRectangle(rectp,attrp)806 clipRectangle(rectp, attrp)
807 register XRectangle *rectp;
808 register XWindowAttributes *attrp;
809 {
810     register int z0, z1, e;
811 
812     z0 = rectp->x; z1 = z0 + rectp->width; e = attrp->width;
813     if (z0 == z1) z1 = e;		/* if (rectp->width == 0)... */
814     if (z0 >= e || z1 <= 0) return False;
815     if (z0 < 0) z0 = 0;
816     if (z1 > e) z1 = e;
817     rectp->x = z0; rectp->width = z1 - z0;
818 
819     z0 = rectp->y; z1 = z0 + rectp->height; e = attrp->height;
820     if (z0 == z1) z1 = e;		/* if (rectp->height == 0)... */
821     if (z0 >= e || z1 <= 0) return False;
822     if (z0 < 0) z0 = 0;
823     if (z1 > e) z1 = e;
824     rectp->y = z0; rectp->height = z1 - z0;
825 
826     return True;
827 }
828 
829 static void
GetClientCoordinates(ccw)830 GetClientCoordinates(ccw)
831 ConversionControlWidget ccw;
832 {
833     Display *dpy = XtDisplay(ccw);
834     Window root = RootWindowOfScreen(XtScreen(ccw));
835     Window win = ccw->ccontrol.clientwindow;
836     Window junk;
837     int rootx, rooty;
838 
839     if (!XTranslateCoordinates(dpy, win, root, 0, 0, &rootx, &rooty, &junk)) {
840 	WidgetWarning((Widget)ccw, "windowError", "differentRoot",
841 		      "clientWindow and conversion widget have different root. this should not happen!");
842 	rootx = rooty = 0;
843     }
844 
845     ccw->ccontrol.client_rootx = rootx;
846     ccw->ccontrol.client_rooty = rooty;
847 }
848 
849 /* ARGSUSED */
850 static void
EventToInputObject(w,event,args,num_args)851 EventToInputObject(w, event, args, num_args)
852 Widget w;
853 XEvent *event;
854 String *args;
855 Cardinal *num_args;
856 {
857     ConversionControlWidget ccw = (ConversionControlWidget)w;
858     Boolean hascallback = False;
859     int r;
860 #ifdef OBSOLETE_FEATURE
861     Boolean sendback = False;
862 #endif
863 
864     if (ccw->ccontrol.inputobj == NULL) return;
865 
866     ccw->ccontrol.endnotify = False;
867 
868     if (ccw->ccontrol.unusedeventcallback != NULL &&
869 	XtHasCallbacks(w, XtNunusedEventCallback) == XtCallbackHasSome) {
870 	hascallback = True;
871     }
872 
873 #ifdef OBSOLETE_FEATURE
874     /*
875      * a cheap little hack -- sending back unused events
876      *
877      * if user set some callback on XtNunusedEventCallback, we call
878      * the callback functions on 'unused' KeyPress events.
879      *
880      * otherwise, if the resource XtNsendbackKeyPress is true, we
881      * attempt to send 'unused' KeyPress events back to the client.
882      *
883      * we call callbacks  or send an event back to the client when
884      * following conditions are satisfied:
885      *    + it is a KeyPress event AND
886      *    + the number of segments is 0 before the conversion object
887      *      processes it AND
888      *    + the number of segments remains 0 after processing AND
889      *    + none of the modeChangeNotify, selectionControl, endNotify and
890      *      fixNofity callbacks are called during processing
891      * it is intentional to exclude textChangeNotify callback from
892      * above condition, because this callback is often called even if
893      * the text doesn't change actually. so we use the condition that
894      * the number of segments remains 0 instead.
895      */
896 
897     if ((hascallback ||ccw->ccontrol.sendbackKeyPress) &&
898 	event->type == KeyPress &&
899 	ICNumSegments(ccw->ccontrol.inputobj) == 0) {
900 	sendback = True;
901     }
902 
903     ccw->ccontrol.eventused = False;
904 
905     if ((r = ICInputEvent(ccw->ccontrol.inputobj, event)) == 1 ||
906 	(sendback && !ccw->ccontrol.eventused &&
907 	 ICNumSegments(ccw->ccontrol.inputobj) == 0)) {
908 #else
909     /*
910      * Above feature is obsolete.  Now it is the input object's
911      * responsibility to decide whether the event should be
912      * sent back to the client or not.
913      */
914     if ((r = ICInputEvent(ccw->ccontrol.inputobj, event)) == 1) {
915 #endif
916 
917 	/* event isn't used */
918 	if (hascallback) {
919 	    TRACE(("call XtNunusedEventCallback\n"));
920 	    XtCallCallbackList(w, ccw->ccontrol.unusedeventcallback,
921 			       (XtPointer)event);
922 	} else if (ccw->ccontrol.sendbackKeyPress) {
923 	    Window savewin;
924 	    Window savesubwin;
925 
926 	    TRACE(("sendback event to window 0x%lx\n", ccw->ccontrol.focuswindow));
927 	    savewin = event->xkey.window;
928 	    savesubwin = event->xkey.subwindow;
929 	    event->xkey.window = ccw->ccontrol.focuswindow;
930 	    event->xkey.subwindow = None;
931 
932 	    /*
933 	     * here we use NoEventMask as the eventmask, not
934 	     * KeyPressMask.  that means the event will be sent only
935 	     * to the client who created the destination window.
936 	     */
937 	    XSendEvent(XtDisplay(w), event->xkey.window,
938 		       False, NoEventMask, event);
939 
940 	    event->xkey.window = savewin;	/* restore */
941 	    event->xkey.subwindow = savesubwin;	/* restore */
942 	}
943     }
944 
945     if (r < 0 || ccw->ccontrol.endnotify) {
946 	CControlEndConversion(w);
947 	XtCallCallbackList(w, ccw->ccontrol.endcallback, (XtPointer)False);
948     }
949 }
950 
951 
952 /*
953  * sub-widget creation
954  */
955 
956 static Widget
CreateInputObject(ccw)957 CreateInputObject(ccw)
958 ConversionControlWidget ccw;
959 {
960     Widget inputobj;
961     Arg args[1];
962 
963     XtSetArg(args[0], XtNdisplayObjectClass, ccw->ccontrol.displayobjclass);
964     inputobj = XtCreateWidget("inputObj", ccw->ccontrol.inputobjclass,
965 			      (Widget)ccw, args, 1);
966     ccw->ccontrol.inputobj = inputobj;
967 
968     return inputobj;
969 }
970 
971 static Boolean
ClassIsSubClassOf(class,reference)972 ClassIsSubClassOf(class, reference)
973 WidgetClass class;
974 WidgetClass reference;
975 {
976     while (class != NULL) {
977 	if (class == reference) return True;
978 	class = class->core_class.superclass;
979     }
980     return False;
981 }
982 
983 static void
CaptureClientDead(ccw)984 CaptureClientDead(ccw)
985 ConversionControlWidget ccw;
986 {
987     Display *dpy = XtDisplay(ccw);
988     Window win = ccw->ccontrol.clientwindow;
989 
990     MyAddEventHandler(dpy, win, DestroyNotify, StructureNotifyMask,
991 		      ClientDead, (XtPointer)ccw);
992 }
993 
994 static void
InterceptClientKeyEvent(ccw)995 InterceptClientKeyEvent(ccw)
996 ConversionControlWidget ccw;
997 {
998     Display *dpy = XtDisplay(ccw);
999     Window win = ccw->ccontrol.clientwindow;
1000     Window probe;
1001 
1002     TRACE(("InterceptClientKeyEvent()\n"));
1003     probe = XCreateWindow(dpy, win, 0, 0, 9999, 9999, 0, 0,
1004 			  InputOnly, (Visual *)CopyFromParent,
1005 			  0L, (XSetWindowAttributes *)NULL);
1006     TRACE(("\tprobewindow = %lx\n", probe));
1007 
1008     MyAddEventHandler(dpy, probe, KeyPress, KeyPressMask,
1009 		      ClientKey, (XtPointer)ccw);
1010     MyAddEventHandler(dpy, probe, KeyRelease, KeyReleaseMask,
1011 		      ClientKey, (XtPointer)ccw);
1012 
1013     ccw->ccontrol.probewindow = probe;
1014 
1015     XMapWindow(dpy, probe);
1016 }
1017 
1018 static void
SelectFocusKeyEvent(ccw)1019 SelectFocusKeyEvent(ccw)
1020 ConversionControlWidget ccw;
1021 {
1022     Display *dpy = XtDisplay(ccw);
1023     Window win = ccw->ccontrol.focuswindow;
1024 
1025     MyAddEventHandler(dpy, win, KeyPress, KeyPressMask,
1026 		      ClientKey, (XtPointer)ccw);
1027     MyAddEventHandler(dpy, win, KeyRelease, KeyReleaseMask,
1028 		      ClientKey, (XtPointer)ccw);
1029 }
1030 
1031 static void
UnselectFocusKeyEvent(ccw)1032 UnselectFocusKeyEvent(ccw)
1033 ConversionControlWidget ccw;
1034 {
1035     Display *dpy = XtDisplay(ccw);
1036     Window win = ccw->ccontrol.focuswindow;
1037 
1038     MyRemoveEventHandler(dpy, win, KeyPress, ClientKey, (XtPointer)ccw);
1039     MyRemoveEventHandler(dpy, win, KeyRelease, ClientKey, (XtPointer)ccw);
1040 }
1041 
1042 static void
ClientKey(ev,data)1043 ClientKey(ev, data)
1044 XEvent *ev;
1045 XtPointer data;
1046 {
1047     Widget w = (Widget)data;
1048     Cardinal num_params = 0;
1049 
1050     EventToInputObject(w, ev, (String *)NULL, &num_params);
1051 }
1052 
1053 static void
ClientDead(ev,data)1054 ClientDead(ev, data)
1055 XEvent *ev;
1056 XtPointer data;
1057 {
1058     ConversionControlWidget ccw = (ConversionControlWidget)data;
1059     ConversionControlWidgetClass class = (ConversionControlWidgetClass)ccw->core.widget_class;
1060 
1061     if (ev->type != DestroyNotify ||
1062 	ev->xdestroywindow.window != ccw->ccontrol.clientwindow) return;
1063 
1064     /*
1065      * Client window is destroyed.
1066      */
1067 
1068     /* remove all event handlers */
1069     MyRemoveAllEventHandler(XtDisplay(ccw), ccw->ccontrol.clientwindow);
1070     if (ccw->ccontrol.probewindow != None) {
1071 	/* no need to destroy probewindow. it's already destroyed. */
1072 	MyRemoveAllEventHandler(XtDisplay(ccw), ccw->ccontrol.probewindow);
1073     }
1074     if (ccw->ccontrol.eventselectmethod == ESMethodSelectFocus &&
1075 	ccw->ccontrol.focuswindow != ccw->ccontrol.clientwindow) {
1076 	MyRemoveAllEventHandler(XtDisplay(ccw), ccw->ccontrol.focuswindow);
1077     }
1078 
1079     ccw->ccontrol.oldclientwindow = ccw->ccontrol.clientwindow;
1080     ccw->ccontrol.clientwindow = None;
1081     ccw->ccontrol.focuswindow = None;
1082     ccw->ccontrol.probewindow = None;
1083     ccw->ccontrol.active = False;
1084 
1085     XtRemoveCallback(ccw->ccontrol.inputobj,
1086 		     XtNfixNotify, FixCallback, (XtPointer)ccw);
1087     XtRemoveCallback(ccw->ccontrol.inputobj,
1088 		     XtNendNotify, ConversionEndCallback, (XtPointer)ccw);
1089     XtRemoveCallback(ccw->ccontrol.inputobj,
1090 		     XtNtextChangeNotify, TextChangeCallback, (XtPointer)ccw);
1091     XtRemoveCallback(ccw->ccontrol.inputobj,
1092 		     XtNmodeChangeNotify, ModeChangeCallback, (XtPointer)ccw);
1093     XtRemoveCallback(ccw->ccontrol.inputobj,
1094 		     XtNselectionControl, SelectionControlCallback,
1095 		     (XtPointer)ccw);
1096     XtRemoveCallback(ccw->ccontrol.inputobj,
1097 		     XtNauxControl, AuxControlCallback,
1098 		     (XtPointer)ccw);
1099 
1100     /* call input style dependent finish */
1101     (*class->conversionControl_class.Finish)((Widget)ccw);
1102 
1103     /* clear conversion object */
1104     ICClearConversion(ccw->ccontrol.inputobj);
1105 
1106     ccw->ccontrol.oldclientwindow = None;
1107     XtCallCallbackList((Widget)ccw, ccw->ccontrol.endcallback, (XtPointer)True);
1108 }
1109 
1110 /* ARGSUSED */
1111 static void
FixCallback(w,client_data,call_data)1112 FixCallback(w, client_data, call_data)
1113 Widget w;
1114 XtPointer client_data;
1115 XtPointer call_data;
1116 {
1117     Widget widget = (Widget)client_data;
1118     ConversionControlWidget ccw = (ConversionControlWidget)widget;
1119     ConversionControlWidgetClass class = (ConversionControlWidgetClass)widget->core.widget_class;
1120     Atom encoding = ccw->ccontrol.textencoding;
1121     int format;
1122     int length;
1123     XtPointer text;
1124     CCTextCallbackArg arg;
1125 
1126     ccw->ccontrol.eventused = True;
1127 
1128     if (ICGetConvertedString(w, &encoding, &format, &length, &text) < 0) {
1129 	return;
1130     }
1131     arg.encoding = encoding;
1132     arg.format = format;
1133     arg.length = length;
1134     arg.text = text;
1135 
1136     (*class->conversionControl_class.Fix)(widget, &arg);
1137 
1138     XtFree(text);
1139 }
1140 
1141 /* ARGSUSED */
1142 static void
ConversionEndCallback(w,client_data,call_data)1143 ConversionEndCallback(w, client_data, call_data)
1144 Widget w;
1145 XtPointer client_data;
1146 XtPointer call_data;
1147 {
1148     ConversionControlWidget ccw = (ConversionControlWidget)client_data;
1149 
1150     ccw->ccontrol.eventused = True;
1151     ccw->ccontrol.endnotify = True;
1152 }
1153 
1154 /* ARGSUSED */
1155 static void
TextChangeCallback(w,client_data,call_data)1156 TextChangeCallback(w, client_data, call_data)
1157 Widget w;
1158 XtPointer client_data;
1159 XtPointer call_data;
1160 {
1161     Widget widget = (Widget)client_data;
1162     ConversionControlWidget ccw = (ConversionControlWidget)widget;
1163     ConversionControlWidgetClass class = (ConversionControlWidgetClass)widget->core.widget_class;
1164     int nsegs = ICNumSegments(ccw->ccontrol.inputobj);
1165 
1166     /*
1167      * don't do:
1168      *	ccw->ccontrol.eventused = True;
1169      * because this callback is often called even if
1170      * the text didn't change actually.
1171      */
1172 
1173     /*
1174      * when num-segments changed from 0 to 1 (or more),
1175      * call new-text calllback
1176      */
1177     if (ccw->ccontrol.notext && nsegs > 0) {
1178 	XtCallCallbackList((Widget)ccw, ccw->ccontrol.newtextcallback,
1179 			   (XtPointer)w);
1180     }
1181     ccw->ccontrol.notext = nsegs == 0;
1182 
1183     (*class->conversionControl_class.TextChange)(widget);
1184 }
1185 
1186 /* ARGSUSED */
1187 static void
ModeChangeCallback(w,client_data,call_data)1188 ModeChangeCallback(w, client_data, call_data)
1189 Widget w;
1190 XtPointer client_data;
1191 XtPointer call_data;
1192 {
1193     Widget widget = (Widget)client_data;
1194     ConversionControlWidget ccw = (ConversionControlWidget)widget;
1195     ConversionControlWidgetClass class = (ConversionControlWidgetClass)widget->core.widget_class;
1196 
1197     ccw->ccontrol.eventused = True;
1198 
1199     (*class->conversionControl_class.ModeChange)(widget);
1200 }
1201 
1202 /* ARGSUSED */
1203 static void
SelectionControlCallback(w,client_data,call_data)1204 SelectionControlCallback(w, client_data, call_data)
1205 Widget w;
1206 XtPointer client_data;
1207 XtPointer call_data;
1208 {
1209     Widget widget = (Widget)client_data;
1210     ConversionControlWidget ccw = (ConversionControlWidget)widget;
1211     ConversionControlWidgetClass class = (ConversionControlWidgetClass)widget->core.widget_class;
1212     ICSelectionControlArg *arg = (ICSelectionControlArg *)call_data;
1213 
1214     ccw->ccontrol.eventused = True;
1215 
1216     (*class->conversionControl_class.SelectionControl)(widget, arg);
1217 }
1218 
1219 /* ARGSUSED */
1220 static void
AuxControlCallback(w,client_data,call_data)1221 AuxControlCallback(w, client_data, call_data)
1222 Widget w;
1223 XtPointer client_data;
1224 XtPointer call_data;
1225 {
1226     Widget widget = (Widget)client_data;
1227     ConversionControlWidget ccw = (ConversionControlWidget)widget;
1228     ConversionControlWidgetClass class = (ConversionControlWidgetClass)widget->core.widget_class;
1229     ICAuxControlArg *arg = (ICAuxControlArg *)call_data;
1230 
1231     ccw->ccontrol.eventused = True;
1232 
1233     (*class->conversionControl_class.AuxControl)(widget, arg);
1234 }
1235 
1236 static void
WidgetError(w,name,type,msg)1237 WidgetError(w, name, type, msg)
1238 Widget w;
1239 String name;
1240 String type;
1241 String msg;
1242 {
1243     char buf[512];
1244     String params[1];
1245     Cardinal num_params;
1246 
1247     params[0] = XtClass(w)->core_class.class_name;
1248     num_params = 1;
1249 
1250     (void)sprintf(buf, "%%s: %s", msg);
1251 
1252     XtAppErrorMsg(XtWidgetToApplicationContext(w),
1253 		  name, type, "WidgetError", buf, params, &num_params);
1254 }
1255 
1256 static void
WidgetWarning(w,name,type,msg)1257 WidgetWarning(w, name, type, msg)
1258 Widget w;
1259 String name;
1260 String type;
1261 String msg;
1262 {
1263     char buf[512];
1264     String params[1];
1265     Cardinal num_params;
1266 
1267     params[0] = XtClass(w)->core_class.class_name;
1268     num_params = 1;
1269 
1270     (void)sprintf(buf, "%%s: %s", msg);
1271 
1272     XtAppWarningMsg(XtWidgetToApplicationContext(w),
1273 		    name, type, "WidgetError", buf, params, &num_params);
1274 }
1275