Mercurial > kinput2.yaz
comparison lib/ConvCtrl.c @ 0:92745d501b9a
initial import from kinput2-v3.1
author | Yoshiki Yazawa <yaz@honeyplanet.jp> |
---|---|
date | Mon, 08 Mar 2010 04:44:30 +0900 |
parents | |
children | 7a454839a6de |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:92745d501b9a |
---|---|
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
425 ConversionFinish(w) | |
426 Widget w; | |
427 { | |
428 /* do nothing */ | |
429 } | |
430 | |
431 /* ARGSUSED */ | |
432 static void | |
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 | |
443 ChangeFocus(w, set) | |
444 Widget w; | |
445 int set; | |
446 { | |
447 /* do nothing */ | |
448 } | |
449 | |
450 /* ARGSUSED */ | |
451 static void | |
452 TextChange(w) | |
453 Widget w; | |
454 { | |
455 /* do nothing */ | |
456 } | |
457 | |
458 /* ARGSUSED */ | |
459 static void | |
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 | |
472 ModeChange(w) | |
473 Widget w; | |
474 { | |
475 /* do nothing */ | |
476 } | |
477 | |
478 /* ARGSUSED */ | |
479 static void | |
480 SelectionControl(w, controlarg) | |
481 Widget w; | |
482 ICSelectionControlArg *controlarg; | |
483 { | |
484 /* do nothing */ | |
485 } | |
486 | |
487 /* ARGSUSED */ | |
488 static void | |
489 AuxControl(w, controlarg) | |
490 Widget w; | |
491 ICAuxControlArg *controlarg; | |
492 { | |
493 /* do nothing */ | |
494 } | |
495 | |
496 /* | |
497 * public functions | |
498 */ | |
499 | |
500 void | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 } |