Mercurial > kinput2.yaz
comparison lib/OffConv.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 | e55ccba56891 07a41a882b14 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:92745d501b9a |
---|---|
1 #ifndef lint | |
2 static char *rcsid = "$Id: OffConv.c,v 1.44 2001/07/01 13:47:00 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 /* | |
22 * Note: This file contains TWO widget classes, OffTheSpotConversionWidget | |
23 * and its subclass SeparateConversionWidget. | |
24 */ | |
25 | |
26 #include <X11/IntrinsicP.h> | |
27 #include <X11/StringDefs.h> | |
28 #if XtSpecificationRelease > 4 | |
29 #include <X11/Xfuncs.h> | |
30 #endif | |
31 #include "CachedAtom.h" | |
32 #include "AsyncErr.h" | |
33 #include "OffConvP.h" | |
34 #include <X11/Xaw/Form.h> | |
35 #include "InputConv.h" | |
36 #include "ConvDisp.h" | |
37 #include "CandPanel.h" | |
38 #include "AuxPanel.h" | |
39 #include "Canvas.h" | |
40 #include "AdoptedShe.h" | |
41 #include "CanvasShel.h" | |
42 #include "ICLabel.h" | |
43 | |
44 #define DEBUG_VAR debug_OffTheSpotConversion | |
45 #include "DebugPrint.h" | |
46 | |
47 /*- resource table for OffTheSpotConversion (SeparateConversion has no resources -*/ | |
48 static XtResource off_resources[] = { | |
49 #define offset(field) XtOffset(OffTheSpotConversionWidget, offthespot.field) | |
50 { XtNleftMargin, XtCMargin, XtRDimension, sizeof(Dimension), | |
51 offset(leftmargin), XtRImmediate, (XtPointer)2 }, | |
52 { XtNrightMargin, XtCMargin, XtRDimension, sizeof(Dimension), | |
53 offset(rightmargin), XtRImmediate, (XtPointer)2 }, | |
54 #undef offset | |
55 }; | |
56 | |
57 /*- default translations -- same as superclass's -*/ | |
58 static char off_translations[] = "<Key>: to-inputobj()"; | |
59 static char sep_translations[] = "<Key>: to-inputobj()"; | |
60 | |
61 /*- declarations of static functions -*/ | |
62 static void OffTheSpot_Initialize(); | |
63 static void OffTheSpot_Destroy(); | |
64 static Boolean OffTheSpot_SetValues(); | |
65 static void OffTheSpot_Startup(); | |
66 static void OffTheSpot_ConversionFinish(); | |
67 static void OffTheSpot_ChangeAttributes(); | |
68 static void OffTheSpot_ChangeFocus(); | |
69 | |
70 static void Separate_Initialize(); | |
71 static void Separate_Startup(); | |
72 static void Separate_ConversionFinish(); | |
73 static void Separate_ChangeAttributes(); | |
74 static void Separate_ChangeFocus(); | |
75 | |
76 static Widget CreateDisplayObject(); | |
77 static Widget CreateSelectionWidget(); | |
78 | |
79 static void SetupDisplayObject(); | |
80 static Boolean ResetDisplayObject(); | |
81 static void SetupModeWidget(); | |
82 static Boolean ResetModeWidget(); | |
83 static void SetupCanvasWidget(); | |
84 static Boolean ResetCanvasWidget(); | |
85 | |
86 static void UpdateText(); | |
87 static void UpdateMode(); | |
88 | |
89 static void SelectionControl(); | |
90 static void SelectionStart(); | |
91 static void LocateSelectionPopup(); | |
92 static void SelectionEnd(); | |
93 static void SelectionSet(); | |
94 static void SelectionGet(); | |
95 static void SelectionMove(); | |
96 | |
97 static Widget CreateAuxWidget(); | |
98 static void AuxControl(); | |
99 static void AuxStart(); | |
100 static void AuxEnd(); | |
101 static void AuxChange(); | |
102 static void LocateAuxPopup(); | |
103 | |
104 static void TextRedisplay(); | |
105 static void TextResize(); | |
106 | |
107 static void SelectionSelected(); | |
108 | |
109 static void computeDisplaySegments(); | |
110 static void recomputeDisplaySegments(); | |
111 static void computeLastPosition(); | |
112 static DisplayFragment * computeDisplayFragments(); | |
113 static int widthAvailable(); | |
114 static void initialLocation(); | |
115 static void nextLocation(); | |
116 static DisplayLocation * findLocation(); | |
117 static void reconfigureDisplay(); | |
118 static void updateDisplay(); | |
119 static void updateDisplaySegment(); | |
120 static void redrawSegments(); | |
121 | |
122 static void eraseCursor(); | |
123 static void showCursor(); | |
124 static Boolean exposeCursor(); | |
125 static void computeCursor(); | |
126 | |
127 static void MoveShell(); | |
128 static Window getToplevelWindow(); | |
129 static void setTransientFor(); | |
130 static Boolean intersectRect(); | |
131 static void unionRect(); | |
132 static DisplayFragment * allocDisplayFragment(); | |
133 static void freeDisplayFragments(); | |
134 static void destroyDisplayFragments(); | |
135 static void allocDisplaySegments(); | |
136 static void freeDisplaySegment(); | |
137 static void clearAllDisplaySegments(); | |
138 static void copyString(); | |
139 static void freeString(); | |
140 | |
141 /*- composite-extension rec: for enabling non-widget children -*/ | |
142 static CompositeClassExtensionRec CompositeExtension = { | |
143 /* next_extension */ NULL, | |
144 /* record_type */ NULLQUARK, | |
145 /* version */ XtCompositeExtensionVersion, | |
146 /* record_size */ sizeof(CompositeClassExtensionRec), | |
147 /* accept_objects */ True, | |
148 }; | |
149 | |
150 /*- offTheSpotConversionClass record -*/ | |
151 OffTheSpotConversionClassRec offTheSpotConversionClassRec = { | |
152 { /* core fields */ | |
153 /* superclass */ (WidgetClass)&conversionControlClassRec, | |
154 /* class_name */ "OffTheSpotConversion", | |
155 /* widget_size */ sizeof(OffTheSpotConversionRec), | |
156 /* class_initialize */ NULL, | |
157 /* class_part_initialize */ NULL, | |
158 /* class_inited */ FALSE, | |
159 /* initialize */ OffTheSpot_Initialize, | |
160 /* initialize_hook */ NULL, | |
161 /* realize */ XtInheritRealize, | |
162 /* actions */ NULL, | |
163 /* num_actions */ 0, | |
164 /* resources */ off_resources, | |
165 /* num_resources */ XtNumber(off_resources), | |
166 /* xrm_class */ NULLQUARK, | |
167 /* compress_motion */ TRUE, | |
168 /* compress_exposure */ TRUE, | |
169 /* compress_enterleave */ TRUE, | |
170 /* visible_interest */ FALSE, | |
171 /* destroy */ OffTheSpot_Destroy, | |
172 /* resize */ XtInheritResize, | |
173 /* expose */ NULL, | |
174 /* set_values */ OffTheSpot_SetValues, | |
175 /* set_values_hook */ NULL, | |
176 /* set_values_almost */ XtInheritSetValuesAlmost, | |
177 /* get_values_hook */ NULL, | |
178 /* accept_focus */ NULL, | |
179 /* version */ XtVersion, | |
180 /* callback_private */ NULL, | |
181 /* tm_table */ off_translations, | |
182 /* query_geometry */ XtInheritQueryGeometry, | |
183 /* display_accelerator */ XtInheritDisplayAccelerator, | |
184 /* extension */ NULL | |
185 }, | |
186 { /* composite fields */ | |
187 /* geometry_manager */ XtInheritGeometryManager, | |
188 /* change_managed */ XtInheritChangeManaged, | |
189 /* insert_child */ XtInheritInsertChild, | |
190 /* delete_child */ XtInheritDeleteChild, | |
191 /* extension */ (XtPointer)&CompositeExtension, | |
192 }, | |
193 { /* shell fields */ | |
194 /* extension */ NULL | |
195 }, | |
196 { /* wm_shell fields */ | |
197 /* extension */ NULL | |
198 }, | |
199 { /* vendor_shell fields */ | |
200 /* extension */ NULL | |
201 }, | |
202 { /* transient_shell fields */ | |
203 /* extension */ NULL | |
204 }, | |
205 { /* conversionControl fields */ | |
206 /* Startup */ OffTheSpot_Startup, | |
207 /* Finish */ OffTheSpot_ConversionFinish, | |
208 /* ChangeAttributes */ OffTheSpot_ChangeAttributes, | |
209 /* ChangeFocus */ OffTheSpot_ChangeFocus, | |
210 /* TextChange */ UpdateText, | |
211 /* Fix */ XtInheritFix, | |
212 /* ModeChange */ UpdateMode, | |
213 /* SelectionControl */ SelectionControl, | |
214 /* AuxControl */ AuxControl, | |
215 }, | |
216 { /* offTheSpotConversion fields */ | |
217 /* empty */ 0 | |
218 }, | |
219 }; | |
220 | |
221 WidgetClass offTheSpotConversionWidgetClass = (WidgetClass)&offTheSpotConversionClassRec; | |
222 | |
223 /*- separateConversionClass record -*/ | |
224 SeparateConversionClassRec separateConversionClassRec = { | |
225 { /* core fields */ | |
226 /* superclass */ (WidgetClass)&offTheSpotConversionClassRec, | |
227 /* class_name */ "SeparateConversion", | |
228 /* widget_size */ sizeof(SeparateConversionRec), | |
229 /* class_initialize */ NULL, | |
230 /* class_part_initialize */ NULL, | |
231 /* class_inited */ FALSE, | |
232 /* initialize */ Separate_Initialize, | |
233 /* initialize_hook */ NULL, | |
234 /* realize */ XtInheritRealize, | |
235 /* actions */ NULL, | |
236 /* num_actions */ 0, | |
237 /* resources */ NULL, | |
238 /* num_resources */ 0, | |
239 /* xrm_class */ NULLQUARK, | |
240 /* compress_motion */ TRUE, | |
241 /* compress_exposure */ TRUE, | |
242 /* compress_enterleave */ TRUE, | |
243 /* visible_interest */ FALSE, | |
244 /* destroy */ NULL, | |
245 /* resize */ XtInheritResize, | |
246 /* expose */ NULL, | |
247 /* set_values */ NULL, | |
248 /* set_values_hook */ NULL, | |
249 /* set_values_almost */ XtInheritSetValuesAlmost, | |
250 /* get_values_hook */ NULL, | |
251 /* accept_focus */ NULL, | |
252 /* version */ XtVersion, | |
253 /* callback_private */ NULL, | |
254 /* tm_table */ sep_translations, | |
255 /* query_geometry */ XtInheritQueryGeometry, | |
256 /* display_accelerator */ XtInheritDisplayAccelerator, | |
257 /* extension */ NULL | |
258 }, | |
259 { /* composite fields */ | |
260 /* geometry_manager */ XtInheritGeometryManager, | |
261 /* change_managed */ XtInheritChangeManaged, | |
262 /* insert_child */ XtInheritInsertChild, | |
263 /* delete_child */ XtInheritDeleteChild, | |
264 /* extension */ (XtPointer)&CompositeExtension, | |
265 }, | |
266 { /* shell fields */ | |
267 /* extension */ NULL | |
268 }, | |
269 { /* wm_shell fields */ | |
270 /* extension */ NULL | |
271 }, | |
272 { /* vendor_shell fields */ | |
273 /* extension */ NULL | |
274 }, | |
275 { /* transient_shell fields */ | |
276 /* extension */ NULL | |
277 }, | |
278 { /* conversionControl fields */ | |
279 /* Startup */ Separate_Startup, | |
280 /* Finish */ Separate_ConversionFinish, | |
281 /* ChangeAttributes */ Separate_ChangeAttributes, | |
282 /* ChangeFocus */ Separate_ChangeFocus, | |
283 /* TextChange */ XtInheritTextChange, | |
284 /* Fix */ XtInheritFix, | |
285 /* ModeChange */ XtInheritModeChange, | |
286 /* SelectionControl */ XtInheritSelectionControl, | |
287 /* AuxControl */ XtInheritAuxControl, | |
288 }, | |
289 { /* offTheSpotConversion fields */ | |
290 /* empty */ 0 | |
291 }, | |
292 { /* separateConversion fields */ | |
293 /* empty */ 0 | |
294 }, | |
295 }; | |
296 | |
297 WidgetClass separateConversionWidgetClass = (WidgetClass)&separateConversionClassRec; | |
298 | |
299 /* | |
300 *+ OffTheSpot -- Core class method | |
301 */ | |
302 | |
303 /*- OffTheSpot_Initialize: initalize method for OffTheSpotCoversion -*/ | |
304 /* ARGSUSED */ | |
305 static void | |
306 OffTheSpot_Initialize(req, new, args, num_args) | |
307 Widget req; | |
308 Widget new; | |
309 ArgList args; | |
310 Cardinal *num_args; | |
311 { | |
312 OffTheSpotConversionWidget ocw = (OffTheSpotConversionWidget)new; | |
313 | |
314 (void)CreateDisplayObject(ocw); | |
315 (void)CreateSelectionWidget(ocw); | |
316 (void)CreateAuxWidget(ocw); | |
317 | |
318 ocw->offthespot.canvaswidget = NULL; | |
319 ocw->offthespot.modewidget = NULL; | |
320 ocw->offthespot.modeshell = NULL; | |
321 | |
322 ocw->offthespot.dispsegments = NULL; | |
323 ocw->offthespot.numsegments = 0; | |
324 ocw->offthespot.dispsegmentsize = 0; | |
325 ocw->offthespot.candlist = NULL; | |
326 ocw->offthespot.numcands = 0; | |
327 ocw->offthespot.selectionpoppedup = False; | |
328 ocw->offthespot.auxpoppedup = False; | |
329 } | |
330 | |
331 /*- OffTheSpot_Destroy: destroy method for OffTheSpotCoversion -*/ | |
332 static void | |
333 OffTheSpot_Destroy(w) | |
334 Widget w; | |
335 { | |
336 OffTheSpotConversionWidget ocw = (OffTheSpotConversionWidget)w; | |
337 | |
338 /* $B%G%#%9%W%l%$%;%0%a%s%H$NNN0h$r2rJ|(B */ | |
339 if (ocw->offthespot.dispsegments) { | |
340 DisplaySegment *dsp = ocw->offthespot.dispsegments; | |
341 int i; | |
342 | |
343 for (i = 0; i < ocw->offthespot.numsegments; i++) { | |
344 freeString(&dsp[i].seg); | |
345 destroyDisplayFragments(dsp->fragments); | |
346 } | |
347 XtFree((char *)dsp); | |
348 } | |
349 } | |
350 | |
351 /*- OffTheSpot_SetValues: setvalues method for OffTheSpotCoversion -*/ | |
352 /* ARGSUSED */ | |
353 static Boolean | |
354 OffTheSpot_SetValues(cur, req, new, args, num_args) | |
355 Widget cur; | |
356 Widget req; | |
357 Widget new; | |
358 ArgList args; | |
359 Cardinal *num_args; | |
360 { | |
361 /* OffTheSpotConversionWidget ocw = (OffTheSpotConversionWidget)new; */ | |
362 return False; | |
363 } | |
364 | |
365 /* | |
366 *+ OffTheSpot -- ConversionControl class method | |
367 */ | |
368 | |
369 /*- OffTheSpot_Startup: OffTheSpot conversion startup -*/ | |
370 static void | |
371 OffTheSpot_Startup(widget, valuemask, value) | |
372 Widget widget; | |
373 unsigned long valuemask; | |
374 ConversionAttributes *value; | |
375 { | |
376 OffTheSpotConversionWidget ocw = (OffTheSpotConversionWidget)widget; | |
377 Window toplevel; | |
378 | |
379 if (!(valuemask & CAStatusArea)) { | |
380 String params[1]; | |
381 Cardinal num_params = 1; | |
382 | |
383 params[0] = XtClass(widget)->core_class.class_name; | |
384 XtAppErrorMsg(XtWidgetToApplicationContext(widget), | |
385 "conversionAttributeError", "statusArea", "WidgetError", | |
386 "%s: status area must be specified", | |
387 params, &num_params); | |
388 } | |
389 | |
390 SetupDisplayObject(ocw, valuemask, value); | |
391 SetupModeWidget(ocw, valuemask, value); | |
392 SetupCanvasWidget(ocw, valuemask, value); | |
393 | |
394 /* $BFbIt$N%P%C%U%!$r%/%j%"$9$k(B */ | |
395 clearAllDisplaySegments(ocw); | |
396 | |
397 /* $B%+!<%=%k$N@_Dj(B */ | |
398 ocw->offthespot.cursorvisible = True; | |
399 eraseCursor(ocw); | |
400 ocw->offthespot.cursorvisible = True; | |
401 initialLocation(ocw, &(ocw->offthespot.cursorlocation)); | |
402 ocw->offthespot.cursorlocation.y += ocw->offthespot.ascent; | |
403 | |
404 /* WM_TRANSIENT_FOR $B%W%m%Q%F%#$r@5$7$/%;%C%H$9$k(B */ | |
405 toplevel = getToplevelWindow(XtDisplay(widget), | |
406 ocw->ccontrol.clientwindow); | |
407 setTransientFor(ocw->offthespot.selectionshell, toplevel); | |
408 setTransientFor(ocw->offthespot.auxshell, toplevel); | |
409 | |
410 /* | |
411 * OffTheSpotConvesion $B$N(B widget $B<+BN$O%]%C%W%"%C%W$5$;$J$$$,!"(B | |
412 * $B%P%C%/%(%s%I%?%$%W$N;~$K$O%/%i%$%"%s%H$,$3$N(B widget $B$N(B | |
413 * $B%&%#%s%I%&$KBP$7$F%$%Y%s%H$rAw$k$N$G(B Realize $B$@$1$7$F$*$/(B | |
414 */ | |
415 if (!XtIsRealized(widget)) { | |
416 Arg args[2]; | |
417 | |
418 XtSetArg(args[0], XtNwidth, 1); | |
419 XtSetArg(args[1], XtNheight, 1); | |
420 XtSetValues(widget, args, 2); | |
421 XtRealizeWidget(widget); | |
422 } | |
423 | |
424 /* $B%]%C%W%"%C%W$9$k(B */ | |
425 XtPopup(ocw->offthespot.modeshell, XtGrabNone); | |
426 XtPopup(ocw->offthespot.canvaswidget, XtGrabNone); | |
427 } | |
428 | |
429 /*- OffTheSpot_ConversionFinish: OffTheSpot conversion finish -*/ | |
430 /* ARGSUSED */ | |
431 static void | |
432 OffTheSpot_ConversionFinish(w) | |
433 Widget w; | |
434 { | |
435 OffTheSpotConversionWidget ocw = (OffTheSpotConversionWidget)w; | |
436 XAEHandle h; | |
437 | |
438 /* Popdown and unrealize textcanvas and mode widget | |
439 * we must be careful here. if clientwindow are destroyed, | |
440 * the text canvas and mode widget are also destroyed. | |
441 * we have to popdown and unrealize those widgets, but if | |
442 * they are destroyed, BadWindow error will be generated. | |
443 * so we must set own error handler that ignores errors. | |
444 */ | |
445 h = XAESetIgnoreErrors(XtDisplay(w)); | |
446 XtPopdown(ocw->offthespot.modeshell); | |
447 XtUnrealizeWidget(ocw->offthespot.modeshell); | |
448 XtPopdown(ocw->offthespot.canvaswidget); | |
449 XtUnrealizeWidget(ocw->offthespot.canvaswidget); | |
450 XAEUnset(h); | |
451 | |
452 if (ocw->offthespot.selectionpoppedup) { | |
453 XtPopdown(ocw->offthespot.selectionshell); | |
454 ocw->offthespot.selectionpoppedup = False; | |
455 } | |
456 if (ocw->offthespot.auxpoppedup) { | |
457 XtPopdown(ocw->offthespot.auxshell); | |
458 ocw->offthespot.auxpoppedup = False; | |
459 } | |
460 } | |
461 | |
462 /*- OffTheSpot_ChangeAttributes: OffTheSpot conversion attribute change -*/ | |
463 /* ARGSUSED */ | |
464 static void | |
465 OffTheSpot_ChangeAttributes(w, valuemask, value) | |
466 Widget w; | |
467 unsigned long valuemask; | |
468 ConversionAttributes *value; | |
469 { | |
470 OffTheSpotConversionWidget ocw = (OffTheSpotConversionWidget)w; | |
471 Boolean redraw, reconfig; | |
472 | |
473 if (ResetModeWidget(ocw, valuemask, value) && | |
474 XtIsRealized(ocw->offthespot.modewidget)) { | |
475 XClearArea(XtDisplay(w), XtWindow((Widget)ocw->offthespot.modewidget), | |
476 0, 0, 0, 0, True); | |
477 } | |
478 | |
479 redraw = ResetDisplayObject(ocw, valuemask, value); | |
480 reconfig = ResetCanvasWidget(ocw, valuemask, value); | |
481 | |
482 if (reconfig) { | |
483 TextResize(ocw->offthespot.canvaswidget, (XtPointer)w, (XtPointer)NULL); | |
484 } else if (redraw && XtIsRealized(ocw->offthespot.canvaswidget)) { | |
485 XClearArea(XtDisplay(w), XtWindow(ocw->offthespot.canvaswidget), | |
486 0, 0, 0, 0, True); | |
487 } | |
488 } | |
489 | |
490 /*- OffTheSpot_ChangeFocus: OffTheSpot focus change -*/ | |
491 static void | |
492 OffTheSpot_ChangeFocus(w, set) | |
493 Widget w; | |
494 int set; | |
495 { | |
496 OffTheSpotConversionWidget ocw = (OffTheSpotConversionWidget)w; | |
497 | |
498 if (set) { | |
499 XtPopup(ocw->offthespot.modeshell, XtGrabNone); | |
500 XtPopup(ocw->offthespot.canvaswidget, XtGrabNone); | |
501 } else { | |
502 XtPopdown(ocw->offthespot.modeshell); | |
503 XtPopdown(ocw->offthespot.canvaswidget); | |
504 } | |
505 } | |
506 | |
507 /* | |
508 *+ Separate -- Core class method | |
509 */ | |
510 | |
511 /*- Separate_Initialize: initialize method for SeparateConversion -*/ | |
512 /* ARGSUSED */ | |
513 static void | |
514 Separate_Initialize(req, new, args, num_args) | |
515 Widget req; | |
516 Widget new; | |
517 ArgList args; | |
518 Cardinal *num_args; | |
519 { | |
520 SeparateConversionWidget scw = (SeparateConversionWidget)new; | |
521 Widget inputobj = scw->ccontrol.inputobj; | |
522 Widget form, canvas, mode, tmp[2]; | |
523 | |
524 form = XtCreateManagedWidget("form", formWidgetClass, (Widget)scw, | |
525 NULL, 0); | |
526 tmp[0] = mode = XtVaCreateWidget("mode", icLabelWidgetClass, form, | |
527 XtNlabel, ICGetMode(inputobj), | |
528 NULL); | |
529 (void)XtCreateWidget("display", scw->ccontrol.displayobjclass, mode, | |
530 NULL, 0); | |
531 | |
532 tmp[1] = canvas = XtCreateWidget("text", canvasWidgetClass, form, NULL, 0); | |
533 XtManageChildren(tmp, 2); | |
534 | |
535 XtAddCallback(canvas, XtNexposeCallback, TextRedisplay, (XtPointer)scw); | |
536 XtAddCallback(canvas, XtNresizeCallback, TextResize, (XtPointer)scw); | |
537 | |
538 XtInstallAccelerators(canvas, (Widget)scw); | |
539 XtInstallAccelerators(mode, (Widget)scw); | |
540 XtInstallAccelerators(form, (Widget)scw); | |
541 | |
542 scw->separate.formwidget = form; | |
543 scw->offthespot.canvaswidget = canvas; | |
544 scw->offthespot.modewidget = mode; | |
545 | |
546 } | |
547 | |
548 /* | |
549 *+ Separate -- ConversionControl class method | |
550 */ | |
551 | |
552 /*- Separate_Startup: Separate conversion startup -*/ | |
553 /* ARGSUSED */ | |
554 static void | |
555 Separate_Startup(widget, valuemask, value) | |
556 Widget widget; | |
557 unsigned long valuemask; | |
558 ConversionAttributes *value; | |
559 { | |
560 SeparateConversionWidget scw = (SeparateConversionWidget)widget; | |
561 Position clx, cly; | |
562 Dimension clw, clh; | |
563 Position x, y; | |
564 Dimension w, h; | |
565 Dimension dpyWidth, dpyHeight; | |
566 Window toplevel; | |
567 | |
568 /* $BFbIt$N%P%C%U%!$r%/%j%"$9$k(B */ | |
569 clearAllDisplaySegments((OffTheSpotConversionWidget)scw); | |
570 | |
571 /* $B%+!<%=%k$N@_Dj(B */ | |
572 scw->offthespot.cursorvisible = True; | |
573 eraseCursor((OffTheSpotConversionWidget)scw); | |
574 scw->offthespot.cursorvisible = True; | |
575 initialLocation((OffTheSpotConversionWidget)scw, | |
576 &(scw->offthespot.cursorlocation)); | |
577 scw->offthespot.cursorlocation.y += scw->offthespot.ascent; | |
578 | |
579 /* $B=i4|%b!<%I$r@_Dj$9$k(B */ | |
580 XtVaSetValues(scw->offthespot.modewidget, | |
581 XtNlabel, ICGetMode(scw->ccontrol.inputobj), | |
582 NULL); | |
583 | |
584 /* $BI=<(0LCV$r7h$a$k(B */ | |
585 clx = scw->ccontrol.client_rootx; | |
586 cly = scw->ccontrol.client_rooty; | |
587 clw = scw->ccontrol.client_attr.width; | |
588 clh = scw->ccontrol.client_attr.height; | |
589 | |
590 XtRealizeWidget((Widget)scw); | |
591 w = scw->core.width; | |
592 h = scw->core.height; | |
593 DPRINT(("Off_the_spot_Startup(): widget size = %dx%d\n", w, h)); | |
594 x = clx + clw / 2 - w / 2; | |
595 y = cly + clh + 8; | |
596 | |
597 dpyWidth = WidthOfScreen(XtScreen(widget)); | |
598 dpyHeight = HeightOfScreen(XtScreen(widget)); | |
599 | |
600 if (x + w > dpyWidth) x = dpyWidth - w; | |
601 if (x < 0) x = 0; | |
602 if (y + h > dpyHeight) { | |
603 y = cly - h; | |
604 if (y < 0) y = dpyHeight - h; | |
605 } | |
606 MoveShell(widget, x, y); | |
607 | |
608 /* WM_TRANSIENT_FOR $B%W%m%Q%F%#$r@5$7$/%;%C%H$9$k(B */ | |
609 toplevel = getToplevelWindow(XtDisplay(widget), | |
610 scw->ccontrol.clientwindow); | |
611 setTransientFor((Widget)scw, toplevel); | |
612 | |
613 /* | |
614 * This is a kind of a magic word... I don't know why, but without this | |
615 * the selection popup will appear in wrong size (1x1) at the first time. | |
616 */ | |
617 XtRealizeWidget(scw->offthespot.selectionshell); | |
618 XtRealizeWidget(scw->offthespot.auxshell); | |
619 | |
620 /* $B%]%C%W%"%C%W$9$k(B */ | |
621 XtPopup(widget, XtGrabNone); | |
622 } | |
623 | |
624 /*- Separate_ConversionFinish: Separate conversion finish -*/ | |
625 /* ARGSUSED */ | |
626 static void | |
627 Separate_ConversionFinish(w) | |
628 Widget w; | |
629 { | |
630 SeparateConversionWidget scw = (SeparateConversionWidget)w; | |
631 | |
632 if (scw->offthespot.selectionpoppedup) { | |
633 XtPopdown(scw->offthespot.selectionshell); | |
634 scw->offthespot.selectionpoppedup = False; | |
635 } | |
636 if (scw->offthespot.auxpoppedup) { | |
637 XtPopdown(scw->offthespot.auxshell); | |
638 scw->offthespot.auxpoppedup = False; | |
639 } | |
640 XtPopdown(w); | |
641 } | |
642 | |
643 /*- Separate_ChangeAttributes: Separate conversion attribute change -*/ | |
644 /* ARGSUSED */ | |
645 static void | |
646 Separate_ChangeAttributes(w, mask, value) | |
647 Widget w; | |
648 unsigned long mask; | |
649 ConversionAttributes *value; | |
650 { | |
651 /* do nothing */ | |
652 } | |
653 | |
654 /*- Separate_ChangeFocus: Separate focus change -*/ | |
655 /* ARGSUSED */ | |
656 static void | |
657 Separate_ChangeFocus(w, set) | |
658 Widget w; | |
659 int set; | |
660 { | |
661 /* do nothing */ | |
662 } | |
663 | |
664 /* | |
665 *+ sub-widget creation | |
666 */ | |
667 | |
668 /*- CreateDisplayObject: create display object for text drawing -*/ | |
669 static Widget | |
670 CreateDisplayObject(ocw) | |
671 OffTheSpotConversionWidget ocw; | |
672 { | |
673 Widget dispobj; | |
674 | |
675 dispobj = XtCreateWidget("displayObj", ocw->ccontrol.displayobjclass, | |
676 (Widget)ocw, NULL, 0); | |
677 | |
678 ocw->offthespot.displayobj = dispobj; | |
679 ocw->offthespot.lineheight = CDLineHeight(dispobj, &ocw->offthespot.ascent); | |
680 | |
681 return dispobj; | |
682 } | |
683 | |
684 /*- CreateSelectionWidget: create selection widget for selecting candidates -*/ | |
685 static Widget | |
686 CreateSelectionWidget(ocw) | |
687 OffTheSpotConversionWidget ocw; | |
688 { | |
689 Widget shell, sel; | |
690 | |
691 /* set width/height so that XtRealizeWidget() doesn't cause error */ | |
692 shell = XtVaCreatePopupShell("selectionShell", | |
693 transientShellWidgetClass, | |
694 (Widget)ocw, | |
695 XtNwidth, 1, | |
696 XtNheight, 1, | |
697 NULL); | |
698 ocw->offthespot.selectionshell = shell; | |
699 | |
700 sel = XtCreateManagedWidget("selection", candidatePanelWidgetClass, | |
701 shell, NULL, 0); | |
702 (void)XtCreateWidget("display", ocw->ccontrol.displayobjclass, sel, | |
703 NULL, 0); | |
704 XtAddCallback(sel, XtNcallback, SelectionSelected, (XtPointer)ocw); | |
705 XtInstallAccelerators(sel, (Widget)ocw); | |
706 | |
707 ocw->offthespot.selectionwidget = sel; | |
708 | |
709 return shell; | |
710 } | |
711 | |
712 /*- CreateAuxWidget: create aux widget for display auxiliary data -*/ | |
713 static Widget | |
714 CreateAuxWidget(ocw) | |
715 OffTheSpotConversionWidget ocw; | |
716 { | |
717 Widget shell, sel; | |
718 | |
719 /* set width/height so that XtRealizeWidget() doesn't cause error */ | |
720 shell = XtVaCreatePopupShell("auxShell", | |
721 transientShellWidgetClass, | |
722 (Widget)ocw, | |
723 XtNwidth, 1, | |
724 XtNheight, 1, | |
725 XtNallowShellResize, True, | |
726 NULL); | |
727 ocw->offthespot.auxshell = shell; | |
728 | |
729 sel = XtCreateManagedWidget("aux", auxPanelWidgetClass, | |
730 shell, NULL, 0); | |
731 (void)XtCreateWidget("display", ocw->ccontrol.displayobjclass, sel, | |
732 NULL, 0); | |
733 XtAddCallback(sel, XtNcallback, SelectionSelected, (XtPointer)ocw); | |
734 XtInstallAccelerators(sel, (Widget)ocw); | |
735 | |
736 ocw->offthespot.auxwidget = sel; | |
737 | |
738 return shell; | |
739 } | |
740 | |
741 /* | |
742 *+ subwidget configuration | |
743 */ | |
744 | |
745 /*- SetupDisplayObject: do display objetct configuration on conversion startup -*/ | |
746 static void | |
747 SetupDisplayObject(ocw, mask, value) | |
748 OffTheSpotConversionWidget ocw; | |
749 unsigned long mask; | |
750 ConversionAttributes *value; | |
751 { | |
752 /* | |
753 * order is important. we must set fonts BEFORE anything else, | |
754 * because it is possible that the fonts previously set in the | |
755 * display object no longer exist, and if so, that causes BadFont | |
756 * error when changing GCs. | |
757 */ | |
758 | |
759 if (mask & CAFonts) { | |
760 CDSetFonts(ocw->offthespot.displayobj, | |
761 value->fonts, value->num_fonts); | |
762 } else { | |
763 CDSetFonts(ocw->offthespot.displayobj, (XFontStruct **)NULL, 0); | |
764 } | |
765 if (mask & CAColor) { | |
766 XtVaSetValues(ocw->offthespot.displayobj, | |
767 XtNforeground, value->foreground, | |
768 XtNbackground, value->background, | |
769 NULL); | |
770 } | |
771 | |
772 ocw->offthespot.lineheight = CDLineHeight(ocw->offthespot.displayobj, | |
773 &ocw->offthespot.ascent); | |
774 } | |
775 | |
776 /*- ResetDisplayObject: do display objetct reconfiguration on attribute change -*/ | |
777 static Boolean | |
778 ResetDisplayObject(ocw, mask, value) | |
779 OffTheSpotConversionWidget ocw; | |
780 unsigned long mask; | |
781 ConversionAttributes *value; | |
782 { | |
783 Boolean redraw = False; | |
784 | |
785 if (mask & CAColor) { | |
786 XtVaSetValues(ocw->offthespot.displayobj, | |
787 XtNforeground, value->foreground, | |
788 XtNbackground, value->background, | |
789 NULL); | |
790 redraw = True; | |
791 } | |
792 if (mask & CAFonts) { | |
793 CDSetFonts(ocw->offthespot.displayobj, | |
794 value->fonts, value->num_fonts); | |
795 redraw = True; | |
796 ocw->offthespot.lineheight = CDLineHeight(ocw->offthespot.displayobj, | |
797 &ocw->offthespot.ascent); | |
798 } | |
799 return redraw; | |
800 } | |
801 | |
802 /*- SetupModeWidget: do mode widget configuration (OffTheSpot only) -*/ | |
803 static void | |
804 SetupModeWidget(ocw, mask, value) | |
805 OffTheSpotConversionWidget ocw; | |
806 unsigned long mask; | |
807 ConversionAttributes *value; | |
808 { | |
809 Window clwin = ocw->ccontrol.clientwindow; | |
810 Widget inputobj = ocw->ccontrol.inputobj; | |
811 Arg shellarg[10], modearg[10], objarg[10]; | |
812 Cardinal i = 0, j = 0, k = 0; | |
813 | |
814 XtSetArg(shellarg[i], XtNparentWindow, clwin); i++; | |
815 XtSetArg(shellarg[i], XtNx, value->statusarea.x); i++; | |
816 XtSetArg(shellarg[i], XtNy, value->statusarea.y); i++; | |
817 XtSetArg(shellarg[i], XtNwidth, value->statusarea.width); i++; | |
818 XtSetArg(shellarg[i], XtNheight, value->statusarea.height); i++; | |
819 | |
820 XtSetArg(modearg[j], XtNlabel, ICGetMode(inputobj)); j++; | |
821 | |
822 if (mask & CAColormap) { | |
823 XtSetArg(modearg[j], XtNcolormap, value->colormap); j++; | |
824 } else { | |
825 XtSetArg(modearg[j], XtNcolormap, | |
826 DefaultColormapOfScreen(XtScreen((Widget)ocw))); j++; | |
827 } | |
828 if (mask & CAColor) { | |
829 XtSetArg(modearg[j], XtNbackground, value->background); j++; | |
830 XtSetArg(objarg[k], XtNforeground, value->foreground); k++; | |
831 XtSetArg(objarg[k], XtNbackground, value->background); k++; | |
832 } else { | |
833 XtSetArg(modearg[j], XtNbackground, ocw->core.background_pixel); j++; | |
834 } | |
835 | |
836 if (ocw->offthespot.modewidget == NULL) { | |
837 Widget shell, mode, disp; | |
838 shell = XtCreatePopupShell("modeShell", adoptedShellWidgetClass, | |
839 (Widget)ocw, shellarg, i); | |
840 mode = XtCreateManagedWidget("mode", icLabelWidgetClass, shell, | |
841 modearg, j); | |
842 disp = XtCreateWidget("display", ocw->ccontrol.displayobjclass, mode, | |
843 objarg, k); | |
844 if (mask & CAStatusFonts) { | |
845 CDSetFonts(disp, value->status_fonts, value->num_status_fonts); | |
846 } | |
847 | |
848 ocw->offthespot.modeshell = shell; | |
849 ocw->offthespot.modewidget = mode; | |
850 ocw->offthespot.modedisplayobj = disp; | |
851 XtInstallAccelerators(mode, (Widget)ocw); | |
852 } else { | |
853 if (mask & CAStatusFonts) { | |
854 CDSetFonts(ocw->offthespot.modedisplayobj, | |
855 value->status_fonts, value->num_status_fonts); | |
856 } else { | |
857 CDSetFonts(ocw->offthespot.modedisplayobj, | |
858 (XFontStruct **)NULL, 0); | |
859 } | |
860 XtSetValues(ocw->offthespot.modeshell, shellarg, i); | |
861 XtSetValues(ocw->offthespot.modewidget, modearg, j); | |
862 XtSetValues(ocw->offthespot.modedisplayobj, objarg, k); | |
863 } | |
864 | |
865 ICLRecomputeSize(ocw->offthespot.modewidget); | |
866 } | |
867 | |
868 /*- ResetModeWidget: do mode widget reconfiguration (OffTheSpot only) -*/ | |
869 static Boolean | |
870 ResetModeWidget(ocw, mask, value) | |
871 OffTheSpotConversionWidget ocw; | |
872 unsigned long mask; | |
873 ConversionAttributes *value; | |
874 { | |
875 Arg shellarg[10], modearg[10], objarg[10]; | |
876 Cardinal i = 0, j = 0, k = 0; | |
877 Boolean redraw = False; | |
878 | |
879 if (mask & CAStatusArea) { | |
880 XtSetArg(shellarg[i], XtNx, value->statusarea.x); i++; | |
881 XtSetArg(shellarg[i], XtNy, value->statusarea.y); i++; | |
882 XtSetArg(shellarg[i], XtNwidth, value->statusarea.width); i++; | |
883 XtSetArg(shellarg[i], XtNheight, value->statusarea.height); i++; | |
884 } | |
885 | |
886 if (mask & CAColormap) { | |
887 XtSetArg(modearg[j], XtNcolormap, value->colormap); j++; | |
888 redraw = True; | |
889 } | |
890 if (mask & CAColor) { | |
891 XtSetArg(modearg[j], XtNbackground, value->background); j++; | |
892 XtSetArg(objarg[k], XtNforeground, value->foreground); k++; | |
893 XtSetArg(objarg[k], XtNbackground, value->background); k++; | |
894 redraw = True; | |
895 } | |
896 XtSetValues(ocw->offthespot.modeshell, shellarg, i); | |
897 XtSetValues(ocw->offthespot.modewidget, modearg, j); | |
898 XtSetValues(ocw->offthespot.modedisplayobj, objarg, k); | |
899 | |
900 if (mask & CAStatusFonts) { | |
901 CDSetFonts(ocw->offthespot.modedisplayobj, | |
902 value->status_fonts, value->num_status_fonts); | |
903 ICLRecomputeSize(ocw->offthespot.modewidget); | |
904 redraw = True; | |
905 } | |
906 | |
907 return redraw; | |
908 } | |
909 | |
910 /*- SetupCanvasWidget: do text canvas configuration on conversion startup -*/ | |
911 static void | |
912 SetupCanvasWidget(ocw, mask, value) | |
913 OffTheSpotConversionWidget ocw; | |
914 unsigned long mask; | |
915 ConversionAttributes *value; | |
916 { | |
917 Window clwin = ocw->ccontrol.clientwindow; | |
918 Arg arg[10]; | |
919 Cardinal i = 0; | |
920 | |
921 XtSetArg(arg[i], XtNparentWindow, clwin); i++; | |
922 | |
923 if (mask & CAClientArea) { | |
924 XtSetArg(arg[i], XtNx, value->clientarea.x); i++; | |
925 XtSetArg(arg[i], XtNy, value->clientarea.y); i++; | |
926 XtSetArg(arg[i], XtNwidth, value->clientarea.width); i++; | |
927 XtSetArg(arg[i], XtNheight, value->clientarea.height); i++; | |
928 } else { | |
929 XtSetArg(arg[i], XtNx, 0); i++; | |
930 XtSetArg(arg[i], XtNy, 0); i++; | |
931 XtSetArg(arg[i], XtNwidth, ocw->ccontrol.client_attr.width); i++; | |
932 XtSetArg(arg[i], XtNheight, ocw->ccontrol.client_attr.height); i++; | |
933 } | |
934 | |
935 /* if (mask & CALineSpacing) ... */ | |
936 if (mask & CAColormap) { | |
937 XtSetArg(arg[i], XtNcolormap, value->colormap); i++; | |
938 } else { | |
939 XtSetArg(arg[i], XtNcolormap, | |
940 DefaultColormapOfScreen(XtScreen((Widget)ocw))); i++; | |
941 } | |
942 if (mask & CAColor) { | |
943 XtSetArg(arg[i], XtNbackground, value->background); i++; | |
944 } else { | |
945 XtSetArg(arg[i], XtNbackground, ocw->core.background_pixel); i++; | |
946 } | |
947 if (mask & CACursor) { | |
948 XtSetArg(arg[i], XtNcursor, value->cursor); i++; | |
949 } else { | |
950 XtSetArg(arg[i], XtNcursor, None); i++; | |
951 } | |
952 | |
953 if (ocw->offthespot.canvaswidget == NULL) { | |
954 Widget canvas; | |
955 canvas = XtCreatePopupShell("text", canvasShellWidgetClass, | |
956 (Widget)ocw, arg, i); | |
957 XtAddCallback(canvas, XtNexposeCallback, TextRedisplay, (XtPointer)ocw); | |
958 XtAddCallback(canvas, XtNresizeCallback, TextResize, (XtPointer)ocw); | |
959 XtInstallAccelerators(canvas, (Widget)ocw); | |
960 ocw->offthespot.canvaswidget = canvas; | |
961 } else { | |
962 XtSetValues(ocw->offthespot.canvaswidget, arg, i); | |
963 } | |
964 } | |
965 | |
966 /*- ResetCanvasWidget: do text canvas reconfiguration on attribute change (OfftheSpot only) -*/ | |
967 static Boolean | |
968 ResetCanvasWidget(ocw, mask, value) | |
969 OffTheSpotConversionWidget ocw; | |
970 unsigned long mask; | |
971 ConversionAttributes *value; | |
972 { | |
973 Arg arg[10]; | |
974 Cardinal i = 0; | |
975 Boolean redraw = False; | |
976 | |
977 if (mask & CAClientArea) { | |
978 XtSetArg(arg[i], XtNx, value->clientarea.x); i++; | |
979 XtSetArg(arg[i], XtNy, value->clientarea.y); i++; | |
980 XtSetArg(arg[i], XtNwidth, value->clientarea.width); i++; | |
981 XtSetArg(arg[i], XtNheight, value->clientarea.height); i++; | |
982 redraw = True; | |
983 } | |
984 | |
985 if (mask & CAColormap) { | |
986 XtSetArg(arg[i], XtNcolormap, value->colormap); i++; | |
987 redraw = True; | |
988 } | |
989 if (mask & CAColor) { | |
990 XtSetArg(arg[i], XtNbackground, value->background); i++; | |
991 redraw = True; | |
992 } | |
993 if (mask & CACursor) { | |
994 XtSetArg(arg[i], XtNcursor, value->cursor); i++; | |
995 } | |
996 | |
997 XtSetValues(ocw->offthespot.canvaswidget, arg, i); | |
998 | |
999 return redraw; | |
1000 } | |
1001 | |
1002 static void | |
1003 UpdateText(w) | |
1004 Widget w; | |
1005 { | |
1006 OffTheSpotConversionWidget ocw = (OffTheSpotConversionWidget)w; | |
1007 | |
1008 TRACE(("OffTheSpotConversion:UpdateText()\n")); | |
1009 eraseCursor(ocw); | |
1010 computeDisplaySegments(ocw); | |
1011 computeCursor(ocw); | |
1012 reconfigureDisplay(ocw); | |
1013 updateDisplay(ocw); | |
1014 showCursor(ocw); | |
1015 } | |
1016 | |
1017 static void | |
1018 UpdateMode(w) | |
1019 Widget w; | |
1020 { | |
1021 OffTheSpotConversionWidget ocw = (OffTheSpotConversionWidget)w; | |
1022 | |
1023 TRACE(("OffTheSpotConversion:UpdateMode()\n")); | |
1024 XtVaSetValues(ocw->offthespot.modewidget, | |
1025 XtNlabel, ICGetMode(ocw->ccontrol.inputobj), | |
1026 NULL); | |
1027 } | |
1028 | |
1029 static void | |
1030 SelectionControl(w, arg) | |
1031 Widget w; | |
1032 ICSelectionControlArg *arg; | |
1033 { | |
1034 OffTheSpotConversionWidget ocw = (OffTheSpotConversionWidget)w; | |
1035 String params[1]; | |
1036 Cardinal num_params; | |
1037 | |
1038 switch (arg->command) { | |
1039 case ICSelectionStart: | |
1040 SelectionStart(ocw, arg->u.selection_kind); | |
1041 break; | |
1042 case ICSelectionEnd: | |
1043 SelectionEnd(ocw, &arg->u.current_item); | |
1044 break; | |
1045 case ICSelectionSet: | |
1046 SelectionSet(ocw, arg->u.current_item); | |
1047 break; | |
1048 case ICSelectionMove: | |
1049 SelectionMove(ocw, arg->u.dir); | |
1050 break; | |
1051 case ICSelectionGet: | |
1052 SelectionGet(ocw, &arg->u.current_item); | |
1053 break; | |
1054 default: | |
1055 params[0] = XtClass(w)->core_class.class_name; | |
1056 num_params = 1; | |
1057 XtAppWarningMsg(XtWidgetToApplicationContext(w), | |
1058 "parameterError", "SelectionControl", "WidgetError", | |
1059 "%s: unknown selection control command", | |
1060 params, &num_params); | |
1061 break; | |
1062 } | |
1063 } | |
1064 | |
1065 /* ARGSUSED */ | |
1066 static void | |
1067 SelectionStart(ocw, kind) | |
1068 OffTheSpotConversionWidget ocw; | |
1069 int kind; | |
1070 { | |
1071 Cardinal ncand; | |
1072 | |
1073 TRACE(("OffTheSpotConversion:SelectionStart()\n")); | |
1074 if (ocw->offthespot.selectionpoppedup) { | |
1075 TRACE(("\tselection already started -- ignored\n")); | |
1076 return; | |
1077 } | |
1078 | |
1079 ocw->offthespot.candlist = ICGetItemList(ocw->ccontrol.inputobj, &ncand); | |
1080 ocw->offthespot.numcands = ncand; | |
1081 | |
1082 TRACE(("\tnumcands=%d\n", ocw->offthespot.numcands)); | |
1083 CPanelSetList(ocw->offthespot.selectionwidget, | |
1084 ocw->offthespot.candlist, | |
1085 ocw->offthespot.numcands, 0, True); | |
1086 | |
1087 /* $B%]%C%W%"%C%W$9$k>l=j$r7h$a$k(B */ | |
1088 LocateSelectionPopup(ocw); | |
1089 | |
1090 XtPopup(ocw->offthespot.selectionshell, XtGrabNone); | |
1091 ocw->offthespot.selectionpoppedup = True; | |
1092 } | |
1093 | |
1094 static void | |
1095 LocateSelectionPopup(ocw) | |
1096 OffTheSpotConversionWidget ocw; | |
1097 { | |
1098 Position x, y; | |
1099 DisplayLocation lastp; | |
1100 Dimension dpyWidth, dpyHeight; | |
1101 Widget canvas = ocw->offthespot.canvaswidget; | |
1102 Widget panel = ocw->offthespot.selectionwidget; | |
1103 Widget shell = ocw->offthespot.selectionshell; | |
1104 int clx, cly; | |
1105 Window junk; | |
1106 int barheight = ocw->ccontrol.titlebarheight; | |
1107 | |
1108 if (ocw->offthespot.numsegments > 0) { | |
1109 computeLastPosition(ocw->offthespot.dispsegments[ocw->offthespot.numsegments - 1].fragments, &lastp); | |
1110 } else { | |
1111 lastp.y = 0; | |
1112 } | |
1113 lastp.x = canvas->core.width / 2; | |
1114 lastp.y += ocw->offthespot.lineheight; | |
1115 (void)XTranslateCoordinates(XtDisplay(canvas), XtWindow(canvas), | |
1116 RootWindowOfScreen(XtScreen(canvas)), | |
1117 0, 0, &clx, &cly, &junk); | |
1118 | |
1119 x = clx + lastp.x - panel->core.width / 2; | |
1120 y = cly + lastp.y + 8; /* XXX */ | |
1121 | |
1122 dpyWidth = WidthOfScreen(XtScreen(canvas)); | |
1123 dpyHeight = HeightOfScreen(XtScreen(canvas)); | |
1124 | |
1125 if (x + panel->core.width > dpyWidth) x = dpyWidth - panel->core.width; | |
1126 if (x < 0) x = 0; | |
1127 if (y + panel->core.height + barheight > dpyHeight) { | |
1128 y = cly - panel->core.height - 8 - barheight; | |
1129 if (y < 0) y = dpyHeight - panel->core.height - barheight; | |
1130 } | |
1131 MoveShell(shell, x, y); | |
1132 } | |
1133 | |
1134 static void | |
1135 SelectionEnd(ocw, current) | |
1136 OffTheSpotConversionWidget ocw; | |
1137 int *current; | |
1138 { | |
1139 TRACE(("OffTheSpotConversion:SelectionEnd()\n")); | |
1140 if (!ocw->offthespot.selectionpoppedup) { /* for safe */ | |
1141 TRACE(("\tnot in selection mode -- ignored\n")); | |
1142 return; | |
1143 } | |
1144 | |
1145 XtVaGetValues(ocw->offthespot.selectionwidget, | |
1146 XtNcurrentItem, current, | |
1147 NULL); | |
1148 | |
1149 XtPopdown(ocw->offthespot.selectionshell); | |
1150 | |
1151 ocw->offthespot.selectionpoppedup = False; | |
1152 } | |
1153 | |
1154 static void | |
1155 SelectionSet(ocw, current) | |
1156 OffTheSpotConversionWidget ocw; | |
1157 int current; | |
1158 { | |
1159 TRACE(("OffTheSpotConversion:SelectionSet()\n")); | |
1160 if (!ocw->offthespot.selectionpoppedup) { /* for safe */ | |
1161 TRACE(("\tnot in selection mode -- ignored\n")); | |
1162 return; | |
1163 } | |
1164 | |
1165 XtVaSetValues(ocw->offthespot.selectionwidget, | |
1166 XtNcurrentItem, current, | |
1167 NULL); | |
1168 } | |
1169 | |
1170 static void | |
1171 SelectionGet(ocw, current) | |
1172 OffTheSpotConversionWidget ocw; | |
1173 int *current; | |
1174 { | |
1175 TRACE(("OffTheSpotConversion:SelectionGet()\n")); | |
1176 if (!ocw->offthespot.selectionpoppedup) { /* for safe */ | |
1177 TRACE(("\tnot in selection mode -- ignored\n")); | |
1178 return; | |
1179 } | |
1180 | |
1181 XtVaGetValues(ocw->offthespot.selectionwidget, | |
1182 XtNcurrentItem, current, | |
1183 NULL); | |
1184 } | |
1185 | |
1186 static void | |
1187 SelectionMove(ocw, dir) | |
1188 OffTheSpotConversionWidget ocw; | |
1189 int dir; | |
1190 { | |
1191 TRACE(("OffTheSpotConversion:SelectionMove()\n")); | |
1192 if (!ocw->offthespot.selectionpoppedup) { /* for safe */ | |
1193 TRACE(("\tnot in selection mode -- ignored\n")); | |
1194 return; | |
1195 } | |
1196 | |
1197 CPanelMoveCurrent(ocw->offthespot.selectionwidget, dir); | |
1198 } | |
1199 | |
1200 /* | |
1201 * Aux Callback | |
1202 */ | |
1203 | |
1204 static void | |
1205 AuxControl(w, arg) | |
1206 Widget w; | |
1207 ICAuxControlArg *arg; | |
1208 { | |
1209 OffTheSpotConversionWidget ocw = (OffTheSpotConversionWidget)w; | |
1210 String params[1]; | |
1211 Cardinal num_params; | |
1212 | |
1213 switch (arg->command) { | |
1214 case ICAuxStart: | |
1215 AuxStart(ocw); | |
1216 break; | |
1217 case ICAuxEnd: | |
1218 AuxEnd(ocw); | |
1219 break; | |
1220 case ICAuxChange: | |
1221 AuxChange(ocw); | |
1222 break; | |
1223 default: | |
1224 params[0] = XtClass(w)->core_class.class_name; | |
1225 num_params = 1; | |
1226 XtAppWarningMsg(XtWidgetToApplicationContext(w), | |
1227 "parameterError", "AuxControl", "WidgetError", | |
1228 "%s: unknown aux control command", | |
1229 params, &num_params); | |
1230 break; | |
1231 } | |
1232 } | |
1233 | |
1234 /* ARGSUSED */ | |
1235 static void | |
1236 AuxStart(ocw) | |
1237 OffTheSpotConversionWidget ocw; | |
1238 { | |
1239 ICString *auxstr; | |
1240 Cardinal ncand, curseg, cursorpos; | |
1241 | |
1242 if (ocw->offthespot.auxpoppedup) return; | |
1243 | |
1244 /* $B%F%-%9%H%3!<%k%P%C%/$N;~$N$h$&$J=hM}$r$9$k(B | |
1245 $B$N$O(B AuxPanel.c $B$K$^$+$;$h$&(B */ | |
1246 | |
1247 auxstr = ICGetAuxSegments(ocw->ccontrol.inputobj, | |
1248 &ncand, &curseg, &cursorpos); | |
1249 | |
1250 APanelStart(ocw->offthespot.auxwidget, auxstr, ncand, curseg, cursorpos); | |
1251 | |
1252 /* $B%]%C%W%"%C%W$9$k>l=j$r7h$a$k(B */ | |
1253 LocateAuxPopup(ocw); | |
1254 | |
1255 XtPopup(ocw->offthespot.auxshell, XtGrabNone); | |
1256 ocw->offthespot.auxpoppedup = True; | |
1257 } | |
1258 | |
1259 /* ARGSUSED */ | |
1260 static void | |
1261 AuxEnd(ocw) | |
1262 OffTheSpotConversionWidget ocw; | |
1263 { | |
1264 if (!ocw->offthespot.auxpoppedup) return; /* for safe */ | |
1265 | |
1266 /* APanelEnd(ocw->offthespot.auxwidget); */ | |
1267 | |
1268 XtPopdown(ocw->offthespot.auxshell); | |
1269 | |
1270 ocw->offthespot.auxpoppedup = False; | |
1271 } | |
1272 | |
1273 /* ARGSUSED */ | |
1274 static void | |
1275 AuxChange(ocw) | |
1276 OffTheSpotConversionWidget ocw; | |
1277 { | |
1278 Cardinal ncand, curseg, cursorpos; | |
1279 ICString *auxstr; | |
1280 | |
1281 if (!ocw->offthespot.auxpoppedup) return; /* for safe */ | |
1282 | |
1283 auxstr = ICGetAuxSegments(ocw->ccontrol.inputobj, | |
1284 &ncand, &curseg, &cursorpos); | |
1285 | |
1286 APanelChange(ocw->offthespot.auxwidget, auxstr, ncand, curseg, cursorpos); | |
1287 } | |
1288 | |
1289 static void | |
1290 LocateAuxPopup(ocw) | |
1291 OffTheSpotConversionWidget ocw; | |
1292 { | |
1293 Position x, y; | |
1294 DisplayLocation lastp; | |
1295 Dimension dpyWidth, dpyHeight; | |
1296 Widget canvas = ocw->offthespot.canvaswidget; | |
1297 Widget panel = ocw->offthespot.auxwidget; | |
1298 Widget shell = ocw->offthespot.auxshell; | |
1299 int clx, cly; | |
1300 Window junk; | |
1301 int barheight = ocw->ccontrol.titlebarheight; | |
1302 | |
1303 if (ocw->offthespot.numsegments > 0) { | |
1304 computeLastPosition(ocw->offthespot.dispsegments[ocw->offthespot.numsegments - 1].fragments, &lastp); | |
1305 } else { | |
1306 lastp.y = 0; | |
1307 } | |
1308 lastp.x = canvas->core.width / 2; | |
1309 lastp.y += ocw->offthespot.lineheight; | |
1310 (void)XTranslateCoordinates(XtDisplay(canvas), XtWindow(canvas), | |
1311 RootWindowOfScreen(XtScreen(canvas)), | |
1312 0, 0, &clx, &cly, &junk); | |
1313 | |
1314 x = clx + lastp.x - panel->core.width / 2; | |
1315 y = cly + lastp.y + 8; /* XXX */ | |
1316 | |
1317 dpyWidth = WidthOfScreen(XtScreen(canvas)); | |
1318 dpyHeight = HeightOfScreen(XtScreen(canvas)); | |
1319 | |
1320 if (x + panel->core.width > dpyWidth) x = dpyWidth - panel->core.width; | |
1321 if (x < 0) x = 0; | |
1322 if (y + panel->core.height + barheight > dpyHeight) { | |
1323 y = cly - panel->core.height - 8 - barheight; | |
1324 if (y < 0) y = dpyHeight - panel->core.height - barheight; | |
1325 } | |
1326 MoveShell(shell, x, y); | |
1327 } | |
1328 | |
1329 | |
1330 /* | |
1331 *+ TextCanvas callback | |
1332 */ | |
1333 | |
1334 /*- TextRedisplay: redraw text canvas -*/ | |
1335 static void | |
1336 TextRedisplay(w, client_data, call_data) | |
1337 Widget w; | |
1338 XtPointer client_data; | |
1339 XtPointer call_data; | |
1340 { | |
1341 OffTheSpotConversionWidget ocw = (OffTheSpotConversionWidget)client_data; | |
1342 XExposeEvent *event = (XExposeEvent *)call_data; | |
1343 XRectangle region; | |
1344 Boolean cursorredraw; | |
1345 | |
1346 TRACE(("OffTheSpotConversion:TextRedisplay()\n")); | |
1347 region.x = event->x; | |
1348 region.y = event->y; | |
1349 region.width = event->width; | |
1350 region.height = event->height; | |
1351 | |
1352 cursorredraw = exposeCursor(ocw, w, ®ion); | |
1353 redrawSegments(ocw, ®ion); | |
1354 if (cursorredraw) showCursor(ocw); | |
1355 } | |
1356 | |
1357 /*- TextResize: do reconfiguration (and redraw) of text canvas when resized -*/ | |
1358 /* ARGSUSED */ | |
1359 static void | |
1360 TextResize(w, client_data, call_data) | |
1361 Widget w; | |
1362 XtPointer client_data; | |
1363 XtPointer call_data; /* unused */ | |
1364 { | |
1365 OffTheSpotConversionWidget ocw = (OffTheSpotConversionWidget)client_data; | |
1366 | |
1367 TRACE(("OffTheSpotConversion:TextResize()\n")); | |
1368 recomputeDisplaySegments(ocw); | |
1369 computeCursor(ocw); | |
1370 if (XtIsRealized(w)) { | |
1371 /* redraw it */ | |
1372 XClearArea(XtDisplay(w), XtWindow(w), 0, 0, 0, 0, True); | |
1373 } | |
1374 } | |
1375 | |
1376 | |
1377 /* | |
1378 *+ Selection Widget callback | |
1379 */ | |
1380 | |
1381 /*- SelectionSelected: selection selected callback -*/ | |
1382 /* ARGSUSED */ | |
1383 static void | |
1384 SelectionSelected(w, client_data, call_data) | |
1385 Widget w; | |
1386 XtPointer client_data; | |
1387 XtPointer call_data; | |
1388 { | |
1389 OffTheSpotConversionWidget ocw = (OffTheSpotConversionWidget)client_data; | |
1390 int current = (int)call_data; | |
1391 | |
1392 TRACE(("OffTheSpotConversion:SelectionSelected()\n")); | |
1393 XtPopdown(ocw->offthespot.selectionshell); | |
1394 ocw->offthespot.selectionpoppedup = False; | |
1395 ICSelectItem(ocw->ccontrol.inputobj, current); | |
1396 } | |
1397 | |
1398 | |
1399 /* | |
1400 *+ text drawing functions | |
1401 */ | |
1402 | |
1403 /*- computeDisplaySegments: compare old&new text and update segments/fragments -*/ | |
1404 static void | |
1405 computeDisplaySegments(ocw) | |
1406 OffTheSpotConversionWidget ocw; | |
1407 { | |
1408 Widget inputobj = ocw->ccontrol.inputobj; | |
1409 Cardinal nnew = ICNumSegments(inputobj); | |
1410 Cardinal nold = ocw->offthespot.numsegments; | |
1411 ICString *newseg; | |
1412 DisplaySegment *dseg; | |
1413 DisplayLocation disploc; | |
1414 Cardinal nsame; | |
1415 int diff; | |
1416 Cardinal i; | |
1417 | |
1418 TRACE(("OffTheSpotConversion:computeDisplaySegments() nnew=%d\n", nnew)); | |
1419 allocDisplaySegments(ocw, nnew); | |
1420 | |
1421 initialLocation(ocw, &disploc); | |
1422 | |
1423 for (i = 0, dseg = ocw->offthespot.dispsegments; i < nnew; i++, dseg++) { | |
1424 newseg = ICGetSegment(ocw->ccontrol.inputobj, i); | |
1425 if (i >= nold) { | |
1426 copyString(newseg, &dseg->seg); | |
1427 dseg->redrawpos = 0; | |
1428 dseg->fragments = computeDisplayFragments(ocw, newseg, &disploc); | |
1429 } else { | |
1430 DisplayFragment *oldfragments, *newfragments; | |
1431 | |
1432 dseg->redrawpos = -1; | |
1433 diff = ICCompareSegment(inputobj, newseg, &dseg->seg, &nsame); | |
1434 if (diff != ICSame || | |
1435 disploc.x != dseg->fragments->region.x || | |
1436 disploc.y != dseg->fragments->region.y) { | |
1437 oldfragments = dseg->fragments; | |
1438 newfragments = computeDisplayFragments(ocw, newseg, &disploc); | |
1439 dseg->fragments = newfragments; | |
1440 } else { | |
1441 oldfragments = NULL; | |
1442 newfragments = dseg->fragments; | |
1443 computeLastPosition(newfragments, &disploc); | |
1444 } | |
1445 | |
1446 switch (diff) { | |
1447 case ICSame: | |
1448 if (oldfragments == NULL || | |
1449 oldfragments->region.x == newfragments->region.x && | |
1450 oldfragments->region.y == newfragments->region.y) { | |
1451 dseg->redrawpos = -1; | |
1452 } else { | |
1453 dseg->redrawpos = 0; | |
1454 } | |
1455 break; | |
1456 case ICAttrChanged: | |
1457 dseg->redrawpos = 0; | |
1458 dseg->seg.attr = newseg->attr; | |
1459 break; | |
1460 case ICStringChanged: | |
1461 if (oldfragments == NULL || | |
1462 oldfragments->region.x == newfragments->region.x && | |
1463 oldfragments->region.y == newfragments->region.y) { | |
1464 dseg->redrawpos = nsame; | |
1465 } else { | |
1466 dseg->redrawpos = 0; | |
1467 } | |
1468 freeString(&dseg->seg); | |
1469 copyString(newseg, &dseg->seg); | |
1470 break; | |
1471 default: | |
1472 dseg->redrawpos = 0; | |
1473 freeString(&dseg->seg); | |
1474 copyString(newseg, &dseg->seg); | |
1475 break; | |
1476 } | |
1477 if (oldfragments) freeDisplayFragments(oldfragments); | |
1478 } | |
1479 } | |
1480 | |
1481 for (; i < nold; i++, dseg++) freeDisplaySegment(dseg); | |
1482 | |
1483 ocw->offthespot.numsegments = nnew; | |
1484 } | |
1485 | |
1486 /*- recomputeDisplaySegments: recompute segments/fragments -*/ | |
1487 static void | |
1488 recomputeDisplaySegments(ocw) | |
1489 OffTheSpotConversionWidget ocw; | |
1490 { | |
1491 Cardinal nsegs = ocw->offthespot.numsegments; | |
1492 DisplaySegment *dseg; | |
1493 DisplayLocation disploc; | |
1494 Cardinal i; | |
1495 | |
1496 initialLocation(ocw, &disploc); | |
1497 | |
1498 for (i = 0, dseg = ocw->offthespot.dispsegments; i < nsegs; i++, dseg++) { | |
1499 freeDisplayFragments(dseg->fragments); | |
1500 dseg->redrawpos = 0; | |
1501 dseg->fragments = computeDisplayFragments(ocw, &dseg->seg, &disploc); | |
1502 } | |
1503 } | |
1504 | |
1505 /*- computeLastPosition: get last position of the specified fragment list -*/ | |
1506 static void | |
1507 computeLastPosition(fragments, disploc) | |
1508 DisplayFragment *fragments; | |
1509 DisplayLocation *disploc; | |
1510 { | |
1511 while (fragments->next != NULL) fragments = fragments->next; | |
1512 disploc->x = fragments->region.x + fragments->region.width; | |
1513 disploc->y = fragments->region.y; | |
1514 } | |
1515 | |
1516 /*- computeDisplayFragments: compute fragment(s) of the specified segment -*/ | |
1517 static DisplayFragment * | |
1518 computeDisplayFragments(ocw, newseg, disploc) | |
1519 OffTheSpotConversionWidget ocw; | |
1520 ICString *newseg; | |
1521 DisplayLocation *disploc; | |
1522 { | |
1523 int start; | |
1524 int nchars; | |
1525 Widget dispobj = ocw->offthespot.displayobj; | |
1526 DisplayFragment *fragments, *dfp; | |
1527 int widthavailable; | |
1528 | |
1529 TRACE(("computeDisplayFragments()\n")); | |
1530 start = 0; | |
1531 fragments = NULL; | |
1532 while (start < newseg->nchars) { | |
1533 widthavailable = widthAvailable(ocw, disploc); | |
1534 nchars = CDMaxChar(dispobj, newseg, start, widthavailable); | |
1535 if (nchars == 0 && disploc->x <= ocw->offthespot.leftmargin) { | |
1536 /* | |
1537 * avoiding infinite loop | |
1538 * we display at least one character per line | |
1539 */ | |
1540 nchars = 1; | |
1541 } | |
1542 TRACE(("\twidthavailable=%d, start=%d, maxchar=%d\n", widthavailable, start, nchars)); | |
1543 if (nchars > 0) { | |
1544 if (fragments == NULL) { | |
1545 fragments = dfp = allocDisplayFragment(); | |
1546 } else { | |
1547 dfp->next = allocDisplayFragment(); | |
1548 dfp = dfp->next; | |
1549 } | |
1550 dfp->from = start; | |
1551 dfp->nchars = nchars; | |
1552 dfp->region.x = disploc->x; | |
1553 dfp->region.y = disploc->y; | |
1554 dfp->region.width = CDStringWidth(dispobj, newseg, start, | |
1555 start + nchars); | |
1556 dfp->region.height = ocw->offthespot.lineheight; | |
1557 dfp->next = NULL; | |
1558 | |
1559 disploc->x += dfp->region.width; | |
1560 } | |
1561 start += nchars; | |
1562 | |
1563 if (start < newseg->nchars) nextLocation(ocw, disploc); | |
1564 } | |
1565 | |
1566 return fragments; | |
1567 } | |
1568 | |
1569 /*- widthAvailable: return the width of the current line left for drawing -*/ | |
1570 static int | |
1571 widthAvailable(ocw, disploc) | |
1572 OffTheSpotConversionWidget ocw; | |
1573 DisplayLocation *disploc; | |
1574 { | |
1575 return ocw->offthespot.canvaswidget->core.width - | |
1576 ocw->offthespot.rightmargin - disploc->x; | |
1577 } | |
1578 | |
1579 /*- initialLocation: return the initial text drawing position -*/ | |
1580 static void | |
1581 initialLocation(ocw, disploc) | |
1582 OffTheSpotConversionWidget ocw; | |
1583 DisplayLocation *disploc; | |
1584 { | |
1585 int cheight = ocw->offthespot.canvaswidget->core.height; | |
1586 int lheight = ocw->offthespot.lineheight; | |
1587 | |
1588 disploc->x = ocw->offthespot.leftmargin; | |
1589 if (cheight / lheight == 1) { | |
1590 /* if there's space for a single line, locate it in the center */ | |
1591 disploc->y = (cheight - lheight) / 2; | |
1592 } else { | |
1593 disploc->y = 0; | |
1594 } | |
1595 } | |
1596 | |
1597 /*- nextLocation: return the position of the next line -*/ | |
1598 static void | |
1599 nextLocation(ocw, disploc) | |
1600 OffTheSpotConversionWidget ocw; | |
1601 DisplayLocation *disploc; | |
1602 { | |
1603 disploc->x = ocw->offthespot.leftmargin; | |
1604 disploc->y += ocw->offthespot.lineheight; | |
1605 } | |
1606 | |
1607 /*- findLocation: compute the display position of specific character -*/ | |
1608 static DisplayLocation * | |
1609 findLocation(ocw, dsp, offset, disploc) | |
1610 OffTheSpotConversionWidget ocw; | |
1611 DisplaySegment *dsp; | |
1612 Cardinal offset; | |
1613 DisplayLocation *disploc; | |
1614 { | |
1615 DisplayFragment *dfp = dsp->fragments; | |
1616 | |
1617 while (dfp != NULL) { | |
1618 if (dfp->nchars > offset || | |
1619 dfp->next == NULL && dfp->nchars == offset) { | |
1620 break; | |
1621 } | |
1622 offset -= dfp->nchars; | |
1623 dfp = dfp->next; | |
1624 } | |
1625 if (dfp == NULL) return NULL; | |
1626 | |
1627 disploc->x = dfp->region.x + CDStringWidth(ocw->offthespot.displayobj, | |
1628 &dsp->seg, dfp->from, | |
1629 dfp->from + offset); | |
1630 disploc->y = dfp->region.y; | |
1631 | |
1632 return disploc; | |
1633 } | |
1634 | |
1635 /*- reconfigureDisplay: do reconfiguration of text canvas (resize/popup/popdown) -*/ | |
1636 static void | |
1637 reconfigureDisplay(ocw) | |
1638 OffTheSpotConversionWidget ocw; | |
1639 { | |
1640 DisplaySegment *dsp; | |
1641 DisplayFragment *dfp; | |
1642 Widget canvas = ocw->offthespot.canvaswidget; | |
1643 Position lastx, lasty; | |
1644 Dimension height = ocw->offthespot.lineheight; | |
1645 int i; | |
1646 | |
1647 lastx = 0; | |
1648 dsp = ocw->offthespot.dispsegments; | |
1649 if (ocw->offthespot.numsegments > 0 && dsp->fragments != NULL) { | |
1650 lasty = dsp->fragments->region.y; | |
1651 } else { | |
1652 lasty = 0; | |
1653 } | |
1654 for (i = 0, dsp = ocw->offthespot.dispsegments; i < ocw->offthespot.numsegments; i++, dsp++) { | |
1655 for (dfp = dsp->fragments; dfp != NULL; dfp = dfp->next) { | |
1656 if (lasty != dfp->region.y) { | |
1657 XClearArea(XtDisplay(canvas), XtWindow(canvas), | |
1658 lastx, lasty, 0, height, False); | |
1659 } | |
1660 lastx = dfp->region.x + dfp->region.width; | |
1661 lasty = dfp->region.y; | |
1662 } | |
1663 } | |
1664 | |
1665 XClearArea(XtDisplay(canvas), XtWindow(canvas), | |
1666 lastx, lasty, 0, 0, False); | |
1667 if (lasty + height < canvas->core.height) { | |
1668 XClearArea(XtDisplay(canvas), XtWindow(canvas), | |
1669 0, lasty + height, 0, 0, False); | |
1670 } | |
1671 } | |
1672 | |
1673 /*- updateDisplay: redraw text (if needed) -*/ | |
1674 static void | |
1675 updateDisplay(ocw) | |
1676 OffTheSpotConversionWidget ocw; | |
1677 { | |
1678 DisplaySegment *dsp = ocw->offthespot.dispsegments; | |
1679 int i; | |
1680 | |
1681 for (i = 0; i < ocw->offthespot.numsegments; i++, dsp++) { | |
1682 if (dsp->redrawpos >= 0) { | |
1683 TRACE(("updateDisplaySegment(seg#=%d)\n", i)); | |
1684 updateDisplaySegment(ocw, dsp); | |
1685 } | |
1686 } | |
1687 } | |
1688 | |
1689 /*- updateDisplaySegment: redraw specified segment (if needed) -*/ | |
1690 static void | |
1691 updateDisplaySegment(ocw, dsp) | |
1692 OffTheSpotConversionWidget ocw; | |
1693 DisplaySegment *dsp; | |
1694 { | |
1695 DisplayFragment *dfp = dsp->fragments; | |
1696 Widget dispobj = ocw->offthespot.displayobj; | |
1697 Widget canvas = ocw->offthespot.canvaswidget; | |
1698 int from; | |
1699 int x; | |
1700 | |
1701 while (dfp != NULL) { | |
1702 if (dsp->redrawpos < dfp->from + dfp->nchars) { | |
1703 from = (dsp->redrawpos > dfp->from) ? dsp->redrawpos : dfp->from; | |
1704 x = dfp->region.x; | |
1705 if (from > dfp->from) { | |
1706 x += CDStringWidth(dispobj, &dsp->seg, dfp->from, from); | |
1707 } | |
1708 CDDrawString(dispobj, canvas, &dsp->seg, | |
1709 from, dfp->from + dfp->nchars, | |
1710 x, dfp->region.y); | |
1711 } | |
1712 dfp = dfp->next; | |
1713 } | |
1714 } | |
1715 | |
1716 /*- redrawSegments: redraw segments in specified area -*/ | |
1717 static void | |
1718 redrawSegments(ocw, region) | |
1719 OffTheSpotConversionWidget ocw; | |
1720 XRectangle *region; | |
1721 { | |
1722 DisplaySegment *dsp = ocw->offthespot.dispsegments; | |
1723 DisplayFragment *dfp; | |
1724 Widget dispobj = ocw->offthespot.displayobj; | |
1725 Widget canvas = ocw->offthespot.canvaswidget; | |
1726 int i; | |
1727 | |
1728 for (i = 0; i < ocw->offthespot.numsegments; i++, dsp++) { | |
1729 for (dfp = dsp->fragments; dfp != NULL; dfp = dfp->next) { | |
1730 if (intersectRect(&dfp->region, region)) { | |
1731 CDDrawString(dispobj, canvas, &dsp->seg, | |
1732 dfp->from, dfp->from + dfp->nchars, | |
1733 dfp->region.x, dfp->region.y); | |
1734 } | |
1735 } | |
1736 } | |
1737 } | |
1738 | |
1739 /* | |
1740 *+ insert cursor handling | |
1741 */ | |
1742 | |
1743 /*- eraseCursor: erase insert cursor -*/ | |
1744 static void | |
1745 eraseCursor(ocw) | |
1746 OffTheSpotConversionWidget ocw; | |
1747 { | |
1748 if (!ocw->offthespot.cursorvisible) return; | |
1749 | |
1750 TRACE(("eraseCursor() at (%d,%d)\n", | |
1751 ocw->offthespot.cursorlocation.x, | |
1752 ocw->offthespot.cursorlocation.y)); | |
1753 CDDrawCursor(ocw->offthespot.displayobj, | |
1754 ocw->offthespot.canvaswidget, | |
1755 ocw->offthespot.cursorlocation.x, | |
1756 ocw->offthespot.cursorlocation.y, | |
1757 False); | |
1758 ocw->offthespot.cursorvisible = False; | |
1759 } | |
1760 | |
1761 /*- showCursor: draw insert cursor -*/ | |
1762 static void | |
1763 showCursor(ocw) | |
1764 OffTheSpotConversionWidget ocw; | |
1765 { | |
1766 if (!ocw->offthespot.cursorvisible) return; | |
1767 | |
1768 TRACE(("showCursor at (%d,%d)\n", | |
1769 ocw->offthespot.cursorlocation.x, | |
1770 ocw->offthespot.cursorlocation.y)); | |
1771 CDDrawCursor(ocw->offthespot.displayobj, | |
1772 ocw->offthespot.canvaswidget, | |
1773 ocw->offthespot.cursorlocation.x, | |
1774 ocw->offthespot.cursorlocation.y, | |
1775 True); | |
1776 } | |
1777 | |
1778 /*- exposeCursor: make the insert cursor redraw correctly when exposing -*/ | |
1779 static Boolean | |
1780 exposeCursor(ocw, w, region) | |
1781 OffTheSpotConversionWidget ocw; | |
1782 Widget w; | |
1783 XRectangle *region; | |
1784 { | |
1785 XRectangle bounds; | |
1786 | |
1787 if (!ocw->offthespot.cursorvisible) return False; | |
1788 | |
1789 TRACE(("exposeCursor(region=%d,%d-%d,%d)\n", | |
1790 region->x, region->y, region->width, region->height)); | |
1791 CDGetCursorBounds(ocw->offthespot.displayobj, &bounds); | |
1792 bounds.x += ocw->offthespot.cursorlocation.x; | |
1793 bounds.y += ocw->offthespot.cursorlocation.y; | |
1794 if (intersectRect(region, &bounds)) { | |
1795 eraseCursor(ocw); | |
1796 XClearArea(XtDisplay(w), XtWindow(w), | |
1797 bounds.x, bounds.y, bounds.width, bounds.height, False); | |
1798 unionRect(region, &bounds, region); | |
1799 } | |
1800 ocw->offthespot.cursorvisible = True; | |
1801 return True; | |
1802 } | |
1803 | |
1804 /*- computeCursor: compute cursor position -*/ | |
1805 static void | |
1806 computeCursor(ocw) | |
1807 OffTheSpotConversionWidget ocw; | |
1808 { | |
1809 DisplaySegment *dsp; | |
1810 DisplayLocation disploc; | |
1811 Cardinal seg, offset; | |
1812 | |
1813 if (ocw->offthespot.numsegments == 0) { | |
1814 /* special case */ | |
1815 initialLocation(ocw, &(ocw->offthespot.cursorlocation)); | |
1816 ocw->offthespot.cursorlocation.y += ocw->offthespot.ascent; | |
1817 ocw->offthespot.cursorvisible = True; | |
1818 return; | |
1819 } | |
1820 | |
1821 if (!ICCursorPos(ocw->ccontrol.inputobj, &seg, &offset)) return; | |
1822 | |
1823 /* sanity check */ | |
1824 if (seg >= ocw->offthespot.numsegments) return; | |
1825 dsp = ocw->offthespot.dispsegments + seg; | |
1826 if (offset > dsp->seg.nchars) return; | |
1827 | |
1828 if (findLocation(ocw, dsp, offset, &disploc) == NULL) return; | |
1829 | |
1830 disploc.y += ocw->offthespot.ascent; | |
1831 | |
1832 ocw->offthespot.cursorvisible = True; | |
1833 ocw->offthespot.cursorlocation = disploc; | |
1834 } | |
1835 | |
1836 /* | |
1837 *+ miscelaneous functions | |
1838 */ | |
1839 | |
1840 /*- MoveShell: move shell widget -*/ | |
1841 static void | |
1842 MoveShell(w, x, y) | |
1843 Widget w; | |
1844 Position x; | |
1845 Position y; | |
1846 { | |
1847 XtWidgetGeometry req; | |
1848 | |
1849 /* | |
1850 * calling XtMoveWidget() is NOT enough to move shell widgets. | |
1851 * we must use XtMakeGeometryRequest() or XtSetValues() to | |
1852 * invoke root-geometry-manager which modifies the size hint | |
1853 * appropriately. | |
1854 */ | |
1855 req.request_mode = CWX | CWY; | |
1856 req.x = x; | |
1857 req.y = y; | |
1858 (void)XtMakeGeometryRequest(w, &req, (XtWidgetGeometry *)NULL); | |
1859 } | |
1860 | |
1861 /*- getToplevelWindow: get top-level window of a given window -*/ | |
1862 static Window | |
1863 getToplevelWindow(dpy, win) | |
1864 Display *dpy; | |
1865 Window win; | |
1866 { | |
1867 Atom wm_state; | |
1868 Atom type; | |
1869 int format; | |
1870 unsigned long nitems, bytesafter; | |
1871 unsigned char *data; | |
1872 Window root, parent; | |
1873 Window *children; | |
1874 unsigned int nchildren; | |
1875 | |
1876 /* | |
1877 * find toplevel window which has WM_STATE property or if no exists, | |
1878 * direct subwindow of the root window. (ie I assume that if a | |
1879 * window manager is running, that is a ICCCM compliant one) | |
1880 */ | |
1881 wm_state = CachedInternAtom(dpy, "WM_STATE", True); | |
1882 for (;;) { | |
1883 type = None; | |
1884 if (wm_state != None) { | |
1885 data = NULL; | |
1886 XGetWindowProperty(dpy, win, wm_state, 0L, 0L, False, | |
1887 AnyPropertyType, &type, &format, | |
1888 &nitems, &bytesafter, &data); | |
1889 if (data != NULL) XtFree((char *)data); | |
1890 if (type != None) break; | |
1891 } | |
1892 if (!XQueryTree(dpy, win, &root, &parent, &children, &nchildren)) break; | |
1893 if (nchildren > 0) XtFree((char *)children); | |
1894 if (root == parent) break; | |
1895 win = parent; | |
1896 } | |
1897 return win; | |
1898 } | |
1899 | |
1900 /*- setTransientFor: set WM_TRANSIENT_FOR property to specified widget -*/ | |
1901 static void | |
1902 setTransientFor(w, win) | |
1903 Widget w; | |
1904 Window win; | |
1905 { | |
1906 if (!XtIsRealized(w)) XtRealizeWidget(w); | |
1907 XSetTransientForHint(XtDisplay(w), XtWindow(w), win); | |
1908 } | |
1909 | |
1910 /*- intersectRect: return whether given two rectangles have a intersection -*/ | |
1911 static Boolean | |
1912 intersectRect(rect1, rect2) | |
1913 register XRectangle *rect1; | |
1914 register XRectangle *rect2; | |
1915 { | |
1916 return (rect1->x + rect1->width <= rect2->x || | |
1917 rect1->x >= rect2->x + rect2->width || | |
1918 rect1->y + rect1->height <= rect2->y || | |
1919 rect1->y >= rect2->y + rect2->height) ? False : True; | |
1920 } | |
1921 | |
1922 /*- unionRect: returns a minimum rectangle that covers given two rectangles -*/ | |
1923 static void | |
1924 unionRect(rect1, rect2, rect_ret) | |
1925 register XRectangle *rect1; | |
1926 register XRectangle *rect2; | |
1927 XRectangle *rect_ret; | |
1928 { | |
1929 int x0, x1, y0, y1; | |
1930 | |
1931 x0 = (rect1->x > rect2->x) ? rect2->x : rect1->x; | |
1932 y0 = (rect1->y > rect2->y) ? rect2->y : rect1->y; | |
1933 x1 = (rect1->x + rect1->width > rect2->x + rect2->width) ? | |
1934 rect1->x + rect1->width : rect2->x + rect2->width; | |
1935 y1 = (rect1->y + rect1->height > rect2->y + rect2->height) ? | |
1936 rect1->y + rect1->height : rect2->y + rect2->height; | |
1937 | |
1938 rect_ret->x = x0; | |
1939 rect_ret->y = y0; | |
1940 rect_ret->width = x1 - x0; | |
1941 rect_ret->height = y1 - y0; | |
1942 } | |
1943 | |
1944 static DisplayFragment *free_fragments = NULL; | |
1945 | |
1946 /*- allocDisplayFragment: get a new fragment -*/ | |
1947 static DisplayFragment * | |
1948 allocDisplayFragment() | |
1949 { | |
1950 if (free_fragments == NULL) { | |
1951 return XtNew(DisplayFragment); | |
1952 } else { | |
1953 DisplayFragment *dfp = free_fragments; | |
1954 free_fragments = dfp->next; | |
1955 return dfp; | |
1956 } | |
1957 } | |
1958 | |
1959 /*- freeDisplayFragments: add specified fragment list to the free-list -*/ | |
1960 static void | |
1961 freeDisplayFragments(fragments) | |
1962 DisplayFragment *fragments; | |
1963 { | |
1964 DisplayFragment *dfp = fragments; | |
1965 | |
1966 if (dfp == NULL) return; | |
1967 while (dfp->next != NULL) dfp = dfp->next; | |
1968 dfp->next = free_fragments; | |
1969 free_fragments = fragments; | |
1970 } | |
1971 | |
1972 /*- destroyDisplayFragments: do 'free()' specified fragment list -*/ | |
1973 static void | |
1974 destroyDisplayFragments(fragments) | |
1975 DisplayFragment *fragments; | |
1976 { | |
1977 DisplayFragment *dfp; | |
1978 | |
1979 while (fragments != NULL) { | |
1980 dfp = fragments->next; | |
1981 XtFree((char *)fragments); | |
1982 fragments = dfp; | |
1983 } | |
1984 } | |
1985 | |
1986 /*- allocDisplaySegments: prepare specified number of display segments -*/ | |
1987 static void | |
1988 allocDisplaySegments(ocw, n) | |
1989 OffTheSpotConversionWidget ocw; | |
1990 Cardinal n; | |
1991 { | |
1992 if (ocw->offthespot.dispsegmentsize > n) return; | |
1993 n = ((n + 3) / 4) * 4 ; | |
1994 if (ocw->offthespot.dispsegments == NULL) { | |
1995 ocw->offthespot.dispsegments = (DisplaySegment *)XtMalloc(n * sizeof(DisplaySegment)); | |
1996 } else { | |
1997 ocw->offthespot.dispsegments = (DisplaySegment *)XtRealloc((char *)ocw->offthespot.dispsegments, n * sizeof(DisplaySegment)); | |
1998 } | |
1999 ocw->offthespot.dispsegmentsize = n; | |
2000 } | |
2001 | |
2002 /*- freeDisplaySegment: free display segment's contents -*/ | |
2003 static void | |
2004 freeDisplaySegment(dsp) | |
2005 DisplaySegment *dsp; | |
2006 { | |
2007 freeString(&dsp->seg); | |
2008 freeDisplayFragments(dsp->fragments); | |
2009 dsp->fragments = NULL; | |
2010 } | |
2011 | |
2012 /*- clearAllDisplaySegments: clear all display segment's -*/ | |
2013 static void | |
2014 clearAllDisplaySegments(ocw) | |
2015 OffTheSpotConversionWidget ocw; | |
2016 { | |
2017 DisplaySegment *dsp = ocw->offthespot.dispsegments; | |
2018 int i; | |
2019 | |
2020 for (i = 0; i < ocw->offthespot.numsegments; i++) { | |
2021 freeDisplaySegment(dsp++); | |
2022 } | |
2023 ocw->offthespot.numsegments = 0; | |
2024 } | |
2025 | |
2026 /*- copyString: copy ICString -*/ | |
2027 static void | |
2028 copyString(from, to) | |
2029 ICString *from; | |
2030 ICString *to; | |
2031 { | |
2032 *to = *from; | |
2033 to->data = XtMalloc(to->nbytes); | |
2034 (void)bcopy(from->data, to->data, to->nbytes); | |
2035 } | |
2036 | |
2037 /*- freeString: free ICString -*/ | |
2038 static void | |
2039 freeString(seg) | |
2040 ICString *seg; | |
2041 { | |
2042 XtFree(seg->data); | |
2043 seg->data = NULL; | |
2044 seg->nbytes = 0; | |
2045 } |