comparison lib/Canna.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 56c98768f86b 1f1719e33c62
comparison
equal deleted inserted replaced
-1:000000000000 0:92745d501b9a
1 /*
2 * Copyright (c) 1990 Software Research Associates, Inc.
3 *
4 * Permission to use, copy, modify, and distribute this software and its
5 * documentation for any purpose and without fee is hereby granted, provided
6 * that the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of Software Research Associates not be
9 * used in advertising or publicity pertaining to distribution of the
10 * software without specific, written prior permission. Software Research
11 * Associates makes no representations about the suitability of this software
12 * for any purpose. It is provided "as is" without express or implied
13 * warranty.
14 *
15 * Author: Makoto Ishisone, Software Research Associates, Inc., Japan
16 */
17
18 /* Copyright 1991 NEC Corporation, Tokyo, Japan.
19 *
20 * Permission to use, copy, modify, and distribute this software and its
21 * documentation for any purpose and without fee is hereby granted,
22 * provided that the above copyright notice appear in all copies and that
23 * both that copyright notice and this permission notice appear in
24 * supporting documentation, and that the name of NEC Corporation
25 * not be used in advertising or publicity pertaining to distribution
26 * of the software without specific, written prior permission. NEC
27 * Corporation makes no representations about the suitability of this
28 * software for any purpose. It is provided "as is" without express
29 * or implied warranty.
30 *
31 * NEC CORPORATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
32 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
33 * NO EVENT SHALL NEC CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
34 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
35 * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
36 * OTHER TORTUOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
37 * PERFORMANCE OF THIS SOFTWARE.
38 *
39 * Author: Akira Kon, NEC Corporation. (kon@d1.bs2.mt.nec.co.jp)
40 */
41
42 /* $BD>$5$J$1$l$P$J$i$J$$$H$3$m(B
43
44 $B!&(BDestroy $B$,8F$P$l$J$$$N$G(B CloseUIContext $B$G$-$J$$!#(B
45 $B!&%b!<%INN0h$NBg$-$5!#(B($B$3$l$OB>$N%U%!%$%k$@$m$&$J(B)
46
47 */
48
49 #ifndef lint
50 static char *rcsid = "$Id: Canna.c,v 1.55 1999/05/25 08:13:03 ishisone Exp $";
51 #endif
52
53 #include <X11/IntrinsicP.h>
54 #include <X11/StringDefs.h>
55 #include <X11/Xmu/Atoms.h>
56 #define XK_KATAKANA
57 #include <X11/keysym.h>
58 #if XtSpecificationRelease > 4
59 #include <X11/Xfuncs.h>
60 #endif
61 #include "CannaP.h"
62 #include "DebugPrint.h"
63
64 #define _WCHAR_T /* $B$3$NDj5A$O(B jrkanji.h $B$G(B wcKanjiStatus $B$J$I$rDj5A$9$k$?$a(B */
65 #define wchar_t wchar
66
67 #include <canna/jrkanji.h>
68
69 static XtResource resources[] = {
70 #define offset(field) XtOffset(CannaObject, canna.field)
71 { XtNcannahost, XtCCannahost, XtRString, sizeof(String),
72 offset(cannahost), XtRString, NULL },
73 { XtNcannafile, XtCCannafile, XtRString, sizeof(String),
74 offset(cannafile), XtRString, NULL },
75 { XtNsendReturnByString, XtCSendReturnByString,
76 XtRBoolean, sizeof(Boolean),
77 offset(sendReturnByString), XtRBoolean, False },
78 #undef offset
79 };
80
81 static void ClassInitialize();
82 static void Initialize(), Destroy();
83 static Boolean SetValues();
84 static int InputEvent();
85 static ICString *GetMode();
86 static int CursorPos();
87 static int NumSegments();
88 static ICString *GetSegment();
89 static int CompareSegment();
90 static ICString *GetItemList();
91 static int SelectItem();
92 static int ConvertedString();
93 static int ClearConversion();
94 static void displayPreEdit();
95 static int GetTriggerKeys();
96 static int PreeditString();
97 static int StatusString();
98
99 static initializeCannaConnection();
100 static toJapaneseMode();
101 static void convend();
102 static changeTextForCanna();
103 static copyInWchar();
104 static fixProcForCanna();
105 static shiftRight(), shiftLeft(), shiftLeftAll();
106 static ibufInitialize(), freeIBuf();
107
108 #ifdef KC_SETLISTCALLBACK
109 #ifdef CANNA_LIST_Convert
110 #define CANNA_LISTFUNCTYPE int
111 #else
112 #define CANNA_LISTFUNCTYPE void
113 #endif
114 static CANNA_LISTFUNCTYPE listfunc();
115
116 static void openSelection();
117 #define SELECTION_SET 0 /* SelectionStart $B$r$7$F$bNI$$$H8@$&>pJs$r@_Dj$9$k(B */
118 #define SELECTION_DO 1 /* $B<B:]$K(B SelectionStart $B$r3+;O$9$k(B */
119 #else /* !KC_SETLISTCALLBACK */
120 #define openSelection(x, y, z)
121 #endif /* !KC_SETLISTCALLBACK */
122
123 static ICString *GetAuxSegments();
124
125 CannaClassRec cannaClassRec = {
126 { /* object fields */
127 /* superclass */ (WidgetClass) &inputConvClassRec,
128 /* class_name */ "Canna",
129 /* widget_size */ sizeof(CannaRec),
130 /* class_initialize */ ClassInitialize,
131 /* class_part_initialize */ NULL,
132 /* class_inited */ FALSE,
133 /* initialize */ Initialize,
134 /* initialize_hook */ NULL,
135 /* obj1 */ NULL,
136 /* obj2 */ NULL,
137 /* obj3 */ 0,
138 /* resources */ resources,
139 /* num_resources */ XtNumber(resources),
140 /* xrm_class */ NULLQUARK,
141 /* obj4 */ FALSE,
142 /* obj5 */ FALSE,
143 /* obj6 */ FALSE,
144 /* obj7 */ FALSE,
145 /* destroy */ Destroy,
146 /* obj8 */ NULL,
147 /* obj9 */ NULL,
148 /* set_values */ SetValues,
149 /* set_values_hook */ NULL,
150 /* obj10 */ NULL,
151 /* get_values_hook */ NULL,
152 /* obj11 */ NULL,
153 /* version */ XtVersion,
154 /* callback_private */ NULL,
155 /* obj12 */ NULL,
156 /* obj13 */ NULL,
157 /* obj14 */ NULL,
158 /* extension */ NULL
159 },
160 { /* inputConv fields */
161 /* InputEvent */ InputEvent,
162 /* GetMode */ GetMode,
163 /* CursorPos */ CursorPos,
164 /* NumSegments */ NumSegments,
165 /* GetSegment */ GetSegment,
166 /* CompareSegment */ CompareSegment,
167 /* GetItemList */ GetItemList,
168 /* SelectItem */ SelectItem,
169 /* GetConvertedString */ ConvertedString,
170 /* ClearConversion */ ClearConversion,
171 /* GetAuxSegments */ GetAuxSegments,
172 /* SupportMultipleObjects */ True,
173 /* GetTriggerKeys */ GetTriggerKeys,
174 /* num_trigger_keys */ 0,
175 /* trigger_keys */ NULL,
176 /* GetPreeditString */ PreeditString,
177 /* GetStatusString */ StatusString,
178 /* NoMoreObjects */ False,
179 },
180 { /* canna fields */
181 /* foo */ 0,
182 }
183 };
184
185 WidgetClass cannaObjectClass = (WidgetClass)&cannaClassRec;
186
187 static void fix();
188
189 static ICString *SymbolList;
190 static int NumSymbols;
191
192 static void addObject();
193 static void deleteObject();
194
195 static int checkIfFunctionalChar();
196
197 static int ignoreListfunc = 0;
198
199 static Display *displaybell = (Display *)0;
200
201 static void
202 ClassInitialize()
203 {
204 TRACE(("CannaObjectClass initialized\n"));
205 /* $B2?$b$7$J$$(B */
206 }
207
208 static int
209 XKanaLookup(event_struct, buffer_return, bytes_buffer,
210 keysym, status_return)
211 XKeyEvent *event_struct;
212 char *buffer_return;
213 int bytes_buffer;
214 KeySym *keysym;
215 XComposeStatus *status_return;
216 {
217 int res;
218 res = XLookupString(event_struct, buffer_return, bytes_buffer,
219 keysym, status_return);
220 if (!res && XK_overline <= *keysym && *keysym <= XK_semivoicedsound) {
221 buffer_return[0] = (unsigned long)(*keysym) & 0xff;
222 res = 1;
223 }
224 return res;
225 }
226
227 static int
228 InputEvent(w, event)
229 Widget w;
230 XEvent *event;
231 {
232 CannaObject obj = (CannaObject)w;
233 wchar buf[1024];
234 char kanabuf[20];
235 KeySym ks;
236 XComposeStatus compose_status;
237 wcKanjiStatus kanji_status;
238 int len, nbytes, functionalChar;
239
240 /* KeyPress$B0J30$O<N$F$k(B */
241 if (event->type != KeyPress /*&& event->type != KeyRelease*/) return 0;
242
243 obj->canna.textchanged = False;
244
245 /* $B<h$j$"$($:J8;z$KD>$7$F$7$^$&(B */
246 kanabuf[0] = '\0';
247 nbytes = XKanaLookup(event, kanabuf, 20, &ks, &compose_status);
248
249 buf[0] = (wchar)kanabuf[0]; /* $B$-$?$J$$(B */
250
251 if (ks == XK_space && (event->xkey.state & ShiftMask)) {
252 void convend();
253
254 convend(obj);
255 return 0;
256 }
257
258 /* $BD9$5$,%<%m$N$b$N$K4X$7$F$O$A$g$C$H5_:Q(B */
259 functionalChar = checkIfFunctionalChar(event, ks, buf, 1024);
260 /* shift+$B"*$N$h$&$JJ8;z$@$C$?$i#1J8;z$H?t$($k(B */
261 if ( !nbytes && functionalChar ) {
262 nbytes = 1;
263 }
264
265 /* $BMW$i$J$$>l9g$OL5;k$9$k(B */
266 if (nbytes == 0) return 1;
267
268 /* $B%Y%k$rLD$i$9%G%#%9%W%l%$$N@_Dj(B */
269
270 displaybell = XtDisplayOfObject((Widget)obj);
271
272 /* $B$+$J4A;zJQ49$9$k(B */
273 len = wcKanjiString((int)obj, (int)buf[0],
274 (wchar_t *)buf, 1024, &kanji_status);
275
276 displayPreEdit(obj, len, buf, &kanji_status);
277 return (kanji_status.info & KanjiThroughInfo) ? 1 : 0;
278 }
279
280 static void
281 displayPreEdit(obj, len, buf, ks)
282 CannaObject obj;
283 int len;
284 wchar *buf;
285 wcKanjiStatus *ks;
286 {
287 Widget w = (Widget)obj;
288
289 if (len > 0) { /* $B3NDjJ8;z$,$"$k>l9g(B */
290 if (len == 1 && (ks->info & KanjiThroughInfo) &&
291 (obj->canna.sendReturnByString == False ||
292 (((buf[0] & 0x7f) < (unsigned)0x20 &&
293 buf[0] != '\r' && buf[0] != '\t') ||
294 buf[0] == '\177'))) {
295 ;/* XSendEvent$B$GAw$C$F$b$i$&$h$&$JJ8;z(B($B2?$b$7$J$$(B) */
296 }
297 else {
298 ks->info &= ~KanjiThroughInfo;
299 fixProcForCanna(obj, buf, len);
300 fix(obj);
301 }
302 }
303
304 changeTextForCanna(obj, ks);
305
306 /* $B%F%-%9%H$NJQ2=$r%A%'%C%/$9$k(B */
307 if (obj->canna.textchanged) {
308 XtCallCallbackList(w, obj->inputConv.textchangecallback,
309 (XtPointer)NULL);
310 obj->canna.textchanged = False;
311 }
312
313 /* $BF~NO%b!<%I$r%A%'%C%/$9$k(B */
314 if (ks->info & KanjiModeInfo) {
315 XtCallCallbackList(w, obj->inputConv.modechangecallback,
316 (XtPointer)NULL);
317 }
318
319 if (ks->info & KanjiGLineInfo) { /* $B0lMw9T$,$"$k>l9g(B */
320 ICAuxControlArg arg;
321
322 switch (obj->canna.ibuf->candstat) {
323 case CANNA_GLINE_Start:
324 arg.command = ICAuxStart;
325 XtCallCallbackList((Widget)obj, obj->inputConv.auxcallback,
326 (XtPointer)&arg);
327 break;
328 case CANNA_GLINE_End:
329 arg.command = ICAuxEnd;
330 XtCallCallbackList((Widget)obj, obj->inputConv.auxcallback,
331 (XtPointer)&arg);
332 break;
333 case CANNA_GLINE_Change:
334 arg.command = ICAuxChange;
335 XtCallCallbackList((Widget)obj, obj->inputConv.auxcallback,
336 (XtPointer)&arg);
337 break;
338 }
339 }
340
341 /* $B=*$o$j$+$I$&$+%A%'%C%/$9$k(B */
342 if (ks->info & KanjiModeInfo) {
343 wchar modeinfo[4];
344
345 wcKanjiControl((int)obj, KC_SETMODEINFOSTYLE, (char *)1);
346 wcKanjiControl((int)obj, KC_QUERYMODE, (char *)modeinfo);
347 wcKanjiControl((int)obj, KC_SETMODEINFOSTYLE, (char *)0);
348 if (modeinfo[0] - '@' == CANNA_MODE_AlphaMode) {
349 toJapaneseMode(obj);
350 convend(obj);
351 }
352 }
353 openSelection(obj, SELECTION_DO, 0/* dummy */);
354 }
355
356 static ICString *
357 GetMode(w)
358 Widget w;
359 {
360 CannaObject obj = (CannaObject)w;
361 wchar *mode;
362 static ICString icstr;
363
364 icstr.nchars = obj->canna.ibuf->modelen;
365 if (icstr.nchars > 0) {
366 mode = obj->canna.ibuf->curmode;
367 icstr.data = (char *)mode;
368 icstr.nbytes = icstr.nchars * sizeof(wchar);
369 icstr.attr = ICAttrNormalString;
370 }
371 return &icstr;
372 }
373
374 static int
375 CursorPos(w, nsegp, ncharp)
376 Widget w;
377 Cardinal *nsegp;
378 Cardinal *ncharp;
379 {
380 CannaObject obj = (CannaObject)w;
381 iBuf *ib = obj->canna.ibuf;
382 Cardinal nseg, nchar;
383 int ret = 0;
384
385 if (ib->curseg < ib->nseg) {
386 nseg = ib->curseg;
387 nchar = 0;
388 }
389 else {
390 nseg = ib->offset;
391 nchar = ib->len[0 + ib->offset];
392 ret = 1;
393 }
394 if (nsegp) {
395 *nsegp = nseg;
396 }
397 if (ncharp) {
398 *ncharp = nchar;
399 }
400
401 return ret;
402 }
403
404 static int
405 NumSegments(w)
406 Widget w;
407 {
408 CannaObject obj = (CannaObject)w;
409 iBuf *ib = obj->canna.ibuf;
410
411 return ib->nseg;
412 }
413
414 static ICString *
415 GetSegment(w, n)
416 Widget w;
417 Cardinal n;
418 {
419 CannaObject obj = (CannaObject)w;
420 iBuf *ib = obj->canna.ibuf;
421 static ICString seg;
422
423 seg.data = (char *)ib->str[n];
424 seg.nchars = ib->len[n];
425 seg.nbytes = seg.nchars * sizeof(wchar);
426 if (ib->curseg == n) {
427 seg.attr = ICAttrConverted | ICAttrCurrentSegment;
428 }
429 else if (n < ib->offset) {
430 seg.attr = ICAttrConverted;
431 }
432 else {
433 seg.attr = ICAttrNotConverted;
434 }
435
436 return &seg;
437 }
438
439 /* ARGSUSED */
440 static int
441 CompareSegment(w, seg1, seg2, n)
442 Widget w;
443 ICString *seg1;
444 ICString *seg2;
445 Cardinal *n;
446 {
447 wchar *p, *q;
448 int len, nsame;
449 int result = 0;
450
451 if (seg1->attr != seg2->attr) result |= ICAttrChanged;
452
453 len = seg1->nchars > seg2->nchars ? seg2->nchars : seg1->nchars;
454 nsame = 0;
455 p = (wchar *)seg1->data;
456 q = (wchar *)seg2->data;
457 while (nsame < len && *p++ == *q++) nsame++;
458
459 if (nsame != len || len != seg1->nchars || len != seg2->nchars)
460 result |= ICStringChanged;
461
462 if (n) *n = nsame;
463
464 return result;
465 }
466
467 static ICString *
468 GetItemList(w, n)
469 Widget w;
470 Cardinal *n;
471 {
472 CannaObject obj = (CannaObject)w;
473
474 *n = obj->canna.numcand;
475 return obj->canna.candlist;
476 }
477
478 #define SELECTBUFSIZE 1024
479
480 static int
481 SelectItem(w, n)
482 Widget w;
483 int n;
484 {
485 CannaObject obj = (CannaObject)w;
486 wcKanjiStatus ks;
487 wcKanjiStatusWithValue ksv;
488 wchar buf[SELECTBUFSIZE];
489
490 if (n >= 0)
491 *(obj->canna.cur_addr) = n;
492
493 ksv.ks = &ks;
494 buf[0] = (wchar)'\r';
495 ksv.buffer = buf;
496 ksv.n_buffer = SELECTBUFSIZE;
497 ksv.val = CANNA_FN_Kakutei;
498 {
499 ignoreListfunc = 1;
500 wcKanjiControl((int)obj, KC_DO, (char *)&ksv);
501 ignoreListfunc = 0;
502 }
503 displayPreEdit(obj, ksv.val, buf, ksv.ks);
504 return 0;
505 }
506
507 static int
508 ConvertedString(w, encoding, format, length, string)
509 Widget w;
510 Atom *encoding;
511 int *format;
512 int *length;
513 XtPointer *string;
514 {
515 CannaObject obj = (CannaObject)w;
516 iBuf *ib = obj->canna.ibuf;
517 wchar *wbuf, *wp;
518 int len, wlen;
519 extern int convJWStoCT();
520 int offset = ib->offset;
521
522 if (ib == NULL) return -1;
523
524 if (ib->nseg == 0 || ib->offset == 0) return -1;
525
526 wlen = ib->len[offset - 1];
527 if (wlen == 0) return -1;
528
529 wbuf = ib->str[offset - 1];
530
531 /*
532 * Canna $B%*%V%8%'%/%H$O(B COMPOUND_TEXT $B%(%s%3!<%G%#%s%0$7$+%5%]!<%H$7$J$$(B
533 * COMPOUND_TEXT $B$KJQ49$9$k(B
534 */
535 *encoding = XA_COMPOUND_TEXT(XtDisplayOfObject((Widget)obj));
536 *format = 8;
537
538 /* COMPOUND_TEXT $B$O(B \r $B$,Aw$l$J$$$N$G(B \n $B$KJQ49$7$F$*$/(B */
539 for (wp = wbuf; *wp != 0; wp++) {
540 if (*wp == '\r') *wp = '\n';
541 }
542
543 *length = len = convJWStoCT(wbuf, (unsigned char *)NULL, 0);
544 *string = XtMalloc(len + 1);
545 (void)convJWStoCT(wbuf, (unsigned char *)*string, 0);
546
547 shiftLeftAll(ib);
548
549 return 0;
550 }
551
552 static int
553 ClearConversion(w)
554 Widget w;
555 {
556 CannaObject obj = (CannaObject)w;
557
558 wcKanjiStatus ks;
559 wcKanjiStatusWithValue ksv;
560 wchar buf[SELECTBUFSIZE];
561
562 ksv.ks = &ks;
563 ksv.buffer = buf;
564 ksv.n_buffer = SELECTBUFSIZE;
565 wcKanjiControl((int)obj, KC_KILL, (char *)&ksv);
566 displayPreEdit(obj, ksv.val, buf, ksv.ks);
567 return 0;
568 }
569
570 static ICString *
571 GetAuxSegments(w, n, ns, nc)
572 Widget w;
573 Cardinal *n, *ns, *nc;
574 {
575 CannaObject obj = (CannaObject)w;
576 iBuf *ib = obj->canna.ibuf;
577 Cardinal nseg, nchar;
578
579 if (n) {
580 *n = ib->ngseg;
581 }
582
583 if (ib->curgseg < ib->ngseg) {
584 nseg = ib->curgseg;
585 nchar = 0;
586 }
587 else {
588 nseg = 0;
589 nchar = ib->gllen[0];
590 }
591 if (ns) {
592 *ns = nseg;
593 }
594 if (nc) {
595 *nc = nchar;
596 }
597
598 return ib->ics;
599 }
600
601 /* ARGSUSED */
602 static void
603 Initialize(req, new, args, num_args)
604 Widget req;
605 Widget new;
606 ArgList args;
607 Cardinal *num_args;
608 {
609 CannaObject obj = (CannaObject)new;
610
611 obj->canna.selectionending = False;
612 obj->canna.textchanged = False;
613 obj->canna.symbollist = SymbolList;
614 obj->canna.numsymbols = NumSymbols;
615 obj->canna.cursymbol = 0;
616 obj->canna.candlist = NULL;
617 obj->canna.candlistsize = 0;
618 obj->canna.numcand = 0;
619 obj->canna.lastTextLengthIsZero = False;
620
621 ibufInitialize(obj);
622
623 /* $BJQ49$N=i4|2=(B */
624 initializeCannaConnection(obj);
625
626 addObject(obj);
627 }
628
629 static int
630 bell()
631 {
632 if (displaybell) {
633 XBell(displaybell, 0);
634 }
635 return 0;
636 }
637
638 static int nCannaContexts = 0;
639
640 static
641 initializeCannaConnection(obj)
642 CannaObject obj;
643 {
644 char **warn = 0;
645 extern (*jrBeepFunc)();
646
647 if (nCannaContexts == 0) {
648 #ifdef KC_SETSERVERNAME
649 if (obj->canna.cannahost != NULL) {
650 wcKanjiControl((int)obj, KC_SETSERVERNAME, obj->canna.cannahost);
651 }
652 #endif /* KC_SETSERVERNAME */
653 #ifdef KC_SETINITFILENAME
654 if (obj->canna.cannafile != NULL) {
655 wcKanjiControl((int)obj, KC_SETINITFILENAME, obj->canna.cannafile);
656 }
657 #endif /* KC_SETINITFILENAME */
658
659 wcKanjiControl((int)obj, KC_INITIALIZE, (char *)&warn);
660 TRACE(("Canna initialized\n"));
661
662 if (warn) {
663 char **p;
664
665 for (p = warn; *p ; p++) {
666 XtAppWarning(XtWidgetToApplicationContext((Widget)obj), *p);
667 }
668 }
669 }
670 nCannaContexts++;
671
672 #ifdef KC_SETAPPNAME
673 wcKanjiControl((int)obj, KC_SETAPPNAME, "kinput2");
674 #endif
675
676 #ifdef DONT_USE_HANKAKU_KATAKANA
677 /* $BH>3Q%+%?%+%J$N6X;_(B */
678 wcKanjiControl((int)obj, KC_INHIBITHANKAKUKANA, (char *)1);
679 #endif
680
681 /* $B0lMw9T$r#7#8%3%i%`$K@_Dj(B */
682 wcKanjiControl((int)obj, KC_SETWIDTH, (char *)78);
683
684 /* $B8uJd0lMw%3!<%k%P%C%/$r@_Dj(B */
685
686 #ifdef KC_SETLISTCALLBACK
687 {
688 jrListCallbackStruct lcs;
689
690 lcs.client_data = (char *)obj;
691 lcs.callback_func = listfunc;
692 wcKanjiControl((int)obj, KC_SETLISTCALLBACK, (char *)&lcs);
693 }
694 #endif /* KC_SETLISTCALLBACK */
695
696 jrBeepFunc = bell;
697
698 /* $B$5$i$KF|K\8lF~NO%b!<%I$K$7$F$*$/(B */
699 toJapaneseMode(obj);
700 }
701
702
703 static void
704 Destroy(w)
705 Widget w;
706 {
707 CannaObject obj = (CannaObject)w;
708 wcKanjiStatusWithValue ksv;
709 wcKanjiStatus ks;
710 wchar buf[512];
711 int i;
712
713 /* $B%P%C%U%!$N2rJ|(B */
714
715 freeIBuf(obj->canna.ibuf);
716
717 if (obj->canna.candlist) {
718 for (i = 0 ; i < obj->canna.candlistsize ; i++) {
719 if ((obj->canna.candlist + i)->data) {
720 XtFree((obj->canna.candlist + i)->data);
721 }
722 }
723
724 XtFree((char *)obj->canna.candlist);
725 }
726
727 /* $B!X$+$s$J!Y$N=hM}(B */
728 ksv.buffer = buf;
729 ksv.n_buffer = 512;
730 ksv.ks = &ks;
731
732 wcKanjiControl((int)obj, KC_CLOSEUICONTEXT, (char *)&ksv);
733
734 if (--nCannaContexts == 0) {
735 char **warn = 0;
736
737 wcKanjiControl(0, KC_FINALIZE, (char *)&warn);
738 if (warn) {
739 char **p;
740
741 for (p = warn; *p ; p++) {
742 XtAppWarning(XtWidgetToApplicationContext((Widget)obj), *p);
743 }
744 }
745 }
746
747 deleteObject(obj);
748 }
749
750 static Boolean
751 SetValues(cur, req, wid, args, num_args)
752 Widget cur;
753 Widget req;
754 Widget wid;
755 ArgList args;
756 Cardinal *num_args;
757 /* ARGSUSED */
758 {
759 CannaObject old = (CannaObject)cur;
760 CannaObject new = (CannaObject)wid;
761
762 return False;
763 }
764
765 static void
766 fix(obj)
767 CannaObject obj;
768 {
769 /* $B3NDj$N=hM}(B */
770 XtCallCallbackList((Widget)obj, obj->inputConv.fixcallback,
771 (XtPointer)NULL); /* $B!)!)!)(B */
772 }
773
774 static void
775 convend(obj)
776 CannaObject obj;
777 {
778 XtCallCallbackList((Widget)obj, obj->inputConv.endcallback,
779 (XtPointer)NULL);
780 }
781
782 /*
783 * keeping list of objects
784 */
785 typedef struct _oblist_ {
786 CannaObject obj;
787 struct _oblist_ *next;
788 } ObjRec;
789
790 static ObjRec *ObjList = NULL;
791
792 static void
793 addObject(obj)
794 CannaObject obj;
795 {
796 ObjRec *objp = XtNew(ObjRec);
797
798 objp->obj = obj;
799 objp->next = ObjList;
800 ObjList = objp;
801 }
802
803 static void
804 deleteObject(obj)
805 CannaObject obj;
806 {
807 ObjRec *objp, *objp0;
808
809 for (objp0 = NULL, objp = ObjList;
810 objp != NULL;
811 objp0 = objp, objp = objp->next) {
812 if (objp->obj == obj) {
813 if (objp0 == NULL) {
814 ObjList = objp->next;
815 } else {
816 objp0->next = objp->next;
817 }
818 XtFree((char *)objp);
819 return;
820 }
821 }
822 }
823
824 /*
825 * Operations to canna.ibuf
826 */
827
828 /* cfuncdef
829
830 changeTextForCanna -- ibuf $B$NFbMF$r(B kanji_status $B$rMQ$$$F=q$-49$($k!#(B
831
832
833 $B4pK\E*$K$O8uJdJ8;zNs$H8uJd0lMw9TJ8;zNs$K4X$7$F0J2<$N=hM}$r9T$&!#(B
834
835 (1) $B$$$:$l$NJ8;zNs$b%F%-%9%H$,H?E>$7$F$$$kItJ,$H$=$&$G$J$$ItJ,(B
836 $B$,B8:_$7!"H?E>$7$F$$$kItJ,$O#1%+=j$7$+B8:_$7$J$$!#(B
837 (2) $B$7$?$,$C$F$$$:$l$NJ8;zNs$bH?E>$7$F$$$k$H$3$m$H$=$NN>C<$KH?E>(B
838 $B$7$F$$$J$$ItJ,$H$,B8:_$9$k>l9g$K#3ItJ,$KJ,$+$l$k$3$H$K$J$j!"(B
839 $BH?E>$7$F$$$kItJ,$N0LCV$d!"H?E>$7$F$$$k2U=j$,$J$$>l9g$J$I$r(B
840 $B9g$o$;$F9M$($F$b#3ItJ,0J>e$KJ,$+$l$k$3$H$O$J$$!#(B
841 (3) $B$7$?$,$C$F!"$$$:$l$NJ8;zNs$b:GBg#3$D$N%;%0%a%s%H$KJ,$1$FI=<((B
842 $B%&%#%8%'%C%H$KEO$9$h$&$K$9$k!#(B
843
844 */
845
846 static
847 changeTextForCanna(cldata, ksp)
848 caddr_t cldata;
849 wcKanjiStatus *ksp;
850 {
851 CannaObject obj = (CannaObject)cldata;
852 iBuf *ibuf = obj->canna.ibuf;
853 int offset = ibuf->offset, i;
854
855 if (ksp->length == 0) {
856 ibuf->curseg = offset;
857 ibuf->nseg = offset;
858 ibuf->len[0 + offset] = ibuf->len[1 + offset] =
859 ibuf->len[2 + offset] = 0;
860 if (!obj->canna.lastTextLengthIsZero) {
861 obj->canna.textchanged = True;
862 obj->canna.lastTextLengthIsZero = True;
863 }
864 }
865 else if (ksp->length > 0) {
866 obj->canna.lastTextLengthIsZero = False;
867 ibuf->len[1 + offset] = ibuf->len[2 + offset] = 0;
868 if (ksp->revLen > 0) {
869 if (ksp->revPos == 0) {
870 int remain = ksp->length - ksp->revLen;
871
872 copyInWchar(ksp->echoStr, ksp->revLen,
873 &(ibuf->str[0 + offset]), &(ibuf->size[0 + offset]),
874 &(ibuf->len[0 + offset]));
875 ibuf->curseg = offset;
876 ibuf->nseg = offset + 1;
877 if (remain) {
878 copyInWchar(ksp->echoStr + ksp->revLen, remain,
879 &(ibuf->str[1 + offset]), &(ibuf->size[1 + offset]),
880 &(ibuf->len[1 + offset]));
881 ibuf->nseg = offset + 2;
882 }
883 }
884 else {
885 int remain = ksp->length - ksp->revPos - ksp->revLen;
886
887 copyInWchar(ksp->echoStr, ksp->revPos,
888 &(ibuf->str[0 + offset]), &(ibuf->size[0 + offset]),
889 &(ibuf->len[0 + offset]));
890 copyInWchar(ksp->echoStr + ksp->revPos, ksp->revLen,
891 &(ibuf->str[1 + offset]), &(ibuf->size[1 + offset]),
892 &(ibuf->len[1 + offset]));
893 ibuf->curseg = offset + 1;
894 ibuf->nseg = offset + 2;
895 if (remain) {
896 copyInWchar(ksp->echoStr + ksp->revPos + ksp->revLen,
897 remain,
898 &(ibuf->str[2 + offset]), &(ibuf->size[2 + offset]),
899 &(ibuf->len[2 + offset]));
900 ibuf->nseg = offset + 3;
901 }
902 }
903 }
904 else {
905 copyInWchar(ksp->echoStr, ksp->length,
906 &(ibuf->str[0 + offset]), &(ibuf->size[0 + offset]),
907 &(ibuf->len[0 + offset]));
908 ibuf->len[1 + offset] = ibuf->len[2 + offset] = 0;
909 ibuf->nseg = offset + 1;
910 ibuf->curseg = offset + 1;
911 }
912 obj->canna.textchanged = True;
913 }
914 /* $B%b!<%I(B */
915 if (ksp->info & KanjiModeInfo) {
916 int modelen = 0;
917
918 while (ksp->mode[modelen]) modelen++;
919 copyInWchar(ksp->mode, modelen,
920 &(ibuf->curmode), &(ibuf->modesize), &(ibuf->modelen));
921 }
922 /* $B0lMw9T(B */
923 if (ksp->info & KanjiGLineInfo) {
924 if (ksp->gline.length == 0) {
925 switch (ibuf->candstat) {
926 case CANNA_GLINE_Empty:
927 case CANNA_GLINE_End:
928 ibuf->candstat = CANNA_GLINE_Empty;
929 break;
930 case CANNA_GLINE_Start:
931 case CANNA_GLINE_Change:
932 ibuf->candstat = CANNA_GLINE_End;
933 break;
934 }
935 ibuf->curgseg = 0;
936 ibuf->ngseg = 0;
937 ibuf->gllen[0] = ibuf->gllen[1] = ibuf->gllen[2] = 0;
938 }
939 else if (ksp->gline.length > 0) {
940 switch (ibuf->candstat) {
941 case CANNA_GLINE_Empty:
942 case CANNA_GLINE_End:
943 ibuf->candstat = CANNA_GLINE_Start;
944 break;
945 case CANNA_GLINE_Start:
946 case CANNA_GLINE_Change:
947 ibuf->candstat = CANNA_GLINE_Change;
948 break;
949 }
950 ibuf->gllen[1] = ibuf->gllen[2] = 0;
951 if (ksp->gline.revLen > 0) {
952 if (ksp->gline.revPos == 0) {
953 int remain = ksp->gline.length - ksp->gline.revLen;
954
955 copyInWchar(ksp->gline.line, ksp->gline.revLen,
956 &(ibuf->gline[0]), &(ibuf->glsize[0]),
957 &(ibuf->gllen[0]));
958 ibuf->curgseg = 0;
959 ibuf->ngseg = 1;
960 if (remain) {
961 copyInWchar(ksp->gline.line + ksp->gline.revLen, remain,
962 &(ibuf->gline[1]), &(ibuf->glsize[1]),
963 &(ibuf->gllen[1]));
964 ibuf->ngseg = 2;
965 }
966 }
967 else {
968 int remain = ksp->gline.length
969 - ksp->gline.revPos - ksp->gline.revLen;
970
971 copyInWchar(ksp->gline.line, ksp->gline.revPos,
972 &(ibuf->gline[0]), &(ibuf->glsize[0]),
973 &(ibuf->gllen[0]));
974 copyInWchar(ksp->gline.line + ksp->gline.revPos, ksp->gline.revLen,
975 &(ibuf->gline[1]), &(ibuf->glsize[1]),
976 &(ibuf->gllen[1]));
977 ibuf->curgseg = 1;
978 ibuf->ngseg = 2;
979 if (remain) {
980 copyInWchar(ksp->gline.line
981 + ksp->gline.revPos + ksp->gline.revLen,
982 remain,
983 &(ibuf->gline[2]), &(ibuf->glsize[2]),
984 &(ibuf->gllen[2]));
985 ibuf->ngseg = 3;
986 }
987 }
988 }
989 else {
990 copyInWchar(ksp->gline.line, ksp->gline.length,
991 &(ibuf->gline[0]), &(ibuf->glsize[0]),
992 &(ibuf->gllen[0]));
993 ibuf->gllen[1] = ibuf->gllen[2] = 0;
994 ibuf->ngseg = 1;
995 ibuf->curgseg = 1;
996 }
997 }
998 for (i = 0 ; i < ibuf->ngseg ; i++) {
999 ibuf->ics[i].data = (char *)ibuf->gline[i];
1000 ibuf->ics[i].nchars = ibuf->gllen[i];
1001 ibuf->ics[i].nbytes = ibuf->gllen[i] * sizeof(wchar);
1002 ibuf->ics[i].attr = ICAttrConverted;
1003 }
1004 if (ibuf->curgseg < ibuf->ngseg) {
1005 ibuf->ics[ibuf->curgseg].attr |= ICAttrCurrentSegment;
1006 }
1007 }
1008 }
1009
1010 /* cfuncdef
1011
1012 copyInWchar -- wchar $B$r%3%T!<$9$k!#(B
1013
1014 ws, wlen $B$G<($5$l$?(B wchar $BJ8;zNs$r(B wsbuf $B$N%]%$%s%H@h$N%P%C%U%!$K3J(B
1015 $BG<$9$k!#(Bwsbuf $B$N%5%$%:$O(B wssize $B$N%]%$%s%H@h$K3JG<$5$l$F$$$kCM$G;X(B
1016 $BDj$5$l$k$,!"$=$l$G$O>.$5$$;~$O(B copyInWchar $BFb$G(B XtRealloc $B$5$l!"?7(B
1017 $B$?$K%"%m%1!<%H$5$l$?%P%C%U%!$,(B wsbuf $B$N%]%$%s%H@h$K3JG<$5$l$k!#$^$?!"(B
1018 $B%P%C%U%!$N?7$?$J%5%$%:$,(B wssize $B$N%]%$%s%H@h$K3JG<$5$l$k!#F@$i$l$?(B
1019 $BJ8;z?t$,(Bwslen $B$N%]%$%s%H@h$K3JG<$5$l$k!#(B
1020
1021 */
1022
1023 static
1024 copyInWchar(ws, wlen, wsbuf, wssize, wslen)
1025 wchar *ws;
1026 int wlen;
1027 wchar **wsbuf;
1028 int *wssize, *wslen;
1029 {
1030 int i;
1031
1032 if (*wssize == 0) {
1033 if ((*wsbuf = (wchar *)XtMalloc((wlen + 1) * sizeof(wchar)))
1034 == (wchar *)0) {
1035 /* $B%(%i!<$@(B */
1036 }
1037 else {
1038 *wssize = wlen + 1;
1039 }
1040 }
1041 if (wlen + 1 > *wssize) {
1042 if ((*wsbuf = (wchar *)XtRealloc((char *)*wsbuf,
1043 (wlen + 1) * sizeof(wchar)))
1044 == (wchar *)0) {
1045 /* $B%(%i!<$@!#$I$&$9$l$PNI$$!)(B */
1046 }
1047 else {
1048 *wssize = wlen + 1;
1049 }
1050 }
1051 *wslen = wlen;
1052 (void)bcopy(ws, *wsbuf, wlen * sizeof(wchar));
1053 *(*wsbuf + wlen) = (wchar)0;
1054
1055 return 0; /* $B#0$OFC$K0UL#$,L5$$(B */
1056 }
1057
1058 /* cfuncdef
1059
1060 fixProcForCanna -- $B3NDj$7$?J8;z$N=hM}$r9T$&(B
1061
1062 */
1063
1064 static
1065 fixProcForCanna(cldata, fixedstr, fixedlen)
1066 caddr_t cldata;
1067 wchar *fixedstr;
1068 int fixedlen;
1069 {
1070 CannaObject obj = (CannaObject)cldata;
1071 iBuf *ib = obj->canna.ibuf;
1072 int offset = ib->offset;
1073
1074 if (offset < NConvertedSegments) {
1075 shiftRight(ib);
1076 offset = ib->offset;
1077 }
1078 else {
1079 shiftLeft(ib);
1080 }
1081 copyInWchar(fixedstr, fixedlen,
1082 &(ib->str[offset - 1]), &(ib->size[offset - 1]),
1083 &(ib->len[offset - 1]));
1084 }
1085
1086 /* cfuncdef
1087
1088 shiftRight -- ibuf $B$NJ8;z%P%C%U%!$N(B offset $B0J9_$r1&$K%7%U%H$9$k(B
1089
1090 */
1091
1092 static
1093 shiftRight(ib)
1094 iBuf *ib;
1095 {
1096 int i;
1097 wchar *tmpbuf;
1098 int tmpsize, tmplen;
1099 int offset = ib->offset;
1100
1101 tmpbuf = ib->str[ib->nseg];
1102 tmpsize = ib->size[ib->nseg];
1103 for (i = ib->nseg ; offset < i ; i--) {
1104 ib->str[i] = ib->str[i - 1];
1105 ib->size[i] = ib->size[i - 1];
1106 ib->len[i] = ib->len[i - 1];
1107 }
1108 ib->str[offset] = tmpbuf;
1109 ib->size[offset] = tmpsize;
1110 ib->offset++;
1111 ib->nseg++;
1112 ib->curseg++;
1113 }
1114
1115 /* cfuncdef
1116
1117 shiftLeft -- ibuf $B$NJ8;z%P%C%U%!$N(B offset $B0JA0$r:8$K%7%U%H$9$k(B
1118
1119 */
1120
1121 static
1122 shiftLeft(ib)
1123 iBuf *ib;
1124 {
1125 int i;
1126 wchar *tmpbuf;
1127 int tmpsize, tmplen;
1128 int offset = ib->offset;
1129
1130 tmpbuf = ib->str[0];
1131 tmpsize = ib->size[0];
1132 for (i = 0 ; i < offset - 1 ; i++) {
1133 ib->str[i] = ib->str[i + 1];
1134 ib->size[i] = ib->size[i + 1];
1135 ib->len[i] = ib->len[i + 1];
1136 }
1137 ib->str[offset - 1] = tmpbuf;
1138 ib->size[offset - 1] = tmpsize;
1139 }
1140
1141 /* cfuncdef
1142
1143 shiftLeftAll -- ibuf $B$NJ8;z%P%C%U%!A4BN$r:8$K%7%U%H$9$k(B
1144
1145 */
1146
1147 static
1148 shiftLeftAll(ib)
1149 iBuf *ib;
1150 {
1151 int i;
1152 wchar *tmpbuf;
1153 int tmpsize, tmplen;
1154 int nseg = ib->nseg;
1155
1156 tmpbuf = ib->str[0];
1157 tmpsize = ib->size[0];
1158 for (i = 0 ; i < nseg - 1 ; i++) {
1159 ib->str[i] = ib->str[i + 1];
1160 ib->size[i] = ib->size[i + 1];
1161 ib->len[i] = ib->len[i + 1];
1162 }
1163 ib->str[nseg - 1] = tmpbuf;
1164 ib->size[nseg - 1] = tmpsize;
1165 ib->nseg--;
1166 ib->curseg--;
1167 ib->offset--;
1168 }
1169
1170 /* cfuncdef
1171
1172 ibufInitialize -- ibuf $B$N=i4|2==hM}(B
1173 */
1174
1175 static
1176 ibufInitialize(obj)
1177 CannaObject obj;
1178 {
1179 int i;
1180 iBuf *ib;
1181
1182 ib = obj->canna.ibuf = (iBuf *)XtMalloc(sizeof(iBuf));
1183 if (ib == 0) {
1184 /* $B%(%i!<$@!#$I$&$9$Y(B */
1185 }
1186 for (i = 0 ; i < NConvertedSegments + 3 ; i++) {
1187 ib->size[i] = 0;
1188 ib->len[i] = 0;
1189 }
1190 ib->offset = ib->curseg = ib->nseg = 0;
1191 ib->candstat = CANNA_GLINE_Empty;
1192 for (i = 0 ; i < 3 ; i++) {
1193 ib->gline[i] = 0;
1194 ib->glsize[i] = ib->gllen[i] = 0;
1195 }
1196 ib->modesize = 0;
1197 ib->modelen = 0;
1198 }
1199
1200 /* cfuncdef
1201
1202 freeIBuf -- ibuf $B$N(B free
1203
1204 */
1205
1206 static
1207 freeIBuf(ib)
1208 iBuf *ib;
1209 {
1210 int i;
1211
1212 if (ib == 0) {
1213 return 0;
1214 }
1215 for (i = 0 ; i < NConvertedSegments + 3 ; i++) {
1216 if (ib->size[i] > 0) {
1217 XtFree((char *)ib->str[i]);
1218 }
1219 }
1220 for (i = 0 ; i < 3 ; i++) {
1221 if (ib->glsize[i] > 0) {
1222 XtFree((char *)ib->gline[i]);
1223 }
1224 }
1225 if (ib->modesize > 0) {
1226 XtFree((char *)ib->curmode);
1227 }
1228 free(ib);
1229 return 0;
1230 }
1231
1232 static
1233 toJapaneseMode(obj)
1234 CannaObject obj;
1235 {
1236 wcKanjiStatusWithValue ksv;
1237 wcKanjiStatus ks;
1238 wchar buf[1024];
1239
1240 buf[0] = '@';
1241 ksv.ks = &ks;
1242 ksv.buffer = buf;
1243 ksv.n_buffer = 1024;
1244 #ifndef KC_DO
1245 ksv.val = CANNA_MODE_HenkanMode;
1246 wcKanjiControl((int)obj, KC_CHANGEMODE, (char *)&ksv);
1247 #else
1248 ksv.val = CANNA_FN_JapaneseMode;
1249 wcKanjiControl((int)obj, KC_DO, (char *)&ksv);
1250 #endif
1251 changeTextForCanna(obj, &ks);
1252 }
1253
1254 /* checkIfFunctionalChar -- $B%7%U%H%-!<$N$h$&$KL50UL#$J%-!<$+$I$&$+$NH=JL(B
1255
1256 $BCM(B: $B#1(B $B0UL#$,$"$k(B
1257 $B#0(B $BL50UL#(B($B%b%G%#%U%!%$%"%-!<$J$I(B)
1258 */
1259
1260 static int
1261 checkIfFunctionalChar(event_struct, keysym, buffer_return, n_buffer)
1262 XKeyEvent *event_struct;
1263 KeySym keysym;
1264 wchar *buffer_return;
1265 int n_buffer;
1266 {
1267 int functionalChar = 0;
1268
1269 switch ((int)keysym)
1270 {
1271 case XK_KP_F1:
1272 case XK_KP_F2:
1273 case XK_KP_F3:
1274 case XK_KP_F4:
1275 *buffer_return = CANNA_KEY_PF1 + (int)keysym - (int)XK_KP_F1;
1276 functionalChar = 1;
1277 break;
1278 case XK_F1:
1279 case XK_F2:
1280 case XK_F3:
1281 case XK_F4:
1282 case XK_F5:
1283 case XK_F6:
1284 case XK_F7:
1285 case XK_F8:
1286 case XK_F9:
1287 case XK_F10:
1288 case XK_F11:
1289 case XK_F12:
1290 case XK_F13:
1291 case XK_F14:
1292 case XK_F15:
1293 case XK_F16:
1294 *buffer_return = CANNA_KEY_F1 + (int)keysym - (int)XK_F1;
1295 functionalChar = 1;
1296 break;
1297 case XK_Insert:
1298 *buffer_return = CANNA_KEY_Insert;
1299 functionalChar = 1;
1300 break;
1301 case XK_Prior:
1302 *buffer_return = CANNA_KEY_Rollup;
1303 functionalChar = 1;
1304 break;
1305 case XK_Next:
1306 *buffer_return = CANNA_KEY_Rolldown;
1307 functionalChar = 1;
1308 break;
1309 case XK_Muhenkan:
1310 if (event_struct->state & 4 /* control-shifted */)
1311 *buffer_return = CANNA_KEY_Cntrl_Nfer;
1312 else if (event_struct->state & 1 /* shifted */)
1313 *buffer_return = CANNA_KEY_Shift_Nfer;
1314 else
1315 *buffer_return = CANNA_KEY_Nfer;
1316 functionalChar = 1;
1317 break;
1318 case XK_Kanji:
1319 if (event_struct->state & 4 /* control-shifted */)
1320 *buffer_return = CANNA_KEY_Cntrl_Xfer;
1321 else if (event_struct->state & 1 /* shifted */)
1322 *buffer_return = CANNA_KEY_Shift_Xfer;
1323 else
1324 *buffer_return = CANNA_KEY_Xfer;
1325 functionalChar = 1;
1326 break;
1327 case XK_Up:
1328 if (event_struct->state & 4 /* control-shifted */)
1329 *buffer_return = CANNA_KEY_Cntrl_Up;
1330 else if (event_struct->state & 1 /* shifted */)
1331 *buffer_return = CANNA_KEY_Shift_Up;
1332 else
1333 *buffer_return = CANNA_KEY_Up;
1334 functionalChar = 1;
1335 break;
1336 case XK_Down:
1337 if (event_struct->state & 4 /* control-shifted */)
1338 *buffer_return = CANNA_KEY_Cntrl_Down;
1339 else if (event_struct->state & 1 /* shifted */)
1340 *buffer_return = CANNA_KEY_Shift_Down;
1341 else
1342 *buffer_return = CANNA_KEY_Down;
1343 functionalChar = 1;
1344 break;
1345 case XK_Right:
1346 if (event_struct->state & 4 /* control-shifted */)
1347 *buffer_return = CANNA_KEY_Cntrl_Right;
1348 else if (event_struct->state & 1 /* shifted */)
1349 *buffer_return = CANNA_KEY_Shift_Right;
1350 else
1351 *buffer_return = CANNA_KEY_Right;
1352 functionalChar = 1;
1353 break;
1354 case XK_Left:
1355 if (event_struct->state & 4 /* control-shifted */)
1356 *buffer_return = CANNA_KEY_Cntrl_Left;
1357 else if (event_struct->state & 1 /* shifted */)
1358 *buffer_return = CANNA_KEY_Shift_Left;
1359 else
1360 *buffer_return = CANNA_KEY_Left;
1361 functionalChar = 1;
1362 break;
1363 case XK_Help:
1364 *buffer_return = CANNA_KEY_Help;
1365 functionalChar = 1;
1366 break;
1367 case XK_Home:
1368 *buffer_return = CANNA_KEY_Home;
1369 functionalChar = 1;
1370 break;
1371 }
1372 return functionalChar;
1373 }
1374
1375 #ifdef KC_SETLISTCALLBACK
1376
1377 static void
1378 moveSelection(obj, dir)
1379 CannaObject obj;
1380 int dir;
1381 {
1382 ICSelectionControlArg arg;
1383
1384 arg.command = ICSelectionMove;
1385 arg.u.dir = dir;
1386 XtCallCallbackList((Widget)obj, obj->inputConv.selectioncallback,
1387 (XtPointer)&arg);
1388 }
1389
1390 static int
1391 insertSelection(obj, selected)
1392 CannaObject obj;
1393 int selected;
1394 {
1395 obj->canna.curcand = selected;
1396 *(obj->canna.cur_addr) = selected;
1397
1398 return 0;
1399 }
1400
1401 static void
1402 endSelection(obj, abort)
1403 CannaObject obj;
1404 int abort;
1405 {
1406 ICSelectionControlArg arg;
1407 int selected;
1408
1409 if (ignoreListfunc) return; /* SelectItem $B$G=hM}$5$l$k$N$G$3$3$OITMW(B */
1410 arg.command = ICSelectionEnd;
1411 arg.u.current_item = -1;
1412 XtCallCallbackList((Widget)obj, obj->inputConv.selectioncallback,
1413 (XtPointer)&arg);
1414
1415 if (!abort && (selected = arg.u.current_item) >= 0) {
1416 insertSelection(obj, selected);
1417 }
1418 }
1419
1420 #ifdef CANNA_LIST_Query
1421 static void
1422 querySelection(obj)
1423 CannaObject obj;
1424 {
1425 ICSelectionControlArg arg;
1426 int selected;
1427
1428 if (ignoreListfunc) return; /* SelectItem $B$G=hM}$5$l$k$N$G$3$3$OITMW(B */
1429 arg.command = ICSelectionGet;
1430 arg.u.current_item = -1;
1431 XtCallCallbackList((Widget)obj, obj->inputConv.selectioncallback,
1432 (XtPointer)&arg);
1433
1434 if ((selected = arg.u.current_item) >= 0) {
1435 insertSelection(obj, selected);
1436 }
1437 }
1438 #endif
1439
1440 static void
1441 openSelection(obj, func, curitem)
1442 CannaObject obj;
1443 int func; /* $B0lHV>e$r8+$h(B */
1444 int curitem;
1445 {
1446 ICSelectionControlArg arg;
1447 static int current = 0;
1448 static int doit = 0;
1449
1450 if (func == SELECTION_SET) {
1451 current = curitem;
1452 doit = 1;
1453 }
1454 else if (func == SELECTION_DO && doit) {
1455 doit = 0;
1456 arg.command = ICSelectionStart;
1457 arg.u.selection_kind = ICSelectionCandidates;
1458 XtCallCallbackList((Widget)obj, obj->inputConv.selectioncallback,
1459 (XtPointer)&arg);
1460
1461 /* set current item */
1462 arg.command = ICSelectionSet;
1463 arg.u.current_item = current;
1464 XtCallCallbackList((Widget)obj, obj->inputConv.selectioncallback,
1465 (XtPointer)&arg);
1466 }
1467 }
1468
1469 static void getAllCandidates();
1470
1471 /* listfunc -- $B8uJd0lMw%b!<%I$K$J$C$?;~$K8F$S=P$5$l$k4X?t(B
1472 *
1473 * obj : KC_SETLISTCALLBACK $B$G@_Dj$7$?%/%i%$%"%s%H%G!<%?(B
1474 * func : $B8uJd0lMw5!G=$N8GM-$N5!G=$rI=$9#I#D(B
1475 * items : Start $B$N;~$K$O8uJd0lMw$NA4%"%$%F%`$,F~$k(B
1476 * nitems : $B!7(B $BA4%"%$%F%`$N?t$,F~$k(B
1477 * cur_item : $B!7(B $B%+%l%s%H%"%$%F%`HV9f$r3JG<$9$k%"%I%l%9$,F~$k(B
1478 */
1479
1480 static CANNA_LISTFUNCTYPE
1481 listfunc(obj, func, items, nitems, cur_item)
1482 CannaObject obj;
1483 int func;
1484 wchar **items;
1485 int nitems, *cur_item;
1486 {
1487 ICSelectionControlArg arg;
1488 int i;
1489 wchar **p;
1490
1491 switch (func) {
1492 case CANNA_LIST_Start:
1493 getAllCandidates(obj, nitems, items);
1494 obj->canna.numcand = nitems;
1495 obj->canna.curcand = *cur_item;
1496 obj->canna.cur_addr = cur_item;
1497 openSelection(obj, SELECTION_SET, *cur_item);
1498 break;
1499 case CANNA_LIST_Select:
1500 endSelection(obj, False);
1501 break;
1502 case CANNA_LIST_Quit:
1503 endSelection(obj, True);
1504 break;
1505 #ifdef CANNA_LIST_Query
1506 case CANNA_LIST_Query:
1507 querySelection(obj);
1508 break;
1509 #endif
1510 #ifdef CANNA_LIST_Convert
1511 case CANNA_LIST_Convert:
1512 #endif
1513 case CANNA_LIST_Forward:
1514 moveSelection(obj, ICMoveRight);
1515 break;
1516 case CANNA_LIST_Backward:
1517 moveSelection(obj, ICMoveLeft);
1518 break;
1519 case CANNA_LIST_Next:
1520 moveSelection(obj, ICMoveDown);
1521 break;
1522 case CANNA_LIST_Prev:
1523 moveSelection(obj, ICMoveUp);
1524 break;
1525 case CANNA_LIST_BeginningOfLine:
1526 moveSelection(obj, ICMoveLeftMost);
1527 break;
1528 case CANNA_LIST_EndOfLine:
1529 moveSelection(obj, ICMoveRightMost);
1530 break;
1531 #ifdef CANNA_LIST_Insert
1532 case CANNA_LIST_Insert:
1533 return 0;
1534 #endif
1535 }
1536 #ifdef CANNA_LIST_Convert
1537 return 1;
1538 #endif
1539 }
1540
1541 static void
1542 allocCandlist(obj, n)
1543 CannaObject obj;
1544 int n;
1545 {
1546 ICString *p;
1547 int i;
1548
1549 if (n <= obj->canna.candlistsize) return;
1550
1551 if (obj->canna.candlistsize == 0) {
1552 p = (ICString *)XtMalloc(n * sizeof(ICString));
1553 } else {
1554 p = (ICString *)XtRealloc((char *)obj->canna.candlist,
1555 n * sizeof(ICString));
1556 }
1557 for (i = obj->canna.candlistsize ; i < n ; i++) {
1558 p[i].nbytes = p[i].nchars = (unsigned short)0;
1559 p[i].data = (char *)0;
1560 p[i].attr = 0;
1561 }
1562
1563 obj->canna.candlist = p;
1564 obj->canna.candlistsize = n;
1565 }
1566
1567 static void
1568 getAllCandidates(obj, ncand, items)
1569 CannaObject obj;
1570 int ncand;
1571 wchar **items;
1572 {
1573 ICString *strp;
1574 wchar **p;
1575 int i, bytes, chars;
1576
1577 allocCandlist(obj, ncand);
1578
1579 for (i = 0, strp = obj->canna.candlist, p = items ;
1580 i < ncand; i++, strp++, p++) {
1581 int len = 0;
1582
1583 bytes = strp->nbytes;
1584 chars = strp->nchars;
1585 while ((*p)[len]) len++;
1586 copyInWchar(*p, len, (wchar **)&(strp->data), &bytes, &chars);
1587 strp->nbytes = bytes;
1588 strp->nchars = chars;
1589 strp->attr = ICAttrNormalString;
1590 }
1591 }
1592 #endif /* KC_SETLISTCALLBACK */
1593
1594 struct _keymap {
1595 unsigned char cannakey;
1596 KeySym keysym;
1597 long modifier;
1598 } cannakeymap[] = {
1599 {(unsigned char)'\b', XK_BackSpace, 0},
1600 {(unsigned char)'\t', XK_Tab, 0},
1601 {(unsigned char)'\n', XK_Linefeed, 0},
1602 {(unsigned char)'\013', XK_Clear, 0},
1603 {(unsigned char)'\r', XK_Return, 0},
1604 {(unsigned char)'\023', XK_Pause, 0},
1605 {(unsigned char)'\024', XK_Scroll_Lock, 0},
1606 {(unsigned char)'\e', XK_Escape, 0},
1607 {(unsigned char)CANNA_KEY_Nfer, XK_Muhenkan, 0},
1608 {(unsigned char)CANNA_KEY_Xfer, XK_Kanji, 0},
1609 {(unsigned char)CANNA_KEY_Up, XK_Up, 0},
1610 {(unsigned char)CANNA_KEY_Left, XK_Left, 0},
1611 {(unsigned char)CANNA_KEY_Right, XK_Right, 0},
1612 {(unsigned char)CANNA_KEY_Down, XK_Down, 0},
1613 {(unsigned char)CANNA_KEY_Insert, XK_Insert, 0},
1614 {(unsigned char)CANNA_KEY_Rollup, XK_Prior, 0},
1615 {(unsigned char)CANNA_KEY_Rolldown, XK_Next, 0},
1616 {(unsigned char)CANNA_KEY_Home, XK_Home, 0},
1617 {(unsigned char)CANNA_KEY_Help, XK_Help, 0},
1618 {(unsigned char)CANNA_KEY_KP_Key, XK_KP_Space, 0}, /* ? */
1619 {(unsigned char)CANNA_KEY_Shift_Nfer, XK_Muhenkan, ShiftMask},
1620 {(unsigned char)CANNA_KEY_Shift_Xfer, XK_Kanji, ShiftMask},
1621 {(unsigned char)CANNA_KEY_Shift_Up, XK_Up, ShiftMask},
1622 {(unsigned char)CANNA_KEY_Shift_Left, XK_Left, ShiftMask},
1623 {(unsigned char)CANNA_KEY_Shift_Right, XK_Right, ShiftMask},
1624 {(unsigned char)CANNA_KEY_Shift_Down, XK_Down, ShiftMask},
1625 {(unsigned char)CANNA_KEY_Cntrl_Nfer, XK_Muhenkan, ControlMask},
1626 {(unsigned char)CANNA_KEY_Cntrl_Xfer, XK_Kanji, ControlMask},
1627 {(unsigned char)CANNA_KEY_Cntrl_Up, XK_Up, ControlMask},
1628 {(unsigned char)CANNA_KEY_Cntrl_Left, XK_Left, ControlMask},
1629 {(unsigned char)CANNA_KEY_Cntrl_Right, XK_Right, ControlMask},
1630 {(unsigned char)CANNA_KEY_Cntrl_Down, XK_Down, ControlMask},
1631 {(unsigned char)CANNA_KEY_F1, XK_F1, 0},
1632 {(unsigned char)CANNA_KEY_F2, XK_F2, 0},
1633 {(unsigned char)CANNA_KEY_F3, XK_F3, 0},
1634 {(unsigned char)CANNA_KEY_F4, XK_F4, 0},
1635 {(unsigned char)CANNA_KEY_F5, XK_F5, 0},
1636 {(unsigned char)CANNA_KEY_F6, XK_F6, 0},
1637 {(unsigned char)CANNA_KEY_F7, XK_F7, 0},
1638 {(unsigned char)CANNA_KEY_F8, XK_F8, 0},
1639 {(unsigned char)CANNA_KEY_F9, XK_F9, 0},
1640 {(unsigned char)CANNA_KEY_F10, XK_F10, 0},
1641 {(unsigned char)CANNA_KEY_PF1, XK_KP_F1, 0},
1642 {(unsigned char)CANNA_KEY_PF2, XK_KP_F2, 0},
1643 {(unsigned char)CANNA_KEY_PF3, XK_KP_F3, 0},
1644 {(unsigned char)CANNA_KEY_PF4, XK_KP_F4, 0},
1645 {(unsigned char)CANNA_KEY_PF5, XK_F15, 0},
1646 {(unsigned char)CANNA_KEY_PF6, XK_F16, 0},
1647 {(unsigned char)CANNA_KEY_PF7, XK_F17, 0},
1648 {(unsigned char)CANNA_KEY_PF8, XK_F18, 0},
1649 {(unsigned char)CANNA_KEY_PF9, XK_F19, 0},
1650 {(unsigned char)CANNA_KEY_PF10, XK_F20, 0},
1651 };
1652
1653 #define NCANNAKEYMAP (sizeof(cannakeymap) / sizeof(struct _keymap))
1654
1655 /* ARGSUSED */
1656 static int
1657 GetTriggerKeys(w, keys_return)
1658 Widget w;
1659 ICTriggerKey **keys_return;
1660 {
1661 CannaObject obj = (CannaObject)w;
1662 ICTriggerKey *keys;
1663 unsigned char c, mkeys[256], *p, *ekeys; /* enough */
1664 int n;
1665 struct _keymap *pk, *ek;
1666
1667 n = wcKanjiControl((int)obj, KC_MODEKEYS, (char *)mkeys);
1668
1669 *keys_return = keys =
1670 (ICTriggerKey *)XtMalloc(2 * n * sizeof(ICTriggerKey));
1671 /* $B!V(B2 *$B!W$N0UL#(B:
1672 $B0l$D$N%3!<%I$K(B2$B$D$N(B X $B$N%-!<$,B8:_$7$F$$$?$j$9$k;v$,$"$k!#(B
1673 ($BNc(B) C-h $B"*(B Ctl<Key>h, <Key>Backspace */
1674
1675 if (keys) {
1676 for (p = mkeys, ekeys = p + n ; p < ekeys ; p++, keys++) {
1677 c = *p;
1678 if (c == (unsigned char)0) {
1679 keys->keysym = XK_space;
1680 keys->modifiers = keys->modifiermask = ControlMask;
1681 keys++;
1682 keys->keysym = XK_at;
1683 keys->modifiers = keys->modifiermask = ControlMask;
1684 }
1685 else if (c < ' ') {
1686 keys->keysym = XK_quoteleft + c;
1687 keys->modifiers = keys->modifiermask = ControlMask;
1688 for (pk = cannakeymap, ek = cannakeymap + NCANNAKEYMAP ;
1689 pk < ek ; pk++) {
1690 if (c == pk->cannakey) {
1691 keys++;
1692 keys->keysym = pk->keysym;
1693 keys->modifiers = keys->modifiermask = pk->modifier;
1694 }
1695 }
1696 }
1697 else if (c <= '~') {
1698 keys->keysym = XK_space + (c - (unsigned char)' ');
1699 keys->modifiers = keys->modifiermask = 0;
1700 }
1701 else if (c == 0x7f) {
1702 keys->keysym = XK_Delete;
1703 keys->modifiers = keys->modifiermask = 0;
1704 }
1705 else if ((unsigned char)0xa1 <= c && c <= (unsigned char)0xdf) {
1706 keys->keysym = XK_kana_fullstop + (c - (unsigned char)0xa1);
1707 keys->modifiers = keys->modifiermask = pk->modifier;
1708 }
1709 else {
1710 keys--;
1711 for (pk = cannakeymap, ek = cannakeymap + NCANNAKEYMAP ;
1712 pk < ek ; pk++) {
1713 if (c == pk->cannakey) {
1714 keys++;
1715 keys->keysym = pk->keysym;
1716 keys->modifiers = keys->modifiermask = pk->modifier;
1717 }
1718 }
1719 }
1720 }
1721 return n;
1722 }
1723 return 0;
1724 }
1725
1726 /* ARGSUSED */
1727 static int
1728 PreeditString(w, segn, offset, encoding, format, length, string)
1729 Widget w;
1730 int segn;
1731 int offset;
1732 Atom *encoding;
1733 int *format;
1734 int *length;
1735 XtPointer *string;
1736 {
1737 CannaObject obj = (CannaObject)w;
1738 iBuf *ib = obj->canna.ibuf;
1739 int i;
1740 wchar *wbuf, *wp;
1741 int len, wlen;
1742 extern int convJWStoCT();
1743
1744 if (ib == NULL) return -1;
1745 if (segn < ib->nseg && offset >= ib->len[segn]) {
1746 /* $B%;%0%a%s%H$N:G8e(B */
1747 ++segn;
1748 offset = 0;
1749 }
1750 if (segn >= ib->nseg || offset >= ib->len[segn]) {
1751 /* $B:o=|$5$l$?(B */
1752 *encoding = XA_COMPOUND_TEXT(XtDisplayOfObject(w));
1753 *format = 8;
1754 *length = 0;
1755 *string = (XtPointer)XtMalloc(1);
1756 return 0;
1757 }
1758
1759 wlen = 0;
1760 for (i = segn; i < ib->nseg; i++) {
1761 wlen += ib->len[i];
1762 }
1763 wlen -= offset;
1764
1765 wp = wbuf = (wchar *)XtMalloc((wlen + 1) * sizeof(wchar));
1766 len = ib->len[segn] - offset;
1767 (void)bcopy((char *)(ib->str[segn] + offset), (char *)wp, sizeof(wchar) * len);
1768 wp += len;
1769 for (i = segn + 1; i < ib->nseg; i++) {
1770 len = ib->len[i];
1771 (void)bcopy((char *)ib->str[i], (char *)wp, sizeof(wchar) * len);
1772 wp += len;
1773 }
1774 wbuf[wlen] = 0;
1775
1776 /*
1777 * Canna $B%*%V%8%'%/%H$O(B COMPOUND_TEXT $B%(%s%3!<%G%#%s%0$7$+%5%]!<%H$7$J$$(B
1778 * COMPOUND_TEXT $B$KJQ49$9$k(B
1779 */
1780 *encoding = XA_COMPOUND_TEXT(XtDisplayOfObject(w));
1781 *format = 8;
1782
1783 /* COMPOUND_TEXT $B$O(B \r $B$,Aw$l$J$$$N$G(B \n $B$KJQ49$7$F$*$/(B */
1784 for (wp = wbuf; *wp != 0; wp++) {
1785 if (*wp == '\r') *wp = '\n';
1786 }
1787
1788 *length = len = convJWStoCT(wbuf, (unsigned char *)NULL, 0);
1789 *string = (XtPointer)XtMalloc(len + 1);
1790 (void)convJWStoCT(wbuf, (unsigned char *)*string, 0);
1791
1792 /* wbuf $B$r(B free $B$7$F$*$/(B */
1793 XtFree((char *)wbuf);
1794
1795 return 0;
1796 }
1797
1798 /* ARGSUSED */
1799 static int
1800 StatusString(w, encoding, format, length, string, nchars)
1801 Widget w;
1802 Atom *encoding;
1803 int *format;
1804 int *length;
1805 XtPointer *string;
1806 int *nchars;
1807 {
1808 ICString *seg;
1809 wchar *wbuf, *wp;
1810 int len, wlen;
1811 extern int convJWStoCT();
1812
1813 seg = GetMode(w);
1814 if (seg == NULL) {
1815 *length = *nchars = 0;
1816 return -1;
1817 }
1818
1819 wlen = seg->nchars;
1820 if (wlen <= 0) {
1821 *length = *nchars = 0;
1822 return -1;
1823 }
1824
1825 /*
1826 * data $B$KF~$C$F$$$kJQ49%F%-%9%H$O(B null $B%?!<%_%M!<%H$5$l$F$$$J$$$+$b(B
1827 * $B$7$l$J$$$N$G!"$^$:%3%T!<$7$F(B null $B%?!<%_%M!<%H$9$k(B
1828 */
1829 wbuf = (wchar *)XtMalloc((wlen + 1) * sizeof(wchar));
1830 (void)bcopy(seg->data, (char *)wbuf, sizeof(wchar) * wlen);
1831 wbuf[wlen] = 0;
1832
1833 /*
1834 * Canna $B%*%V%8%'%/%H$O(B COMPOUND_TEXT $B%(%s%3!<%G%#%s%0$7$+%5%]!<%H$7$J$$(B
1835 * COMPOUND_TEXT $B$KJQ49$9$k(B
1836 */
1837 *encoding = XA_COMPOUND_TEXT(XtDisplayOfObject(w));
1838 *format = 8;
1839
1840 /* COMPOUND_TEXT $B$O(B \r $B$,Aw$l$J$$$N$G(B \n $B$KJQ49$7$F$*$/(B */
1841 for (wp = wbuf; *wp != 0; wp++) {
1842 if (*wp == '\r') *wp = '\n';
1843 }
1844
1845 *length = len = convJWStoCT(wbuf, (unsigned char *)NULL, 0);
1846 *string = XtMalloc(len + 1);
1847 (void)convJWStoCT(wbuf, (unsigned char *)*string, 0);
1848 *nchars = seg->nchars;
1849
1850 /* wbuf $B$r(B free $B$7$F$*$/(B */
1851 XtFree((char *)wbuf);
1852
1853 return 0;
1854 }