modified for dynamic loading of Emacs/mule on Linux.
[elisp/emacs-canna.git] / canna.c
1 /* CANNA interface for Emacs/mule and XEmacs/mule.
2
3    Copyright (C) 1995 Free Software Foundation, Inc.
4    Copyright (C) 1996 MORIOKA Tomohiko
5
6    This file is not part of GNU Emacs.
7    
8    This program is free software; you can redistribute it and/or
9    modify it under the terms of the GNU General Public License as
10    published by the Free Software Foundation; either version 2, or (at
11    your option) any later version.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16    General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with GNU Emacs; see the file COPYING.  If not, write to the
20    Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21    Boston, MA 02111-1307, USA.
22
23   Authors: Akira Kon (kon@d1.bs2.mt.nec.co.jp)
24            Ichiro Hirakura (hirakura@uxp.bs2.mt.nec.co.jp)
25            modified by MORIOKA Tomohiko <morioka@jaist.ac.jp>
26
27   Functions defined in this file are
28
29   (canna-key-proc key)
30                 key: single STRING
31                 RETURNS:
32                          Length of converted string if no error occurs.
33                          Error string if error occurs.
34                 DESCRIPTION:
35                          Convert a key input to a set of strings.  The
36                          strings contain both well-formed string and a
37                          intermediate result to show the translation
38                          information to a user.  converted strings are
39                          stored in specific variables.
40
41   (canna-initialize)
42                 RETURNS:
43                         List of the following things:
44                         - list of keys to toggle Japanese-mode
45                         - error message
46                         - list of warning messages
47                 DESCRIPTION:
48                         Initialize ``canna'', which is a kana-to-kanji
49                         converter for GNU Emacs.  The first arg
50                         specifies if inserting space character between
51                         BUNSETSU when candidates are displayed.  The
52                         second arg specifies server.  The third arg
53                         specifies a file which will be used as a
54                         customization description.  If nil is
55                         specified for each arg, the default value will
56                         be used.
57
58   (canna-finalize)
59                 RETURNS:
60                         list of warning messages
61                 DESCRIPTION:
62                         finalize ``canna'', which is a kana-to-kanji
63                         converter for GNU Emacs.  This cause to write
64                         miscellaneous informations to kana-to-kanji
65                         dictionary.
66
67   (canna-touroku-string string)
68                 string:
69                         String to register to a dictionary.
70                 RETURNS:
71                         The same thing returns as canna-key-proc does.
72                 DESCRIPTION:
73                         Register Kanji words into kana-to-kanji
74                         conversion dictionary.
75
76   (canna-set-width width)
77                 width:
78                         Column width of the place where the candidates
79                         of kana-to-kanji conversion will be shown.
80                 RETURNS:
81                         nil
82                 DESCRIPTION:
83                         Set status-line width information, which is
84                         used to display kanji candidates.
85
86   (canna-change-mode num)
87                 num:
88                         The mode number of Canna.
89                 RETURNS:
90                         The same thing returns as canna-key-proc does.
91                 DESCRIPTION:
92                         Change Japanese pre-edit mode.
93
94   (canna-store-yomi yomi roma)
95                 yomi:
96                         ``Yomi'' to be stored.
97                 roma:
98                         ``Romaji'' which corresponds to the ``Yomi''.
99                 RETURNS:
100                         The same thing returns as canna-key-proc does.
101                 DESCRIPTION:
102                         Store yomi characters as a YOMI of
103                         kana-to-kanji conversion.
104
105   (canna-do-function num ch)
106                 num:
107                         A function number to be called.
108                 ch:
109                         A character will be specified in order to feed
110                         the character to the function if the function
111                         needs a input character.
112                 RETURNS:
113                         The same thing returns as canna-key-proc does.
114                 DESCRIPTION:
115                         Do specified function at current mode.
116
117   (canna-parse string)
118                 string:
119                         To be parsed.
120                 RETURNS:
121                         List of warning messages.
122                 DESCRIPTION:
123                         Parse customize string.
124
125   (canna-query-mode)
126                 RETURNS:
127                         A string which indicate the current mode.
128                 DESCRIPTION:
129                         Get current mode string.
130
131   Functions below are used for KKCP compatible library.  These
132   functions provides a base kana-to-kanji conversion system for EGG.
133   These functions may be used when users want to change the engine
134   from Wnn to Canna without changing user interface of Japanese input.
135
136   (canna-henkan-begin)
137   (canna-henkan-next)
138   (canna-bunsetu-henkou)
139   (canna-henkan-kakutei)
140   (canna-henkan-end)
141   (canna-henkan-quit)
142
143  */
144
145 #ifndef lint
146 static char rcs_id[] = "$Id: canna.c,v 1.35.1.1 1997-03-06 12:45:30 morioka Exp $";
147 #endif
148
149 #include <stdio.h>
150
151 #include "config.h"
152 #include "lisp.h"
153 #include "buffer.h"
154 #ifndef CANNA_NEMACS
155 #include "charset.h"
156 #endif
157 #ifdef CANNA_EMACS
158 #include "coding.h"
159 #endif
160
161 #ifdef CANNA_EMACS
162 #define CHARSET_KATAKANA_JISX0201 137
163 #define CHARSET_JAPANESE_JISX0208 146
164 #define CHARSET_JAPANESE_JISX0212 148
165 #else
166 #ifdef CANNA_MULE
167 #define CHARSET_KATAKANA_JISX0201 LCKANA
168 #define CHARSET_JAPANESE_JISX0208 LCJP
169 #define CHARSET_JAPANESE_JISX0212 LCJP2
170 #define ISO_CODE_SS2 SS2
171 #define ISO_CODE_SS3 SS3
172 #endif /* CANNA_MULE */
173 #endif
174
175 #define IROHA_BC
176 #include "canna/jrkanji.h"
177 #include "canna/RK.h"
178
179 extern char *jrKanjiError;
180
181 #define KEYTOSTRSIZE 2048
182 static unsigned char buf[KEYTOSTRSIZE];
183 static char **warning;
184
185 static int Vcanna_empty_info, Vcanna_through_info;
186 static int Vcanna_underline;
187 static int Vcanna_inhibit_hankakukana;          /* hir, 1994.12.5 */
188
189 static Lisp_Object Vcanna_kakutei_string;
190 static Lisp_Object Vcanna_kakutei_yomi;
191 static Lisp_Object Vcanna_kakutei_romaji;
192 static Lisp_Object Vcanna_henkan_string;
193 static int         Vcanna_henkan_length;
194 static int         Vcanna_henkan_revPos;
195 static int         Vcanna_henkan_revLen;
196 static Lisp_Object Vcanna_ichiran_string;
197 static int         Vcanna_ichiran_length;
198 static int         Vcanna_ichiran_revPos;
199 static int         Vcanna_ichiran_revLen;
200 static Lisp_Object Vcanna_mode_string;
201
202 static int IRCP_context;
203
204 #if __STDC__
205 static Lisp_Object storeResults(unsigned char *, int, jrKanjiStatus *);
206 static Lisp_Object kanjiYomiList(int, int);
207 #else
208 static Lisp_Object storeResults();
209 static Lisp_Object kanjiYomiList();
210 #endif
211
212 #ifndef CANNA_NEMACS
213 #if __STDC__
214 static m2c(unsigned char *, int, unsigned char *);
215 static Lisp_Object mule_make_string(unsigned char *, int);
216 static mule_strlen(unsigned char *, int);
217 static count_char(unsigned char *,int, int, int, int *, int *, int *);
218 #else
219 static m2c();
220 static Lisp_Object mule_make_string();
221 static mule_strlen();
222 static count_char();
223 #endif
224 #define make_string mule_make_string
225 #endif
226
227 /* Lisp functions definition */
228
229 DEFUN ("canna-key-proc", Fcanna_key_proc, Scanna_key_proc,
230        1, 1, 0,
231 "Translate a key input to a set of strings.  The strings contain both\n\
232 well-formed string and intermediate result to show the translation\n\
233 information to a user.  Converted strings are stored in specific\n\
234 variables.")
235         (ch)
236 Lisp_Object ch;
237 {
238   jrKanjiStatus ks;
239   int len;
240
241   CHECK_NUMBER (ch, 0);
242   len = jrKanjiString(0, XINT (ch), buf, KEYTOSTRSIZE, &ks);
243   return storeResults(buf, len, &ks);
244 }
245
246 static
247 Lisp_Object
248 storeResults(buf, len, ks)
249 unsigned char *buf;
250 int len;
251 jrKanjiStatus *ks;
252 {
253   Lisp_Object val = Qnil;
254
255   if (len < 0) { /* Error detected */
256     val = make_string((unsigned char*)jrKanjiError, strlen(jrKanjiError));
257   }
258   else {
259     /* ³ÎÄꤷ¤¿Ê¸»úÎó */
260     Vcanna_kakutei_string = make_string(buf, len);
261     val = make_number(len);
262     /* ³ÎÄꤷ¤¿Ê¸»úÎó¤ÎÆɤߤξðÊó... */
263     Vcanna_kakutei_yomi = Vcanna_kakutei_romaji = Qnil;
264     if (ks->info & KanjiYomiInfo) {
265       unsigned char *p = buf + len + 1;
266       int yomilen = strlen(p);
267
268       if (len + yomilen + 1 < KEYTOSTRSIZE) {
269         int yomilen2;
270
271         Vcanna_kakutei_yomi = make_string(p, yomilen); /* Æɤߠ*/
272         p += yomilen + 1;
273         yomilen2 = strlen(p);
274         if (len + yomilen + yomilen2 + 2 < KEYTOSTRSIZE) {
275           Vcanna_kakutei_romaji = make_string(p, yomilen2); /* ¥í¡¼¥Þ»ú */
276         }
277       }
278     }
279
280
281     /* ¸õÊäɽ¼¨¤Îʸ»úÎó¤Ç¤¹¡£*/
282     Vcanna_henkan_string = Qnil;
283     if (ks->length >= 0) {
284       Vcanna_henkan_string = make_string(ks->echoStr, ks->length);
285 #ifdef CANNA_NEMACS
286       Vcanna_henkan_length = ks->length;
287       Vcanna_henkan_revPos = ks->revPos;
288       Vcanna_henkan_revLen = ks->revLen;
289 #else /* CANNA_MULE */
290       if (Vcanna_underline) {
291         Vcanna_henkan_length = mule_strlen(ks->echoStr,ks->length);
292         Vcanna_henkan_revPos = mule_strlen(ks->echoStr,ks->revPos);
293         Vcanna_henkan_revLen = mule_strlen(ks->echoStr+ks->revPos,ks->revLen);
294       }
295       else {
296         count_char(ks->echoStr, ks->length, ks->revPos, ks->revLen,
297                    &Vcanna_henkan_length, &Vcanna_henkan_revPos,
298                    &Vcanna_henkan_revLen);
299       }
300 #endif /* CANNA_MULE */
301     }
302
303     /* °ìÍ÷¤Î¾ðÊó */
304     Vcanna_ichiran_string = Qnil;
305     if (ks->info & KanjiGLineInfo && ks->gline.length >= 0) {
306       Vcanna_ichiran_string = make_string(ks->gline.line, ks->gline.length);
307 #ifdef CANNA_NEMACS
308       Vcanna_ichiran_length = ks->gline.length;
309       Vcanna_ichiran_revPos = ks->gline.revPos;
310       Vcanna_ichiran_revLen = ks->gline.revLen;
311 #else /* CANNA_MULE */
312       count_char(ks->gline.line, ks->gline.length,
313                  ks->gline.revPos, ks->gline.revLen, &Vcanna_ichiran_length,
314                  &Vcanna_ichiran_revPos, &Vcanna_ichiran_revLen);
315 #endif /* CANNA_MULE */
316     }
317
318     /* ¥â¡¼¥É¤Î¾ðÊó */
319     Vcanna_mode_string = Qnil;
320     if (ks->info & KanjiModeInfo) {
321       Vcanna_mode_string = make_string(ks->mode, strlen(ks->mode));
322     }
323
324     /* ¤½¤Î¾¤Î¾ðÊó */
325     Vcanna_empty_info = (ks->info & KanjiEmptyInfo) ? 1 : 0;
326     Vcanna_through_info = (ks->info & KanjiThroughInfo) ? 1 : 0;
327   }
328
329   return val;
330 }
331
332 DEFUN ("canna-set-bunsetsu-kugiri", Fcanna_set_bunsetsu, Scanna_set_bunsetsu,
333        0, 1, 0,
334 "This function sets the clause separator.\n\
335 If non-nil value is specified, the white space separator will be used.\n\
336 No separator will be used otherwise.")
337      (num)
338      Lisp_Object num;
339 {
340   int kugiri; /* Ê¸Àá¶èÀÚ¤ê¤ò¤¹¤ë¤«¡© */
341
342   kugiri = NILP(num) ? 0 : 1;
343
344   jrKanjiControl(0, KC_SETBUNSETSUKUGIRI, (char *)kugiri);
345
346   return Qnil;
347 }
348
349 DEFUN ("canna-initialize", Fcanna_initialize, Scanna_initialize, 0, 3, 0,
350 "Initialize ``canna'', which is a kana-to-kanji converter for GNU Emacs.\n\
351 The first arg specifies if inserting space character between BUNSETSU when\n\
352 candidates are displayed.\n\
353 The second arg specifies server.\n\
354 The third arg specifies a file which will be used as a customization\n\
355 description.\n\
356 If nil is specified for each arg, the default value will be used.")
357 (num, server, rcfile)
358 Lisp_Object num, server, rcfile;
359 {
360   Lisp_Object val;
361   int res;
362   unsigned char **p, **q;
363
364   int kugiri; /* Ê¸Àá¶èÀÚ¤ê¤ò¤¹¤ë¤«¡© */
365
366   IRCP_context = -1;
367
368   if (NILP(num)) {
369     kugiri = 1;
370   }
371   else {
372     CHECK_NUMBER(num, 0);
373     kugiri = XINT(num);
374     kugiri = (kugiri == 1) ? 1 : 0;
375   }
376
377   if (NILP(server)) {
378     jrKanjiControl(0, KC_SETSERVERNAME, (char *)0);
379   }
380   else {
381     char servername[256];
382
383     CHECK_STRING(server, 0);
384     strncpy(servername, XSTRING(server)->data, XSTRING(server)->size);
385     servername[XSTRING(server)->size] = '\0';
386     jrKanjiControl(0, KC_SETSERVERNAME, servername);
387   }
388
389   if (NILP(rcfile)) {
390     jrKanjiControl(0, KC_SETINITFILENAME, (char *)0);
391   }
392   else {
393     char rcname[256];
394
395     CHECK_STRING(rcfile, 0);
396     strncpy(rcname, XSTRING(rcfile)->data, XSTRING(rcfile)->size);
397     rcname[XSTRING(rcfile)->size] = '\0';
398     jrKanjiControl(0, KC_SETINITFILENAME, rcname);
399   }
400
401   warning = (char **)0;
402 #ifdef nec_ews_svr4                             /* hir, 1994.2.24 */
403   stop_polling ();
404 #endif /* nec_ews_svr4 */
405   res = jrKanjiControl(0, KC_INITIALIZE, (char *)&warning);
406 #ifdef nec_ews_svr4                             /* hir, 1994.2.24 */
407   start_polling ();
408 #endif /* nec_ews_svr4 */
409   val = Qnil;
410   if (warning) {
411     for (p = q = (unsigned char **)warning ; *q ; q++)
412       ;
413     while (p < q) {
414       q--;
415       val = Fcons(make_string(*q, strlen(*q)), val);
416     }
417   }
418   val = Fcons(val, Qnil);
419
420   if (res == -1) {
421     val = Fcons(make_string((unsigned char*)jrKanjiError, 
422                             strlen(jrKanjiError)), val);
423     /* ¥¤¥Ë¥·¥ã¥é¥¤¥º¤Ç¼ºÇÔ¤·¤¿¾ì¹ç¡£ */
424     return Fcons(Qnil, val);
425   }
426   else {
427     extern (*jrBeepFunc)();
428     Lisp_Object Fding(), CANNA_mode_keys();
429
430     jrBeepFunc = Fding;
431
432 #ifdef KC_SETAPPNAME
433 #ifdef CANNA_NEMACS
434     wcKanjiControl(0, KC_SETAPPNAME, "nemacs");
435 #else /* CANNA_MULE */
436     wcKanjiControl(0, KC_SETAPPNAME, "mule");
437 #endif /* CANNA_MULE */
438 #endif /* KC_SETAPPNAME */
439
440     jrKanjiControl(0, KC_SETBUNSETSUKUGIRI, (char *)kugiri);
441     jrKanjiControl(0, KC_SETWIDTH, (char *)78);
442 #ifdef CANNA_NEMACS
443     jrKanjiControl(0, KC_INHIBITHANKAKUKANA, (char *)1);
444 #else                                   /* hir, 1994.12.5 */
445     /* mule ¤À¤Ã¤¿¤éȾ³Ñ¥«¥¿¥«¥Ê¤â»È¤¨¤ë */
446     if (Vcanna_inhibit_hankakukana)
447       jrKanjiControl(0, KC_INHIBITHANKAKUKANA, (char *)1);
448 #endif
449     jrKanjiControl(0, KC_YOMIINFO, (char *)2); /* ¢¨£²: ¥í¡¼¥Þ»ú¤Þ¤ÇÊÖ¤¹ */
450     val = Fcons(Qnil, val);
451     return Fcons(CANNA_mode_keys(), val);
452   }
453 }
454
455 DEFUN ("canna-finalize", Fcanna_finalize, Scanna_finalize, 0, 0, 0,
456 "finalize ``canna'', which is a kana-to-kanji converter for GNU Emacs.\n\
457 This cause to write miscellaneous informations to kana-to-kanji dictionary.")
458 ()
459 {
460   Lisp_Object val;
461   unsigned char **p;
462
463   jrKanjiControl(0, KC_FINALIZE, (char *)&warning);
464
465   val = Qnil;
466   if (warning) {
467     for (p = (unsigned char**)warning ; *p ; p++) {
468       val = Fcons(make_string(*p, strlen(*p)), val);
469     }
470   }
471   val = Fcons(val, Qnil);
472   IRCP_context = -1;
473   return val;
474 }
475
476 DEFUN ("canna-touroku-string", Fcanna_touroku_string, 
477        Scanna_touroku_string, 1, 1, 0,
478 "Register Kanji words into kana-to-kanji conversion dictionary.")
479         (str)
480 Lisp_Object str;
481 {
482   jrKanjiStatusWithValue ksv;
483   jrKanjiStatus ks;
484   int len;
485   Lisp_Object val;
486 #ifndef CANNA_NEMACS
487   unsigned char cbuf[4096];
488 #endif
489
490   CHECK_STRING(str, 0);
491   ksv.buffer = (unsigned char *)buf;
492   ksv.bytes_buffer = KEYTOSTRSIZE;
493 #ifdef CANNA_NEMACS
494   ks.echoStr = XSTRING (str)->data;
495   ks.length = XSTRING (str)->size;
496 #else /* CANNA_MULE */
497   m2c(XSTRING (str)->data, XSTRING (str)->size, cbuf);
498   ks.echoStr = cbuf;
499   ks.length = strlen(cbuf);
500 #endif /* CANNA_MULE */
501   ksv.ks = &ks;
502   len = jrKanjiControl(0, KC_DEFINEKANJI, (char *)&ksv);
503   val = storeResults(buf, ksv.val, ksv.ks);
504   return val;
505 }
506
507 DEFUN ("canna-set-width", Fcanna_set_width,
508        Scanna_set_width, 1, 1, 0,
509 "Set status-line width information, which is used to display \n\
510 kanji candidates.")
511         (num)
512 Lisp_Object num;
513 {
514   CHECK_NUMBER(num, 0);
515
516   jrKanjiControl(0, KC_SETWIDTH,  (char *)XINT (num));
517   return Qnil;
518 }
519
520 DEFUN ("canna-change-mode", Fcanna_change_mode,
521        Scanna_change_mode, 1, 1, 0,
522 "Change Japanese pre-edit mode.")
523         (num)
524 Lisp_Object num;
525 {
526   jrKanjiStatusWithValue ksv;
527   jrKanjiStatus ks;
528   Lisp_Object val;
529
530   CHECK_NUMBER(num, 0);
531
532   ksv.buffer = (unsigned char *)buf;
533   ksv.bytes_buffer = KEYTOSTRSIZE;
534   ksv.ks = &ks;
535   ksv.val = XINT (num);
536   jrKanjiControl(0, KC_CHANGEMODE,  (char *)&ksv);
537   val = storeResults(buf, ksv.val, ksv.ks);
538   return val;
539 }
540
541 Lisp_Object
542 CANNA_mode_keys()
543 {
544 #define CANNAWORKBUFSIZE 32
545   char xxx[CANNAWORKBUFSIZE];
546   Lisp_Object val;
547   int i, n;
548
549   n = jrKanjiControl(0, KC_MODEKEYS, xxx);
550   val = Qnil;
551   for (i = n ; i > 0 ;) {
552     --i;
553     val = Fcons(make_number((int)(0xFF & (unsigned char)xxx[i])), val);
554   }
555   return val;
556 }
557
558 DEFUN ("canna-store-yomi", Fcanna_store_yomi, Scanna_store_yomi, 
559        1, 2, 0,
560 "Store yomi characters as a YOMI of kana-to-kanji conversion.")
561         (yomi, roma)
562 Lisp_Object yomi, roma;
563 {
564   jrKanjiStatusWithValue ksv;
565   jrKanjiStatus ks;
566
567   CHECK_STRING(yomi, 0);
568 #ifdef CANNA_NEMACS
569   strncpy(buf, XSTRING(yomi)->data, XSTRING(yomi)->size);
570   ks.length = XSTRING (yomi)->size;
571   buf[ks.length] = '\0';
572 #else /* CANNA_MULE */
573   m2c(XSTRING(yomi)->data, XSTRING(yomi)->size, buf);
574   ks.length = strlen(buf);
575 #endif /* CANNA_MULE */
576
577   if (NILP(roma)) {
578     ks.mode = 0;
579   }
580   else {
581     CHECK_STRING(roma, 0);
582
583 #ifdef CANNA_NEMACS
584     strncpy(buf + XSTRING(yomi)->size + 1, XSTRING(roma)->data,
585             XSTRING(roma)->size);
586     buf[XSTRING(yomi)->size + 1 + XSTRING(roma)->size] = '\0';
587     ks.mode = (unsigned char *)(buf + XSTRING(yomi)->size + 1);
588 #else /* CANNA_MULE */
589     ks.mode = (unsigned char *)(buf + ks.length + 1);
590     m2c(XSTRING(roma)->data, XSTRING(roma)->size, ks.mode);
591 #endif /* CANNA_MULE */
592   }
593
594   ks.echoStr = (unsigned char *)buf;
595   ksv.buffer = (unsigned char *)buf; /* ÊÖÃÍÍÑ */
596   ksv.bytes_buffer = KEYTOSTRSIZE;
597   ksv.ks = &ks;
598
599   jrKanjiControl(0, KC_STOREYOMI, (char *)&ksv);
600
601   return storeResults(buf, ksv.val, ksv.ks);
602 }
603
604 DEFUN ("canna-do-function", Fcanna_do_function, Scanna_do_function, 
605        1, 2, 0,
606 "Do specified function at current mode.")
607         (num, ch)
608 Lisp_Object num, ch;
609 {
610   jrKanjiStatusWithValue ksv;
611   jrKanjiStatus ks;
612   Lisp_Object val;
613
614   CHECK_NUMBER(num, 0);
615
616   if (NILP(ch)) {
617     *buf = '@';
618   }
619   else {
620     CHECK_NUMBER(ch, 0);
621     *buf = XINT (ch);
622   }
623
624   ksv.buffer = (unsigned char *)buf;
625   ksv.bytes_buffer = KEYTOSTRSIZE;
626   ksv.ks = &ks;
627   ksv.val = XINT (num);
628   jrKanjiControl(0, KC_DO,  (char *)&ksv);
629   val = storeResults(buf, ksv.val, ksv.ks);
630   return val;
631 }
632
633 DEFUN ("canna-parse", Fcanna_parse, Scanna_parse, 
634        1, 1, 0,
635 "Parse customize string.")
636         (str)
637 Lisp_Object str;
638 {
639   jrKanjiStatusWithValue ksv;
640   jrKanjiStatus ks;
641   Lisp_Object val;
642   unsigned char **p;
643   int n;
644
645   CHECK_STRING(str, 0);
646
647 #ifdef CANNA_NEMACS
648   strncpy(buf, XSTRING(str)->data, XSTRING(str)->size);
649   buf[XSTRING(str)->size] = '\0';
650 #else /* CANNA_MULE */
651   m2c(XSTRING(str)->data, XSTRING(str)->size, buf);
652 #endif /* CANNA_MULE */
653   p = (unsigned char**)buf;
654   n = jrKanjiControl(0, KC_PARSE,  (char *)&p);
655   val = Qnil;
656   while (n > 0) {
657     n--;
658     val = Fcons(make_string(p[n], strlen(p[n])), val);
659   }
660   return val;
661 }
662
663 DEFUN ("canna-query-mode", Fcanna_query_mode, Scanna_query_mode, 
664        0, 0, 0,
665 "Get current mode string.")
666         ()
667 {
668   unsigned char buf[256];
669
670   jrKanjiControl(0, KC_QUERYMODE, buf);
671   return make_string(buf, strlen(buf));
672 }
673
674 /*
675  * Functions following this line are for KKCP interface compatible
676  * library.  These functions may be used by MILK system.
677  */
678
679 #define RKBUFSIZE 1024
680
681 static unsigned char yomibuf[RKBUFSIZE];
682 static short kugiri[RKBUFSIZE / 2];
683
684 static confirmContext()
685 {
686   if (IRCP_context < 0) {
687     int context;
688
689     if ((context = jrKanjiControl(0, KC_GETCONTEXT, (char *)0)) == -1) {
690       return 0;
691     }
692     IRCP_context = context;
693   }
694   return 1;
695 }
696
697 static byteLen(bun, len)
698 int bun, len;
699 {
700   int i = 0, offset = 0, ch;
701
702   if (0 <= bun && bun < RKBUFSIZE) {
703     offset = kugiri[bun];
704   }
705
706   while (len-- > 0 && (ch = (int)yomibuf[offset + i])) {
707     i++;
708     if (ch & 0x80) {
709       i++;
710     }
711   }
712   return i;
713 }
714
715 DEFUN ("canna-henkan-begin", Fcanna_henkan_begin, Scanna_henkan_begin,
716        1, 1, 0,
717 "¤«¤Ê´Á»úÊÑ´¹¤·¤¿·ë²Ì¤òÊÖ´Ô¤¹¤ë¡£Ê¸ÀáÀڤ꤬¤·¤Æ¤¢¤ë¡£")
718         (yomi)
719     Lisp_Object yomi;
720 {
721   int nbun;
722   Lisp_Object res;
723
724   CHECK_STRING(yomi, 0);
725   if (confirmContext() == 0) {
726     return Qnil;
727   }
728 #ifdef CANNA_NEMACS
729   strncpy(yomibuf, XSTRING(yomi)->data, XSTRING(yomi)->size);
730   yomibuf[XSTRING(yomi)->size] = '\0';
731   nbun = RkBgnBun(IRCP_context, XSTRING(yomi)->data, XSTRING(yomi)->size,
732                   (RK_XFER << RK_XFERBITS) | RK_KFER);
733 #else /* CANNA_MULE */
734   m2c(XSTRING(yomi)->data, XSTRING(yomi)->size, yomibuf);
735   nbun = RkBgnBun(IRCP_context, (char *)yomibuf, strlen(yomibuf),
736                   (RK_XFER << RK_XFERBITS) | RK_KFER);
737 #endif /* CANNA_MULE */
738
739   return kanjiYomiList(IRCP_context, nbun);
740 }
741
742 static Lisp_Object kanjiYomiList(context, nbun)
743 int context, nbun;
744 {
745   Lisp_Object val, res = Qnil;
746   unsigned char RkBuf[RKBUFSIZE];
747   int len, i, total;
748
749   for (i = nbun ; i > 0 ; ) {
750     i--;
751     RkGoTo(context, i);
752     len = RkGetKanji(context, RkBuf, RKBUFSIZE);
753     val = make_string(RkBuf, len);
754     len = RkGetYomi(context, RkBuf, RKBUFSIZE);
755     res = Fcons(Fcons(val, make_string(RkBuf, len)), res);
756     if (i < RKBUFSIZE / 2) {
757       kugiri[i] = len;
758     }
759   }
760   for (i = 0, total = 0 ; i < nbun ; i++) {
761     int temp = kugiri[i];
762     kugiri[i] = total;
763     total += temp;
764   }
765   return res;
766 }
767
768 DEFUN ("canna-henkan-next", Fcanna_henkan_next, Scanna_henkan_next,
769        1, 1, 0,
770 "¸õÊä°ìÍ÷¤òµá¤á¤ë¡£")
771         (bunsetsu)
772     Lisp_Object bunsetsu;
773 {
774   int i, nbun, slen, len;
775   unsigned char *p, RkBuf[RKBUFSIZE];
776   Lisp_Object res = Qnil, endp;
777
778   CHECK_NUMBER(bunsetsu, 0);
779   if (confirmContext() == 0) {
780     return Qnil;
781   }
782   RkGoTo(IRCP_context, XINT (bunsetsu));
783   len = RkGetKanjiList(IRCP_context, RkBuf, RKBUFSIZE);
784   p = RkBuf;
785   for (i = 0 ; i < len ; i++) {
786     slen = strlen(p);
787     if (res == Qnil) {
788       endp = res = Fcons(make_string(p, slen), Qnil);
789     }
790     else {
791       endp = XCONS (endp)->cdr = Fcons(make_string(p, slen), Qnil);
792     }
793     p += slen + 1;
794   }
795   return res;
796 }
797
798 DEFUN ("canna-bunsetu-henkou", Fcanna_bunsetu_henkou, Scanna_bunsetu_henkou,
799        2, 2, 0,
800 "ʸÀá¤ÎŤµ¤ò»ØÄꤹ¤ë¡£")
801         (bunsetsu, bunlen)
802     Lisp_Object bunsetsu, bunlen;
803 {
804   int nbun, len;
805
806   CHECK_NUMBER(bunsetsu, 0);
807   CHECK_NUMBER(bunlen, 0);
808   
809   nbun = XINT (bunsetsu);
810   if (confirmContext() == 0) {
811     return Qnil;
812   }
813   RkGoTo(IRCP_context, nbun);
814   len = byteLen(nbun, XINT(bunlen));
815   return kanjiYomiList(IRCP_context, RkResize(IRCP_context, len));
816 }
817
818 DEFUN ("canna-henkan-kakutei", Fcanna_henkan_kakutei, Scanna_henkan_kakutei,
819        2, 2, 0,
820 "¸õÊäÁªÂò¡£")
821         (bun, kouho)
822 register Lisp_Object bun, kouho;
823 {
824   if (confirmContext() == 0) {
825     return Qnil;
826   }
827   RkGoTo(IRCP_context, bun);
828   RkXfer(IRCP_context, kouho);
829   return Qt;
830 }
831
832 DEFUN ("canna-henkan-end", Fcanna_henkan_end, Scanna_henkan_end,
833        0, 0, 0,
834 "ÊÑ´¹½ªÎ»¡£")
835         ()
836 {
837   if (confirmContext() == 0) {
838     return Qnil;
839   }
840   RkEndBun(IRCP_context, 1); /* ³Ø½¬¤Ï¤¤¤Ä¤Ç¤â¹Ô¤Ã¤ÆÎɤ¤¤â¤Î¤Ê¤Î¤«¡© */
841   return Qt;
842 }
843
844 DEFUN ("canna-henkan-quit", Fcanna_henkan_quit, Scanna_henkan_quit,
845        0, 0, 0,
846 "ÊÑ´¹½ªÎ»¡£")
847         ()
848 {
849   if (confirmContext() == 0) {
850     return Qnil;
851   }
852   RkEndBun(IRCP_context, 0);
853   return Qt;
854 }
855
856 /* variables below this line is constants of Canna */
857
858 static int Vcanna_mode_AlphaMode = IROHA_MODE_AlphaMode;
859 static int Vcanna_mode_EmptyMode = IROHA_MODE_EmptyMode;
860 static int Vcanna_mode_KigoMode = IROHA_MODE_KigoMode;
861 static int Vcanna_mode_YomiMode = IROHA_MODE_YomiMode;
862 static int Vcanna_mode_JishuMode = IROHA_MODE_JishuMode;
863 static int Vcanna_mode_TankouhoMode = IROHA_MODE_TankouhoMode;
864 static int Vcanna_mode_IchiranMode = IROHA_MODE_IchiranMode;
865 static int Vcanna_mode_YesNoMode = IROHA_MODE_YesNoMode;
866 static int Vcanna_mode_OnOffMode = IROHA_MODE_OnOffMode;
867 #ifdef CANNA_MODE_AdjustBunsetsuMode
868 static int Vcanna_mode_AdjustBunsetsuMode = CANNA_MODE_AdjustBunsetsuMode;
869 #endif
870 #ifdef CANNA_MODE_ChikujiYomiMode
871 static int Vcanna_mode_ChikujiYomiMode = CANNA_MODE_ChikujiYomiMode;
872 static int Vcanna_mode_ChikujiTanMode = CANNA_MODE_ChikujiTanMode;
873 #endif
874
875 static int Vcanna_mode_HenkanMode = IROHA_MODE_HenkanMode;
876 #ifdef CANNA_MODE_HenkanNyuryokuMode
877 static int Vcanna_mode_HenkanNyuryokuMode = CANNA_MODE_HenkanNyuryokuMode;
878 #endif
879 #ifdef CANNA_MODE_ZenHiraHenkanMode
880 static int Vcanna_mode_ZenHiraHenkanMode = CANNA_MODE_ZenHiraHenkanMode;
881 #ifdef CANNA_MODE_HanHiraHenkanMode
882 static int Vcanna_mode_HanHiraHenkanMode = CANNA_MODE_HanHiraHenkanMode;
883 #endif
884 static int Vcanna_mode_ZenKataHenkanMode = CANNA_MODE_ZenKataHenkanMode;
885 static int Vcanna_mode_HanKataHenkanMode = CANNA_MODE_HanKataHenkanMode;
886 static int Vcanna_mode_ZenAlphaHenkanMode = CANNA_MODE_ZenAlphaHenkanMode;
887 static int Vcanna_mode_HanAlphaHenkanMode = CANNA_MODE_HanAlphaHenkanMode;
888 #endif
889 static int Vcanna_mode_ZenHiraKakuteiMode = IROHA_MODE_ZenHiraKakuteiMode;
890 #ifdef CANNA_MODE_HanHiraKakuteiMode
891 static int Vcanna_mode_HanHiraKakuteiMode = CANNA_MODE_HanHiraKakuteiMode;
892 #endif
893 static int Vcanna_mode_ZenKataKakuteiMode = IROHA_MODE_ZenKataKakuteiMode;
894 static int Vcanna_mode_HanKataKakuteiMode = IROHA_MODE_HanKataKakuteiMode;
895 static int Vcanna_mode_ZenAlphaKakuteiMode = IROHA_MODE_ZenAlphaKakuteiMode;
896 static int Vcanna_mode_HanAlphaKakuteiMode = IROHA_MODE_HanAlphaKakuteiMode;
897 static int Vcanna_mode_HexMode = IROHA_MODE_HexMode;
898 static int Vcanna_mode_BushuMode = IROHA_MODE_BushuMode;
899 static int Vcanna_mode_ExtendMode = IROHA_MODE_ExtendMode;
900 static int Vcanna_mode_RussianMode = IROHA_MODE_RussianMode;
901 static int Vcanna_mode_GreekMode = IROHA_MODE_GreekMode;
902 static int Vcanna_mode_LineMode = IROHA_MODE_LineMode;
903 static int Vcanna_mode_ChangingServerMode = IROHA_MODE_ChangingServerMode;
904 static int Vcanna_mode_HenkanMethodMode = IROHA_MODE_HenkanMethodMode;
905 static int Vcanna_mode_DeleteDicMode = IROHA_MODE_DeleteDicMode;
906 static int Vcanna_mode_TourokuMode = IROHA_MODE_TourokuMode;
907 static int Vcanna_mode_TourokuEmptyMode = IROHA_MODE_TourokuEmptyMode;
908 static int Vcanna_mode_TourokuHinshiMode = IROHA_MODE_TourokuHinshiMode;
909 static int Vcanna_mode_TourokuDicMode = IROHA_MODE_TourokuDicMode;
910 static int Vcanna_mode_QuotedInsertMode = IROHA_MODE_QuotedInsertMode;
911 static int Vcanna_mode_BubunMuhenkanMode = IROHA_MODE_BubunMuhenkanMode;
912 static int Vcanna_mode_MountDicMode = IROHA_MODE_MountDicMode;
913
914 static int Vcanna_fn_SelfInsert = IROHA_FN_SelfInsert;
915 static int Vcanna_fn_FunctionalInsert = IROHA_FN_FunctionalInsert;
916 static int Vcanna_fn_QuotedInsert = IROHA_FN_QuotedInsert;
917 static int Vcanna_fn_JapaneseMode = IROHA_FN_JapaneseMode;
918 static int Vcanna_fn_AlphaMode = IROHA_FN_AlphaMode;
919 static int Vcanna_fn_HenkanNyuryokuMode = IROHA_FN_HenkanNyuryokuMode;
920 static int Vcanna_fn_Forward = IROHA_FN_Forward;
921 static int Vcanna_fn_Backward = IROHA_FN_Backward;
922 static int Vcanna_fn_Next = IROHA_FN_Next;
923 static int Vcanna_fn_Prev = IROHA_FN_Prev;
924 static int Vcanna_fn_BeginningOfLine = IROHA_FN_BeginningOfLine;
925 static int Vcanna_fn_EndOfLine = IROHA_FN_EndOfLine;
926 static int Vcanna_fn_DeleteNext = IROHA_FN_DeleteNext;
927 static int Vcanna_fn_DeletePrevious = IROHA_FN_DeletePrevious;
928 static int Vcanna_fn_KillToEndOfLine = IROHA_FN_KillToEndOfLine;
929 static int Vcanna_fn_Henkan = IROHA_FN_Henkan;
930 static int Vcanna_fn_Kakutei = IROHA_FN_Kakutei;
931 static int Vcanna_fn_Extend = IROHA_FN_Extend;
932 static int Vcanna_fn_Shrink = IROHA_FN_Shrink;
933 #ifdef CANNA_FN_AdjustBunsetsu
934 static int Vcanna_fn_AdjustBunsetsu = CANNA_FN_AdjustBunsetsu;
935 #endif
936 static int Vcanna_fn_Quit = IROHA_FN_Quit;
937 static int Vcanna_fn_ConvertAsHex = IROHA_FN_ConvertAsHex;
938 static int Vcanna_fn_ConvertAsBushu = IROHA_FN_ConvertAsBushu;
939 static int Vcanna_fn_KouhoIchiran = IROHA_FN_KouhoIchiran;
940 static int Vcanna_fn_BubunMuhenkan = IROHA_FN_BubunMuhenkan;
941 static int Vcanna_fn_Zenkaku = IROHA_FN_Zenkaku;
942 static int Vcanna_fn_Hankaku = IROHA_FN_Hankaku;
943 static int Vcanna_fn_ToUpper = IROHA_FN_ToUpper;
944 static int Vcanna_fn_Capitalize = IROHA_FN_Capitalize;
945 static int Vcanna_fn_ToLower = IROHA_FN_ToLower;
946 static int Vcanna_fn_Hiragana = IROHA_FN_Hiragana;
947 static int Vcanna_fn_Katakana = IROHA_FN_Katakana;
948 static int Vcanna_fn_Romaji = IROHA_FN_Romaji;
949 #ifdef CANNA_FN_BaseHiragana
950 static int Vcanna_fn_BaseHiragana = CANNA_FN_BaseHiragana;
951 static int Vcanna_fn_BaseKatakana = CANNA_FN_BaseKatakana;
952 static int Vcanna_fn_BaseEisu = CANNA_FN_BaseEisu;
953 static int Vcanna_fn_BaseZenkaku = CANNA_FN_BaseZenkaku;
954 static int Vcanna_fn_BaseHankaku = CANNA_FN_BaseHankaku;
955 static int Vcanna_fn_BaseKana = CANNA_FN_BaseKana;
956 static int Vcanna_fn_BaseKakutei = CANNA_FN_BaseKakutei;
957 static int Vcanna_fn_BaseHenkan = CANNA_FN_BaseHenkan;
958 static int Vcanna_fn_BaseHiraKataToggle = CANNA_FN_BaseHiraKataToggle;
959 static int Vcanna_fn_BaseZenHanToggle = CANNA_FN_BaseZenHanToggle;
960 static int Vcanna_fn_BaseKanaEisuToggle = CANNA_FN_BaseKanaEisuToggle;
961 static int Vcanna_fn_BaseKakuteiHenkanToggle =
962   CANNA_FN_BaseKakuteiHenkanToggle;
963 static int Vcanna_fn_BaseRotateForward = CANNA_FN_BaseRotateForward;
964 static int Vcanna_fn_BaseRotateBackward = CANNA_FN_BaseRotateBackward;
965 #endif
966 static int Vcanna_fn_ExtendMode = IROHA_FN_ExtendMode;
967 static int Vcanna_fn_Touroku = IROHA_FN_Touroku;
968 static int Vcanna_fn_HexMode = IROHA_FN_HexMode;
969 static int Vcanna_fn_BushuMode = IROHA_FN_BushuMode;
970 static int Vcanna_fn_KigouMode = IROHA_FN_KigouMode;
971 #ifdef CANNA_FN_Mark
972 static int Vcanna_fn_Mark = CANNA_FN_Mark;
973 #endif
974 #ifdef CANNA_FN_TemporalMode
975 static int Vcanna_fn_TemporalMode = CANNA_FN_TemporalMode;
976 #endif
977
978 static int Vcanna_key_Nfer = IROHA_KEY_Nfer;
979 static int Vcanna_key_Xfer = IROHA_KEY_Xfer;
980 static int Vcanna_key_Up = IROHA_KEY_Up;
981 static int Vcanna_key_Left = IROHA_KEY_Left;
982 static int Vcanna_key_Right = IROHA_KEY_Right;
983 static int Vcanna_key_Down = IROHA_KEY_Down;
984 static int Vcanna_key_Insert = IROHA_KEY_Insert;
985 static int Vcanna_key_Rollup = IROHA_KEY_Rollup;
986 static int Vcanna_key_Rolldown = IROHA_KEY_Rolldown;
987 static int Vcanna_key_Home = IROHA_KEY_Home;
988 static int Vcanna_key_Help = IROHA_KEY_Help;
989 static int Vcanna_key_KP_Key = IROHA_KEY_KP_Key;
990 static int Vcanna_key_Shift_Nfer = IROHA_KEY_Shift_Nfer;
991 static int Vcanna_key_Shift_Xfer = IROHA_KEY_Shift_Xfer;
992 static int Vcanna_key_Shift_Up = IROHA_KEY_Shift_Up;
993 static int Vcanna_key_Shift_Left = IROHA_KEY_Shift_Left;
994 static int Vcanna_key_Shift_Right = IROHA_KEY_Shift_Right;
995 static int Vcanna_key_Shift_Down = IROHA_KEY_Shift_Down;
996 static int Vcanna_key_Cntrl_Nfer = IROHA_KEY_Cntrl_Nfer;
997 static int Vcanna_key_Cntrl_Xfer = IROHA_KEY_Cntrl_Xfer;
998 static int Vcanna_key_Cntrl_Up = IROHA_KEY_Cntrl_Up;
999 static int Vcanna_key_Cntrl_Left = IROHA_KEY_Cntrl_Left;
1000 static int Vcanna_key_Cntrl_Right = IROHA_KEY_Cntrl_Right;
1001 static int Vcanna_key_Cntrl_Down = IROHA_KEY_Cntrl_Down;
1002
1003 static Lisp_Object VCANNA;                              /* hir@nec, 1992.5.21 */
1004
1005 #ifdef CANNA_EMACS_DL
1006 static struct Lisp_Subr *s_canna_key_proc;
1007 static struct Lisp_Subr *s_canna_set_bunsetsu;
1008 static struct Lisp_Subr *s_canna_initialize;
1009 static struct Lisp_Subr *s_canna_finalize;
1010 static struct Lisp_Subr *s_canna_touroku_string;
1011 static struct Lisp_Subr *s_canna_set_width;
1012 static struct Lisp_Subr *s_canna_change_mode;
1013 static struct Lisp_Subr *s_canna_store_yomi;
1014 static struct Lisp_Subr *s_canna_do_function;
1015 static struct Lisp_Subr *s_canna_parse;
1016 static struct Lisp_Subr *s_canna_query_mode;
1017 static struct Lisp_Subr *s_canna_henkan_begin;
1018 static struct Lisp_Subr *s_canna_henkan_next;
1019 static struct Lisp_Subr *s_canna_bunsetu_henkou;
1020 static struct Lisp_Subr *s_canna_henkan_kakutei;
1021 static struct Lisp_Subr *s_canna_henkan_end;
1022 static struct Lisp_Subr *s_canna_henkan_quit;
1023 #endif
1024
1025 #ifndef CANNA_EMACS_DL
1026 syms_of_canna ()
1027 #else /* CANNA_EMACS_DL */
1028 void
1029 emacs_canna_init ()
1030 #endif
1031 {
1032   DEFVAR_LISP ("CANNA", &VCANNA, "");           /* hir@nec, 1992.5.21 */
1033   VCANNA = Qt;                                  /* hir@nec, 1992.5.21 */
1034
1035 #ifndef CANNA_EMACS_DL
1036   defsubr (&Scanna_key_proc);
1037   defsubr (&Scanna_initialize);
1038   defsubr (&Scanna_finalize);
1039   defsubr (&Scanna_touroku_string);
1040   defsubr (&Scanna_set_width);
1041   defsubr (&Scanna_change_mode);
1042   defsubr (&Scanna_store_yomi);
1043   defsubr (&Scanna_do_function);
1044   defsubr (&Scanna_parse);
1045   defsubr (&Scanna_query_mode);
1046   defsubr (&Scanna_set_bunsetsu);
1047 #else /* CANNA_EMACS_DL */
1048   s_canna_key_proc
1049     = (struct Lisp_Subr *)xmalloc (sizeof (struct Lisp_Subr));
1050   bcopy (&Scanna_key_proc, s_canna_key_proc, sizeof (struct Lisp_Subr));
1051   defsubr (s_canna_key_proc);
1052
1053   s_canna_initialize
1054     = (struct Lisp_Subr *)xmalloc (sizeof (struct Lisp_Subr));
1055   bcopy (&Scanna_initialize, s_canna_initialize, sizeof (struct Lisp_Subr));
1056   defsubr (s_canna_initialize);
1057   
1058   s_canna_finalize
1059     = (struct Lisp_Subr *)xmalloc (sizeof (struct Lisp_Subr));
1060   bcopy (&Scanna_finalize, s_canna_finalize, sizeof (struct Lisp_Subr));
1061   defsubr (s_canna_finalize);
1062   
1063   s_canna_touroku_string
1064     = (struct Lisp_Subr *)xmalloc (sizeof (struct Lisp_Subr));
1065   bcopy (&Scanna_touroku_string, s_canna_touroku_string,
1066          sizeof (struct Lisp_Subr));
1067   defsubr (s_canna_touroku_string);
1068
1069   s_canna_set_width
1070     = (struct Lisp_Subr *)xmalloc (sizeof (struct Lisp_Subr));
1071   bcopy (&Scanna_set_width, s_canna_set_width,
1072          sizeof (struct Lisp_Subr));
1073   defsubr (s_canna_set_width);
1074
1075   s_canna_change_mode
1076     = (struct Lisp_Subr *)xmalloc (sizeof (struct Lisp_Subr));
1077   bcopy (&Scanna_change_mode, s_canna_change_mode,
1078          sizeof (struct Lisp_Subr));
1079   defsubr (s_canna_change_mode);
1080   
1081   s_canna_store_yomi
1082     = (struct Lisp_Subr *)xmalloc (sizeof (struct Lisp_Subr));
1083   bcopy (&Scanna_store_yomi, s_canna_store_yomi,
1084          sizeof (struct Lisp_Subr));
1085   defsubr (s_canna_store_yomi);
1086   
1087   s_canna_do_function
1088     = (struct Lisp_Subr *)xmalloc (sizeof (struct Lisp_Subr));
1089   bcopy (&Scanna_do_function, s_canna_do_function,
1090          sizeof (struct Lisp_Subr));
1091   defsubr (s_canna_do_function);
1092   
1093   s_canna_parse
1094     = (struct Lisp_Subr *)xmalloc (sizeof (struct Lisp_Subr));
1095   bcopy (&Scanna_parse, s_canna_parse,
1096          sizeof (struct Lisp_Subr));
1097   defsubr (s_canna_parse);
1098   
1099   s_canna_query_mode
1100     = (struct Lisp_Subr *)xmalloc (sizeof (struct Lisp_Subr));
1101   bcopy (&Scanna_query_mode, s_canna_query_mode,
1102          sizeof (struct Lisp_Subr));
1103   defsubr (s_canna_query_mode);
1104   
1105   s_canna_set_bunsetsu
1106     = (struct Lisp_Subr *)xmalloc (sizeof (struct Lisp_Subr));
1107   bcopy (&Scanna_set_bunsetsu, s_canna_set_bunsetsu,
1108          sizeof (struct Lisp_Subr));
1109   defsubr (s_canna_set_bunsetsu);
1110 #endif
1111
1112   DEFVAR_LISP("canna-kakutei-string", &Vcanna_kakutei_string, "");
1113   DEFVAR_LISP("canna-kakutei-yomi",   &Vcanna_kakutei_yomi,   "");
1114   DEFVAR_LISP("canna-kakutei-romaji", &Vcanna_kakutei_romaji, "");
1115   DEFVAR_LISP("canna-henkan-string",  &Vcanna_henkan_string,  "");
1116   DEFVAR_INT ("canna-henkan-length",  &Vcanna_henkan_length,  "");
1117   DEFVAR_INT ("canna-henkan-revpos",  &Vcanna_henkan_revPos,  "");
1118   DEFVAR_INT ("canna-henkan-revlen",  &Vcanna_henkan_revLen,  "");
1119   DEFVAR_LISP("canna-ichiran-string", &Vcanna_ichiran_string, "");
1120   DEFVAR_INT ("canna-ichiran-length", &Vcanna_ichiran_length, "");
1121   DEFVAR_INT ("canna-ichiran-revpos", &Vcanna_ichiran_revPos, "");
1122   DEFVAR_INT ("canna-ichiran-revlen", &Vcanna_ichiran_revLen, "");
1123   DEFVAR_LISP("canna-mode-string",    &Vcanna_mode_string,    "");
1124
1125   DEFVAR_BOOL ("canna-empty-info", &Vcanna_empty_info, "For canna");
1126   DEFVAR_BOOL ("canna-through-info", &Vcanna_through_info, "For canna");
1127   DEFVAR_BOOL ("canna-underline", &Vcanna_underline, "For canna");
1128   DEFVAR_BOOL ("canna-inhibit-hankakukana", &Vcanna_inhibit_hankakukana, 
1129                "For canna");                    /* hir, 1994.12.5 */
1130
1131 #ifndef CANNA_EMACS_DL
1132   defsubr (&Scanna_henkan_begin);
1133   defsubr (&Scanna_henkan_next);
1134   defsubr (&Scanna_bunsetu_henkou);
1135   defsubr (&Scanna_henkan_kakutei);
1136   defsubr (&Scanna_henkan_end);
1137   defsubr (&Scanna_henkan_quit);
1138 #else /* CANNA_EMACS_DL */
1139   s_canna_henkan_begin
1140     = (struct Lisp_Subr *)xmalloc (sizeof (struct Lisp_Subr));
1141   bcopy (&Scanna_henkan_begin, s_canna_henkan_begin,
1142          sizeof (struct Lisp_Subr));
1143   defsubr (s_canna_henkan_begin);
1144   
1145   s_canna_henkan_next
1146     = (struct Lisp_Subr *)xmalloc (sizeof (struct Lisp_Subr));
1147   bcopy (&Scanna_henkan_next, s_canna_henkan_next,
1148          sizeof (struct Lisp_Subr));
1149   defsubr (s_canna_henkan_next);
1150   
1151   s_canna_bunsetu_henkou
1152     = (struct Lisp_Subr *)xmalloc (sizeof (struct Lisp_Subr));
1153   bcopy (&Scanna_bunsetu_henkou, s_canna_bunsetu_henkou,
1154          sizeof (struct Lisp_Subr));
1155   defsubr (s_canna_bunsetu_henkou);
1156   
1157   s_canna_henkan_kakutei
1158     = (struct Lisp_Subr *)xmalloc (sizeof (struct Lisp_Subr));
1159   bcopy (&Scanna_henkan_kakutei, s_canna_henkan_kakutei,
1160          sizeof (struct Lisp_Subr));
1161   defsubr (s_canna_henkan_kakutei);
1162   
1163   s_canna_henkan_end
1164     = (struct Lisp_Subr *)xmalloc (sizeof (struct Lisp_Subr));
1165   bcopy (&Scanna_henkan_end, s_canna_henkan_end,
1166          sizeof (struct Lisp_Subr));
1167   defsubr (s_canna_henkan_end);
1168   
1169   s_canna_henkan_quit
1170     = (struct Lisp_Subr *)xmalloc (sizeof (struct Lisp_Subr));
1171   bcopy (&Scanna_henkan_quit, s_canna_henkan_quit,
1172          sizeof (struct Lisp_Subr));
1173   defsubr (s_canna_henkan_quit);
1174 #endif
1175
1176   DEFVAR_INT ("canna-mode-alpha-mode", &Vcanna_mode_AlphaMode, "");
1177   DEFVAR_INT ("canna-mode-empty-mode", &Vcanna_mode_EmptyMode, "");
1178   DEFVAR_INT ("canna-mode-kigo-mode",  &Vcanna_mode_KigoMode,  "");
1179   DEFVAR_INT ("canna-mode-yomi-mode",  &Vcanna_mode_YomiMode,  "");
1180   DEFVAR_INT ("canna-mode-jishu-mode", &Vcanna_mode_JishuMode, "");
1181   DEFVAR_INT ("canna-mode-tankouho-mode", &Vcanna_mode_TankouhoMode, "");
1182   DEFVAR_INT ("canna-mode-ichiran-mode",  &Vcanna_mode_IchiranMode,  "");
1183   DEFVAR_INT ("canna-mode-yes-no-mode", &Vcanna_mode_YesNoMode, "");
1184   DEFVAR_INT ("canna-mode-on-off-mode", &Vcanna_mode_OnOffMode, "");
1185 #ifdef CANNA_MODE_AdjustBunsetsuMode
1186   DEFVAR_INT ("canna-mode-adjust-bunsetsu-mode",
1187               &Vcanna_mode_AdjustBunsetsuMode, "");
1188 #endif
1189 #ifdef CANNA_MODE_ChikujiYomiMode
1190   DEFVAR_INT ("canna-mode-chikuji-yomi-mode", &Vcanna_mode_ChikujiYomiMode,"");
1191   DEFVAR_INT ("canna-mode-chikuji-bunsetsu-mode",
1192               &Vcanna_mode_ChikujiTanMode, "");
1193 #endif
1194
1195   DEFVAR_INT ("canna-mode-henkan-mode", &Vcanna_mode_HenkanMode, "");
1196 #ifdef CANNA_MODE_HenkanNyuryokuMode
1197   DEFVAR_INT ("canna-mode-henkan-nyuuryoku-mode",
1198               &Vcanna_mode_HenkanNyuryokuMode, 0);
1199 #endif
1200 #ifdef CANNA_MODE_ZenHiraHenkanMode
1201   DEFVAR_INT ("canna-mode-zen-hira-henkan-mode",
1202               &Vcanna_mode_ZenHiraHenkanMode, "");
1203 #ifdef CANNA_MODE_HanHiraHenkanMode
1204   DEFVAR_INT ("canna-mode-han-hira-henkan-mode",
1205               &Vcanna_mode_HanHiraHenkanMode, "");
1206 #endif
1207   DEFVAR_INT ("canna-mode-zen-kata-henkan-mode",
1208               &Vcanna_mode_ZenKataHenkanMode, "");
1209   DEFVAR_INT ("canna-mode-han-kata-henkan-mode",
1210               &Vcanna_mode_HanKataHenkanMode, "");
1211   DEFVAR_INT ("canna-mode-zen-alpha-henkan-mode",
1212               &Vcanna_mode_ZenAlphaHenkanMode, "");
1213   DEFVAR_INT ("canna-mode-han-alpha-henkan-mode",
1214               &Vcanna_mode_HanAlphaHenkanMode, "");
1215 #endif
1216   DEFVAR_INT ("canna-mode-zen-hira-kakutei-mode",
1217               &Vcanna_mode_ZenHiraKakuteiMode, "");
1218 #ifdef CANNA_MODE_HanHiraKakuteiMode
1219   DEFVAR_INT ("canna-mode-han-hira-kakutei-mode",
1220               &Vcanna_mode_HanHiraKakuteiMode, "");
1221 #endif
1222   DEFVAR_INT ("canna-mode-zen-kata-kakutei-mode",
1223               &Vcanna_mode_ZenKataKakuteiMode, "");
1224   DEFVAR_INT ("canna-mode-han-kata-kakutei-mode",
1225               &Vcanna_mode_HanKataKakuteiMode, "");
1226   DEFVAR_INT ("canna-mode-zen-alpha-kakutei-mode",
1227               &Vcanna_mode_ZenAlphaKakuteiMode, "");
1228   DEFVAR_INT ("canna-mode-han-alpha-kakutei-mode",
1229               &Vcanna_mode_HanAlphaKakuteiMode, "");
1230   DEFVAR_INT ("canna-mode-hex-mode", &Vcanna_mode_HexMode, "");
1231   DEFVAR_INT ("canna-mode-bushu-mode", &Vcanna_mode_BushuMode, "");
1232   DEFVAR_INT ("canna-mode-extend-mode", &Vcanna_mode_ExtendMode, "");
1233   DEFVAR_INT ("canna-mode-russian-mode", &Vcanna_mode_RussianMode, "");
1234   DEFVAR_INT ("canna-mode-greek-mode", &Vcanna_mode_GreekMode, "");
1235   DEFVAR_INT ("canna-mode-line-mode", &Vcanna_mode_LineMode, "");
1236   DEFVAR_INT ("canna-mode-changing-server-mode",
1237               &Vcanna_mode_ChangingServerMode, "");
1238   DEFVAR_INT ("canna-mode-henkan-method-mode",
1239               &Vcanna_mode_HenkanMethodMode, "");
1240   DEFVAR_INT ("canna-mode-delete-dic-mode", &Vcanna_mode_DeleteDicMode, "");
1241   DEFVAR_INT ("canna-mode-touroku-mode", &Vcanna_mode_TourokuMode, "");
1242   DEFVAR_INT ("canna-mode-touroku-empty-mode",
1243               &Vcanna_mode_TourokuEmptyMode, "");
1244   DEFVAR_INT ("canna-mode-touroku-hinshi-mode",
1245               &Vcanna_mode_TourokuHinshiMode, "");
1246   DEFVAR_INT ("canna-mode-touroku-dic-mode", &Vcanna_mode_TourokuDicMode, "");
1247   DEFVAR_INT ("canna-mode-quoted-insert-mode",
1248               &Vcanna_mode_QuotedInsertMode, "");
1249   DEFVAR_INT ("canna-mode-bubun-muhenkan-mode",
1250               &Vcanna_mode_BubunMuhenkanMode, "");
1251   DEFVAR_INT ("canna-mode-mount-dic-mode", &Vcanna_mode_MountDicMode, "");
1252
1253   DEFVAR_INT ("canna-func-self-insert", &Vcanna_fn_SelfInsert ,"");
1254   DEFVAR_INT ("canna-func-functional-insert", &Vcanna_fn_FunctionalInsert ,"");
1255   DEFVAR_INT ("canna-func-quoted-insert", &Vcanna_fn_QuotedInsert ,"");
1256   DEFVAR_INT ("canna-func-japanese-mode", &Vcanna_fn_JapaneseMode ,"");
1257   DEFVAR_INT ("canna-func-alpha-mode", &Vcanna_fn_AlphaMode ,"");
1258   DEFVAR_INT ("canna-func-henkan-nyuryoku-mode",
1259               &Vcanna_fn_HenkanNyuryokuMode ,"");
1260   DEFVAR_INT ("canna-func-forward", &Vcanna_fn_Forward ,"");
1261   DEFVAR_INT ("canna-func-backward", &Vcanna_fn_Backward ,"");
1262   DEFVAR_INT ("canna-func-next", &Vcanna_fn_Next ,"");
1263   DEFVAR_INT ("canna-func-previous", &Vcanna_fn_Prev ,"");
1264   DEFVAR_INT ("canna-func-beginning-of-line", &Vcanna_fn_BeginningOfLine ,"");
1265   DEFVAR_INT ("canna-func-end-of-line", &Vcanna_fn_EndOfLine ,"");
1266   DEFVAR_INT ("canna-func-delete-next", &Vcanna_fn_DeleteNext ,"");
1267   DEFVAR_INT ("canna-func-delete_previous", &Vcanna_fn_DeletePrevious ,"");
1268   DEFVAR_INT ("canna-func-kill-to-end-of-line", &Vcanna_fn_KillToEndOfLine,"");
1269   DEFVAR_INT ("canna-func-henkan", &Vcanna_fn_Henkan ,"");
1270   DEFVAR_INT ("canna-func-kakutei", &Vcanna_fn_Kakutei ,"");
1271   DEFVAR_INT ("canna-func-extend", &Vcanna_fn_Extend ,"");
1272   DEFVAR_INT ("canna-func-shrink", &Vcanna_fn_Shrink ,"");
1273 #ifdef CANNA_FN_AdjustBunsetsu
1274   DEFVAR_INT ("canna-func-adjust-bunsetsu", &Vcanna_fn_AdjustBunsetsu ,"");
1275 #endif
1276   DEFVAR_INT ("canna-func-quit", &Vcanna_fn_Quit ,"");
1277   DEFVAR_INT ("canna-func-convert-as-hex", &Vcanna_fn_ConvertAsHex ,"");
1278   DEFVAR_INT ("canna-func-convert-as-bushu", &Vcanna_fn_ConvertAsBushu ,"");
1279   DEFVAR_INT ("canna-func-kouho-ichiran", &Vcanna_fn_KouhoIchiran ,"");
1280   DEFVAR_INT ("canna-func-bubun-muhenkan", &Vcanna_fn_BubunMuhenkan ,"");
1281   DEFVAR_INT ("canna-func-zenkaku", &Vcanna_fn_Zenkaku ,"");
1282   DEFVAR_INT ("canna-func-hankaku", &Vcanna_fn_Hankaku ,"");
1283   DEFVAR_INT ("canna-func-to-upper", &Vcanna_fn_ToUpper ,"");
1284   DEFVAR_INT ("canna-func-capitalize", &Vcanna_fn_Capitalize ,"");
1285   DEFVAR_INT ("canna-func-to-lower", &Vcanna_fn_ToLower ,"");
1286   DEFVAR_INT ("canna-func-hiragana", &Vcanna_fn_Hiragana ,"");
1287   DEFVAR_INT ("canna-func-katakana", &Vcanna_fn_Katakana ,"");
1288   DEFVAR_INT ("canna-func-romaji", &Vcanna_fn_Romaji ,"");
1289 #ifdef CANNA_FN_BaseHiragana
1290   DEFVAR_INT ("canna-func-base-hiragana", &Vcanna_fn_BaseHiragana ,"");
1291   DEFVAR_INT ("canna-func-base-katakana", &Vcanna_fn_BaseKatakana ,"");
1292   DEFVAR_INT ("canna-func-base-eisu", &Vcanna_fn_BaseEisu ,"");
1293   DEFVAR_INT ("canna-func-base-zenkaku", &Vcanna_fn_BaseZenkaku ,"");
1294   DEFVAR_INT ("canna-func-base-hankaku", &Vcanna_fn_BaseHankaku ,"");
1295   DEFVAR_INT ("canna-func-base-kana", &Vcanna_fn_BaseKana ,"");
1296   DEFVAR_INT ("canna-func-base-kakutei", &Vcanna_fn_BaseKakutei ,"");
1297   DEFVAR_INT ("canna-func-base-henkan", &Vcanna_fn_BaseHenkan ,"");
1298   DEFVAR_INT ("canna-func-base-hiragana-katakana-toggle",
1299               &Vcanna_fn_BaseHiraKataToggle ,"");
1300   DEFVAR_INT ("canna-func-base-zenkaku-hankaku-toggle",
1301               &Vcanna_fn_BaseZenHanToggle ,"");
1302   DEFVAR_INT ("canna-func-base-kana-eisu-toggle",
1303               &Vcanna_fn_BaseKanaEisuToggle ,"");
1304   DEFVAR_INT ("canna-func-base-kakutei-henkan-toggle",
1305               &Vcanna_fn_BaseKakuteiHenkanToggle ,"");
1306   DEFVAR_INT ("canna-func-base-rotate-forward",
1307               &Vcanna_fn_BaseRotateForward ,"");
1308   DEFVAR_INT ("canna-func-base-rotate-backward",
1309               &Vcanna_fn_BaseRotateBackward ,"");
1310 #endif
1311   DEFVAR_INT ("canna-func-extend-mode", &Vcanna_fn_ExtendMode ,"");
1312   DEFVAR_INT ("canna-func-touroku", &Vcanna_fn_Touroku ,"");
1313   DEFVAR_INT ("canna-func-hex-mode", &Vcanna_fn_HexMode ,"");
1314   DEFVAR_INT ("canna-func-bushu-mode", &Vcanna_fn_BushuMode ,"");
1315   DEFVAR_INT ("canna-func-kigo-mode", &Vcanna_fn_KigouMode ,"");
1316 #ifdef CANNA_FN_Mark
1317   DEFVAR_INT ("canna-func-mark", &Vcanna_fn_Mark ,"");
1318 #endif
1319 #ifdef CANNA_FN_TemporalMode
1320   DEFVAR_INT ("canna-func-temporal-mode", &Vcanna_fn_TemporalMode ,"");
1321 #endif
1322
1323   DEFVAR_INT ("canna-key-nfer", &Vcanna_key_Nfer, "");
1324   DEFVAR_INT ("canna-key-xfer", &Vcanna_key_Xfer, "");
1325   DEFVAR_INT ("canna-key-up", &Vcanna_key_Up, "");
1326   DEFVAR_INT ("canna-key-left", &Vcanna_key_Left, "");
1327   DEFVAR_INT ("canna-key-right", &Vcanna_key_Right, "");
1328   DEFVAR_INT ("canna-key-down", &Vcanna_key_Down, "");
1329   DEFVAR_INT ("canna-key-insert", &Vcanna_key_Insert, "");
1330   DEFVAR_INT ("canna-key-rollup", &Vcanna_key_Rollup, "");
1331   DEFVAR_INT ("canna-key-rolldown", &Vcanna_key_Rolldown, "");
1332   DEFVAR_INT ("canna-key-home", &Vcanna_key_Home, "");
1333   DEFVAR_INT ("canna-key-help", &Vcanna_key_Help, "");
1334   DEFVAR_INT ("canna-key-kp-key", &Vcanna_key_KP_Key, "");
1335   DEFVAR_INT ("canna-key-shift-nfer", &Vcanna_key_Shift_Nfer, "");
1336   DEFVAR_INT ("canna-key-shift-xfer", &Vcanna_key_Shift_Xfer, "");
1337   DEFVAR_INT ("canna-key-shift-up", &Vcanna_key_Shift_Up, "");
1338   DEFVAR_INT ("canna-key-shift-left", &Vcanna_key_Shift_Left, "");
1339   DEFVAR_INT ("canna-key-shift-right", &Vcanna_key_Shift_Right, "");
1340   DEFVAR_INT ("canna-key-shift-down", &Vcanna_key_Shift_Down, "");
1341   DEFVAR_INT ("canna-key-control-nfer", &Vcanna_key_Cntrl_Nfer, "");
1342   DEFVAR_INT ("canna-key-control-xfer", &Vcanna_key_Cntrl_Xfer, "");
1343   DEFVAR_INT ("canna-key-control-up", &Vcanna_key_Cntrl_Up, "");
1344   DEFVAR_INT ("canna-key-control-left", &Vcanna_key_Cntrl_Left, "");
1345   DEFVAR_INT ("canna-key-control-right", &Vcanna_key_Cntrl_Right, "");
1346   DEFVAR_INT ("canna-key-control-down", &Vcanna_key_Cntrl_Down, "");
1347 }
1348
1349 #ifdef CANNA_EMACS_DL
1350 void
1351 emacs_wnnfns_fini ()
1352 {
1353   undefsubr (s_canna_key_proc);
1354   free (s_canna_key_proc);
1355   
1356   undefsubr (s_canna_initialize);
1357   free (s_canna_initialize);
1358
1359   undefsubr (s_canna_finalize);
1360   free (s_canna_finalize);
1361
1362   undefsubr (s_canna_touroku_string);
1363   free (s_canna_touroku_string);
1364
1365   undefsubr (s_canna_set_width);
1366   free (s_canna_set_width);
1367
1368   undefsubr (s_canna_change_mode);
1369   free (s_canna_change_mode);
1370
1371   undefsubr (s_canna_store_yomi);
1372   free (s_canna_store_yomi);
1373
1374   undefsubr (s_canna_do_function);
1375   free (s_canna_do_function);
1376
1377   undefsubr (s_canna_parse);
1378   free (s_canna_parse);
1379
1380   undefsubr (s_canna_query_mode);
1381   free (s_canna_query_mode);
1382
1383   undefsubr (s_canna_set_bunsetsu);
1384   free (s_canna_set_bunsetsu);
1385
1386   undefsubr (s_canna_henkan_begin);
1387   free (s_canna_henkan_begin);
1388
1389   undefsubr (s_canna_henkan_next);
1390   free (s_canna_henkan_next);
1391
1392   undefsubr (s_canna_bunsetu_henkou);
1393   free (s_canna_bunsetu_henkou);
1394
1395   undefsubr (s_canna_henkan_kakutei);
1396   free (s_canna_henkan_kakutei);
1397
1398   undefsubr (s_canna_henkan_end);
1399   free (s_canna_henkan_end);
1400
1401   undefsubr (s_canna_henkan_quit);
1402   free (s_canna_henkan_quit);
1403 }
1404 #endif
1405
1406 #ifndef CANNA_NEMACS
1407 /* To handle MULE internal code and EUC.
1408    I assume CANNA can handle only Japanese EUC. */
1409
1410 /* EUC multibyte string to MULE internal string */
1411
1412 static
1413 c2mu(cp, l, mp)
1414 char    *cp;
1415 int     l;
1416 char    *mp;
1417 {
1418   char  ch, *ep = cp+l;
1419   
1420   while((cp < ep) && (ch = *cp)) {
1421     if ((unsigned char)ch == ISO_CODE_SS2) {
1422       *mp++ = CHARSET_KATAKANA_JISX0201;
1423       cp++;
1424     }
1425     else if ((unsigned char)ch == ISO_CODE_SS3) {
1426       *mp++ = CHARSET_JAPANESE_JISX0212;
1427       cp++;
1428       *mp++ = *cp++;
1429     }
1430     else if(ch & 0x80) {
1431       *mp++ = CHARSET_JAPANESE_JISX0208;
1432       *mp++ = *cp++;
1433     }
1434     *mp++ = *cp++;
1435   }
1436   *mp = 0;
1437 }
1438
1439 /* MULE internal string to EUC multibyte string */
1440
1441 static
1442 m2c(mp, l, cp)
1443 unsigned char   *mp;
1444 int     l;
1445 unsigned char   *cp;
1446 {
1447   unsigned char ch, *ep = mp + l;;
1448   
1449   while((mp < ep) && (ch = *mp++)) {
1450     switch (ch) {
1451     case CHARSET_KATAKANA_JISX0201:
1452       *cp++ = ISO_CODE_SS2;
1453       *cp++ = *mp++;
1454       break;
1455     case CHARSET_JAPANESE_JISX0212:
1456       *cp++ = ISO_CODE_SS3;
1457     case CHARSET_JAPANESE_JISX0208:
1458       *cp++ = *mp++;
1459       *cp++ = *mp++;
1460       break;
1461     default:
1462       *cp++ = ch;
1463       break;
1464     }
1465   }     
1466   *cp = 0;
1467 }
1468
1469 #undef make_string
1470
1471 /* make_string after converting EUC string to MULE internal string */
1472 static
1473 Lisp_Object
1474 mule_make_string(p,l)
1475 unsigned char *p;
1476 int l;
1477 {
1478   unsigned char cbuf[4096];
1479   
1480   c2mu(p,l,cbuf);
1481   return (make_string(cbuf,strlen(cbuf)));
1482 }       
1483
1484 /* return the MULE internal string length of EUC string */
1485 static
1486 mule_strlen(p,l)
1487 unsigned char *p;
1488 int l;
1489 {
1490   unsigned char ch, *cp = p;
1491   int len = 0;
1492   
1493   while((cp < p + l) && (ch = *cp)) {
1494     if ((unsigned char)ch == ISO_CODE_SS2) {
1495       len += 2;
1496       cp += 2;
1497     }
1498     else if ((unsigned char)ch == ISO_CODE_SS3) {
1499       len += 3;
1500       cp += 3;
1501     }
1502     else if(ch & 0x80) {
1503       len += 3;
1504       cp += 2;
1505     }
1506     else {
1507       len++;
1508       cp++;     
1509     }
1510   }
1511   return(len);
1512 }
1513
1514 /* count number of characters */
1515 static
1516 count_char(p,len,pos,rev,clen,cpos,crev)
1517 unsigned char *p;       
1518 int len,pos,rev,*clen,*cpos,*crev;
1519 {
1520   unsigned char *q = p;
1521   
1522   *clen = *cpos = *crev = 0;
1523   if (len == 0) return;
1524   while (q < p + pos) {
1525     (*clen)++;
1526     (*cpos)++;
1527     if (*q++ & 0x80) q++;
1528   }
1529   while (q < p + pos + rev) {
1530     (*clen)++;
1531     (*crev)++;
1532     if (*q++ & 0x80) q++;
1533   }             
1534   while (q < p + len) {
1535     (*clen)++;
1536     if (*q++ & 0x80) q++;
1537   }
1538 }
1539 #endif /* CANNA_MULE */