comparison lib/Sj3.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
comparison
equal deleted inserted replaced
-1:000000000000 0:92745d501b9a
1 #ifndef lint
2 static char *rcsid = "$Id: Sj3.c,v 2.10 1999/05/25 08:13:05 ishisone Exp $";
3 #endif
4 /*
5 * Copyright (c) 1990 Software Research Associates, Inc.
6 *
7 * Permission to use, copy, modify, and distribute this software and its
8 * documentation for any purpose and without fee is hereby granted, provided
9 * that the above copyright notice appear in all copies and that both that
10 * copyright notice and this permission notice appear in supporting
11 * documentation, and that the name of Software Research Associates not be
12 * used in advertising or publicity pertaining to distribution of the
13 * software without specific, written prior permission. Software Research
14 * Associates makes no representations about the suitability of this software
15 * for any purpose. It is provided "as is" without express or implied
16 * warranty.
17 *
18 * Author: Makoto Ishisone, Software Research Associates, Inc., Japan
19 */
20 /*
21 * Copyright 1991 Sony Corporation
22 *
23 * Permission to use, copy, modify, distribute, and sell this software and its
24 * documentation for any purpose is hereby granted without fee, provided that
25 * the above copyright notice appear in all copies and that both that
26 * copyright notice and this permission notice appear in supporting
27 * documentation, and that the name of Sony not be used in advertising or
28 * publicity pertaining to distribution of the software without specific,
29 * written prior permission. Sony makes no representations about the
30 * suitability of this software for any purpose. It is provided "as is"
31 * without express or implied warranty.
32 *
33 * SONY DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
34 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SONY
35 * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
36 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
37 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
38 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
39 */
40 /*
41 * Author: Naoshi Suzuki, SONY Corporation. (nao@sm.sony.co.jp)
42 */
43
44 #include <X11/IntrinsicP.h>
45 #include <X11/StringDefs.h>
46 #if XtSpecificationRelease > 4
47 #include <X11/Xfuncs.h>
48 #endif
49 #include <X11/Xmu/Atoms.h>
50 #include <X11/Xutil.h>
51 #include <X11/keysym.h>
52 #ifdef X_LOCALE
53 #include <X11/Xlocale.h>
54 #else /* X_LOCALE */
55 #include <locale.h>
56 #endif /* X_LOCALE */
57 #include <pwd.h>
58 #include "Sj3P.h"
59
60 static XtResource resources[] = {
61 #define offset(field) XtOffset(Sj3Object, sj3.field)
62 { XtNsj3serv, XtCSj3serv, XtRString, sizeof(String),
63 offset(sj3serv), XtRString, NULL },
64 { XtNsj3serv2, XtCSj3serv2, XtRString, sizeof(String),
65 offset(sj3serv2), XtRString, NULL },
66 { XtNsj3user, XtCSj3user, XtRString, sizeof(String),
67 offset(sj3user), XtRString, NULL },
68 { XtNrcfile, XtCRcfile, XtRString, sizeof(String),
69 offset(rcfile), XtRString, NULL },
70 { XtNsbfile, XtCSbfile, XtRString, sizeof(String),
71 offset(sbfile), XtRString, NULL },
72 { XtNrkfile, XtCRkfile, XtRString, sizeof(String),
73 offset(rkfile), XtRString, NULL },
74 { XtNhkfile, XtCHkfile, XtRString, sizeof(String),
75 offset(hkfile), XtRString, NULL },
76 { XtNzhfile, XtCZhfile, XtRString, sizeof(String),
77 offset(zhfile), XtRString, NULL },
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 ICString *GetAuxSegments();
95 static int PreeditString();
96 static int StatusString();
97
98 Sj3ClassRec sj3ClassRec = {
99 { /* object fields */
100 /* superclass */ (WidgetClass) &inputConvClassRec,
101 /* class_name */ "Sj3",
102 /* widget_size */ sizeof(Sj3Rec),
103 /* class_initialize */ ClassInitialize,
104 /* class_part_initialize */ NULL,
105 /* class_inited */ FALSE,
106 /* initialize */ Initialize,
107 /* initialize_hook */ NULL,
108 /* obj1 */ NULL,
109 /* obj2 */ NULL,
110 /* obj3 */ 0,
111 /* resources */ resources,
112 /* num_resources */ XtNumber(resources),
113 /* xrm_class */ NULLQUARK,
114 /* obj4 */ FALSE,
115 /* obj5 */ FALSE,
116 /* obj6 */ FALSE,
117 /* obj7 */ FALSE,
118 /* destroy */ Destroy,
119 /* obj8 */ NULL,
120 /* obj9 */ NULL,
121 /* set_values */ SetValues,
122 /* set_values_hook */ NULL,
123 /* obj10 */ NULL,
124 /* get_values_hook */ NULL,
125 /* obj11 */ NULL,
126 /* version */ XtVersion,
127 /* callback_private */ NULL,
128 /* obj12 */ NULL,
129 /* obj13 */ NULL,
130 /* obj14 */ NULL,
131 /* extension */ NULL
132 },
133 { /* inputConv fields */
134 /* InputEvent */ InputEvent,
135 /* GetMode */ GetMode,
136 /* CursorPos */ CursorPos,
137 /* NumSegments */ NumSegments,
138 /* GetSegment */ GetSegment,
139 /* CompareSegment */ CompareSegment,
140 /* GetItemList */ GetItemList,
141 /* SelectItem */ SelectItem,
142 /* GetConvertedString */ ConvertedString,
143 /* ClearConversion */ ClearConversion,
144 /* GetAuxSegments */ GetAuxSegments,
145 /* SupportMultipleObjects */ True,
146 /* GetTriggerKeys */ XtInheritGetTriggerKeys,
147 /* num_trigger_keys */ 0,
148 /* trigger_keys */ NULL,
149 /* GetPreeditString */ PreeditString,
150 /* GetStatusString */ StatusString,
151 /* NoMoreObjects */ False,
152 },
153 { /* sj3 fields */
154 /* foo */ (int)NULL,
155 }
156 };
157
158 WidgetClass sj3ObjectClass = (WidgetClass)&sj3ClassRec;
159
160 static void startCandidate();
161 static void startSymbol();
162 static void startHinsi();
163 static void moveSelection();
164 static int endSelection();
165 static int insertSelection();
166 static void hinsiInit();
167 static void symbolInit();
168 static void allocCandlist();
169 static void startRegistration();
170 static void changeRegistration();
171 static void endRegistration();
172 static void setLocale();
173 static void setUser();
174
175 static void addObject();
176 static void deleteObject();
177 static void bell();
178
179 static ICString *SymbolList = NULL;
180 static int NumSymbol;
181 static ICString *HinsiList = NULL;
182 static int NumHinsi;
183
184 static int clcount = 0;
185
186 static int usr_code;
187 static char home[256];
188 static char uname[32];
189
190 /*
191 * ClassInitialize()
192 * Initialize common resource.
193 */
194 static void
195 ClassInitialize()
196 {
197 setLocale();
198 setUser();
199
200 Xsj3cSetInLang(usr_code);
201 Xsj3cSetOutLang(JP_EUC);
202 }
203
204 /*
205 * setLocale()
206 * Set locale and decide file code for all set-up files.
207 */
208 static void
209 setLocale()
210 {
211 char *loc;
212
213 #ifdef X_LOCALE
214 if (loc = _Xsetlocale (LC_CTYPE, "")) {
215 #else /* X_LOCALE */
216 if (loc = setlocale (LC_CTYPE, "")) {
217 #endif /* X_LOCALE */
218 if (!strcmp(loc, "ja_JP.SJIS")||!strcmp(loc, "ja_JP.mscode"))
219 usr_code = JP_SJIS;
220 else if (!strcmp(loc, "ja_JP.jis7"))
221 usr_code = JP_JIS7;
222 else if (!strcmp(loc, "ja_JP.jis8"))
223 usr_code = JP_JIS8;
224 else
225 usr_code = JP_EUC;
226 } else
227 usr_code = JP_EUC;
228 #ifdef FORCE_SJIS
229 usr_code = JP_SJIS;
230 #endif
231 #ifdef FORCE_JIS8
232 usr_code = JP_JIS8;
233 #endif
234 #ifdef FORCE_JIS7
235 usr_code = JP_JIS7;
236 #endif
237 }
238
239 /*
240 * setUser()
241 * Set user name and home directory.
242 */
243 static void
244 setUser()
245 {
246 extern char *getenv(), *getlogin();
247 char *login;
248 struct passwd *pwd, *getpwnam(), *getpwuid();
249
250
251 if (login = getlogin())
252 strcpy(uname, login);
253 setpwent();
254 if (!uname || *uname == '\0') {
255 if (pwd = getpwuid(getuid())) {
256 strcpy(uname, pwd->pw_name);
257 }
258 } else {
259 pwd = getpwnam(uname);
260 }
261 if (pwd)
262 strcpy(home, pwd->pw_dir);
263 else
264 strcpy(home, getenv("HOME"));
265 endpwent();
266 }
267
268 /*
269 * InputEvent()
270 * KeyPress event dispatch routine
271 */
272 static int
273 InputEvent(w, ev)
274 Widget w;
275 XEvent *ev;
276 {
277 Sj3Object obj = (Sj3Object)w;
278 Xsj3cBuf buf = obj->sj3.sj3buf;
279 int ret = 0, len, nbytes;
280 unsigned char *pre;
281 unsigned long modmask;
282 KeySym ks;
283 register Xsj3cEvent value, select, dict;
284
285 /* KeyPress$B0J30$O<N$F$k(B */
286 if (ev->type != KeyPress)
287 return ret;
288
289 pre = Xsj3cGetPreeditArea(buf, &len);
290
291 /* $B%$%Y%s%H$rJ8;zNs5Z$S(B KeySym $B$KJQ49$9$k(B */
292 nbytes = XmuLookupKana((XKeyPressedEvent *)ev, (char *)pre, len, &ks, NULL);
293 modmask = ev->xkey.state & 0xff;
294
295 value = Xsj3cKeyConv(buf, nbytes, modmask, ks);
296
297 if (select = (value & KEY_SELECT)) {
298 switch (select) {
299 case KEY_CAND_START:
300 startCandidate(obj);
301 break;
302 case KEY_SYMBOL_START:
303 startSymbol(obj);
304 break;
305 case KEY_HINSI_START:
306 startHinsi(obj);
307 break;
308 case KEY_SELECT_RIGHT:
309 moveSelection(obj, ICMoveRight);
310 break;
311 case KEY_SELECT_LEFT:
312 moveSelection(obj, ICMoveLeft);
313 break;
314 case KEY_SELECT_UP:
315 moveSelection(obj, ICMoveUp);
316 break;
317 case KEY_SELECT_DOWN:
318 moveSelection(obj, ICMoveDown);
319 break;
320 case KEY_SELECT_FIRST:
321 moveSelection(obj, ICMoveFirst);
322 break;
323 case KEY_SELECT_LAST:
324 moveSelection(obj, ICMoveLast);
325 break;
326 case KEY_SELECT_NEXTP:
327 moveSelection(obj, ICMoveNextPage);
328 break;
329 case KEY_SELECT_PREVP:
330 moveSelection(obj, ICMovePrevPage);
331 break;
332 case KEY_SELECT_RIGHTMOST:
333 moveSelection(obj, ICMoveRightMost);
334 break;
335 case KEY_SELECT_LEFTMOST:
336 moveSelection(obj, ICMoveLeftMost);
337 break;
338 case KEY_SELECT_END:
339 endSelection(obj, False);
340 break;
341 case KEY_SELECT_ABORT:
342 endSelection(obj, True);
343 break;
344 default:
345 break;
346 }
347 }
348 if (dict = (value & KEY_DICT)) {
349 switch (dict) {
350 case KEY_DICT_START:
351 startRegistration(obj);
352 break;
353 case KEY_DICT_CHANGE:
354 changeRegistration(obj);
355 break;
356 case KEY_DICT_REGISTER:
357 Xsj3cDictRegister(buf);
358 changeRegistration(obj);
359 break;
360 case KEY_DICT_CLEAR:
361 Xsj3cDictClear(buf);
362 changeRegistration(obj);
363 break;
364 case KEY_DICT_END:
365 endRegistration(obj);
366 break;
367 default:
368 break;
369 }
370 }
371 if (value & KEY_CONTROL || value == KEY_NULL)
372 ret = 1;
373 if (value & KEY_CHANGE){
374 if (value & KEY_MODE_CHANGE) {
375 /* Change display mode string */
376 XtCallCallbackList(w, obj->inputConv.modechangecallback,
377 (XtPointer)NULL);
378 }
379 if (value & KEY_TEXT_FIXED) {
380 /* Fix converting strings */
381 XtCallCallbackList(w, obj->inputConv.fixcallback,
382 (XtPointer)NULL);
383 Xsj3cFixBuffer(buf);
384 } else if (value & KEY_TEXT_FLUSH) {
385 /* Fix & Input strings at same time */
386 XtCallCallbackList(w, obj->inputConv.fixcallback,
387 (XtPointer)NULL);
388 Xsj3cFlushBuffer(buf);
389 }
390 if (value & KEY_TEXT_CHANGE) {
391 /* Change converting strings */
392 XtCallCallbackList(w, obj->inputConv.textchangecallback,
393 (XtPointer)NULL);
394 }
395 if (value & KEY_HENKAN_END) {
396 /* End conversion */
397 XtCallCallbackList((Widget)obj, obj->inputConv.endcallback,
398 (XtPointer)NULL);
399 Xsj3cClearBuffer(buf);
400 }
401 }
402 if (value & KEY_BELL){
403 bell(obj);
404 return ret;
405 } else if (value & KEY_RECONNECT) {
406 Xsj3cConnect(buf, obj->sj3.sj3serv,
407 obj->sj3.sj3serv2, obj->sj3.sj3user);
408 Xsj3cClearBuffer(buf);
409 return ret;
410 }
411 return ret;
412 }
413
414 static ICString *
415 GetMode(w)
416 Widget w;
417 {
418 Sj3Object obj = (Sj3Object)w;
419 Xsj3cBuf buf = obj->sj3.sj3buf;
420 int len;
421 static ICString icstr;
422
423 icstr.data = (char *)Xsj3cGetModeStr(buf, &len);
424 icstr.nchars = len;
425 icstr.nbytes = icstr.nchars * sizeof(wchar);
426 icstr.attr = ICAttrNormalString;
427 return &icstr;
428 }
429
430 static int
431 CursorPos(w, nsegp, ncharp)
432 Widget w;
433 Cardinal *nsegp;
434 Cardinal *ncharp;
435 {
436 Sj3Object obj = (Sj3Object)w;
437 Xsj3cBuf buf = obj->sj3.sj3buf;
438
439 return(Xsj3cGetPosition(buf, nsegp, ncharp));
440 }
441
442 static int
443 NumSegments(w)
444 Widget w;
445 {
446 Sj3Object obj = (Sj3Object)w;
447 Xsj3cBuf buf = obj->sj3.sj3buf;
448
449 return (Xsj3cGetSegNum(buf));
450 }
451
452 static ICString *
453 GetSegment(w, n)
454 Widget w;
455 Cardinal n;
456 {
457 Sj3Object obj = (Sj3Object)w;
458 Xsj3cBuf buf = obj->sj3.sj3buf;
459 static ICString seg;
460 int len, attr;
461
462 seg.data = (char *)Xsj3cGetSeg(buf, n, &len, &attr);
463 seg.nchars = len;
464 seg.nbytes = seg.nchars * sizeof(wchar);
465 switch (attr) {
466 case SEG_REVERSED:
467 seg.attr = ICAttrConverted|ICAttrCurrentSegment;
468 break;
469 case SEG_UNDER_LINE:
470 seg.attr = ICAttrNotConverted;
471 break;
472 case SEG_NORMAL:
473 seg.attr = ICAttrConverted;
474 break;
475 default:
476 seg.attr = ICAttrConverted;
477 break;
478 }
479
480 return &seg;
481 }
482
483 /* ARGSUSED */
484 static int
485 CompareSegment(w, seg1, seg2, n)
486 Widget w;
487 ICString *seg1;
488 ICString *seg2;
489 Cardinal *n;
490 {
491 register unsigned char *p, *q;
492 register int len, nsame = 0;
493 int result = ICSame;
494
495 if (seg1->attr != seg2->attr)
496 result |= ICAttrChanged;
497
498 len = seg1->nbytes > seg2->nbytes ? seg2->nbytes : seg1->nbytes;
499 p = (unsigned char *)seg1->data;
500 q = (unsigned char *)seg2->data;
501 while (nsame < len && *p++ == *q++) nsame++;
502
503 if (nsame != len || len != seg1->nbytes
504 || len != seg2->nbytes || seg1->data != seg2->data)
505 result |= ICStringChanged;
506
507 if (n)
508 *n = nsame / sizeof(wchar);
509
510 return result;
511
512 }
513
514 static ICString *
515 GetItemList(w, n)
516 Widget w;
517 Cardinal *n;
518 {
519 Sj3Object obj = (Sj3Object)w;
520
521 switch (obj->sj3.state) {
522 case candidate_state:
523 *n = obj->sj3.numcand;
524 return obj->sj3.candlist;
525 case symbol_state:
526 *n = NumSymbol;
527 return obj->sj3.symbollist;
528 case hinsi_state:
529 *n = NumHinsi;
530 return obj->sj3.hinsilist;
531 default:
532 *n = 0;
533 return NULL; /* no item available */
534 }
535 /* NOTREACHED */
536
537 }
538
539 static int
540 SelectItem(w, n)
541 Widget w;
542 int n;
543 {
544 Sj3Object obj = (Sj3Object)w;
545 Xsj3cBuf buf = obj->sj3.sj3buf;
546 int ret = 0, changed = False, flush = False;
547
548 if (obj->sj3.state == normal_state )
549 return -1;
550 else if (n >= 0)
551 ret = insertSelection(obj, n, &changed, &flush);
552
553 switch (obj->sj3.state) {
554 case candidate_state:
555 Xsj3cEndCandidate(buf, changed);
556 break;
557 case symbol_state:
558 Xsj3cEndSymbol(buf);
559 break;
560 case hinsi_state:
561 Xsj3cEndHinsi(buf);
562 break;
563 default:
564 XtAppWarning(XtWidgetToApplicationContext((Widget)obj),
565 "sj3 Object: Unknown ConvMode state");
566 break;
567 }
568 obj->sj3.state = normal_state;
569
570 if (changed) {
571 if (flush) {
572 XtCallCallbackList((Widget)obj, obj->inputConv.fixcallback,
573 (XtPointer)NULL);
574 Xsj3cFlushBuffer(buf);
575 }
576 XtCallCallbackList((Widget)obj,
577 obj->inputConv.textchangecallback,
578 (XtPointer)NULL);
579 }
580
581 return ret;
582
583 }
584
585 static int
586 ConvertedString(w, encoding, format, length, string)
587 Widget w;
588 Atom *encoding;
589 int *format;
590 int *length;
591 XtPointer *string;
592 {
593 Sj3Object obj = (Sj3Object)w;
594 Xsj3cBuf buf = obj->sj3.sj3buf;
595 wchar *wbuf, *wp;
596 wchar *data;
597 int len, wlen;
598 extern int convJWStoCT();
599
600 wlen = Xsj3cGetConvertedLength(buf);
601 wbuf = (wchar *)XtMalloc((wlen + 1) * sizeof(wchar));
602
603 if ((Xsj3cGetConvertedStr(buf, wbuf)) == NULL) {
604 XtAppWarning(XtWidgetToApplicationContext(w),
605 "sj3 Object: Could not get converted string");
606 return -1;
607 }
608 *encoding = XA_COMPOUND_TEXT(XtDisplayOfObject((Widget)obj));
609 *format = 8;
610
611 for (wp = wbuf; *wp != 0; wp++) {
612 if (*wp == '\r') *wp = '\n';
613 }
614
615 *length = len = convJWStoCT(wbuf, (unsigned char *)NULL, 0);
616 *string = XtMalloc(len + 1);
617 (void)convJWStoCT(wbuf, (unsigned char *)*string, 0);
618
619 XtFree((char *)wbuf);
620
621 return 0;
622 }
623
624 static int
625 ClearConversion(w)
626 Widget w;
627 {
628 Sj3Object obj = (Sj3Object)w;
629 Xsj3cBuf buf = obj->sj3.sj3buf;
630
631 Xsj3cClearBuffer(buf);
632 XtCallCallbackList(w, obj->inputConv.textchangecallback, (XtPointer)NULL);
633 return 0;
634 }
635
636 static ICString *
637 GetAuxSegments(w, n, ns, nc)
638 Widget w;
639 Cardinal *n, *ns, *nc;
640 {
641 Sj3Object obj = (Sj3Object)w;
642 Xsj3cBuf buf = obj->sj3.sj3buf;
643 register int i;
644 register Xsj3cDictMsg p;
645 register ICString *seg;
646 static ICString *ics;
647
648 *n = Xsj3cGetDictMsgNum(buf);
649 if (!ics) {
650 ics = (ICString *)XtCalloc(*n, sizeof(ICString));
651 } else {
652 ics = (ICString *)XtRealloc((char *)ics, *n * sizeof(ICString));
653 }
654 bzero(ics, *n * sizeof(ICString));
655 for (i = 0, seg = ics, p = Xsj3cGetDictMsgs(buf);
656 i < *n; i++, seg++) {
657 seg->data = (char *)p[i].data;
658 seg->nchars = p[i].len;
659 seg->nbytes = seg->nchars * sizeof(wchar);
660 switch (p[i].attr) {
661 case SEG_REVERSED:
662 seg->attr = ICAttrConverted|ICAttrCurrentSegment;
663 break;
664 case SEG_UNDER_LINE:
665 seg->attr = ICAttrNotConverted;
666 break;
667 case SEG_NORMAL:
668 seg->attr = ICAttrConverted;
669 break;
670 default:
671 seg->attr = ICAttrNotConverted;
672 break;
673 }
674 }
675 *ns = *n - 1;
676 *nc = 0;
677
678 return ics;
679 }
680
681 /* ARGSUSED */
682 static int
683 PreeditString(w, segn, offset, encoding, format, length, string)
684 Widget w;
685 int segn;
686 int offset;
687 Atom *encoding;
688 int *format;
689 int *length;
690 XtPointer *string;
691 {
692 Sj3Object obj = (Sj3Object)w;
693 Xsj3cBuf buf = obj->sj3.sj3buf;
694 int segnum = Xsj3cGetSegNum(buf);
695 int seglen, junk;
696 wchar *segdata;
697 Boolean deleted;
698 int i;
699 wchar *wbuf, *wp;
700 int len, wlen;
701 extern int convJWStoCT();
702
703 if (segn < segnum) {
704 segdata = Xsj3cGetSeg(buf, segn, &seglen, &junk);
705 if (offset >= seglen) {
706 /* $B%;%0%a%s%H$N:G8e(B */
707 ++segn;
708 offset = 0;
709 }
710 }
711 if (segn >= segnum) {
712 deleted = True;
713 }
714 else {
715 segdata = Xsj3cGetSeg(buf, segn, &seglen, &junk);
716 deleted = (offset >= seglen);
717 }
718 if (deleted) {
719 /* $B:o=|$5$l$?(B */
720 *encoding = XA_COMPOUND_TEXT(XtDisplayOfObject(w));
721 *format = 8;
722 *length = 0;
723 *string = (XtPointer)XtMalloc(1);
724 return 0;
725 }
726
727 wlen = 0;
728 for (i = segn; i < segnum; i++) {
729 segdata = Xsj3cGetSeg(buf, i, &seglen, &junk);
730 wlen += seglen;
731 }
732 wlen -= offset;
733
734 wp = wbuf = (wchar *)XtMalloc((wlen + 1) * sizeof(wchar));
735 segdata = Xsj3cGetSeg(buf, segn, &seglen, &junk);
736 len = seglen - offset;
737 (void)bcopy((char *)(segdata + offset), (char *)wp, sizeof(wchar) * len);
738 wp += len;
739 for (i = segn + 1; i < segnum; i++) {
740 segdata = Xsj3cGetSeg(buf, i, &seglen, &junk);
741 (void)bcopy((char *)segdata, (char *)wp, sizeof(wchar) * seglen);
742 wp += seglen;
743 }
744 wbuf[wlen] = 0;
745
746 /*
747 * Sj3 $B%*%V%8%'%/%H$O(B COMPOUND_TEXT $B%(%s%3!<%G%#%s%0$7$+%5%]!<%H$7$J$$(B
748 * COMPOUND_TEXT $B$KJQ49$9$k(B
749 */
750 *encoding = XA_COMPOUND_TEXT(XtDisplayOfObject(w));
751 *format = 8;
752
753 /* COMPOUND_TEXT $B$O(B \r $B$,Aw$l$J$$$N$G(B \n $B$KJQ49$7$F$*$/(B */
754 for (wp = wbuf; *wp != 0; wp++) {
755 if (*wp == '\r') *wp = '\n';
756 }
757
758 *length = len = convJWStoCT(wbuf, (unsigned char *)NULL, 0);
759 *string = (XtPointer)XtMalloc(len + 1);
760 (void)convJWStoCT(wbuf, (unsigned char *)*string, 0);
761
762 /* wbuf $B$r(B free $B$7$F$*$/(B */
763 XtFree((char *)wbuf);
764
765 return 0;
766 }
767
768 /* ARGSUSED */
769 static int
770 StatusString(w, encoding, format, length, string, nchars)
771 Widget w;
772 Atom *encoding;
773 int *format;
774 int *length;
775 XtPointer *string;
776 int *nchars;
777 {
778 ICString *seg;
779 wchar *wbuf, *wp;
780 int len, wlen;
781 extern int convJWStoCT();
782
783 seg = GetMode(w);
784 if (seg == NULL) {
785 *length = *nchars = 0;
786 return -1;
787 }
788
789 wlen = seg->nchars;
790 if (wlen <= 0) {
791 *length = *nchars = 0;
792 return -1;
793 }
794
795 /*
796 * data $B$KF~$C$F$$$kJQ49%F%-%9%H$O(B null $B%?!<%_%M!<%H$5$l$F$$$J$$$+$b(B
797 * $B$7$l$J$$$N$G!"$^$:%3%T!<$7$F(B null $B%?!<%_%M!<%H$9$k(B
798 */
799 wbuf = (wchar *)XtMalloc((wlen + 1) * sizeof(wchar));
800 (void)bcopy(seg->data, (char *)wbuf, sizeof(wchar) * wlen);
801 wbuf[wlen] = 0;
802
803 /*
804 * Sj3 $B%*%V%8%'%/%H$O(B COMPOUND_TEXT $B%(%s%3!<%G%#%s%0$7$+%5%]!<%H$7$J$$(B
805 * COMPOUND_TEXT $B$KJQ49$9$k(B
806 */
807 *encoding = XA_COMPOUND_TEXT(XtDisplayOfObject(w));
808 *format = 8;
809
810 /* COMPOUND_TEXT $B$O(B \r $B$,Aw$l$J$$$N$G(B \n $B$KJQ49$7$F$*$/(B */
811 for (wp = wbuf; *wp != 0; wp++) {
812 if (*wp == '\r') *wp = '\n';
813 }
814
815 *length = len = convJWStoCT(wbuf, (unsigned char *)NULL, 0);
816 *string = XtMalloc(len + 1);
817 (void)convJWStoCT(wbuf, (unsigned char *)*string, 0);
818 *nchars = seg->nchars;
819
820 /* wbuf $B$r(B free $B$7$F$*$/(B */
821 XtFree((char *)wbuf);
822
823 return 0;
824 }
825
826 /* ARGSUSED */
827 static void
828 Initialize(req, new, args, num_args)
829 Widget req;
830 Widget new;
831 ArgList args;
832 Cardinal *num_args;
833 {
834 Sj3Object obj = (Sj3Object)new;
835 Xsj3cBuf buf = NULL;
836 int min_keycode, max_keycode, keysyms_per_keycode;
837 register int i, j, k;
838 unsigned long kanamod = 0;
839 KeySym *keymap;
840 XModifierKeymap *modmap;
841
842 obj->sj3.symbollist = SymbolList;
843 obj->sj3.hinsilist = HinsiList;
844 obj->sj3.candlist = NULL;
845 obj->sj3.numcand = 0;
846 obj->sj3.curcand = 0;
847 obj->sj3.cursymbol = 0;
848 obj->sj3.curhinsi = 0;
849 obj->sj3.candlistsize = 0;
850 obj->sj3.state = normal_state;
851 obj->sj3.selectionending = False;
852
853 if (!obj->sj3.sj3user || *obj->sj3.sj3user == '\0')
854 obj->sj3.sj3user = uname;
855
856 if (!clcount++) {
857 /* Get kana lock modmask */
858 XDisplayKeycodes (XtDisplayOfObject((Widget)obj),
859 &min_keycode, &max_keycode);
860 keymap = XGetKeyboardMapping (XtDisplayOfObject((Widget)obj),
861 min_keycode, (max_keycode - min_keycode + 1),
862 &keysyms_per_keycode);
863 XFree(keymap);
864
865 if (keysyms_per_keycode == 4) {
866 modmap = XGetModifierMapping(XtDisplayOfObject((Widget)obj));
867 k = 0;
868 for (i = 0; i < 8; i++) {
869 for (j = 0; j < modmap->max_keypermod; j++) {
870 if (XK_Mode_switch ==
871 XKeycodeToKeysym(XtDisplayOfObject((Widget)obj),
872 modmap->modifiermap[k], 0)) {
873 kanamod |= 1 << i;
874 }
875 k++;
876 }
877 }
878 XFreeModifiermap(modmap);
879 }
880
881 /* Set kana lock modmask */
882 Xsj3cSetKanaMod(kanamod);
883
884 }
885
886 /* Making buffer for Xsj3clib */
887 buf = obj->sj3.sj3buf = Xsj3cCreateBuffer();
888 if (!buf) {
889 XtAppError(XtWidgetToApplicationContext(new),
890 "sj3 Object: Failed to allocate buffers");
891 }
892
893 /* Read user resource customize file and set flags */
894 (void)Xsj3cRCInit(buf, obj->sj3.rcfile, home);
895
896 /* Convertion table initialization */
897 Xsj3cInitializeTables(buf, home, obj->sj3.rkfile, obj->sj3.hkfile,
898 obj->sj3.zhfile, obj->sj3.sbfile);
899
900 /* Connect to Kana-kanji conversion server */
901 if ((Xsj3cOpen(buf, obj->sj3.sj3serv,
902 obj->sj3.sj3user, False, False)) != CONNECT_OK) {
903 XtAppWarning(XtWidgetToApplicationContext(new),
904 "sj3 Object: Failed to connect first server, then try to second server");
905 if ((Xsj3cOpen(buf, obj->sj3.sj3serv2,
906 obj->sj3.sj3user, False, True)) != CONNECT_OK) {
907 XtAppError(XtWidgetToApplicationContext(new),
908 "sj3 Object: Failed to connect to second server");
909 }
910 };
911
912 addObject(obj);
913 }
914
915 static void
916 Destroy(w)
917 Widget w;
918 {
919 Sj3Object obj = (Sj3Object)w;
920 Xsj3cBuf buf = obj->sj3.sj3buf;
921
922 Xsj3cClose(buf, False);
923 Xsj3cFreeBuffer(buf);
924 deleteObject(obj);
925 }
926
927 static void
928 symbolInit(obj)
929 Sj3Object obj;
930 {
931 Xsj3cBuf buf = obj->sj3.sj3buf;
932 register ICString *strp;
933 register int i;
934 register Xsj3cSymbol p;
935
936 for (i = 0, strp = SymbolList, p = Xsj3cGetSymbols(buf);
937 i < NumSymbol; i++, strp++) {
938 strp->data = (char *)p[i].data;
939 strp->nchars = p[i].len;
940 strp->nbytes = strp->nchars * sizeof(wchar);
941 strp->attr = ICAttrNormalString;
942 }
943 }
944
945 static void
946 startSymbol(obj)
947 Sj3Object obj;
948 {
949 Xsj3cBuf buf = obj->sj3.sj3buf;
950 ICSelectionControlArg arg;
951
952 /* Symbol list initialization */
953 if (!SymbolList) {
954 NumSymbol = Xsj3cGetSymbolNum(buf, &obj->sj3.cursymbol);
955 SymbolList = (ICString *)XtMalloc(NumSymbol * sizeof(ICString));
956 symbolInit(obj);
957 obj->sj3.symbollist = SymbolList;
958 } else if (!obj->sj3.symbollist) {
959 obj->sj3.symbollist = SymbolList;
960 }
961
962 obj->sj3.state = symbol_state;
963
964 arg.command = ICSelectionStart;
965 arg.u.selection_kind = ICSelectionCandidates;
966 XtCallCallbackList((Widget)obj, obj->inputConv.selectioncallback,
967 (XtPointer)&arg);
968
969 /* set current item */
970 arg.command = ICSelectionSet;
971 arg.u.current_item = obj->sj3.cursymbol;
972 XtCallCallbackList((Widget)obj, obj->inputConv.selectioncallback,
973 (XtPointer)&arg);
974 }
975
976 static void
977 startCandidate(obj)
978 Sj3Object obj;
979 {
980 Xsj3cBuf buf = obj->sj3.sj3buf;
981 ICSelectionControlArg arg;
982 register ICString *strp;
983 register int i;
984 int ncand, curcand;
985 register Xsj3cCand p;
986
987 if ((ncand = Xsj3cGetCandidateNum(buf, &curcand)) <= 0) {
988 bell(obj);
989 return;
990 }
991 obj->sj3.curcand = curcand;
992 obj->sj3.numcand = ncand;
993
994 allocCandlist(obj, obj->sj3.numcand);
995
996 for (i = 0, strp = obj->sj3.candlist, p = Xsj3cGetCandidates(buf);
997 i < obj->sj3.numcand; i++, strp++) {
998 strp->data = (char *)p[i].data;
999 strp->nchars = p[i].len;
1000 strp->nbytes = strp->nchars * sizeof(wchar);
1001 strp->attr = ICAttrNormalString;
1002 }
1003
1004 obj->sj3.state = candidate_state;
1005
1006 arg.command = ICSelectionStart;
1007 arg.u.selection_kind = ICSelectionCandidates;
1008 XtCallCallbackList((Widget)obj, obj->inputConv.selectioncallback,
1009 (XtPointer)&arg);
1010
1011 /* set current candidate */
1012 arg.command = ICSelectionSet;
1013 arg.u.current_item = curcand;
1014 XtCallCallbackList((Widget)obj, obj->inputConv.selectioncallback,
1015 (XtPointer)&arg);
1016 }
1017
1018 static void
1019 hinsiInit(obj)
1020 Sj3Object obj;
1021 {
1022 Xsj3cBuf buf = obj->sj3.sj3buf;
1023 register ICString *strp;
1024 register int i;
1025 register Xsj3cHinsi p;
1026
1027 for (i = 0, strp = HinsiList, p = Xsj3cGetHinsis(buf);
1028 i < NumHinsi; i++, strp++) {
1029 strp->data = (char *)p[i].data;
1030 strp->nchars = p[i].len;
1031 strp->nbytes = strp->nchars * sizeof(wchar);
1032 strp->attr = ICAttrNormalString;
1033 }
1034 }
1035
1036 static void
1037 startHinsi(obj)
1038 Sj3Object obj;
1039 {
1040 Xsj3cBuf buf = obj->sj3.sj3buf;
1041 ICSelectionControlArg arg;
1042
1043 /* Hinsi list initialization */
1044 if (!HinsiList) {
1045 NumHinsi = Xsj3cGetHinsiNum(buf, &obj->sj3.curhinsi);
1046 HinsiList = (ICString *)XtMalloc(NumHinsi * sizeof(ICString));
1047 hinsiInit(obj);
1048 obj->sj3.hinsilist = HinsiList;
1049 } else if (!obj->sj3.hinsilist) {
1050 obj->sj3.hinsilist = HinsiList;
1051 }
1052
1053 obj->sj3.state = hinsi_state;
1054
1055 arg.command = ICSelectionStart;
1056 arg.u.selection_kind = ICSelectionCandidates;
1057 XtCallCallbackList((Widget)obj, obj->inputConv.selectioncallback,
1058 (XtPointer)&arg);
1059
1060 /* set current item */
1061 arg.command = ICSelectionSet;
1062 arg.u.current_item = obj->sj3.curhinsi;
1063 XtCallCallbackList((Widget)obj, obj->inputConv.selectioncallback,
1064 (XtPointer)&arg);
1065 }
1066
1067 static void
1068 moveSelection(obj, dir)
1069 Sj3Object obj;
1070 int dir;
1071 {
1072 ICSelectionControlArg arg;
1073
1074 if (obj->sj3.state == normal_state) return;
1075 arg.command = ICSelectionMove;
1076 arg.u.dir = dir;
1077 XtCallCallbackList((Widget)obj, obj->inputConv.selectioncallback,
1078 (XtPointer)&arg);
1079 }
1080
1081 static int
1082 endSelection(obj, abort)
1083 Sj3Object obj;
1084 int abort;
1085 {
1086 ICSelectionControlArg arg;
1087 int selected;
1088 int ret = 0, changed = False, flush = False;
1089 Xsj3cBuf buf = obj->sj3.sj3buf;
1090
1091 if (obj->sj3.selectionending)
1092 return 0;
1093
1094 if (obj->sj3.state == normal_state)
1095 return -1;
1096
1097 arg.command = ICSelectionEnd;
1098 arg.u.current_item = -1;
1099 XtCallCallbackList((Widget)obj, obj->inputConv.selectioncallback,
1100 (XtPointer)&arg);
1101
1102 if (!abort && (selected = arg.u.current_item) >= 0) {
1103 ret = insertSelection(obj, selected, &changed, &flush);
1104 }
1105
1106 switch (obj->sj3.state) {
1107 case candidate_state:
1108 Xsj3cEndCandidate(buf, changed);
1109 break;
1110 case symbol_state:
1111 Xsj3cEndSymbol(buf);
1112 break;
1113 case hinsi_state:
1114 Xsj3cEndHinsi(buf);
1115 break;
1116 default:
1117 XtAppWarning(XtWidgetToApplicationContext((Widget)obj),
1118 "sj3 Object: Unknow ConvMode state");
1119 break;
1120 }
1121 obj->sj3.state = normal_state;
1122
1123 if (changed) {
1124 if (flush) {
1125 XtCallCallbackList((Widget)obj, obj->inputConv.fixcallback,
1126 (XtPointer)NULL);
1127 Xsj3cFlushBuffer(buf);
1128 }
1129 XtCallCallbackList((Widget)obj,
1130 obj->inputConv.textchangecallback,
1131 (XtPointer)NULL);
1132 }
1133
1134 return ret;
1135 }
1136
1137 /* ARGSUSED */
1138 static Boolean
1139 SetValues(cur, req, wid, args, num_args)
1140 Widget cur;
1141 Widget req;
1142 Widget wid;
1143 ArgList args;
1144 Cardinal *num_args;
1145 {
1146 return False;
1147 }
1148
1149 static int
1150 insertSelection(obj, selected, changed, flush)
1151 Sj3Object obj;
1152 int selected;
1153 int *changed;
1154 int *flush;
1155 {
1156 Xsj3cBuf buf = obj->sj3.sj3buf;
1157 int ret = 0;
1158
1159 obj->sj3.selectionending = True;
1160 switch (obj->sj3.state) {
1161 case candidate_state:
1162 obj->sj3.curcand = selected;
1163 ret = Xsj3cSetCandidate(buf, selected, changed, flush);
1164 break;
1165 case symbol_state:
1166 obj->sj3.cursymbol = selected;
1167 ret = Xsj3cSetSymbol(buf, selected, changed, flush);
1168 break;
1169 case hinsi_state:
1170 obj->sj3.curhinsi = selected;
1171 ret = Xsj3cSetHinsi(buf, selected, changed, flush);
1172 break;
1173 }
1174 obj->sj3.selectionending = False;
1175
1176 return ret;
1177 }
1178
1179 static void
1180 allocCandlist(obj, n)
1181 Sj3Object obj;
1182 int n;
1183 {
1184 ICString *p;
1185
1186 if (n <= obj->sj3.candlistsize)
1187 return;
1188
1189 if (obj->sj3.candlistsize == 0) {
1190 p = (ICString *)XtMalloc(n * sizeof(ICString));
1191 } else {
1192 p = (ICString *)XtRealloc((char *)obj->sj3.candlist,
1193 n * sizeof(ICString));
1194 }
1195
1196 obj->sj3.candlist = p;
1197 obj->sj3.candlistsize = n;
1198 }
1199
1200 static void
1201 startRegistration(obj)
1202 Sj3Object obj;
1203 {
1204 ICAuxControlArg arg;
1205
1206 arg.command = ICAuxStart;
1207 XtCallCallbackList((Widget)obj, obj->inputConv.auxcallback,
1208 (XtPointer)&arg);
1209 }
1210
1211 static void
1212 changeRegistration(obj)
1213 Sj3Object obj;
1214 {
1215 ICAuxControlArg arg;
1216
1217 arg.command = ICAuxChange;
1218 XtCallCallbackList((Widget)obj, obj->inputConv.auxcallback,
1219 (XtPointer)&arg);
1220 }
1221
1222 static void
1223 endRegistration(obj)
1224 Sj3Object obj;
1225 {
1226 Xsj3cBuf buf = obj->sj3.sj3buf;
1227 ICAuxControlArg arg;
1228
1229 arg.command = ICAuxEnd;
1230 XtCallCallbackList((Widget)obj, obj->inputConv.auxcallback,
1231 (XtPointer)&arg);
1232 Xsj3cEndDict(buf);
1233 }
1234
1235 /*
1236 * keeping list of objects
1237 */
1238 typedef struct _oblist_ {
1239 Sj3Object obj;
1240 struct _oblist_ *next;
1241 } ObjRec;
1242
1243 static ObjRec *ObjList = NULL;
1244
1245 static void
1246 addObject(obj)
1247 Sj3Object obj;
1248 {
1249 ObjRec *objp = XtNew(ObjRec);
1250
1251 objp->obj = obj;
1252 objp->next = ObjList;
1253 ObjList = objp;
1254 }
1255
1256 static void
1257 deleteObject(obj)
1258 Sj3Object obj;
1259 {
1260 ObjRec *objp, *objp0;
1261
1262 for (objp0 = NULL, objp = ObjList;
1263 objp != NULL;
1264 objp0 = objp, objp = objp->next) {
1265 if (objp->obj == obj) {
1266 if (objp0 == NULL) {
1267 ObjList = objp->next;
1268 } else {
1269 objp0->next = objp->next;
1270 }
1271 XtFree((char *)objp);
1272 return;
1273 }
1274 }
1275 }
1276
1277 static void
1278 bell(obj)
1279 Sj3Object obj;
1280 {
1281 XBell(XtDisplayOfObject((Widget)obj), 0);
1282 }