Initial git import
[sxemacs] / src / mule / mule-canna.c
1 /* CANNA interface -*- coding: euc-jp -*-
2
3    Copyright (C) 1995 Free Software Foundation, Inc.
4    Copyright (C) 1995 Sun Microsystems, Inc.
5
6 This file is part of SXEmacs
7
8 SXEmacs is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
12
13 SXEmacs is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program.  If not, see <http://www.gnu.org/licenses/>. */
20
21
22 /* Synched up with: Mule 2.3.  Not in FSF. */
23
24 /* Japanese comments were translated 2000-12-06 by Stephen Turnbull
25    <stephen@xemacs.org>.  I haven't verified that the Japanese comments
26    were correct.  YMMV, NO WARRANTY, not even the implied warranty of
27    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  (^^;;; as the
28    Japanese say. */
29
30 /*
31
32   Authors: Akira Kon (kon@uxd.fc.nec.co.jp)
33            Ichiro Hirakura (hirakura@uxd.fc.nec.co.jp)
34
35   Functions defined in this file are
36
37   (canna-key-proc key)
38                 key: single STRING
39                 RETURNS:
40                          Length of converted string if no error occurs.
41                          Error string if error occurs.
42                 DESCRIPTION:
43                          Convert a key input to a set of strings.  The
44                          strings contain both well-formed string and a
45                          intermediate result to show the translation
46                          information to a user.  converted strings are
47                          stored in specific variables.
48
49   (canna-initialize)
50                 RETURNS:
51                         List of the following things:
52                         - list of keys to toggle Japanese-mode
53                         - error message
54                         - list of warning messages
55                 DESCRIPTION:
56                         Initialize ``canna'', which is a kana-to-kanji
57                         converter for GNU Emacs.  The first arg
58                         specifies if inserting space character between
59                         BUNSETSU when candidates are displayed.  The
60                         second arg specifies server.  The third arg
61                         specifies a file which will be used as a
62                         customization description.  If nil is
63                         specified for each arg, the default value will
64                         be used.
65
66   (canna-finalize)
67                 RETURNS:
68                         list of warning messages
69                 DESCRIPTION:
70                         finalize ``canna'', which is a kana-to-kanji
71                         converter for GNU Emacs.  This cause to write
72                         miscellaneous informations to kana-to-kanji
73                         dictionary.
74
75   (canna-touroku-string string)
76                 string:
77                         String to register to a dictionary.
78                 RETURNS:
79                         The same thing returns as canna-key-proc does.
80                 DESCRIPTION:
81                         Register Kanji words into kana-to-kanji
82                         conversion dictionary.
83
84   (canna-set-width width)
85                 width:
86                         Column width of the place where the candidates
87                         of kana-to-kanji conversion will be shown.
88                 RETURNS:
89                         nil
90                 DESCRIPTION:
91                         Set status-line width information, which is
92                         used to display kanji candidates.
93
94   (canna-change-mode num)
95                 num:
96                         The mode number of Canna.
97                 RETURNS:
98                         The same thing returns as canna-key-proc does.
99                 DESCRIPTION:
100                         Change Japanese pre-edit mode.
101
102   (canna-store-yomi yomi roma)
103                 yomi:
104                         ``Yomi'' to be stored.
105                 roma:
106                         ``Romaji'' which corresponds to the ``Yomi''.
107                 RETURNS:
108                         The same thing returns as canna-key-proc does.
109                 DESCRIPTION:
110                         Store yomi characters as a YOMI of
111                         kana-to-kanji conversion.
112
113   (canna-do-function num ch)
114                 num:
115                         A function number to be called.
116                 ch:
117                         A character will be specified in order to feed
118                         the character to the function if the function
119                         needs a input character.
120                 RETURNS:
121                         The same thing returns as canna-key-proc does.
122                 DESCRIPTION:
123                         Do specified function at current mode.
124
125   (canna-parse string)
126                 string:
127                         To be parsed.
128                 RETURNS:
129                         List of warning messages.
130                 DESCRIPTION:
131                         Parse customize string.
132
133   (canna-query-mode)
134                 RETURNS:
135                         A string which indicate the current mode.
136                 DESCRIPTION:
137                         Get current mode string.
138
139   Functions below are used for KKCP compatible library.  These
140   functions provides a base kana-to-kanji conversion system for EGG.
141   These functions may be used when users want to change the engine
142   from Wnn to Canna without changing user interface of Japanese input.
143
144   (canna-henkan-begin)
145   (canna-henkan-next)
146   (canna-bunsetu-henkou)
147   (canna-henkan-kakutei)
148   (canna-henkan-end)
149   (canna-henkan-quit)
150
151  */
152
153 #include <config.h>
154 #include "lisp.h"
155
156 #include "buffer.h"
157 #include "file-coding.h"
158
159 #ifdef CANNA2
160 #define IROHA_BC
161 #include "canna/jrkanji.h"
162 #include "canna/RK.h"
163 #else                           /* !CANNA2 */
164 #include "iroha/jrkanji.h"
165 #include "iroha/RK.h"
166 #endif                          /* !CANNA2 */
167 extern char *jrKanjiError;
168
169 /* #### is this global really necessary? */
170 #define KEYTOSTRSIZE 2048
171 static unsigned char key_buffer[KEYTOSTRSIZE];
172 static char **warning;
173
174 static int canna_empty_info, canna_through_info;
175 static int canna_underline;
176 static int canna_inhibit_hankakukana;
177
178 static Lisp_Object Vcanna_kakutei_string;
179 static Lisp_Object Vcanna_kakutei_yomi;
180 static Lisp_Object Vcanna_kakutei_romaji;
181 static Lisp_Object Vcanna_henkan_string;
182 static Fixnum canna_henkan_length;
183 static Fixnum canna_henkan_revPos;
184 static Fixnum canna_henkan_revLen;
185 static Lisp_Object Vcanna_ichiran_string;
186 static Fixnum canna_ichiran_length;
187 static Fixnum canna_ichiran_revPos;
188 static Fixnum canna_ichiran_revLen;
189 static Lisp_Object Vcanna_mode_string;
190
191 static int IRCP_context;
192
193 static Lisp_Object storeResults(unsigned char *, int, jrKanjiStatus *);
194 static Lisp_Object kanjiYomiList(int, int);
195 static Lisp_Object CANNA_mode_keys(void);
196
197 #ifdef CANNA_MULE
198 static void m2c(unsigned char *, int, unsigned char *);
199 static Lisp_Object mule_make_string(unsigned char *, int);
200 static int mule_strlen(unsigned char *, int);
201 static void count_char(unsigned char *, int, int, int, Fixnum *, Fixnum *,
202                        Fixnum *);
203 #define make_string mule_make_string
204 #endif
205
206 /* Lisp functions definition */
207
208 DEFUN("canna-key-proc", Fcanna_key_proc, 1, 1, 0,       /*
209 Translate a key input to a set of strings.  The strings contain both
210 well-formed string and intermediate result to show the translation
211 information to a user.  Converted strings are stored in specific
212 variables.
213 */
214       (ch))
215 {
216         jrKanjiStatus ks;
217         int len;
218
219         CHECK_CHAR_COERCE_INT(ch);
220         len = jrKanjiString(0, XCHAR(ch), key_buffer, KEYTOSTRSIZE, &ks);
221         return storeResults(key_buffer, len, &ks);
222 }
223
224 static Lisp_Object storeResults(unsigned char *buf, int len, jrKanjiStatus * ks)
225 {
226         Lisp_Object val = Qnil;
227
228         if (len < 0) {          /* Error detected */
229                 val =
230                     make_string((unsigned char *)jrKanjiError,
231                                 strlen(jrKanjiError));
232         } else {
233                 /* ³ÎÄꤷ¤¿Ê¸»úÎó (the confirmed string) */
234                 Vcanna_kakutei_string = make_string(buf, len);
235                 val = make_int(len);
236                 /* ³ÎÄꤷ¤¿Ê¸»úÎó¤ÎÆɤߤξðÊó...
237                    (info about the reading of the confirmed string) */
238                 Vcanna_kakutei_yomi = Vcanna_kakutei_romaji = Qnil;
239                 if (ks->info & KanjiYomiInfo) {
240                         unsigned char *p = buf + len + 1;
241                         int yomilen = strlen(p);
242
243                         if (len + yomilen + 1 < KEYTOSTRSIZE) {
244                                 int yomilen2;
245
246                                 Vcanna_kakutei_yomi = make_string(p, yomilen);  /* Æɤß
247                                                                                    (reading) */
248                                 p += yomilen + 1;
249                                 yomilen2 = strlen(p);
250                                 if (len + yomilen + yomilen2 + 2 < KEYTOSTRSIZE) {
251                                         Vcanna_kakutei_romaji =
252                                             make_string(p, yomilen2);
253                                         /* ¥í¡¼¥Þ»ú (romanization) */
254                                 }
255                         }
256                 }
257
258                 /* ¸õÊäɽ¼¨¤Îʸ»úÎó¤Ç¤¹¡£
259                    (string for displaying candidate translations) */
260                 Vcanna_henkan_string = Qnil;
261                 if (ks->length >= 0) {
262                         Vcanna_henkan_string =
263                             make_string(ks->echoStr, ks->length);
264 #ifndef CANNA_MULE
265                         canna_henkan_length = ks->length;
266                         canna_henkan_revPos = ks->revPos;
267                         canna_henkan_revLen = ks->revLen;
268 #else                           /* CANNA_MULE */
269                         if (canna_underline) {
270                                 canna_henkan_length =
271                                     mule_strlen(ks->echoStr, ks->length);
272                                 canna_henkan_revPos =
273                                     mule_strlen(ks->echoStr, ks->revPos);
274                                 canna_henkan_revLen =
275                                     mule_strlen(ks->echoStr + ks->revPos,
276                                                 ks->revLen);
277                         } else {
278                                 count_char(ks->echoStr, ks->length, ks->revPos,
279                                            ks->revLen, &canna_henkan_length,
280                                            &canna_henkan_revPos,
281                                            &canna_henkan_revLen);
282                         }
283 #endif                          /* CANNA_MULE */
284                 }
285
286                 /* °ìÍ÷¤Î¾ðÊó (information about the echo area menu) */
287                 Vcanna_ichiran_string = Qnil;
288                 if (ks->info & KanjiGLineInfo && ks->gline.length >= 0) {
289                         Vcanna_ichiran_string = make_string(ks->gline.line,
290                                                             ks->gline.length);
291 #ifndef CANNA_MULE
292                         canna_ichiran_length = ks->gline.length;
293                         canna_ichiran_revPos = ks->gline.revPos;
294                         canna_ichiran_revLen = ks->gline.revLen;
295 #else                           /* CANNA_MULE */
296                         count_char(ks->gline.line, ks->gline.length,
297                                    ks->gline.revPos, ks->gline.revLen,
298                                    &canna_ichiran_length,
299                                    &canna_ichiran_revPos,
300                                    &canna_ichiran_revLen);
301 #endif                          /* CANNA_MULE */
302                 }
303
304                 /* ¥â¡¼¥É¤Î¾ðÊó (mode information) */
305                 Vcanna_mode_string = Qnil;
306                 if (ks->info & KanjiModeInfo) {
307                         Vcanna_mode_string =
308                             make_string(ks->mode, strlen(ks->mode));
309                 }
310
311                 /* ¤½¤Î¾¤Î¾ðÊó (other information) */
312                 canna_empty_info = (ks->info & KanjiEmptyInfo) ? 1 : 0;
313                 canna_through_info = (ks->info & KanjiThroughInfo) ? 1 : 0;
314         }
315
316         return val;
317 }
318
319 DEFUN("canna-set-bunsetsu-kugiri", Fcanna_set_bunsetsu, 0, 1, 0,        /*
320 This function sets the clause separator.
321 If non-nil value is specified, the white space separator will be used.
322 No separator will be used otherwise.
323 */
324       (num))
325 {
326         int kugiri;             /* Ê¸Àá¶èÀÚ¤ê¤ò¤¹¤ë¤«¡© (display clause separator?) */
327
328         kugiri = NILP(num) ? 0 : 1;
329
330         jrKanjiControl(0, KC_SETBUNSETSUKUGIRI, (char *)kugiri);
331
332         return Qnil;
333 }
334
335 /* For whatever reason, calling Fding directly from libCanna loses */
336 static void call_Fding(void)
337 {
338         Fding(Qnil, Qnil, Qnil);
339 }
340
341 DEFUN("canna-initialize", Fcanna_initialize, 0, 3, 0,   /*
342 Initialize ``canna'', which is a kana-to-kanji converter for GNU Emacs.
343 The first arg specifies if inserting space character between BUNSETSU when
344 candidates are displayed.
345 The second arg specifies server.
346 The third arg specifies a file which will be used as a customization
347 description.
348 If nil is specified for each arg, the default value will be used.
349 */
350       (num, server, rcfile))
351 {
352         Lisp_Object val;
353         int res;
354         unsigned char **p, **q;
355
356         int kugiri;             /* Ê¸Àá¶èÀÚ¤ê¤ò¤¹¤ë¤«¡© (display clause separator?) */
357
358         IRCP_context = -1;
359
360         if (NILP(num)) {
361                 kugiri = 1;
362         } else {
363                 CHECK_INT(num);
364                 kugiri = XINT(num);
365                 kugiri = (kugiri == 1) ? 1 : 0;
366         }
367
368         if (NILP(server)) {
369                 jrKanjiControl(0, KC_SETSERVERNAME, (char *)0);
370         } else {
371                 char servername[256];
372
373                 CHECK_STRING(server);
374                 strncpy(servername, XSTRING_DATA(server),
375                         XSTRING_LENGTH(server));
376                 servername[XSTRING_LENGTH(server)] = '\0';
377                 jrKanjiControl(0, KC_SETSERVERNAME, servername);
378         }
379
380         if (NILP(rcfile)) {
381                 jrKanjiControl(0, KC_SETINITFILENAME, (char *)0);
382         } else {
383                 char rcname[256];
384
385                 CHECK_STRING(rcfile);
386                 strncpy(rcname, XSTRING_DATA(rcfile), XSTRING_LENGTH(rcfile));
387                 rcname[XSTRING_LENGTH(rcfile)] = '\0';
388                 jrKanjiControl(0, KC_SETINITFILENAME, rcname);
389         }
390
391         warning = (char **)0;
392 #ifdef nec_ews_svr4
393         stop_polling();
394 #endif                          /* nec_ews_svr4 */
395         res = jrKanjiControl(0, KC_INITIALIZE, (char *)&warning);
396 #ifdef nec_ews_svr4
397         start_polling();
398 #endif                          /* nec_ews_svr4 */
399         val = Qnil;
400         if (warning) {
401                 for (p = q = (unsigned char **)warning; *q; q++) ;
402                 while (p < q) {
403                         q--;
404                         val = Fcons(make_string(*q, strlen(*q)), val);
405                 }
406         }
407         val = Fcons(val, Qnil);
408
409         if (res == -1) {
410                 val = Fcons(make_string((unsigned char *)jrKanjiError,
411                                         strlen(jrKanjiError)), val);
412                 /* ¥¤¥Ë¥·¥ã¥é¥¤¥º¤Ç¼ºÇÔ¤·¤¿¾ì¹ç¡£ (on initialization failure) */
413                 return Fcons(Qnil, val);
414         } else {
415                 extern void (*jrBeepFunc) (void);
416
417                 jrBeepFunc = call_Fding;
418
419 #ifdef KC_SETAPPNAME
420 #ifndef CANNA_MULE
421                 wcKanjiControl(0, KC_SETAPPNAME, "nemacs");
422 #else                           /* CANNA_MULE */
423                 wcKanjiControl(0, KC_SETAPPNAME, "mule");
424 #endif                          /* CANNA_MULE */
425 #endif                          /* KC_SETAPPNAME */
426
427                 jrKanjiControl(0, KC_SETBUNSETSUKUGIRI, (char *)kugiri);
428                 jrKanjiControl(0, KC_SETWIDTH, (char *)78);
429 #ifndef CANNA_MULE
430                 jrKanjiControl(0, KC_INHIBITHANKAKUKANA, (char *)1);
431 #else
432                 /* mule ¤À¤Ã¤¿¤éȾ³Ñ¥«¥¿¥«¥Ê¤â»È¤¨¤ë
433                    (Mule can use half-width katakana) */
434                 if (canna_inhibit_hankakukana)
435                         jrKanjiControl(0, KC_INHIBITHANKAKUKANA, (char *)1);
436 #endif
437                 jrKanjiControl(0, KC_YOMIINFO, (char *)2);      /* ¢¨£²: ¥í¡¼¥Þ»ú¤Þ¤ÇÊÖ¤¹
438                                                                    (*2: return to
439                                                                    romanized form) */
440                 val = Fcons(Qnil, val);
441                 return Fcons(CANNA_mode_keys(), val);
442         }
443 }
444
445 DEFUN("canna-finalize", Fcanna_finalize, 0, 0, 0,       /*
446 finalize ``canna'', which is a kana-to-kanji converter for GNU Emacs.
447 This cause to write miscellaneous informations to kana-to-kanji dictionary.
448 */
449       ())
450 {
451         Lisp_Object val;
452         unsigned char **p;
453
454         jrKanjiControl(0, KC_FINALIZE, (char *)&warning);
455
456         val = Qnil;
457         if (warning) {
458                 for (p = (unsigned char **)warning; *p; p++) {
459                         val = Fcons(make_string(*p, strlen(*p)), val);
460                 }
461         }
462         val = Fcons(val, Qnil);
463         IRCP_context = -1;
464         return val;
465 }
466
467 DEFUN("canna-touroku-string", Fcanna_touroku_string, 1, 1, 0,   /*
468 Register Kanji words into kana-to-kanji conversion dictionary.
469 */
470       (str))
471 {
472         jrKanjiStatusWithValue ksv;
473         jrKanjiStatus ks;
474         int len;
475         Lisp_Object val;
476 #ifdef CANNA_MULE
477         unsigned char cbuf[4096];
478 #endif
479
480         CHECK_STRING(str);
481         ksv.buffer = (unsigned char *)key_buffer;
482         ksv.bytes_buffer = KEYTOSTRSIZE;
483 #ifndef CANNA_MULE
484         ks.echoStr = XSTRING_DATA(str);
485         ks.length = XSTRING_LENGTH(str);
486 #else                           /* CANNA_MULE */
487         m2c(XSTRING_DATA(str), XSTRING_LENGTH(str), cbuf);
488         ks.echoStr = cbuf;
489         ks.length = strlen(cbuf);
490 #endif                          /* CANNA_MULE */
491         ksv.ks = &ks;
492         len = jrKanjiControl(0, KC_DEFINEKANJI, (char *)&ksv);
493         val = storeResults(key_buffer, ksv.val, ksv.ks);
494         return val;
495 }
496
497 DEFUN("canna-set-width", Fcanna_set_width, 1, 1, 0,     /*
498 Set status-line width information, which is used to display
499 kanji candidates.
500 */
501       (num))
502 {
503         CHECK_INT(num);
504
505         jrKanjiControl(0, KC_SETWIDTH, (char *)XINT(num));
506         return Qnil;
507 }
508
509 DEFUN("canna-change-mode", Fcanna_change_mode, 1, 1, 0, /*
510 Change Japanese pre-edit mode.
511 */
512       (num))
513 {
514         jrKanjiStatusWithValue ksv;
515         jrKanjiStatus ks;
516         Lisp_Object val;
517
518         CHECK_INT(num);
519
520         ksv.buffer = (unsigned char *)key_buffer;
521         ksv.bytes_buffer = KEYTOSTRSIZE;
522         ksv.ks = &ks;
523         ksv.val = XINT(num);
524         jrKanjiControl(0, KC_CHANGEMODE, (char *)&ksv);
525         val = storeResults(key_buffer, ksv.val, ksv.ks);
526         return val;
527 }
528
529 static Lisp_Object CANNA_mode_keys(void)
530 {
531 #define CANNAWORKBUFSIZE 32
532         char xxx[CANNAWORKBUFSIZE];
533         Lisp_Object val;
534         int i, n;
535
536         n = jrKanjiControl(0, KC_MODEKEYS, xxx);
537         val = Qnil;
538         for (i = n; i > 0;) {
539                 --i;
540                 /* !!#### something fucked here */
541                 val =
542                     Fcons(make_char((int)(0xFF & (unsigned char)xxx[i])), val);
543         }
544         return val;
545 }
546
547 DEFUN("canna-store-yomi", Fcanna_store_yomi, 1, 2, 0,   /*
548 Store yomi characters as a YOMI of kana-to-kanji conversion.
549 */
550       (yomi, roma))
551 {
552         jrKanjiStatusWithValue ksv;
553         jrKanjiStatus ks;
554
555         CHECK_STRING(yomi);
556 #ifndef CANNA_MULE
557         strncpy(key_buffer, XSTRING_DATA(yomi), XSTRING_LENGTH(yomi));
558         ks.length = XSTRING_LENGTH(yomi);
559         key_buffer[ks.length] = '\0';
560 #else                           /* CANNA_MULE */
561         m2c(XSTRING_DATA(yomi), XSTRING_LENGTH(yomi), key_buffer);
562         ks.length = strlen(key_buffer);
563 #endif                          /* CANNA_MULE */
564
565         if (NILP(roma)) {
566                 ks.mode = 0;
567         } else {
568                 CHECK_STRING(roma);
569
570 #ifndef CANNA_MULE
571                 strncpy(key_buffer + XSTRING_LENGTH(yomi) + 1,
572                         XSTRING_DATA(roma), XSTRING_LENGTH(roma));
573                 key_buffer[XSTRING_LENGTH(yomi) + 1 + XSTRING_LENGTH(roma)] =
574                     '\0';
575                 ks.mode =
576                     (unsigned char *)(key_buffer + XSTRING_LENGTH(yomi) + 1);
577 #else                           /* CANNA_MULE */
578                 ks.mode = (unsigned char *)(key_buffer + ks.length + 1);
579                 m2c(XSTRING_DATA(roma), XSTRING_LENGTH(roma), ks.mode);
580 #endif                          /* CANNA_MULE */
581         }
582
583         ks.echoStr = (unsigned char *)key_buffer;
584         ksv.buffer = (unsigned char *)key_buffer;       /* ÊÖÃÍÍÑ (return value) */
585         ksv.bytes_buffer = KEYTOSTRSIZE;
586         ksv.ks = &ks;
587
588         jrKanjiControl(0, KC_STOREYOMI, (char *)&ksv);
589
590         return storeResults(key_buffer, ksv.val, ksv.ks);
591 }
592
593 DEFUN("canna-do-function", Fcanna_do_function, 1, 2, 0, /*
594 Do specified function at current mode.
595 */
596       (num, ch))
597 {
598         jrKanjiStatusWithValue ksv;
599         jrKanjiStatus ks;
600         Lisp_Object val;
601
602         CHECK_INT(num);
603
604         if (NILP(ch)) {
605                 *key_buffer = '@';
606         } else {
607                 CHECK_CHAR(ch);
608                 *key_buffer = XCHAR(ch);
609         }
610
611         ksv.buffer = (unsigned char *)key_buffer;
612         ksv.bytes_buffer = KEYTOSTRSIZE;
613         ksv.ks = &ks;
614         ksv.val = XINT(num);
615         jrKanjiControl(0, KC_DO, (char *)&ksv);
616         val = storeResults(key_buffer, ksv.val, ksv.ks);
617         return val;
618 }
619
620 DEFUN("canna-parse", Fcanna_parse, 1, 1, 0,     /*
621 Parse customize string.
622 */
623       (str))
624 {
625         Lisp_Object val;
626         unsigned char **p;
627         int n;
628
629         CHECK_STRING(str);
630
631 #ifndef CANNA_MULE
632         strncpy(key_buffer, XSTRING_DATA(str), XSTRING_LENGTH(str));
633         key_buffer[XSTRING_LENGTH(str)] = '\0';
634 #else                           /* CANNA_MULE */
635         m2c(XSTRING_DATA(str), XSTRING_LENGTH(str), key_buffer);
636 #endif                          /* CANNA_MULE */
637         p = (unsigned char **)key_buffer;
638         n = jrKanjiControl(0, KC_PARSE, (char *)&p);
639         val = Qnil;
640         while (n > 0) {
641                 n--;
642                 val = Fcons(make_string(p[n], strlen(p[n])), val);
643         }
644         return val;
645 }
646
647 DEFUN("canna-query-mode", Fcanna_query_mode, 0, 0, 0,   /*
648 Get current mode string.
649 */
650       ())
651 {
652         unsigned char buf[256];
653
654         jrKanjiControl(0, KC_QUERYMODE, buf);
655         return make_string(buf, strlen(buf));
656 }
657
658 /*
659  * Functions following this line are for KKCP interface compatible
660  * library.  These functions may be used by MILK system.
661  */
662
663 #define RKBUFSIZE 1024
664
665 static unsigned char yomibuf[RKBUFSIZE];
666 static short kugiri[RKBUFSIZE / 2];
667
668 static int confirmContext(void)
669 {
670         if (IRCP_context < 0) {
671                 int context;
672
673                 if ((context =
674                      jrKanjiControl(0, KC_GETCONTEXT, (char *)0)) == -1) {
675                         return 0;
676                 }
677                 IRCP_context = context;
678         }
679         return 1;
680 }
681
682 static int byteLen(int bun, int len)
683 {
684         int i = 0, offset = 0, ch;
685
686         if (0 <= bun && bun < RKBUFSIZE) {
687                 offset = kugiri[bun];
688         }
689
690         while (len-- > 0 && (ch = (int)yomibuf[offset + i])) {
691                 i++;
692                 if (ch & 0x80) {
693                         i++;
694                 }
695         }
696         return i;
697 }
698
699 DEFUN("canna-henkan-begin", Fcanna_henkan_begin, 1, 1, 0,       /*
700 Return the result of kana-to-kanji conversion.
701 Clause separator is set.
702 */
703       (yomi))
704 {
705         int nbun;
706
707         CHECK_STRING(yomi);
708         if (confirmContext() == 0) {
709                 return Qnil;
710         }
711 #ifndef CANNA_MULE
712         strncpy(yomibuf, XSTRING_DATA(yomi), XSTRING_LENGTH(yomi));
713         yomibuf[XSTRING_LENGTH(yomi)] = '\0';
714         nbun = RkBgnBun(IRCP_context, XSTRING_DATA(yomi), XSTRING_LENGTH(yomi),
715                         (RK_XFER << RK_XFERBITS) | RK_KFER);
716 #else                           /* CANNA_MULE */
717         m2c(XSTRING_DATA(yomi), XSTRING_LENGTH(yomi), yomibuf);
718         nbun = RkBgnBun(IRCP_context, (char *)yomibuf, strlen(yomibuf),
719                         (RK_XFER << RK_XFERBITS) | RK_KFER);
720 #endif                          /* CANNA_MULE */
721
722         return kanjiYomiList(IRCP_context, nbun);
723 }
724
725 static Lisp_Object kanjiYomiList(int context, int nbun)
726 {
727         Lisp_Object val, res = Qnil;
728         unsigned char RkBuf[RKBUFSIZE];
729         int len, i, total;
730
731         for (i = nbun; i > 0;) {
732                 i--;
733                 RkGoTo(context, i);
734                 len = RkGetKanji(context, RkBuf, RKBUFSIZE);
735                 val = make_string(RkBuf, len);
736                 len = RkGetYomi(context, RkBuf, RKBUFSIZE);
737                 res = Fcons(Fcons(val, make_string(RkBuf, len)), res);
738                 if (i < RKBUFSIZE / 2) {
739                         kugiri[i] = len;
740                 }
741         }
742         for (i = 0, total = 0; i < nbun; i++) {
743                 int temp = kugiri[i];
744                 kugiri[i] = total;
745                 total += temp;
746         }
747         return res;
748 }
749
750 DEFUN("canna-henkan-next", Fcanna_henkan_next, 1, 1, 0, /*
751 Return the list of candidates.
752 */
753       (bunsetsu))
754 {
755         int i, slen, len;
756         unsigned char *p, RkBuf[RKBUFSIZE];
757         Lisp_Object res = Qnil, endp;
758
759         CHECK_INT(bunsetsu);
760         if (confirmContext() == 0) {
761                 return Qnil;
762         }
763         RkGoTo(IRCP_context, XINT(bunsetsu));
764         len = RkGetKanjiList(IRCP_context, RkBuf, RKBUFSIZE);
765         p = RkBuf;
766         for (i = 0; i < len; i++) {
767                 slen = strlen(p);
768                 if (NILP(res)) {
769                         endp = res = Fcons(make_string(p, slen), Qnil);
770                 } else {
771                         endp = XCDR(res) = Fcons(make_string(p, slen), Qnil);
772                 }
773                 p += slen + 1;
774         }
775         return res;
776 }
777
778 DEFUN("canna-bunsetu-henkou", Fcanna_bunsetu_henkou, 2, 2, 0,   /*
779 Specify the length of a clause.
780 */
781       (bunsetsu, bunlen))
782 {
783         int nbun, len;
784
785         CHECK_INT(bunsetsu);
786         CHECK_INT(bunlen);
787
788         nbun = XINT(bunsetsu);
789         if (confirmContext() == 0) {
790                 return Qnil;
791         }
792         RkGoTo(IRCP_context, nbun);
793         len = byteLen(nbun, XINT(bunlen));
794         return kanjiYomiList(IRCP_context, RkResize(IRCP_context, len));
795 }
796
797 DEFUN("canna-henkan-kakutei", Fcanna_henkan_kakutei, 2, 2, 0,   /*
798 Select a candidate.
799 */
800       (bun, kouho))
801 {
802         int nbun, nkouho;
803
804         if (confirmContext() == 0) {
805                 return Qnil;
806         }
807         nbun = XINT(bun);
808         RkGoTo(IRCP_context, nbun);
809
810         nkouho = XINT(kouho);
811         RkXfer(IRCP_context, nkouho);
812         return Qt;
813 }
814
815 DEFUN("canna-henkan-end", Fcanna_henkan_end, 0, 0, 0,   /*
816 End conversion.
817 */
818       ())
819 {
820         if (confirmContext() == 0) {
821                 return Qnil;
822         }
823         RkEndBun(IRCP_context, 1);      /* ³Ø½¬¤Ï¤¤¤Ä¤Ç¤â¹Ô¤Ã¤ÆÎɤ¤¤â¤Î¤Ê¤Î¤«¡©
824                                            (is it OK to invoke learning function
825                                            at arbitrary times?) */
826         return Qt;
827 }
828
829 DEFUN("canna-henkan-quit", Fcanna_henkan_quit, 0, 0, 0, /*
830 Quit conversion.
831 */
832       ())
833 {
834         if (confirmContext() == 0) {
835                 return Qnil;
836         }
837         RkEndBun(IRCP_context, 0);
838         return Qt;
839 }
840
841 /* variables below this line is constants of Canna */
842
843 static Fixnum canna_mode_AlphaMode;
844 static Fixnum canna_mode_EmptyMode;
845 static Fixnum canna_mode_KigoMode;
846 static Fixnum canna_mode_YomiMode;
847 static Fixnum canna_mode_JishuMode;
848 static Fixnum canna_mode_TankouhoMode;
849 static Fixnum canna_mode_IchiranMode;
850 static Fixnum canna_mode_YesNoMode;
851 static Fixnum canna_mode_OnOffMode;
852 #ifdef CANNA_MODE_AdjustBunsetsuMode
853 static Fixnum canna_mode_AdjustBunsetsuMode;
854 #endif
855 #ifdef CANNA_MODE_ChikujiYomiMode
856 static Fixnum canna_mode_ChikujiYomiMode;
857 static Fixnum canna_mode_ChikujiTanMode;
858 #endif
859
860 static Fixnum canna_mode_HenkanMode;
861 #ifdef CANNA_MODE_HenkanNyuryokuMode
862 static Fixnum canna_mode_HenkanNyuryokuMode;
863 #endif
864 #ifdef CANNA_MODE_ZenHiraHenkanMode
865 static Fixnum canna_mode_ZenHiraHenkanMode;
866 #ifdef CANNA_MODE_HanHiraHenkanMode
867 static Fixnum canna_mode_HanHiraHenkanMode;
868 #endif
869 static Fixnum canna_mode_ZenKataHenkanMode;
870 static Fixnum canna_mode_HanKataHenkanMode;
871 static Fixnum canna_mode_ZenAlphaHenkanMode;
872 static Fixnum canna_mode_HanAlphaHenkanMode;
873 #endif
874 static Fixnum canna_mode_ZenHiraKakuteiMode;
875 #ifdef CANNA_MODE_HanHiraKakuteiMode
876 static Fixnum canna_mode_HanHiraKakuteiMode;
877 #endif
878 static Fixnum canna_mode_ZenKataKakuteiMode;
879 static Fixnum canna_mode_HanKataKakuteiMode;
880 static Fixnum canna_mode_ZenAlphaKakuteiMode;
881 static Fixnum canna_mode_HanAlphaKakuteiMode;
882 static Fixnum canna_mode_HexMode;
883 static Fixnum canna_mode_BushuMode;
884 static Fixnum canna_mode_ExtendMode;
885 static Fixnum canna_mode_RussianMode;
886 static Fixnum canna_mode_GreekMode;
887 static Fixnum canna_mode_LineMode;
888 static Fixnum canna_mode_ChangingServerMode;
889 static Fixnum canna_mode_HenkanMethodMode;
890 static Fixnum canna_mode_DeleteDicMode;
891 static Fixnum canna_mode_TourokuMode;
892 static Fixnum canna_mode_TourokuEmptyMode;
893 static Fixnum canna_mode_TourokuHinshiMode;
894 static Fixnum canna_mode_TourokuDicMode;
895 static Fixnum canna_mode_QuotedInsertMode;
896 static Fixnum canna_mode_BubunMuhenkanMode;
897 static Fixnum canna_mode_MountDicMode;
898
899 static Fixnum canna_fn_SelfInsert;
900 static Fixnum canna_fn_FunctionalInsert;
901 static Fixnum canna_fn_QuotedInsert;
902 static Fixnum canna_fn_JapaneseMode;
903 static Fixnum canna_fn_AlphaMode;
904 static Fixnum canna_fn_HenkanNyuryokuMode;
905 static Fixnum canna_fn_Forward;
906 static Fixnum canna_fn_Backward;
907 static Fixnum canna_fn_Next;
908 static Fixnum canna_fn_Prev;
909 static Fixnum canna_fn_BeginningOfLine;
910 static Fixnum canna_fn_EndOfLine;
911 static Fixnum canna_fn_DeleteNext;
912 static Fixnum canna_fn_DeletePrevious;
913 static Fixnum canna_fn_KillToEndOfLine;
914 static Fixnum canna_fn_Henkan;
915 static Fixnum canna_fn_Kakutei;
916 static Fixnum canna_fn_Extend;
917 static Fixnum canna_fn_Shrink;
918 #ifdef CANNA_FN_AdjustBunsetsu
919 static Fixnum canna_fn_AdjustBunsetsu;
920 #endif
921 static Fixnum canna_fn_Quit;
922 static Fixnum canna_fn_ConvertAsHex;
923 static Fixnum canna_fn_ConvertAsBushu;
924 static Fixnum canna_fn_KouhoIchiran;
925 static Fixnum canna_fn_BubunMuhenkan;
926 static Fixnum canna_fn_Zenkaku;
927 static Fixnum canna_fn_Hankaku;
928 static Fixnum canna_fn_ToUpper;
929 static Fixnum canna_fn_Capitalize;
930 static Fixnum canna_fn_ToLower;
931 static Fixnum canna_fn_Hiragana;
932 static Fixnum canna_fn_Katakana;
933 static Fixnum canna_fn_Romaji;
934 #ifdef CANNA_FN_BaseHiragana
935 static Fixnum canna_fn_BaseHiragana;
936 static Fixnum canna_fn_BaseKatakana;
937 static Fixnum canna_fn_BaseEisu;
938 static Fixnum canna_fn_BaseZenkaku;
939 static Fixnum canna_fn_BaseHankaku;
940 static Fixnum canna_fn_BaseKana;
941 static Fixnum canna_fn_BaseKakutei;
942 static Fixnum canna_fn_BaseHenkan;
943 static Fixnum canna_fn_BaseHiraKataToggle;
944 static Fixnum canna_fn_BaseZenHanToggle;
945 static Fixnum canna_fn_BaseKanaEisuToggle;
946 static Fixnum canna_fn_BaseKakuteiHenkanToggle;
947 static Fixnum canna_fn_BaseRotateForward;
948 static Fixnum canna_fn_BaseRotateBackward;
949 #endif
950 static Fixnum canna_fn_ExtendMode;
951 static Fixnum canna_fn_Touroku;
952 static Fixnum canna_fn_HexMode;
953 static Fixnum canna_fn_BushuMode;
954 static Fixnum canna_fn_KigouMode;
955 #ifdef CANNA_FN_Mark
956 static Fixnum canna_fn_Mark;
957 #endif
958 #ifdef CANNA_FN_TemporalMode
959 static Fixnum canna_fn_TemporalMode;
960 #endif
961
962 static Fixnum canna_key_Nfer;
963 static Fixnum canna_key_Xfer;
964 static Fixnum canna_key_Up;
965 static Fixnum canna_key_Left;
966 static Fixnum canna_key_Right;
967 static Fixnum canna_key_Down;
968 static Fixnum canna_key_Insert;
969 static Fixnum canna_key_Rollup;
970 static Fixnum canna_key_Rolldown;
971 static Fixnum canna_key_Home;
972 static Fixnum canna_key_Help;
973 static Fixnum canna_key_KP_Key;
974 static Fixnum canna_key_Shift_Nfer;
975 static Fixnum canna_key_Shift_Xfer;
976 static Fixnum canna_key_Shift_Up;
977 static Fixnum canna_key_Shift_Left;
978 static Fixnum canna_key_Shift_Right;
979 static Fixnum canna_key_Shift_Down;
980 static Fixnum canna_key_Cntrl_Nfer;
981 static Fixnum canna_key_Cntrl_Xfer;
982 static Fixnum canna_key_Cntrl_Up;
983 static Fixnum canna_key_Cntrl_Left;
984 static Fixnum canna_key_Cntrl_Right;
985 static Fixnum canna_key_Cntrl_Down;
986
987 Lisp_Object VCANNA;             /* by MORIOKA Tomohiko <morioka@jaist.ac.jp>
988                                    1996/6/7 */
989
990 void syms_of_mule_canna(void)
991 {
992         DEFSUBR(Fcanna_key_proc);
993         DEFSUBR(Fcanna_initialize);
994         DEFSUBR(Fcanna_finalize);
995         DEFSUBR(Fcanna_touroku_string);
996         DEFSUBR(Fcanna_set_width);
997         DEFSUBR(Fcanna_change_mode);
998         DEFSUBR(Fcanna_store_yomi);
999         DEFSUBR(Fcanna_do_function);
1000         DEFSUBR(Fcanna_parse);
1001         DEFSUBR(Fcanna_query_mode);
1002         DEFSUBR(Fcanna_set_bunsetsu);
1003
1004         DEFSUBR(Fcanna_henkan_begin);
1005         DEFSUBR(Fcanna_henkan_next);
1006         DEFSUBR(Fcanna_bunsetu_henkou);
1007         DEFSUBR(Fcanna_henkan_kakutei);
1008         DEFSUBR(Fcanna_henkan_end);
1009         DEFSUBR(Fcanna_henkan_quit);
1010 }
1011
1012 void vars_of_mule_canna(void)
1013 {
1014         DEFVAR_LISP("CANNA", &VCANNA);  /* hir@nec, 1992.5.21 */
1015         VCANNA = Qt;            /* hir@nec, 1992.5.21 */
1016
1017         DEFVAR_LISP("canna-kakutei-string", &Vcanna_kakutei_string      /*
1018
1019                                                                          */ );
1020         Vcanna_kakutei_string = Qnil;
1021
1022         DEFVAR_LISP("canna-kakutei-yomi", &Vcanna_kakutei_yomi  /*
1023
1024                                                                  */ );
1025         Vcanna_kakutei_yomi = Qnil;
1026
1027         DEFVAR_LISP("canna-kakutei-romaji", &Vcanna_kakutei_romaji      /*
1028
1029                                                                          */ );
1030         Vcanna_kakutei_romaji = Qnil;
1031
1032         DEFVAR_LISP("canna-henkan-string", &Vcanna_henkan_string        /*
1033
1034                                                                          */ );
1035         Vcanna_henkan_string = Qnil;
1036
1037         DEFVAR_INT("canna-henkan-length", &canna_henkan_length  /*
1038
1039                                                                  */ );
1040         canna_henkan_length = 0;
1041
1042         DEFVAR_INT("canna-henkan-revpos", &canna_henkan_revPos  /*
1043
1044                                                                  */ );
1045         canna_henkan_revPos = 0;
1046
1047         DEFVAR_INT("canna-henkan-revlen", &canna_henkan_revLen  /*
1048
1049                                                                  */ );
1050         canna_henkan_revLen = 0;
1051
1052         DEFVAR_LISP("canna-ichiran-string", &Vcanna_ichiran_string      /*
1053
1054                                                                          */ );
1055         Vcanna_ichiran_string = Qnil;
1056
1057         DEFVAR_INT("canna-ichiran-length", &canna_ichiran_length        /*
1058
1059                                                                          */ );
1060         canna_ichiran_length = 0;
1061
1062         DEFVAR_INT("canna-ichiran-revpos", &canna_ichiran_revPos        /*
1063
1064                                                                          */ );
1065         canna_ichiran_revPos = 0;
1066
1067         DEFVAR_INT("canna-ichiran-revlen", &canna_ichiran_revLen        /*
1068
1069                                                                          */ );
1070         canna_ichiran_revLen = 0;
1071
1072         DEFVAR_LISP("canna-mode-string", &Vcanna_mode_string    /*
1073
1074                                                                  */ );
1075         Vcanna_mode_string = Qnil;
1076
1077         DEFVAR_BOOL("canna-empty-info", &canna_empty_info       /*
1078                                                                    For canna
1079                                                                  */ );
1080         canna_empty_info = 0;
1081
1082         DEFVAR_BOOL("canna-through-info", &canna_through_info   /*
1083                                                                    For canna
1084                                                                  */ );
1085         canna_through_info = 0;
1086
1087         DEFVAR_BOOL("canna-underline", &canna_underline /*
1088                                                            For canna
1089                                                          */ );
1090         canna_underline = 0;
1091
1092         DEFVAR_BOOL("canna-inhibit-hankakukana", &canna_inhibit_hankakukana     /*
1093                                                                                    For canna
1094                                                                                  */ );
1095         canna_inhibit_hankakukana = 0;
1096
1097         DEFVAR_INT("canna-mode-alpha-mode", &canna_mode_AlphaMode       /*
1098
1099                                                                          */ );
1100         canna_mode_AlphaMode = IROHA_MODE_AlphaMode;
1101
1102         DEFVAR_INT("canna-mode-empty-mode", &canna_mode_EmptyMode       /*
1103
1104                                                                          */ );
1105         canna_mode_EmptyMode = IROHA_MODE_EmptyMode;
1106
1107         DEFVAR_INT("canna-mode-kigo-mode", &canna_mode_KigoMode /*
1108
1109                                                                  */ );
1110         canna_mode_KigoMode = IROHA_MODE_KigoMode;
1111
1112         DEFVAR_INT("canna-mode-yomi-mode", &canna_mode_YomiMode /*
1113
1114                                                                  */ );
1115         canna_mode_YomiMode = IROHA_MODE_YomiMode;
1116
1117         DEFVAR_INT("canna-mode-jishu-mode", &canna_mode_JishuMode       /*
1118
1119                                                                          */ );
1120         canna_mode_JishuMode = IROHA_MODE_JishuMode;
1121
1122         DEFVAR_INT("canna-mode-tankouho-mode", &canna_mode_TankouhoMode /*
1123
1124                                                                          */ );
1125         canna_mode_TankouhoMode = IROHA_MODE_TankouhoMode;
1126
1127         DEFVAR_INT("canna-mode-ichiran-mode", &canna_mode_IchiranMode   /*
1128
1129                                                                          */ );
1130         canna_mode_IchiranMode = IROHA_MODE_IchiranMode;
1131
1132         DEFVAR_INT("canna-mode-yes-no-mode", &canna_mode_YesNoMode      /*
1133
1134                                                                          */ );
1135         canna_mode_YesNoMode = IROHA_MODE_YesNoMode;
1136
1137         DEFVAR_INT("canna-mode-on-off-mode", &canna_mode_OnOffMode      /*
1138
1139                                                                          */ );
1140         canna_mode_OnOffMode = IROHA_MODE_OnOffMode;
1141
1142 #ifdef CANNA_MODE_AdjustBunsetsuMode
1143         DEFVAR_INT("canna-mode-adjust-bunsetsu-mode", &canna_mode_AdjustBunsetsuMode    /*
1144
1145                                                                                          */ );
1146         canna_mode_AdjustBunsetsuMode = CANNA_MODE_AdjustBunsetsuMode;
1147 #endif
1148 #ifdef CANNA_MODE_ChikujiYomiMode
1149         DEFVAR_INT("canna-mode-chikuji-yomi-mode", &canna_mode_ChikujiYomiMode  /*
1150
1151                                                                                  */ );
1152         canna_mode_ChikujiYomiMode = CANNA_MODE_ChikujiYomiMode;
1153
1154         DEFVAR_INT("canna-mode-chikuji-bunsetsu-mode", &canna_mode_ChikujiTanMode       /*
1155
1156                                                                                          */ );
1157         canna_mode_ChikujiTanMode = CANNA_MODE_ChikujiTanMode;
1158 #endif
1159
1160         DEFVAR_INT("canna-mode-henkan-mode", &canna_mode_HenkanMode     /*
1161
1162                                                                          */ );
1163         canna_mode_HenkanMode = IROHA_MODE_HenkanMode;
1164
1165 #ifdef CANNA_MODE_HenkanNyuryokuMode
1166         DEFVAR_INT("canna-mode-henkan-nyuuryoku-mode", &canna_mode_HenkanNyuryokuMode   /*
1167
1168                                                                                          */ );
1169         canna_mode_HenkanNyuryokuMode = CANNA_MODE_HenkanNyuryokuMode;
1170 #endif
1171 #ifdef CANNA_MODE_ZenHiraHenkanMode
1172         DEFVAR_INT("canna-mode-zen-hira-henkan-mode", &canna_mode_ZenHiraHenkanMode     /*
1173
1174                                                                                          */ );
1175         canna_mode_ZenHiraHenkanMode = CANNA_MODE_ZenHiraHenkanMode;
1176 #ifdef CANNA_MODE_HanHiraHenkanMode
1177         DEFVAR_INT("canna-mode-han-hira-henkan-mode", &canna_mode_HanHiraHenkanMode     /*
1178
1179                                                                                          */ );
1180         canna_mode_HanHiraHenkanMode = CANNA_MODE_HanHiraHenkanMode;
1181 #endif
1182         DEFVAR_INT("canna-mode-zen-kata-henkan-mode", &canna_mode_ZenKataHenkanMode     /*
1183
1184                                                                                          */ );
1185         canna_mode_ZenKataHenkanMode = CANNA_MODE_ZenKataHenkanMode;
1186
1187         DEFVAR_INT("canna-mode-han-kata-henkan-mode", &canna_mode_HanKataHenkanMode     /*
1188
1189                                                                                          */ );
1190         canna_mode_HanKataHenkanMode = CANNA_MODE_HanKataHenkanMode;
1191
1192         DEFVAR_INT("canna-mode-zen-alpha-henkan-mode", &canna_mode_ZenAlphaHenkanMode   /*
1193
1194                                                                                          */ );
1195         canna_mode_ZenAlphaHenkanMode = CANNA_MODE_ZenAlphaHenkanMode;
1196
1197         DEFVAR_INT("canna-mode-han-alpha-henkan-mode", &canna_mode_HanAlphaHenkanMode   /*
1198
1199                                                                                          */ );
1200         canna_mode_HanAlphaHenkanMode = CANNA_MODE_HanAlphaHenkanMode;
1201 #endif
1202         DEFVAR_INT("canna-mode-zen-hira-kakutei-mode", &canna_mode_ZenHiraKakuteiMode   /*
1203
1204                                                                                          */ );
1205         canna_mode_ZenHiraKakuteiMode = IROHA_MODE_ZenHiraKakuteiMode;
1206 #ifdef CANNA_MODE_HanHiraKakuteiMode
1207         DEFVAR_INT("canna-mode-han-hira-kakutei-mode", &canna_mode_HanHiraKakuteiMode   /*
1208
1209                                                                                          */ );
1210         canna_mode_HanHiraKakuteiMode = CANNA_MODE_HanHiraKakuteiMode;
1211 #endif
1212         DEFVAR_INT("canna-mode-zen-kata-kakutei-mode", &canna_mode_ZenKataKakuteiMode   /*
1213
1214                                                                                          */ );
1215         canna_mode_ZenKataKakuteiMode = IROHA_MODE_ZenKataKakuteiMode;
1216
1217         DEFVAR_INT("canna-mode-han-kata-kakutei-mode", &canna_mode_HanKataKakuteiMode   /*
1218
1219                                                                                          */ );
1220         canna_mode_HanKataKakuteiMode = IROHA_MODE_HanKataKakuteiMode;
1221
1222         DEFVAR_INT("canna-mode-zen-alpha-kakutei-mode", &canna_mode_ZenAlphaKakuteiMode /*
1223
1224                                                                                          */ );
1225         canna_mode_ZenAlphaKakuteiMode = IROHA_MODE_ZenAlphaKakuteiMode;
1226
1227         DEFVAR_INT("canna-mode-han-alpha-kakutei-mode", &canna_mode_HanAlphaKakuteiMode /*
1228
1229                                                                                          */ );
1230         canna_mode_HanAlphaKakuteiMode = IROHA_MODE_HanAlphaKakuteiMode;
1231
1232         DEFVAR_INT("canna-mode-hex-mode", &canna_mode_HexMode   /*
1233
1234                                                                  */ );
1235         canna_mode_HexMode = IROHA_MODE_HexMode;
1236
1237         DEFVAR_INT("canna-mode-bushu-mode", &canna_mode_BushuMode       /*
1238
1239                                                                          */ );
1240         canna_mode_BushuMode = IROHA_MODE_BushuMode;
1241
1242         DEFVAR_INT("canna-mode-extend-mode", &canna_mode_ExtendMode     /*
1243
1244                                                                          */ );
1245         canna_mode_ExtendMode = IROHA_MODE_ExtendMode;
1246
1247         DEFVAR_INT("canna-mode-russian-mode", &canna_mode_RussianMode   /*
1248
1249                                                                          */ );
1250         canna_mode_RussianMode = IROHA_MODE_RussianMode;
1251
1252         DEFVAR_INT("canna-mode-greek-mode", &canna_mode_GreekMode       /*
1253
1254                                                                          */ );
1255         canna_mode_GreekMode = IROHA_MODE_GreekMode;
1256
1257         DEFVAR_INT("canna-mode-line-mode", &canna_mode_LineMode /*
1258
1259                                                                  */ );
1260         canna_mode_LineMode = IROHA_MODE_LineMode;
1261
1262         DEFVAR_INT("canna-mode-changing-server-mode", &canna_mode_ChangingServerMode    /*
1263
1264                                                                                          */ );
1265         canna_mode_ChangingServerMode = IROHA_MODE_ChangingServerMode;
1266
1267         DEFVAR_INT("canna-mode-henkan-method-mode", &canna_mode_HenkanMethodMode        /*
1268
1269                                                                                          */ );
1270         canna_mode_HenkanMethodMode = IROHA_MODE_HenkanMethodMode;
1271
1272         DEFVAR_INT("canna-mode-delete-dic-mode", &canna_mode_DeleteDicMode      /*
1273
1274                                                                                  */ );
1275         canna_mode_DeleteDicMode = IROHA_MODE_DeleteDicMode;
1276
1277         DEFVAR_INT("canna-mode-touroku-mode", &canna_mode_TourokuMode   /*
1278
1279                                                                          */ );
1280         canna_mode_TourokuMode = IROHA_MODE_TourokuMode;
1281
1282         DEFVAR_INT("canna-mode-touroku-empty-mode", &canna_mode_TourokuEmptyMode        /*
1283
1284                                                                                          */ );
1285         canna_mode_TourokuEmptyMode = IROHA_MODE_TourokuEmptyMode;
1286
1287         DEFVAR_INT("canna-mode-touroku-hinshi-mode", &canna_mode_TourokuHinshiMode      /*
1288
1289                                                                                          */ );
1290         canna_mode_TourokuHinshiMode = IROHA_MODE_TourokuHinshiMode;
1291
1292         DEFVAR_INT("canna-mode-touroku-dic-mode", &canna_mode_TourokuDicMode    /*
1293
1294                                                                                  */ );
1295         canna_mode_TourokuDicMode = IROHA_MODE_TourokuDicMode;
1296
1297         DEFVAR_INT("canna-mode-quoted-insert-mode", &canna_mode_QuotedInsertMode        /*
1298
1299                                                                                          */ );
1300         canna_mode_QuotedInsertMode = IROHA_MODE_QuotedInsertMode;
1301
1302         DEFVAR_INT("canna-mode-bubun-muhenkan-mode", &canna_mode_BubunMuhenkanMode      /*
1303
1304                                                                                          */ );
1305         canna_mode_BubunMuhenkanMode = IROHA_MODE_BubunMuhenkanMode;
1306
1307         DEFVAR_INT("canna-mode-mount-dic-mode", &canna_mode_MountDicMode        /*
1308
1309                                                                                  */ );
1310         canna_mode_MountDicMode = IROHA_MODE_MountDicMode;
1311
1312         DEFVAR_INT("canna-func-self-insert", &canna_fn_SelfInsert       /*
1313
1314                                                                          */ );
1315         canna_fn_SelfInsert = IROHA_FN_SelfInsert;
1316
1317         DEFVAR_INT("canna-func-functional-insert", &canna_fn_FunctionalInsert   /*
1318
1319                                                                                  */ );
1320         canna_fn_FunctionalInsert = IROHA_FN_FunctionalInsert;
1321
1322         DEFVAR_INT("canna-func-quoted-insert", &canna_fn_QuotedInsert   /*
1323
1324                                                                          */ );
1325         canna_fn_QuotedInsert = IROHA_FN_QuotedInsert;
1326
1327         DEFVAR_INT("canna-func-japanese-mode", &canna_fn_JapaneseMode   /*
1328
1329                                                                          */ );
1330         canna_fn_JapaneseMode = IROHA_FN_JapaneseMode;
1331
1332         DEFVAR_INT("canna-func-alpha-mode", &canna_fn_AlphaMode /*
1333
1334                                                                  */ );
1335         canna_fn_AlphaMode = IROHA_FN_AlphaMode;
1336
1337         DEFVAR_INT("canna-func-henkan-nyuryoku-mode", &canna_fn_HenkanNyuryokuMode      /*
1338
1339                                                                                          */ );
1340         canna_fn_HenkanNyuryokuMode = IROHA_FN_HenkanNyuryokuMode;
1341
1342         DEFVAR_INT("canna-func-forward", &canna_fn_Forward      /*
1343
1344                                                                  */ );
1345         canna_fn_Forward = IROHA_FN_Forward;
1346
1347         DEFVAR_INT("canna-func-backward", &canna_fn_Backward    /*
1348
1349                                                                  */ );
1350         canna_fn_Backward = IROHA_FN_Backward;
1351
1352         DEFVAR_INT("canna-func-next", &canna_fn_Next    /*
1353
1354                                                          */ );
1355         canna_fn_Next = IROHA_FN_Next;
1356
1357         DEFVAR_INT("canna-func-previous", &canna_fn_Prev        /*
1358
1359                                                                  */ );
1360         canna_fn_Prev = IROHA_FN_Prev;
1361
1362         DEFVAR_INT("canna-func-beginning-of-line", &canna_fn_BeginningOfLine    /*
1363
1364                                                                                  */ );
1365         canna_fn_BeginningOfLine = IROHA_FN_BeginningOfLine;
1366
1367         DEFVAR_INT("canna-func-end-of-line", &canna_fn_EndOfLine        /*
1368
1369                                                                          */ );
1370         canna_fn_EndOfLine = IROHA_FN_EndOfLine;
1371
1372         DEFVAR_INT("canna-func-delete-next", &canna_fn_DeleteNext       /*
1373
1374                                                                          */ );
1375         canna_fn_DeleteNext = IROHA_FN_DeleteNext;
1376
1377         DEFVAR_INT("canna-func-delete-previous", &canna_fn_DeletePrevious       /*
1378
1379                                                                                  */ );
1380         canna_fn_DeletePrevious = IROHA_FN_DeletePrevious;
1381
1382         DEFVAR_INT("canna-func-kill-to-end-of-line", &canna_fn_KillToEndOfLine  /*
1383
1384                                                                                  */ );
1385         canna_fn_KillToEndOfLine = IROHA_FN_KillToEndOfLine;
1386
1387         DEFVAR_INT("canna-func-henkan", &canna_fn_Henkan        /*
1388
1389                                                                  */ );
1390         canna_fn_Henkan = IROHA_FN_Henkan;
1391
1392         DEFVAR_INT("canna-func-kakutei", &canna_fn_Kakutei      /*
1393
1394                                                                  */ );
1395         canna_fn_Kakutei = IROHA_FN_Kakutei;
1396
1397         DEFVAR_INT("canna-func-extend", &canna_fn_Extend        /*
1398
1399                                                                  */ );
1400         canna_fn_Extend = IROHA_FN_Extend;
1401
1402         DEFVAR_INT("canna-func-shrink", &canna_fn_Shrink        /*
1403
1404                                                                  */ );
1405         canna_fn_Shrink = IROHA_FN_Shrink;
1406
1407 #ifdef CANNA_FN_AdjustBunsetsu
1408         DEFVAR_INT("canna-func-adjust-bunsetsu", &canna_fn_AdjustBunsetsu       /*
1409
1410                                                                                  */ );
1411         canna_fn_AdjustBunsetsu = CANNA_FN_AdjustBunsetsu;
1412 #endif
1413         DEFVAR_INT("canna-func-quit", &canna_fn_Quit    /*
1414
1415                                                          */ );
1416         canna_fn_Quit = IROHA_FN_Quit;
1417
1418         DEFVAR_INT("canna-func-convert-as-hex", &canna_fn_ConvertAsHex  /*
1419
1420                                                                          */ );
1421         canna_fn_ConvertAsHex = IROHA_FN_ConvertAsHex;
1422
1423         DEFVAR_INT("canna-func-convert-as-bushu", &canna_fn_ConvertAsBushu      /*
1424
1425                                                                                  */ );
1426         canna_fn_ConvertAsBushu = IROHA_FN_ConvertAsBushu;
1427
1428         DEFVAR_INT("canna-func-kouho-ichiran", &canna_fn_KouhoIchiran   /*
1429
1430                                                                          */ );
1431         canna_fn_KouhoIchiran = IROHA_FN_KouhoIchiran;
1432
1433         DEFVAR_INT("canna-func-bubun-muhenkan", &canna_fn_BubunMuhenkan /*
1434
1435                                                                          */ );
1436         canna_fn_BubunMuhenkan = IROHA_FN_BubunMuhenkan;
1437
1438         DEFVAR_INT("canna-func-zenkaku", &canna_fn_Zenkaku      /*
1439
1440                                                                  */ );
1441         canna_fn_Zenkaku = IROHA_FN_Zenkaku;
1442
1443         DEFVAR_INT("canna-func-hankaku", &canna_fn_Hankaku      /*
1444
1445                                                                  */ );
1446         canna_fn_Hankaku = IROHA_FN_Hankaku;
1447
1448         DEFVAR_INT("canna-func-to-upper", &canna_fn_ToUpper     /*
1449
1450                                                                  */ );
1451         canna_fn_ToUpper = IROHA_FN_ToUpper;
1452
1453         DEFVAR_INT("canna-func-capitalize", &canna_fn_Capitalize        /*
1454
1455                                                                          */ );
1456         canna_fn_Capitalize = IROHA_FN_Capitalize;
1457
1458         DEFVAR_INT("canna-func-to-lower", &canna_fn_ToLower     /*
1459
1460                                                                  */ );
1461         canna_fn_ToLower = IROHA_FN_ToLower;
1462
1463         DEFVAR_INT("canna-func-hiragana", &canna_fn_Hiragana    /*
1464
1465                                                                  */ );
1466         canna_fn_Hiragana = IROHA_FN_Hiragana;
1467
1468         DEFVAR_INT("canna-func-katakana", &canna_fn_Katakana    /*
1469
1470                                                                  */ );
1471         canna_fn_Katakana = IROHA_FN_Katakana;
1472
1473         DEFVAR_INT("canna-func-romaji", &canna_fn_Romaji        /*
1474
1475                                                                  */ );
1476         canna_fn_Romaji = IROHA_FN_Romaji;
1477
1478 #ifdef CANNA_FN_BaseHiragana
1479         DEFVAR_INT("canna-func-base-hiragana", &canna_fn_BaseHiragana   /*
1480
1481                                                                          */ );
1482         canna_fn_BaseHiragana = CANNA_FN_BaseHiragana;
1483
1484         DEFVAR_INT("canna-func-base-katakana", &canna_fn_BaseKatakana   /*
1485
1486                                                                          */ );
1487         canna_fn_BaseKatakana = CANNA_FN_BaseKatakana;
1488
1489         DEFVAR_INT("canna-func-base-eisu", &canna_fn_BaseEisu   /*
1490
1491                                                                  */ );
1492         canna_fn_BaseEisu = CANNA_FN_BaseEisu;
1493
1494         DEFVAR_INT("canna-func-base-zenkaku", &canna_fn_BaseZenkaku     /*
1495
1496                                                                          */ );
1497         canna_fn_BaseZenkaku = CANNA_FN_BaseZenkaku;
1498
1499         DEFVAR_INT("canna-func-base-hankaku", &canna_fn_BaseHankaku     /*
1500
1501                                                                          */ );
1502         canna_fn_BaseHankaku = CANNA_FN_BaseHankaku;
1503
1504         DEFVAR_INT("canna-func-base-kana", &canna_fn_BaseKana   /*
1505
1506                                                                  */ );
1507         canna_fn_BaseKana = CANNA_FN_BaseKana;
1508
1509         DEFVAR_INT("canna-func-base-kakutei", &canna_fn_BaseKakutei     /*
1510
1511                                                                          */ );
1512         canna_fn_BaseKakutei = CANNA_FN_BaseKakutei;
1513
1514         DEFVAR_INT("canna-func-base-henkan", &canna_fn_BaseHenkan       /*
1515
1516                                                                          */ );
1517         canna_fn_BaseHenkan = CANNA_FN_BaseHenkan;
1518
1519         DEFVAR_INT("canna-func-base-hiragana-katakana-toggle", &canna_fn_BaseHiraKataToggle     /*
1520
1521                                                                                                  */ );
1522         canna_fn_BaseHiraKataToggle = CANNA_FN_BaseHiraKataToggle;
1523
1524         DEFVAR_INT("canna-func-base-zenkaku-hankaku-toggle", &canna_fn_BaseZenHanToggle /*
1525
1526                                                                                          */ );
1527         canna_fn_BaseZenHanToggle = CANNA_FN_BaseZenHanToggle;
1528
1529         DEFVAR_INT("canna-func-base-kana-eisu-toggle", &canna_fn_BaseKanaEisuToggle     /*
1530
1531                                                                                          */ );
1532         canna_fn_BaseKanaEisuToggle = CANNA_FN_BaseKanaEisuToggle;
1533
1534         DEFVAR_INT("canna-func-base-kakutei-henkan-toggle", &canna_fn_BaseKakuteiHenkanToggle   /*
1535
1536                                                                                                  */ );
1537         canna_fn_BaseKakuteiHenkanToggle = CANNA_FN_BaseKakuteiHenkanToggle;
1538
1539         DEFVAR_INT("canna-func-base-rotate-forward", &canna_fn_BaseRotateForward        /*
1540
1541                                                                                          */ );
1542         canna_fn_BaseRotateForward = CANNA_FN_BaseRotateForward;
1543
1544         DEFVAR_INT("canna-func-base-rotate-backward", &canna_fn_BaseRotateBackward      /*
1545
1546                                                                                          */ );
1547         canna_fn_BaseRotateBackward = CANNA_FN_BaseRotateBackward;
1548
1549 #endif
1550         DEFVAR_INT("canna-func-extend-mode", &canna_fn_ExtendMode       /*
1551
1552                                                                          */ );
1553         canna_fn_ExtendMode = IROHA_FN_ExtendMode;
1554
1555         DEFVAR_INT("canna-func-touroku", &canna_fn_Touroku      /*
1556
1557                                                                  */ );
1558         canna_fn_Touroku = IROHA_FN_Touroku;
1559
1560         DEFVAR_INT("canna-func-hex-mode", &canna_fn_HexMode     /*
1561
1562                                                                  */ );
1563         canna_fn_HexMode = IROHA_FN_HexMode;
1564
1565         DEFVAR_INT("canna-func-bushu-mode", &canna_fn_BushuMode /*
1566
1567                                                                  */ );
1568         canna_fn_BushuMode = IROHA_FN_BushuMode;
1569
1570         DEFVAR_INT("canna-func-kigo-mode", &canna_fn_KigouMode  /*
1571
1572                                                                  */ );
1573         canna_fn_KigouMode = IROHA_FN_KigouMode;
1574
1575 #ifdef CANNA_FN_Mark
1576         DEFVAR_INT("canna-func-mark", &canna_fn_Mark    /*
1577
1578                                                          */ );
1579         canna_fn_Mark = CANNA_FN_Mark;
1580 #endif
1581 #ifdef CANNA_FN_TemporalMode
1582         DEFVAR_INT("canna-func-temporal-mode", &canna_fn_TemporalMode   /*
1583
1584                                                                          */ );
1585         canna_fn_TemporalMode = CANNA_FN_TemporalMode;
1586 #endif
1587
1588         DEFVAR_INT("canna-key-nfer", &canna_key_Nfer    /*
1589
1590                                                          */ );
1591         canna_key_Nfer = IROHA_KEY_Nfer;
1592
1593         DEFVAR_INT("canna-key-xfer", &canna_key_Xfer    /*
1594
1595                                                          */ );
1596         canna_key_Xfer = IROHA_KEY_Xfer;
1597
1598         DEFVAR_INT("canna-key-up", &canna_key_Up        /*
1599
1600                                                          */ );
1601         canna_key_Up = IROHA_KEY_Up;
1602
1603         DEFVAR_INT("canna-key-left", &canna_key_Left    /*
1604
1605                                                          */ );
1606         canna_key_Left = IROHA_KEY_Left;
1607
1608         DEFVAR_INT("canna-key-right", &canna_key_Right  /*
1609
1610                                                          */ );
1611         canna_key_Right = IROHA_KEY_Right;
1612
1613         DEFVAR_INT("canna-key-down", &canna_key_Down    /*
1614
1615                                                          */ );
1616         canna_key_Down = IROHA_KEY_Down;
1617
1618         DEFVAR_INT("canna-key-insert", &canna_key_Insert        /*
1619
1620                                                                  */ );
1621         canna_key_Insert = IROHA_KEY_Insert;
1622
1623         DEFVAR_INT("canna-key-rollup", &canna_key_Rollup        /*
1624
1625                                                                  */ );
1626         canna_key_Rollup = IROHA_KEY_Rollup;
1627
1628         DEFVAR_INT("canna-key-rolldown", &canna_key_Rolldown    /*
1629
1630                                                                  */ );
1631         canna_key_Rolldown = IROHA_KEY_Rolldown;
1632
1633         DEFVAR_INT("canna-key-home", &canna_key_Home    /*
1634
1635                                                          */ );
1636         canna_key_Home = IROHA_KEY_Home;
1637
1638         DEFVAR_INT("canna-key-help", &canna_key_Help    /*
1639
1640                                                          */ );
1641         canna_key_Help = IROHA_KEY_Help;
1642
1643         DEFVAR_INT("canna-key-kp-key", &canna_key_KP_Key        /*
1644
1645                                                                  */ );
1646         canna_key_KP_Key = IROHA_KEY_KP_Key;
1647
1648         DEFVAR_INT("canna-key-shift-nfer", &canna_key_Shift_Nfer        /*
1649
1650                                                                          */ );
1651         canna_key_Shift_Nfer = IROHA_KEY_Shift_Nfer;
1652
1653         DEFVAR_INT("canna-key-shift-xfer", &canna_key_Shift_Xfer        /*
1654
1655                                                                          */ );
1656         canna_key_Shift_Xfer = IROHA_KEY_Shift_Xfer;
1657
1658         DEFVAR_INT("canna-key-shift-up", &canna_key_Shift_Up    /*
1659
1660                                                                  */ );
1661         canna_key_Shift_Up = IROHA_KEY_Shift_Up;
1662
1663         DEFVAR_INT("canna-key-shift-left", &canna_key_Shift_Left        /*
1664
1665                                                                          */ );
1666         canna_key_Shift_Left = IROHA_KEY_Shift_Left;
1667
1668         DEFVAR_INT("canna-key-shift-right", &canna_key_Shift_Right      /*
1669
1670                                                                          */ );
1671         canna_key_Shift_Right = IROHA_KEY_Shift_Right;
1672
1673         DEFVAR_INT("canna-key-shift-down", &canna_key_Shift_Down        /*
1674
1675                                                                          */ );
1676         canna_key_Shift_Down = IROHA_KEY_Shift_Down;
1677
1678         DEFVAR_INT("canna-key-control-nfer", &canna_key_Cntrl_Nfer      /*
1679
1680                                                                          */ );
1681         canna_key_Cntrl_Nfer = IROHA_KEY_Cntrl_Nfer;
1682
1683         DEFVAR_INT("canna-key-control-xfer", &canna_key_Cntrl_Xfer      /*
1684
1685                                                                          */ );
1686         canna_key_Cntrl_Xfer = IROHA_KEY_Cntrl_Xfer;
1687
1688         DEFVAR_INT("canna-key-control-up", &canna_key_Cntrl_Up  /*
1689
1690                                                                  */ );
1691         canna_key_Cntrl_Up = IROHA_KEY_Cntrl_Up;
1692
1693         DEFVAR_INT("canna-key-control-left", &canna_key_Cntrl_Left      /*
1694
1695                                                                          */ );
1696         canna_key_Cntrl_Left = IROHA_KEY_Cntrl_Left;
1697
1698         DEFVAR_INT("canna-key-control-right", &canna_key_Cntrl_Right    /*
1699
1700                                                                          */ );
1701         canna_key_Cntrl_Right = IROHA_KEY_Cntrl_Right;
1702
1703         DEFVAR_INT("canna-key-control-down", &canna_key_Cntrl_Down      /*
1704
1705                                                                          */ );
1706         canna_key_Cntrl_Down = IROHA_KEY_Cntrl_Down;
1707
1708         Fprovide(intern("CANNA"));
1709 }
1710
1711 #ifdef CANNA_MULE
1712 /* To handle MULE internal code and EUC.
1713    I assume CANNA can handle only Japanese EUC. */
1714
1715 /* EUC multibyte string to MULE internal string */
1716
1717 static void c2mu(unsigned char *cp, int l, unsigned char *mp)
1718 {
1719         unsigned char ch, *ep = cp + l;
1720
1721         while ((cp < ep) && (ch = *cp)) {
1722                 if ((unsigned char)ch == ISO_CODE_SS2) {
1723                         *mp++ = LEADING_BYTE_KATAKANA_JISX0201;
1724                         cp++;
1725                 } else if ((unsigned char)ch == ISO_CODE_SS3) {
1726                         *mp++ = LEADING_BYTE_JAPANESE_JISX0212;
1727                         cp++;
1728                         *mp++ = *cp++;
1729                 } else if (ch & 0x80) {
1730                         *mp++ = LEADING_BYTE_JAPANESE_JISX0208;
1731                         *mp++ = *cp++;
1732                 }
1733                 *mp++ = *cp++;
1734         }
1735         *mp = 0;
1736 }
1737
1738 /* MULE internal string to EUC multibyte string */
1739
1740 static void m2c(unsigned char *mp, int l, unsigned char *cp)
1741 {
1742         unsigned char ch, *ep = mp + l;
1743
1744         while ((mp < ep) && (ch = *mp++)) {
1745                 switch (ch) {
1746                 case LEADING_BYTE_KATAKANA_JISX0201:
1747                         *cp++ = ISO_CODE_SS2;
1748                         *cp++ = *mp++;
1749                         break;
1750                 case LEADING_BYTE_JAPANESE_JISX0212:
1751                         *cp++ = ISO_CODE_SS3;
1752                 case LEADING_BYTE_JAPANESE_JISX0208:
1753                         *cp++ = *mp++;
1754                         *cp++ = *mp++;
1755                         break;
1756                 default:
1757                         *cp++ = ch;
1758                         break;
1759                 }
1760         }
1761         *cp = 0;
1762 }
1763
1764 #undef make_string
1765
1766 /* make_string after converting EUC string to MULE internal string */
1767 static Lisp_Object mule_make_string(unsigned char *p, int l)
1768 {
1769         unsigned char cbuf[4096];
1770
1771         c2mu(p, l, cbuf);
1772         return (make_string(cbuf, strlen(cbuf)));
1773 }
1774
1775 /* return the MULE internal string length of EUC string */
1776 /* Modified by sb to return a character count not byte count. */
1777 static int mule_strlen(unsigned char *p, int l)
1778 {
1779         unsigned char ch, *cp = p;
1780         int len = 0;
1781
1782         while ((cp < p + l) && (ch = *cp)) {
1783                 if ((unsigned char)ch == ISO_CODE_SS2) {
1784                         len++;
1785                         cp += 2;
1786                 } else if ((unsigned char)ch == ISO_CODE_SS3) {
1787                         len++;
1788                         cp += 3;
1789                 } else if (ch & 0x80) {
1790                         len++;
1791                         cp += 2;
1792                 } else {
1793                         len++;
1794                         cp++;
1795                 }
1796         }
1797         return (len);
1798 }
1799
1800 /* count number of characters */
1801 static void
1802 count_char(unsigned char *p, int len, int pos, int rev,
1803            Fixnum * clen, Fixnum * cpos, Fixnum * crev)
1804 {
1805         unsigned char *q = p;
1806
1807         *clen = *cpos = *crev = 0;
1808         if (len == 0)
1809                 return;
1810         while (q < p + pos) {
1811                 (*clen)++;
1812                 (*cpos)++;
1813                 if (*q++ & 0x80)
1814                         q++;
1815         }
1816         while (q < p + pos + rev) {
1817                 (*clen)++;
1818                 (*crev)++;
1819                 if (*q++ & 0x80)
1820                         q++;
1821         }
1822         while (q < p + len) {
1823                 (*clen)++;
1824                 if (*q++ & 0x80)
1825                         q++;
1826         }
1827 }
1828 #endif                          /* CANNA_MULE */