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, &region);
1353 redrawSegments(ocw, &region);
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 }