Mercurial > kinput2.yaz
comparison lib/OnConv.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: OnConv.c,v 10.9 1999/05/19 08:52:42 ishisone Exp $"; | |
3 #endif | |
4 /* | |
5 * Copyright (c) 1990 Software Research Associates, Inc. | |
6 * Copyright (c) 1999 Kazuki YASUMATSU | |
7 * | |
8 * Permission to use, copy, modify, and distribute this software and its | |
9 * documentation for any purpose and without fee is hereby granted, provided | |
10 * that the above copyright notice appear in all copies and that both that | |
11 * copyright notice and this permission notice appear in supporting | |
12 * documentation, and that the name of Software Research Associates not be | |
13 * used in advertising or publicity pertaining to distribution of the | |
14 * software without specific, written prior permission. Software Research | |
15 * Associates makes no representations about the suitability of this software | |
16 * for any purpose. It is provided "as is" without express or implied | |
17 * warranty. | |
18 * | |
19 * Author: Makoto Ishisone, Software Research Associates, Inc., Japan | |
20 * Author: Kazuki YASUMATSU (Kazuki.Yasumatsu@fujixerox.co.jp) | |
21 */ | |
22 | |
23 | |
24 #include <X11/IntrinsicP.h> | |
25 #include <X11/StringDefs.h> | |
26 #include <X11/Xmu/Atoms.h> | |
27 #if XtSpecificationRelease > 4 | |
28 #include <X11/Xfuncs.h> | |
29 #endif | |
30 #include "CachedAtom.h" | |
31 #include "AsyncErr.h" | |
32 #include "OnConvP.h" | |
33 #include "InputConv.h" | |
34 #include "ConvDisp.h" | |
35 #include "CandPanel.h" | |
36 #include "AuxPanel.h" | |
37 #include "ICLabel.h" | |
38 | |
39 #define DEBUG_VAR debug_OnTheSpotConversion | |
40 #include "DebugPrint.h" | |
41 | |
42 /*- resource table -*/ | |
43 static XtResource resources[] = { | |
44 #define offset(field) XtOffset(OnTheSpotConversionWidget, onthespot.field) | |
45 { XtNpreeditStartCallback, XtCCallback, XtRCallback, sizeof(XtCallbackList), | |
46 offset(preeditstartcallback), XtRCallback, (XtPointer)NULL }, | |
47 { XtNpreeditDoneCallback, XtCCallback, XtRCallback, sizeof(XtCallbackList), | |
48 offset(preeditdonecallback), XtRCallback, (XtPointer)NULL }, | |
49 { XtNpreeditDrawCallback, XtCCallback, XtRCallback, sizeof(XtCallbackList), | |
50 offset(preeditdrawcallback), XtRCallback, (XtPointer)NULL }, | |
51 { XtNpreeditCaretCallback, XtCCallback, XtRCallback, sizeof(XtCallbackList), | |
52 offset(preeditcaretcallback), XtRCallback, (XtPointer)NULL }, | |
53 { XtNstatusStartCallback, XtCCallback, XtRCallback, sizeof(XtCallbackList), | |
54 offset(statusstartcallback), XtRCallback, (XtPointer)NULL }, | |
55 { XtNstatusDoneCallback, XtCCallback, XtRCallback, sizeof(XtCallbackList), | |
56 offset(statusdonecallback), XtRCallback, (XtPointer)NULL }, | |
57 { XtNstatusDrawCallback, XtCCallback, XtRCallback, sizeof(XtCallbackList), | |
58 offset(statusdrawcallback), XtRCallback, (XtPointer)NULL }, | |
59 { XtNfeedbackAttributes, XtCFeedbackAttributes, | |
60 XtRFeedbackAttributes, sizeof(FeedbackAttributes), | |
61 offset(feedbackattrs), XtRString, (XtPointer)"U,,R,H" }, | |
62 #undef offset | |
63 }; | |
64 | |
65 /*- default translations -*/ | |
66 static char translations[] = "<Key>: to-inputobj()"; /* same as superclass's */ | |
67 | |
68 /*- declarations of local structures -*/ | |
69 typedef struct { | |
70 int attrs_length; | |
71 int attrs_limit; | |
72 unsigned long *attrs_buffer; | |
73 } AttributeBuffer; | |
74 | |
75 /*- declarations of static functions -*/ | |
76 static void ClassInitialize(); | |
77 static void Initialize(); | |
78 static void Destroy(); | |
79 static Boolean SetValues(); | |
80 | |
81 static void ConversionStartup(); | |
82 static void ConversionFinish(); | |
83 static void ChangeAttributes(); | |
84 static void ChangeFocus(); | |
85 | |
86 static void StringToFeedbackAttrs(); | |
87 | |
88 static Widget CreateSelectionWidget(); | |
89 | |
90 static void UpdateText(); | |
91 static void CommitText(); | |
92 static void UpdateMode(); | |
93 static void SelectionControl(); | |
94 | |
95 static void SelectionStart(); | |
96 static void LocateSelectionPopup(); | |
97 static void SelectionEnd(); | |
98 static void SelectionSet(); | |
99 static void SelectionGet(); | |
100 static void SelectionMove(); | |
101 | |
102 static Widget CreateAuxWidget(); | |
103 static void AuxControl(); | |
104 static void AuxStart(); | |
105 static void AuxEnd(); | |
106 static void AuxChange(); | |
107 static void LocateAuxPopup(); | |
108 | |
109 static void SelectionSelected(); | |
110 | |
111 static Boolean SafeGetWindowAttributes(); | |
112 static void MoveShell(); | |
113 static Window getToplevelWindow(); | |
114 static void setTransientFor(); | |
115 static void allocDisplaySegments(); | |
116 static void freeDisplaySegment(); | |
117 static void clearAllDisplaySegments(); | |
118 static void copyString(); | |
119 static void freeString(); | |
120 static AttributeBuffer *allocAttributeBuffer(); | |
121 static void destroyAttributeBuffer(); | |
122 static void addAttributeBuffer(); | |
123 static unsigned long attrToFeedback(); | |
124 static void CBPreeditStart(); | |
125 static void CBPreeditDone(); | |
126 static void CBPreeditDraw(); | |
127 static void CBPreeditCaret(); | |
128 static void CBStatusStart(); | |
129 static void CBStatusDone(); | |
130 static void CBStatusDraw(); | |
131 | |
132 /*- composite-extension rec: for enabling non-widget children -*/ | |
133 static CompositeClassExtensionRec CompositeExtension = { | |
134 /* next_extension */ NULL, | |
135 /* record_type */ NULLQUARK, | |
136 /* version */ XtCompositeExtensionVersion, | |
137 /* record_size */ sizeof(CompositeClassExtensionRec), | |
138 /* accept_objects */ True, | |
139 }; | |
140 | |
141 /*- onTheSpotConversionClass record -*/ | |
142 OnTheSpotConversionClassRec onTheSpotConversionClassRec = { | |
143 { /* core fields */ | |
144 /* superclass */ (WidgetClass)&conversionControlClassRec, | |
145 /* class_name */ "OnTheSpotConversion", | |
146 /* widget_size */ sizeof(OnTheSpotConversionRec), | |
147 /* class_initialize */ ClassInitialize, | |
148 /* class_part_initialize */ NULL, | |
149 /* class_inited */ FALSE, | |
150 /* initialize */ Initialize, | |
151 /* initialize_hook */ NULL, | |
152 /* realize */ XtInheritRealize, | |
153 /* actions */ NULL, | |
154 /* num_actions */ 0, | |
155 /* resources */ resources, | |
156 /* num_resources */ XtNumber(resources), | |
157 /* xrm_class */ NULLQUARK, | |
158 /* compress_motion */ TRUE, | |
159 /* compress_exposure */ TRUE, | |
160 /* compress_enterleave */ TRUE, | |
161 /* visible_interest */ FALSE, | |
162 /* destroy */ Destroy, | |
163 /* resize */ XtInheritResize, | |
164 /* expose */ NULL, | |
165 /* set_values */ SetValues, | |
166 /* set_values_hook */ NULL, | |
167 /* set_values_almost */ XtInheritSetValuesAlmost, | |
168 /* get_values_hook */ NULL, | |
169 /* accept_focus */ NULL, | |
170 /* version */ XtVersion, | |
171 /* callback_private */ NULL, | |
172 /* tm_table */ translations, | |
173 /* query_geometry */ XtInheritQueryGeometry, | |
174 /* display_accelerator */ XtInheritDisplayAccelerator, | |
175 /* extension */ NULL | |
176 }, | |
177 { /* composite fields */ | |
178 /* geometry_manager */ XtInheritGeometryManager, | |
179 /* change_managed */ XtInheritChangeManaged, | |
180 /* insert_child */ XtInheritInsertChild, | |
181 /* delete_child */ XtInheritDeleteChild, | |
182 /* extension */ (XtPointer)&CompositeExtension, | |
183 }, | |
184 { /* shell fields */ | |
185 /* extension */ NULL | |
186 }, | |
187 { /* wm_shell fields */ | |
188 /* extension */ NULL | |
189 }, | |
190 { /* vendor_shell fields */ | |
191 /* extension */ NULL | |
192 }, | |
193 { /* transient_shell fields */ | |
194 /* extension */ NULL | |
195 }, | |
196 { /* conversionControl fields */ | |
197 /* Startup */ ConversionStartup, | |
198 /* Finish */ ConversionFinish, | |
199 /* ChangeAttributes */ ChangeAttributes, | |
200 /* ChangeFocus */ ChangeFocus, | |
201 /* TextChange */ UpdateText, | |
202 /* Fix */ CommitText, | |
203 /* ModeChange */ UpdateMode, | |
204 /* SelectionControl */ SelectionControl, | |
205 /* AuxControl */ AuxControl, | |
206 }, | |
207 { /* onTheSpotConversion fields */ | |
208 /* empty */ 0 | |
209 }, | |
210 }; | |
211 | |
212 WidgetClass onTheSpotConversionWidgetClass = (WidgetClass)&onTheSpotConversionClassRec; | |
213 | |
214 /* | |
215 *+ Core class method | |
216 */ | |
217 | |
218 /*- ClassInitialize: class initializer -*/ | |
219 /* ARGSUSED */ | |
220 static void | |
221 ClassInitialize() | |
222 { | |
223 /* add String -> FeedbackAttributes converter */ | |
224 XtAddConverter(XtRString, XtRFeedbackAttributes, StringToFeedbackAttrs, | |
225 (XtConvertArgList)NULL, (Cardinal)0); | |
226 } | |
227 | |
228 /*- Initialize: initalize method -*/ | |
229 /* ARGSUSED */ | |
230 static void | |
231 Initialize(req, new, args, num_args) | |
232 Widget req; | |
233 Widget new; | |
234 ArgList args; | |
235 Cardinal *num_args; | |
236 { | |
237 OnTheSpotConversionWidget ocw = (OnTheSpotConversionWidget)new; | |
238 | |
239 (void)CreateSelectionWidget(ocw); | |
240 (void)CreateAuxWidget(ocw); | |
241 | |
242 ocw->onthespot.dispsegments = NULL; | |
243 ocw->onthespot.numsegments = 0; | |
244 ocw->onthespot.dispsegmentsize = 0; | |
245 ocw->onthespot.candlist = NULL; | |
246 ocw->onthespot.numcands = 0; | |
247 ocw->onthespot.selectionpoppedup = False; | |
248 ocw->onthespot.auxpoppedup = False; | |
249 ocw->onthespot.lastcaret = 0; | |
250 ocw->onthespot.fixnotify = False; | |
251 } | |
252 | |
253 /*- Destroy: destroy method -*/ | |
254 static void | |
255 Destroy(w) | |
256 Widget w; | |
257 { | |
258 OnTheSpotConversionWidget ocw = (OnTheSpotConversionWidget)w; | |
259 | |
260 /* $B%G%#%9%W%l%$%;%0%a%s%H$NNN0h$r2rJ|(B */ | |
261 if (ocw->onthespot.dispsegments) { | |
262 DisplaySegment *dsp = ocw->onthespot.dispsegments; | |
263 int i; | |
264 | |
265 for (i = 0; i < ocw->onthespot.numsegments; i++) { | |
266 freeString(&dsp[i].seg); | |
267 } | |
268 XtFree((char *)dsp); | |
269 } | |
270 } | |
271 | |
272 /*- SetValues: setvalues method -*/ | |
273 /* ARGSUSED */ | |
274 static Boolean | |
275 SetValues(cur, req, new, args, num_args) | |
276 Widget cur; | |
277 Widget req; | |
278 Widget new; | |
279 ArgList args; | |
280 Cardinal *num_args; | |
281 { | |
282 /* OnTheSpotConversionWidget ocw = (OnTheSpotConversionWidget)new; */ | |
283 return False; | |
284 } | |
285 | |
286 /* | |
287 *+ ConversionControl class method | |
288 */ | |
289 | |
290 /*- ConversionStartup: class specific conversion startup -*/ | |
291 static void | |
292 ConversionStartup(widget, valuemask, value) | |
293 Widget widget; | |
294 unsigned long valuemask; | |
295 ConversionAttributes *value; | |
296 { | |
297 OnTheSpotConversionWidget ocw = (OnTheSpotConversionWidget)widget; | |
298 Widget inputobj = ocw->ccontrol.inputobj; | |
299 Window toplevel; | |
300 | |
301 TRACE(("OnTheSpot:ConversionStartup()\n")); | |
302 | |
303 /* $BFbIt$N%P%C%U%!$r%/%j%"$9$k(B */ | |
304 clearAllDisplaySegments(ocw); | |
305 | |
306 /* WM_TRANSIENT_FOR $B%W%m%Q%F%#$r@5$7$/%;%C%H$9$k(B */ | |
307 toplevel = getToplevelWindow(XtDisplay(widget), | |
308 ocw->ccontrol.clientwindow); | |
309 setTransientFor(ocw->onthespot.selectionshell, toplevel); | |
310 setTransientFor(ocw->onthespot.auxshell, toplevel); | |
311 | |
312 /* | |
313 * OnTheSpotConvesion $B$N(B widget $B<+BN$O%]%C%W%"%C%W$5$;$J$$$,!"(B | |
314 * $B%P%C%/%(%s%I%?%$%W$N;~$K$O%/%i%$%"%s%H$,$3$N(B widget $B$N(B | |
315 * $B%&%#%s%I%&$KBP$7$F%$%Y%s%H$rAw$k$N$G(B Realize $B$@$1$7$F$*$/(B | |
316 */ | |
317 if (!XtIsRealized(widget)) { | |
318 Arg args[2]; | |
319 | |
320 XtSetArg(args[0], XtNwidth, 1); | |
321 XtSetArg(args[1], XtNheight, 1); | |
322 XtSetValues(widget, args, 2); | |
323 XtRealizeWidget(widget); | |
324 } | |
325 | |
326 ocw->onthespot.lastcaret = 0; | |
327 ocw->onthespot.fixnotify = False; | |
328 | |
329 /* $B%9%F!<%?%9$r99?7$9$k(B */ | |
330 UpdateMode(widget); | |
331 | |
332 /* $B%W%l%(%G%#%C%H$r3+;O$9$k(B */ | |
333 CBPreeditStart(widget); | |
334 } | |
335 | |
336 /*- ConversionFinish: class specific conversion finish -*/ | |
337 /* ARGSUSED */ | |
338 static void | |
339 ConversionFinish(w) | |
340 Widget w; | |
341 { | |
342 OnTheSpotConversionWidget ocw = (OnTheSpotConversionWidget)w; | |
343 Atom encoding = XA_COMPOUND_TEXT(XtDisplayOfObject(w)); | |
344 int format = 8; | |
345 | |
346 if (!ocw->onthespot.fixnotify) { | |
347 /* $B3NDj$7$F$$$J$$(B */ | |
348 DisplaySegment *dseg = ocw->onthespot.dispsegments; | |
349 int i, len = 0; | |
350 for (i = 0; i < ocw->onthespot.numsegments; i++, dseg++) { | |
351 len += dseg->seg.nchars; | |
352 } | |
353 if (len > 0) { | |
354 /* $B%W%l%(%G%#%C%H%P%C%U%!$N>C5n(B */ | |
355 unsigned long attr = 0; | |
356 CBPreeditDraw(ocw, 0, 0, len, encoding, format, 0, (XPointer)"", | |
357 0, &attr); | |
358 } | |
359 } | |
360 | |
361 /* $B%W%l%(%G%#%C%H$r=*N;$9$k(B */ | |
362 CBPreeditDone(w); | |
363 | |
364 /* $B%9%F!<%?%9$r99?7(B($B=i4|2=(B)$B$9$k(B */ | |
365 CBStatusDraw(ocw, encoding, format, 0, (XPointer)"", 0); | |
366 | |
367 if (ocw->onthespot.selectionpoppedup) { | |
368 XtPopdown(ocw->onthespot.selectionshell); | |
369 ocw->onthespot.selectionpoppedup = False; | |
370 } | |
371 if (ocw->onthespot.auxpoppedup) { | |
372 XtPopdown(ocw->onthespot.auxshell); | |
373 ocw->onthespot.auxpoppedup = False; | |
374 } | |
375 } | |
376 | |
377 /*- ChangeAttributes: class specific conversion attribute change routine -*/ | |
378 /* ARGSUSED */ | |
379 static void | |
380 ChangeAttributes(w, valuemask, value) | |
381 Widget w; | |
382 unsigned long valuemask; | |
383 ConversionAttributes *value; | |
384 { | |
385 /* do nothing */ | |
386 } | |
387 | |
388 /*- ChangeFocus: class specific conversion attribute change routine -*/ | |
389 static void | |
390 ChangeFocus(w, set) | |
391 Widget w; | |
392 int set; | |
393 { | |
394 if (set) { | |
395 UpdateMode(w); | |
396 } else { | |
397 #if 0 | |
398 /* $B%U%)!<%+%9$r<:$C$?>l9g$K$O2?$b$7$J$$(B */ | |
399 OnTheSpotConversionWidget ocw = (OnTheSpotConversionWidget)w; | |
400 Atom encoding = XA_COMPOUND_TEXT(XtDisplayOfObject(w)); | |
401 int format = 8; | |
402 | |
403 CBStatusDraw(ocw, encoding, format, 0, (XPointer)"", 0); | |
404 #endif | |
405 } | |
406 } | |
407 | |
408 /* | |
409 *+ resource converter | |
410 */ | |
411 | |
412 /*- StringToFeedbackAttrs: string to feedback attiributes converter -*/ | |
413 static void | |
414 StringToFeedbackAttrs(args, num_args, from, to) | |
415 XrmValue *args; | |
416 Cardinal *num_args; | |
417 XrmValue *from; | |
418 XrmValue *to; | |
419 { | |
420 char *s = (char *)from->addr; | |
421 int idx; | |
422 int invalid = 0; | |
423 static FeedbackAttributes fba; | |
424 | |
425 for (idx = 0; idx < 4; idx++) fba.feedbacks[idx] = 0; | |
426 | |
427 for (idx = 0; idx < 4; idx++) { | |
428 int c; | |
429 unsigned long fb = 0; | |
430 | |
431 while ((c = *s++) != ',' && c != '\0') { | |
432 switch (c) { | |
433 case 'R': case 'r': fb |= XIMReverse; break; | |
434 case 'U': case 'u': fb |= XIMUnderline; break; | |
435 case 'H': case 'h': fb |= XIMHighlight; break; | |
436 case 'P': case 'p': fb |= XIMPrimary; break; | |
437 case 'S': case 's': fb |= XIMSecondary; break; | |
438 case 'T': case 't': fb |= XIMTertiary; break; | |
439 case ' ': case '\t': | |
440 break; | |
441 default: | |
442 invalid++; | |
443 break; | |
444 } | |
445 } | |
446 fba.feedbacks[idx] = fb; | |
447 if (c == '\0') break; | |
448 } | |
449 | |
450 if (invalid) { | |
451 XtStringConversionWarning((char *)from->addr, XtRFeedbackAttributes); | |
452 } | |
453 to->size = sizeof(fba); | |
454 to->addr = (caddr_t)&fba; | |
455 } | |
456 | |
457 /* | |
458 *+ sub-widget creation | |
459 */ | |
460 | |
461 /*- CreateSelectionWidget: create selection widget for selecting candidates -*/ | |
462 static Widget | |
463 CreateSelectionWidget(ocw) | |
464 OnTheSpotConversionWidget ocw; | |
465 { | |
466 Widget shell, sel; | |
467 | |
468 /* set width/height so that XtRealizeWidget() doesn't cause error */ | |
469 shell = XtVaCreatePopupShell("selectionShell", | |
470 transientShellWidgetClass, | |
471 (Widget)ocw, | |
472 XtNwidth, 1, | |
473 XtNheight, 1, | |
474 NULL); | |
475 ocw->onthespot.selectionshell = shell; | |
476 | |
477 sel = XtCreateManagedWidget("selection", candidatePanelWidgetClass, | |
478 shell, NULL, 0); | |
479 (void)XtCreateWidget("display", ocw->ccontrol.displayobjclass, sel, | |
480 NULL, 0); | |
481 XtAddCallback(sel, XtNcallback, SelectionSelected, (XtPointer)ocw); | |
482 XtInstallAccelerators(sel, (Widget)ocw); | |
483 | |
484 ocw->onthespot.selectionwidget = sel; | |
485 | |
486 return shell; | |
487 } | |
488 | |
489 /*- CreateAuxWidget: create aux widget for display auxiliary data -*/ | |
490 static Widget | |
491 CreateAuxWidget(ocw) | |
492 OnTheSpotConversionWidget ocw; | |
493 { | |
494 Widget shell, sel; | |
495 | |
496 /* set width/height so that XtRealizeWidget() doesn't cause error */ | |
497 shell = XtVaCreatePopupShell("auxShell", | |
498 transientShellWidgetClass, | |
499 (Widget)ocw, | |
500 XtNwidth, 1, | |
501 XtNheight, 1, | |
502 XtNallowShellResize, True, | |
503 NULL); | |
504 ocw->onthespot.auxshell = shell; | |
505 | |
506 sel = XtCreateManagedWidget("aux", auxPanelWidgetClass, | |
507 shell, NULL, 0); | |
508 (void)XtCreateWidget("display", ocw->ccontrol.displayobjclass, sel, | |
509 NULL, 0); | |
510 XtAddCallback(sel, XtNcallback, SelectionSelected, (XtPointer)ocw); | |
511 XtInstallAccelerators(sel, (Widget)ocw); | |
512 | |
513 ocw->onthespot.auxwidget = sel; | |
514 | |
515 return shell; | |
516 } | |
517 | |
518 /* | |
519 *+ inputobject callback | |
520 */ | |
521 | |
522 /*- UpdateText: update text -*/ | |
523 static void | |
524 UpdateText(w) | |
525 Widget w; | |
526 { | |
527 OnTheSpotConversionWidget ocw = (OnTheSpotConversionWidget)w; | |
528 Widget inputobj = ocw->ccontrol.inputobj; | |
529 int nnew = ICNumSegments(inputobj); | |
530 int nold = ocw->onthespot.numsegments; | |
531 FeedbackAttributes *fba = &ocw->onthespot.feedbackattrs; | |
532 Cardinal cseg, caret; | |
533 ICString *newseg; | |
534 DisplaySegment *dseg; | |
535 Boolean changed; | |
536 int chgseg, chgoffset; | |
537 int oldlen; | |
538 AttributeBuffer *buffer; | |
539 int i; | |
540 int diff; | |
541 Cardinal nsame; | |
542 | |
543 TRACE(("OnTheSpotConversion:UpdateText() nnew=%d\n", nnew)); | |
544 | |
545 ocw->onthespot.fixnotify = False; | |
546 | |
547 if (!ICCursorPos(inputobj, &cseg, &caret)) { | |
548 cseg = nnew; | |
549 caret = 0; | |
550 } | |
551 | |
552 allocDisplaySegments(ocw, nnew); | |
553 | |
554 changed = False; | |
555 chgseg = chgoffset = 0; | |
556 oldlen = 0; | |
557 buffer = allocAttributeBuffer(); | |
558 for (i = 0, dseg = ocw->onthespot.dispsegments; i < nnew; i++, dseg++) { | |
559 newseg = ICGetSegment(inputobj, i); | |
560 if (i < cseg) { | |
561 caret += newseg->nchars; | |
562 } | |
563 if (i >= nold) { | |
564 copyString(newseg, &dseg->seg); | |
565 addAttributeBuffer(buffer, inputobj, newseg, 0, fba); | |
566 if (!changed) { | |
567 chgseg = i; | |
568 chgoffset = 0; | |
569 changed = True; | |
570 } | |
571 } else { | |
572 oldlen += dseg->seg.nchars; | |
573 diff = ICCompareSegment(inputobj, newseg, &dseg->seg, &nsame); | |
574 switch (diff) { | |
575 case ICSame: | |
576 if (changed) { | |
577 addAttributeBuffer(buffer, inputobj, newseg, 0, fba); | |
578 } | |
579 break; | |
580 case ICAttrChanged: | |
581 dseg->seg.attr = newseg->attr; | |
582 addAttributeBuffer(buffer, inputobj, newseg, 0, fba); | |
583 if (!changed) { | |
584 chgseg = i; | |
585 chgoffset = 0; | |
586 changed = True; | |
587 } | |
588 break; | |
589 case ICStringChanged: | |
590 freeString(&dseg->seg); | |
591 copyString(newseg, &dseg->seg); | |
592 if (!changed) { | |
593 addAttributeBuffer(buffer, inputobj, newseg, nsame, fba); | |
594 chgseg = i; | |
595 chgoffset = nsame; | |
596 changed = True; | |
597 } | |
598 else { | |
599 addAttributeBuffer(buffer, inputobj, newseg, 0, fba); | |
600 } | |
601 break; | |
602 default: /* ICAttrChanged | ICStringChanged */ | |
603 freeString(&dseg->seg); | |
604 copyString(newseg, &dseg->seg); | |
605 addAttributeBuffer(buffer, inputobj, newseg, 0, fba); | |
606 if (!changed) { | |
607 chgseg = i; | |
608 chgoffset = 0; | |
609 changed = True; | |
610 } | |
611 break; | |
612 } | |
613 } | |
614 } | |
615 | |
616 for (; i < nold; i++, dseg++) { | |
617 oldlen += dseg->seg.nchars; | |
618 if (!changed) { | |
619 chgseg = i; | |
620 chgoffset = 0; | |
621 changed = True; | |
622 } | |
623 freeDisplaySegment(dseg); | |
624 } | |
625 | |
626 ocw->onthespot.numsegments = nnew; | |
627 | |
628 if (!changed) { | |
629 if (ocw->onthespot.lastcaret != caret) { | |
630 CBPreeditCaret(ocw, caret); | |
631 } | |
632 } | |
633 else { /* changed */ | |
634 Atom encoding = ocw->ccontrol.textencoding; | |
635 int format; | |
636 int length; | |
637 XtPointer string; | |
638 | |
639 if (ICGetPreeditString(inputobj, chgseg, chgoffset, &encoding, &format, | |
640 &length, &string) == 0) { | |
641 | |
642 dseg = ocw->onthespot.dispsegments; | |
643 for (i = 0; i < chgseg; i++, dseg++) { | |
644 chgoffset += dseg->seg.nchars; | |
645 } | |
646 CBPreeditDraw(ocw, caret, chgoffset, oldlen - chgoffset, | |
647 encoding, format, length, string, | |
648 buffer->attrs_length, buffer->attrs_buffer); | |
649 | |
650 /* string $B$r(B free $B$7$F$*$/(B */ | |
651 XtFree((char *)string); | |
652 } | |
653 } | |
654 | |
655 ocw->onthespot.lastcaret = caret; | |
656 | |
657 /* buffer $B$r(B destroy $B$7$F$*$/(B */ | |
658 destroyAttributeBuffer(buffer); | |
659 } | |
660 | |
661 /*- CommitText: commit text -*/ | |
662 static void | |
663 CommitText(w, arg) | |
664 Widget w; | |
665 CCTextCallbackArg *arg; | |
666 { | |
667 OnTheSpotConversionWidget ocw = (OnTheSpotConversionWidget)w; | |
668 DisplaySegment *dseg; | |
669 int i, len; | |
670 | |
671 dseg = ocw->onthespot.dispsegments; | |
672 len = 0; | |
673 for (i = 0; i < ocw->onthespot.numsegments; i++, dseg++) { | |
674 len += dseg->seg.nchars; | |
675 } | |
676 if (len > 0) { | |
677 /* $B%W%l%(%G%#%C%H%P%C%U%!$N>C5n(B */ | |
678 Atom encoding = XA_COMPOUND_TEXT(XtDisplayOfObject(w)); | |
679 int format = 8; | |
680 unsigned long attr = 0; | |
681 CBPreeditDraw(ocw, 0, 0, len, encoding, format, 0, (XPointer)"", | |
682 0, &attr); | |
683 } | |
684 /* $BFbIt$N%P%C%U%!$r%/%j%"$9$k(B */ | |
685 clearAllDisplaySegments(ocw); | |
686 ocw->onthespot.lastcaret = 0; | |
687 | |
688 XtCallCallbackList((Widget)ocw, ocw->ccontrol.textcallback, | |
689 (XtPointer)arg); | |
690 | |
691 ocw->onthespot.fixnotify = True; | |
692 } | |
693 | |
694 /*- UpdateMode: update mode -*/ | |
695 static void | |
696 UpdateMode(w) | |
697 Widget w; | |
698 { | |
699 OnTheSpotConversionWidget ocw = (OnTheSpotConversionWidget)w; | |
700 Widget inputobj = ocw->ccontrol.inputobj; | |
701 Atom encoding = ocw->ccontrol.textencoding; | |
702 int format; | |
703 int length; | |
704 XtPointer string; | |
705 int nchars; | |
706 | |
707 TRACE(("OnTheSpotConversion:UpdateMode()\n")); | |
708 | |
709 if (ICGetStatusString(inputobj, &encoding, &format, &length, &string, | |
710 &nchars) == -1) | |
711 return; | |
712 | |
713 CBStatusDraw(ocw, encoding, format, length, string, nchars); | |
714 | |
715 /* string $B$r(B free $B$7$F$*$/(B */ | |
716 XtFree((char *)string); | |
717 } | |
718 | |
719 /*- SelectionControl: selection control -*/ | |
720 static void | |
721 SelectionControl(w, arg) | |
722 Widget w; | |
723 ICSelectionControlArg *arg; | |
724 { | |
725 OnTheSpotConversionWidget ocw = (OnTheSpotConversionWidget)w; | |
726 String params[1]; | |
727 Cardinal num_params; | |
728 | |
729 switch (arg->command) { | |
730 case ICSelectionStart: | |
731 SelectionStart(ocw, arg->u.selection_kind); | |
732 break; | |
733 case ICSelectionEnd: | |
734 SelectionEnd(ocw, &arg->u.current_item); | |
735 break; | |
736 case ICSelectionSet: | |
737 SelectionSet(ocw, arg->u.current_item); | |
738 break; | |
739 case ICSelectionMove: | |
740 SelectionMove(ocw, arg->u.dir); | |
741 break; | |
742 case ICSelectionGet: | |
743 SelectionGet(ocw, &arg->u.current_item); | |
744 break; | |
745 default: | |
746 params[0] = XtClass(w)->core_class.class_name; | |
747 num_params = 1; | |
748 XtAppWarningMsg(XtWidgetToApplicationContext(w), | |
749 "parameterError", "SelectionControl", "WidgetError", | |
750 "%s: unknown selection control command", | |
751 params, &num_params); | |
752 break; | |
753 } | |
754 } | |
755 | |
756 /*- SelectionStart: selection startup -*/ | |
757 /* ARGSUSED */ | |
758 static void | |
759 SelectionStart(ocw, kind) | |
760 OnTheSpotConversionWidget ocw; | |
761 int kind; | |
762 { | |
763 Cardinal ncand; | |
764 | |
765 TRACE(("OnTheSpotConversion:SelectionStart()\n")); | |
766 if (ocw->onthespot.selectionpoppedup) { | |
767 TRACE(("\tselection already started -- ignored\n")); | |
768 return; | |
769 } | |
770 | |
771 ocw->onthespot.candlist = ICGetItemList(ocw->ccontrol.inputobj, &ncand); | |
772 ocw->onthespot.numcands = ncand; | |
773 | |
774 TRACE(("\tnumcands=%d\n", ocw->onthespot.numcands)); | |
775 CPanelSetList(ocw->onthespot.selectionwidget, | |
776 ocw->onthespot.candlist, | |
777 ocw->onthespot.numcands, 0, True); | |
778 | |
779 LocateSelectionPopup(ocw); | |
780 XtPopup(ocw->onthespot.selectionshell, XtGrabNone); | |
781 ocw->onthespot.selectionpoppedup = True; | |
782 } | |
783 | |
784 /*- LocateSelectionPopup: put selection popup at an appropriate position -*/ | |
785 static void | |
786 LocateSelectionPopup(ocw) | |
787 OnTheSpotConversionWidget ocw; | |
788 { | |
789 Position x, y; | |
790 int clx, cly; | |
791 Dimension dpyWidth, dpyHeight; | |
792 Widget panel = ocw->onthespot.selectionwidget; | |
793 Widget shell = ocw->onthespot.selectionshell; | |
794 Window junk; | |
795 int barheight = ocw->ccontrol.titlebarheight; | |
796 | |
797 (void)XTranslateCoordinates(XtDisplay(ocw), | |
798 ocw->ccontrol.clientwindow, | |
799 RootWindowOfScreen(XtScreen(ocw)), | |
800 0, 0, &clx, &cly, &junk); | |
801 | |
802 (void)SafeGetWindowAttributes(XtDisplay(ocw), ocw->ccontrol.clientwindow, | |
803 &(ocw->ccontrol.client_attr)); | |
804 | |
805 x = clx; | |
806 y = cly + ocw->ccontrol.client_attr.height; | |
807 | |
808 dpyWidth = WidthOfScreen(XtScreen(shell)); | |
809 dpyHeight = HeightOfScreen(XtScreen(shell)); | |
810 | |
811 if (x + panel->core.width > (int)dpyWidth) x = dpyWidth - panel->core.width; | |
812 if (x < 0) x = 0; | |
813 #if 0 | |
814 if (y + panel->core.height + barheight > (int)dpyHeight) { | |
815 y = cly - panel->core.height - 8 - barheight - 20; /* XXX */ | |
816 if (y < 0) y = dpyHeight - panel->core.height - barheight; | |
817 } | |
818 #endif | |
819 if (y + panel->core.height + barheight > (int)dpyHeight) | |
820 y = dpyHeight - panel->core.height - 8 - barheight - 20; /* XXX */ | |
821 if (y < 0) y = 0; | |
822 MoveShell(shell, x, y); | |
823 } | |
824 | |
825 /*- SelectionEnd: selection finish -*/ | |
826 static void | |
827 SelectionEnd(ocw, current) | |
828 OnTheSpotConversionWidget ocw; | |
829 int *current; | |
830 { | |
831 TRACE(("OnTheSpotConversion:SelectionEnd()\n")); | |
832 | |
833 if (!ocw->onthespot.selectionpoppedup) { /* for safe */ | |
834 TRACE(("\tnot in selection mode -- ignored\n")); | |
835 return; | |
836 } | |
837 | |
838 XtVaGetValues(ocw->onthespot.selectionwidget, | |
839 XtNcurrentItem, current, | |
840 NULL); | |
841 | |
842 XtPopdown(ocw->onthespot.selectionshell); | |
843 | |
844 ocw->onthespot.selectionpoppedup = False; | |
845 } | |
846 | |
847 /*- SelectionSet: set current selection item -*/ | |
848 static void | |
849 SelectionSet(ocw, current) | |
850 OnTheSpotConversionWidget ocw; | |
851 int current; | |
852 { | |
853 TRACE(("OnTheSpotConversion:SelectionSet()\n")); | |
854 | |
855 if (!ocw->onthespot.selectionpoppedup) { /* for safe */ | |
856 TRACE(("\tnot in selection mode -- ignored\n")); | |
857 return; | |
858 } | |
859 | |
860 XtVaSetValues(ocw->onthespot.selectionwidget, | |
861 XtNcurrentItem, current, | |
862 NULL); | |
863 } | |
864 | |
865 /*- SelectionGet: get current selection item -*/ | |
866 static void | |
867 SelectionGet(ocw, current) | |
868 OnTheSpotConversionWidget ocw; | |
869 int *current; | |
870 { | |
871 TRACE(("OnTheSpotConversion:SelectionGet()\n")); | |
872 | |
873 if (!ocw->onthespot.selectionpoppedup) { /* for safe */ | |
874 TRACE(("\tnot in selection mode -- ignored\n")); | |
875 return; | |
876 } | |
877 | |
878 XtVaGetValues(ocw->onthespot.selectionwidget, | |
879 XtNcurrentItem, current, | |
880 NULL); | |
881 } | |
882 | |
883 /*- SelectionMove: move crrent selection to specified direction -*/ | |
884 static void | |
885 SelectionMove(ocw, dir) | |
886 OnTheSpotConversionWidget ocw; | |
887 int dir; | |
888 { | |
889 TRACE(("OnTheSpotConversion:SelectionMove()\n")); | |
890 | |
891 if (!ocw->onthespot.selectionpoppedup) { /* for safe */ | |
892 TRACE(("\tnot in selection mode -- ignored\n")); | |
893 return; | |
894 } | |
895 | |
896 CPanelMoveCurrent(ocw->onthespot.selectionwidget, dir); | |
897 } | |
898 | |
899 /* | |
900 * Aux Callback | |
901 */ | |
902 | |
903 static void | |
904 AuxControl(w, arg) | |
905 Widget w; | |
906 ICAuxControlArg *arg; | |
907 { | |
908 OnTheSpotConversionWidget ocw = (OnTheSpotConversionWidget)w; | |
909 String params[1]; | |
910 Cardinal num_params; | |
911 | |
912 switch (arg->command) { | |
913 case ICAuxStart: | |
914 AuxStart(ocw); | |
915 break; | |
916 case ICAuxEnd: | |
917 AuxEnd(ocw); | |
918 break; | |
919 case ICAuxChange: | |
920 AuxChange(ocw); | |
921 break; | |
922 default: | |
923 params[0] = XtClass(w)->core_class.class_name; | |
924 num_params = 1; | |
925 XtAppWarningMsg(XtWidgetToApplicationContext(w), | |
926 "parameterError", "AuxControl", "WidgetError", | |
927 "%s: unknown aux control command", | |
928 params, &num_params); | |
929 break; | |
930 } | |
931 } | |
932 | |
933 /* ARGSUSED */ | |
934 static void | |
935 AuxStart(ocw) | |
936 OnTheSpotConversionWidget ocw; | |
937 { | |
938 ICString *auxstr; | |
939 Cardinal ncand, curseg, cursorpos; | |
940 | |
941 if (ocw->onthespot.auxpoppedup) return; | |
942 | |
943 /* $B%F%-%9%H%3!<%k%P%C%/$N;~$N$h$&$J=hM}$r$9$k(B | |
944 $B$N$O(B AuxPanel.c $B$K$^$+$;$h$&(B */ | |
945 | |
946 auxstr = ICGetAuxSegments(ocw->ccontrol.inputobj, | |
947 &ncand, &curseg, &cursorpos); | |
948 | |
949 APanelStart(ocw->onthespot.auxwidget, auxstr, ncand, curseg, cursorpos); | |
950 | |
951 /* $B%]%C%W%"%C%W$9$k>l=j$r7h$a$k(B */ | |
952 LocateAuxPopup(ocw); | |
953 | |
954 XtPopup(ocw->onthespot.auxshell, XtGrabNone); | |
955 ocw->onthespot.auxpoppedup = True; | |
956 } | |
957 | |
958 /* ARGSUSED */ | |
959 static void | |
960 AuxEnd(ocw) | |
961 OnTheSpotConversionWidget ocw; | |
962 { | |
963 if (!ocw->onthespot.auxpoppedup) return; /* for safe */ | |
964 | |
965 /* APanelEnd(ocw->onthespot.auxwidget); */ | |
966 | |
967 XtPopdown(ocw->onthespot.auxshell); | |
968 | |
969 ocw->onthespot.auxpoppedup = False; | |
970 } | |
971 | |
972 /* ARGSUSED */ | |
973 static void | |
974 AuxChange(ocw) | |
975 OnTheSpotConversionWidget ocw; | |
976 { | |
977 Cardinal ncand, curseg, cursorpos; | |
978 ICString *auxstr; | |
979 | |
980 if (!ocw->onthespot.auxpoppedup) return; /* for safe */ | |
981 | |
982 auxstr = ICGetAuxSegments(ocw->ccontrol.inputobj, | |
983 &ncand, &curseg, &cursorpos); | |
984 | |
985 APanelChange(ocw->onthespot.auxwidget, auxstr, ncand, curseg, cursorpos); | |
986 } | |
987 | |
988 /*- LocateAuxPopup: put aux popup at an appropriate position -*/ | |
989 static void | |
990 LocateAuxPopup(ocw) | |
991 OnTheSpotConversionWidget ocw; | |
992 { | |
993 Position x, y; | |
994 int clx, cly; | |
995 Dimension dpyWidth, dpyHeight; | |
996 Widget panel = ocw->onthespot.auxwidget; | |
997 Widget shell = ocw->onthespot.auxshell; | |
998 Window junk; | |
999 int barheight = ocw->ccontrol.titlebarheight; | |
1000 | |
1001 (void)XTranslateCoordinates(XtDisplay(ocw), | |
1002 ocw->ccontrol.clientwindow, | |
1003 RootWindowOfScreen(XtScreen(ocw)), | |
1004 0, 0, &clx, &cly, &junk); | |
1005 | |
1006 (void)SafeGetWindowAttributes(XtDisplay(ocw), ocw->ccontrol.clientwindow, | |
1007 &(ocw->ccontrol.client_attr)); | |
1008 | |
1009 x = clx; | |
1010 y = cly + ocw->ccontrol.client_attr.height; | |
1011 | |
1012 dpyWidth = WidthOfScreen(XtScreen(shell)); | |
1013 dpyHeight = HeightOfScreen(XtScreen(shell)); | |
1014 | |
1015 if (x + panel->core.width > (int)dpyWidth) x = dpyWidth - panel->core.width; | |
1016 if (x < 0) x = 0; | |
1017 #if 0 | |
1018 if (y + panel->core.height + barheight > (int)dpyHeight) { | |
1019 y = cly - panel->core.height - 8 - barheight - 20; /* XXX */ | |
1020 if (y < 0) y = dpyHeight - panel->core.height - barheight; | |
1021 } | |
1022 #endif | |
1023 if (y + panel->core.height + barheight > (int)dpyHeight) | |
1024 y = dpyHeight - panel->core.height - 8 - barheight - 20; /* XXX */ | |
1025 if (y < 0) y = 0; | |
1026 MoveShell(shell, x, y); | |
1027 } | |
1028 | |
1029 /* | |
1030 *+ Selection Widget callback | |
1031 */ | |
1032 | |
1033 /*- SelectionSelected: selection selected callback -*/ | |
1034 /* ARGSUSED */ | |
1035 static void | |
1036 SelectionSelected(w, client_data, call_data) | |
1037 Widget w; | |
1038 XtPointer client_data; | |
1039 XtPointer call_data; | |
1040 { | |
1041 OnTheSpotConversionWidget ocw = (OnTheSpotConversionWidget)client_data; | |
1042 int current = (int)call_data; | |
1043 | |
1044 TRACE(("OnTheSpotConversion:SelectionSelected()\n")); | |
1045 XtPopdown(ocw->onthespot.selectionshell); | |
1046 ocw->onthespot.selectionpoppedup = False; | |
1047 ICSelectItem(ocw->ccontrol.inputobj, current); | |
1048 } | |
1049 | |
1050 /* | |
1051 *+ miscelaneous functions | |
1052 */ | |
1053 | |
1054 /*- SafeGetWindowAttributes: get window attributes -*/ | |
1055 static Boolean | |
1056 SafeGetWindowAttributes(dpy, w, attr) | |
1057 Display *dpy; | |
1058 Window w; | |
1059 XWindowAttributes *attr; | |
1060 { | |
1061 XAEHandle h; | |
1062 unsigned long errbits = 0; | |
1063 | |
1064 h = XAESetRecordErrors(dpy, &errbits); | |
1065 (void)XGetWindowAttributes(dpy, w, attr); | |
1066 XAEUnset(h); | |
1067 | |
1068 return (errbits == 0); | |
1069 } | |
1070 | |
1071 /*- MoveShell: move shell widget -*/ | |
1072 static void | |
1073 MoveShell(w, x, y) | |
1074 Widget w; | |
1075 Position x; | |
1076 Position y; | |
1077 { | |
1078 XtWidgetGeometry req; | |
1079 | |
1080 /* | |
1081 * calling XtMoveWidget() is NOT enough to move shell widgets. | |
1082 * we must use XtMakeGeometryRequest() or XtSetValues() to | |
1083 * invoke root-geometry-manager which modifies the size hint | |
1084 * appropriately. | |
1085 */ | |
1086 req.request_mode = CWX | CWY; | |
1087 req.x = x; | |
1088 req.y = y; | |
1089 (void)XtMakeGeometryRequest(w, &req, (XtWidgetGeometry *)NULL); | |
1090 } | |
1091 | |
1092 /*- getToplevelWindow: get top-level window of a given window -*/ | |
1093 static Window | |
1094 getToplevelWindow(dpy, win) | |
1095 Display *dpy; | |
1096 Window win; | |
1097 { | |
1098 Atom wm_state; | |
1099 Atom type; | |
1100 int format; | |
1101 unsigned long nitems, bytesafter; | |
1102 unsigned char *data; | |
1103 Window root, parent; | |
1104 Window *children; | |
1105 unsigned int nchildren; | |
1106 | |
1107 /* | |
1108 * find toplevel window which has WM_STATE property or if no exists, | |
1109 * direct subwindow of the root window. (ie I assume that if a | |
1110 * window manager is running, that is a ICCCM compliant one) | |
1111 */ | |
1112 wm_state = CachedInternAtom(dpy, "WM_STATE", True); | |
1113 for (;;) { | |
1114 type = None; | |
1115 if (wm_state != None) { | |
1116 data = NULL; | |
1117 XGetWindowProperty(dpy, win, wm_state, 0L, 0L, False, | |
1118 AnyPropertyType, &type, &format, | |
1119 &nitems, &bytesafter, &data); | |
1120 if (data != NULL) XtFree((char *)data); | |
1121 if (type != None) break; | |
1122 } | |
1123 if (!XQueryTree(dpy, win, &root, &parent, &children, &nchildren)) break; | |
1124 if (nchildren > 0) XtFree((char *)children); | |
1125 if (root == parent) break; | |
1126 win = parent; | |
1127 } | |
1128 return win; | |
1129 } | |
1130 | |
1131 /*- setTransientFor: set WM_TRANSIENT_FOR property to specified widget -*/ | |
1132 static void | |
1133 setTransientFor(w, win) | |
1134 Widget w; | |
1135 Window win; | |
1136 { | |
1137 if (!XtIsRealized(w)) XtRealizeWidget(w); | |
1138 XSetTransientForHint(XtDisplay(w), XtWindow(w), win); | |
1139 } | |
1140 | |
1141 /*- allocDisplaySegments: prepare specified number of display segments -*/ | |
1142 static void | |
1143 allocDisplaySegments(ocw, n) | |
1144 OnTheSpotConversionWidget ocw; | |
1145 Cardinal n; | |
1146 { | |
1147 if (ocw->onthespot.dispsegmentsize > n) return; | |
1148 n = ((n + 3) / 4) * 4 ; | |
1149 if (ocw->onthespot.dispsegments == NULL) { | |
1150 ocw->onthespot.dispsegments = (DisplaySegment *)XtMalloc(n * sizeof(DisplaySegment)); | |
1151 } else { | |
1152 ocw->onthespot.dispsegments = (DisplaySegment *)XtRealloc((char *)ocw->onthespot.dispsegments, n * sizeof(DisplaySegment)); | |
1153 } | |
1154 ocw->onthespot.dispsegmentsize = n; | |
1155 } | |
1156 | |
1157 /*- freeDisplaySegment: free display segment's contents -*/ | |
1158 static void | |
1159 freeDisplaySegment(dsp) | |
1160 DisplaySegment *dsp; | |
1161 { | |
1162 freeString(&dsp->seg); | |
1163 } | |
1164 | |
1165 /*- clearAllDisplaySegments: clear all display segment's -*/ | |
1166 static void | |
1167 clearAllDisplaySegments(ocw) | |
1168 OnTheSpotConversionWidget ocw; | |
1169 { | |
1170 DisplaySegment *dsp = ocw->onthespot.dispsegments; | |
1171 int i; | |
1172 | |
1173 for (i = 0; i < ocw->onthespot.numsegments; i++) { | |
1174 freeDisplaySegment(dsp++); | |
1175 } | |
1176 ocw->onthespot.numsegments = 0; | |
1177 } | |
1178 | |
1179 /*- copyString: copy ICString -*/ | |
1180 static void | |
1181 copyString(from, to) | |
1182 ICString *from; | |
1183 ICString *to; | |
1184 { | |
1185 *to = *from; | |
1186 to->data = XtMalloc(to->nbytes); | |
1187 (void)bcopy(from->data, to->data, to->nbytes); | |
1188 } | |
1189 | |
1190 /*- freeString: free ICString -*/ | |
1191 static void | |
1192 freeString(seg) | |
1193 ICString *seg; | |
1194 { | |
1195 XtFree(seg->data); | |
1196 seg->data = NULL; | |
1197 seg->nbytes = 0; | |
1198 } | |
1199 | |
1200 /*- allocAttributeBuffer: allocate attribute buffer -*/ | |
1201 static AttributeBuffer * | |
1202 allocAttributeBuffer() | |
1203 { | |
1204 AttributeBuffer *buffer; | |
1205 | |
1206 buffer = (AttributeBuffer *)XtMalloc(sizeof(AttributeBuffer)); | |
1207 buffer->attrs_length = 0; | |
1208 buffer->attrs_limit = 64; | |
1209 buffer->attrs_buffer = (unsigned long *)XtMalloc(buffer->attrs_limit * sizeof(unsigned long)); | |
1210 return buffer; | |
1211 } | |
1212 | |
1213 /*- destroyAttributeBuffer: destroy draw string buffer's contents -*/ | |
1214 static void | |
1215 destroyAttributeBuffer(buffer) | |
1216 AttributeBuffer *buffer; | |
1217 { | |
1218 XtFree((char *)buffer->attrs_buffer); | |
1219 XtFree((char *)buffer); | |
1220 } | |
1221 | |
1222 /*- addAttributeBuffer: add segment to draw string buffer's contents -*/ | |
1223 static void | |
1224 addAttributeBuffer(buffer, inputobj, seg, offset, fba) | |
1225 AttributeBuffer *buffer; | |
1226 Widget inputobj; | |
1227 ICString *seg; | |
1228 int offset; | |
1229 FeedbackAttributes *fba; | |
1230 { | |
1231 int nchars = seg->nchars - offset; | |
1232 unsigned long fb; | |
1233 int i; | |
1234 | |
1235 if (buffer->attrs_length + nchars > buffer->attrs_limit) { | |
1236 unsigned long *new_attrs_buffer; | |
1237 int new_limit = buffer->attrs_limit * 2; | |
1238 if (new_limit < buffer->attrs_length + nchars) | |
1239 new_limit = buffer->attrs_length + nchars + 8; | |
1240 new_attrs_buffer = (unsigned long *)XtMalloc(new_limit * sizeof(unsigned long)); | |
1241 bcopy(buffer->attrs_buffer, new_attrs_buffer, | |
1242 buffer->attrs_length * sizeof(unsigned long)); | |
1243 XtFree((char *)buffer->attrs_buffer); | |
1244 buffer->attrs_limit = new_limit; | |
1245 buffer->attrs_buffer = new_attrs_buffer; | |
1246 } | |
1247 fb = attrToFeedback(fba, seg->attr); | |
1248 for (i = 0; i < nchars; i++) { | |
1249 buffer->attrs_buffer[buffer->attrs_length + i] = fb; | |
1250 } | |
1251 buffer->attrs_length += nchars; | |
1252 } | |
1253 | |
1254 /*- attrToFeedback: ICString attribute -> XIMFeedback attribute converter -*/ | |
1255 static unsigned long | |
1256 attrToFeedback(fba, attr) | |
1257 FeedbackAttributes *fba; | |
1258 int attr; | |
1259 { | |
1260 int idx; | |
1261 | |
1262 if (attr == ICAttrNormalString) return 0; | |
1263 | |
1264 if (!(attr & ICAttrConverted)) { | |
1265 /* Not yet converted */ | |
1266 idx = FEEDBACK_NOCONV; | |
1267 } else if (attr & ICAttrCurrentSegment) { | |
1268 /* it's converted and the current segment */ | |
1269 idx = FEEDBACK_CURRENT; | |
1270 } else if (attr & ICAttrCurrentSubSegment) { | |
1271 /* it's converted and the current sub segment */ | |
1272 idx = FEEDBACK_CURRENTSUB; | |
1273 } else { | |
1274 /* converted, not current */ | |
1275 idx = FEEDBACK_CONV; | |
1276 } | |
1277 return fba->feedbacks[idx]; | |
1278 } | |
1279 | |
1280 /*- CBPreeditStart: callback preedit start -*/ | |
1281 static void | |
1282 CBPreeditStart(ocw) | |
1283 OnTheSpotConversionWidget ocw; | |
1284 { | |
1285 if (ocw->onthespot.preeditstartcallback == NULL || | |
1286 XtHasCallbacks((Widget)ocw, XtNpreeditStartCallback) != XtCallbackHasSome) | |
1287 { | |
1288 /* no callback */ | |
1289 return; | |
1290 } | |
1291 | |
1292 TRACE(("OnTheSpot:CBPreeditStart()\n")); | |
1293 | |
1294 XtCallCallbackList((Widget)ocw, ocw->onthespot.preeditstartcallback, | |
1295 (XtPointer)NULL); | |
1296 } | |
1297 | |
1298 /*- CBPreeditDone: callback preedit done -*/ | |
1299 static void | |
1300 CBPreeditDone(ocw) | |
1301 OnTheSpotConversionWidget ocw; | |
1302 { | |
1303 if (ocw->onthespot.preeditdonecallback == NULL || | |
1304 XtHasCallbacks((Widget)ocw, XtNpreeditDoneCallback) != XtCallbackHasSome) | |
1305 { | |
1306 /* no callback */ | |
1307 return; | |
1308 } | |
1309 | |
1310 TRACE(("OnTheSpot:CBPreeditDone()\n")); | |
1311 | |
1312 XtCallCallbackList((Widget)ocw, ocw->onthespot.preeditdonecallback, | |
1313 (XtPointer)NULL); | |
1314 } | |
1315 | |
1316 /*- CBPreeditDraw: callback preedit draw -*/ | |
1317 static void | |
1318 CBPreeditDraw(ocw, caret, chg_first, chg_length, encoding, format, text_length, text, attrs_length, attrs) | |
1319 OnTheSpotConversionWidget ocw; | |
1320 int caret; | |
1321 int chg_first; | |
1322 int chg_length; | |
1323 Atom encoding; | |
1324 int format; | |
1325 int text_length; | |
1326 XtPointer text; | |
1327 int attrs_length; | |
1328 unsigned long *attrs; | |
1329 { | |
1330 OCCPreeditDrawArg arg; | |
1331 | |
1332 if (ocw->onthespot.preeditdrawcallback == NULL || | |
1333 XtHasCallbacks((Widget)ocw, XtNpreeditDrawCallback) != XtCallbackHasSome) | |
1334 { | |
1335 /* no callback */ | |
1336 return; | |
1337 } | |
1338 | |
1339 TRACE(("OnTheSpot:CBPreeditDraw()\n")); | |
1340 | |
1341 arg.caret = caret; | |
1342 arg.chg_first = chg_first; | |
1343 arg.chg_length = chg_length; | |
1344 arg.encoding = encoding; | |
1345 arg.format = format; | |
1346 arg.text_length = text_length; | |
1347 arg.text = text; | |
1348 arg.attrs_length = attrs_length; | |
1349 arg.attrs = attrs; | |
1350 XtCallCallbackList((Widget)ocw, ocw->onthespot.preeditdrawcallback, | |
1351 (XtPointer)&arg); | |
1352 } | |
1353 | |
1354 /*- CBPreeditCaret: callback preedit caret -*/ | |
1355 static void | |
1356 CBPreeditCaret(ocw, caret) | |
1357 OnTheSpotConversionWidget ocw; | |
1358 int caret; | |
1359 { | |
1360 if (ocw->onthespot.preeditcaretcallback == NULL || | |
1361 XtHasCallbacks((Widget)ocw, XtNpreeditCaretCallback) != XtCallbackHasSome) | |
1362 { | |
1363 /* no callback */ | |
1364 return; | |
1365 } | |
1366 | |
1367 TRACE(("OnTheSpot:CBPreeditCaret()\n")); | |
1368 | |
1369 XtCallCallbackList((Widget)ocw, ocw->onthespot.preeditcaretcallback, | |
1370 (XtPointer)caret); | |
1371 } | |
1372 | |
1373 /*- CBStatusStart: callback status start -*/ | |
1374 static void | |
1375 CBStatusStart(ocw) | |
1376 OnTheSpotConversionWidget ocw; | |
1377 { | |
1378 if (ocw->onthespot.statusstartcallback == NULL || | |
1379 XtHasCallbacks((Widget)ocw, XtNstatusStartCallback) != XtCallbackHasSome) | |
1380 { | |
1381 /* no callback */ | |
1382 return; | |
1383 } | |
1384 | |
1385 TRACE(("OnTheSpot:CBStatusStart()\n")); | |
1386 | |
1387 XtCallCallbackList((Widget)ocw, ocw->onthespot.statusstartcallback, | |
1388 (XtPointer)NULL); | |
1389 } | |
1390 | |
1391 /*- CBStatusDone: callback status done -*/ | |
1392 static void | |
1393 CBStatusDone(ocw) | |
1394 OnTheSpotConversionWidget ocw; | |
1395 { | |
1396 if (ocw->onthespot.statusdonecallback == NULL || | |
1397 XtHasCallbacks((Widget)ocw, XtNstatusDoneCallback) != XtCallbackHasSome) | |
1398 { | |
1399 /* no callback */ | |
1400 return; | |
1401 } | |
1402 | |
1403 TRACE(("OnTheSpot:CBStatusDone()\n")); | |
1404 | |
1405 XtCallCallbackList((Widget)ocw, ocw->onthespot.statusdonecallback, | |
1406 (XtPointer)NULL); | |
1407 } | |
1408 | |
1409 /*- CBStatusDraw: callback status draw -*/ | |
1410 static void | |
1411 CBStatusDraw(ocw, encoding, format, length, text, nchars) | |
1412 OnTheSpotConversionWidget ocw; | |
1413 Atom encoding; | |
1414 int format; | |
1415 int length; | |
1416 XtPointer text; | |
1417 int nchars; | |
1418 { | |
1419 OCCPreeditDrawArg arg; | |
1420 | |
1421 if (ocw->onthespot.statusdrawcallback == NULL || | |
1422 XtHasCallbacks((Widget)ocw, XtNstatusDrawCallback) != XtCallbackHasSome) | |
1423 { | |
1424 /* no callback */ | |
1425 return; | |
1426 } | |
1427 | |
1428 TRACE(("OnTheSpot:CBStatusDraw()\n")); | |
1429 | |
1430 arg.caret = 0; /* ignored */ | |
1431 arg.chg_first = 0; /* ignored */ | |
1432 arg.chg_length = 0; /* ignored */ | |
1433 arg.encoding = encoding; | |
1434 arg.format = format; | |
1435 arg.text_length = length; | |
1436 arg.text = text; | |
1437 arg.attrs_length = nchars; | |
1438 arg.attrs = NULL; /* ignored */ | |
1439 XtCallCallbackList((Widget)ocw, ocw->onthespot.statusdrawcallback, | |
1440 (XtPointer)&arg); | |
1441 } | |
1442 |