1/* Copyright 1992 NEC Corporation, Tokyo, Japan.
2 *
3 * Permission to use, copy, modify, distribute and sell this software
4 * and its documentation for any purpose is hereby granted without
5 * fee, provided that the above copyright notice appear in all copies
6 * and that both that copyright notice and this permission notice
7 * appear in supporting documentation, and that the name of NEC
8 * Corporation not be used in advertising or publicity pertaining to
9 * distribution of the software without specific, written prior
10 * permission.  NEC Corporation makes no representations about the
11 * suitability of this software for any purpose.  It is provided "as
12 * is" without express or implied warranty.
13 *
14 * NEC CORPORATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
16 * NO EVENT SHALL NEC CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
18 * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
19 * OTHER TORTUOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20 * PERFORMANCE OF THIS SOFTWARE.
21 */
22
23/************************************************************************/
24/* THIS SOURCE CODE IS MODIFIED FOR TKO BY T.MURAI 1997
25/************************************************************************/
26
27
28#if !defined(lint) && !defined(__CODECENTER__)
29static	char	rcs_id[] = "@(#) 102.1 $Id: henkan.c 14875 2005-11-12 21:25:31Z bonefish $";
30#endif /* lint */
31
32#include	"canna.h"
33#include "RK.h"
34#include "RKintern.h"
35
36#include	<errno.h>
37#include	<fcntl.h>
38#ifdef MEASURE_TIME
39#include <sys/types.h>
40#ifdef WIN
41#include <sys/timeb.h>
42#else
43/* If you compile with Visual C++ on WIN, then please comment out next line. */
44#include <sys/times.h>
45#endif
46#endif
47
48extern struct RkRxDic *romajidic, *englishdic;
49
50extern int defaultBushuContext;
51extern int yomiInfoLevel;
52extern int ckverbose;
53extern int defaultContext;
54extern struct dicname *RengoGakushu, *KatakanaGakushu, *HiraganaGakushu;
55extern KanjiModeRec cy_mode, cb_mode, yomi_mode, tankouho_mode, empty_mode;
56extern char saveapname[];
57extern int RkwGetServerVersion (int *, int *);
58
59#define DICERRORMESGLEN 78
60
61
62static int doYomiHenkan(uiContext d, int len, WCHAR_T *kanji);
63
64static char dictmp[DICERRORMESGLEN];
65
66inline int
67kanakanError(uiContext d)
68{
69  return makeRkError(d, "Kana-kanji conversion feiled");
70                        /* ¤«¤Ê´Á»úÊÑ´¹¤Ë¼ºÇÔ¤·¤Þ¤·¤¿ */
71}
72
73static void
74dicMesg(char *s, char *d)
75{
76#ifndef WIN
77  if (ckverbose == CANNA_FULL_VERBOSE) {
78    char buf[128];
79    sprintf(buf, "\"%s\"", d);
80    printf("%14s %-20s ¤ò»ØÄꤷ¤Æ¤¤¤Þ¤¹¡£\n", s, buf);
81  }
82#endif
83}
84
85static void
86RkwInitError(void)
87{
88  if (errno == EPIPE) {
89    jrKanjiError = KanjiInitError();
90  }else {
91    jrKanjiError = "Error in initailzaton of Kana-kanji conversion dictionaly.";
92                   /* ¤«¤Ê´Á»úÊÑ´¹¼­½ñ¤Î½é´ü²½¤Ë¼ºÇÔ¤·¤Þ¤·¤¿ */
93  }
94  addWarningMesg(jrKanjiError);
95  RkwFinalize();
96}
97
98static void
99mountError(char *dic)
100{
101static char		*mountErrorMessage = " can't mount. "; /* ¤ò¥Þ¥¦¥ó¥È¤Ç¤­¤Þ¤»¤ó¤Ç¤·¤¿ */
102int				mnterrlen;
103
104  if (DICERRORMESGLEN <
105      (unsigned)(strlen(dic) + (mnterrlen = strlen(mountErrorMessage)) + 1)) {
106    (void)strncpy(dictmp, dic, DICERRORMESGLEN - mnterrlen - 3/* ... */ - 1);
107    (void)strcpy(dictmp + DICERRORMESGLEN - mnterrlen - 3 - 1, "...");
108    strcpy(dictmp + DICERRORMESGLEN - mnterrlen - 1, mountErrorMessage);
109  }
110  else {
111    sprintf(dictmp, "%s%s", dic, mountErrorMessage);
112  }
113  jrKanjiError = dictmp;
114  addWarningMesg(dictmp);
115}
116
117inline void
118autodicError(void)
119{
120  jrKanjiError = "¼«Æ°ÅÐÏ¿ÍѼ­½ñ¤¬Â¸ºß¤·¤Þ¤»¤ó";
121  addWarningMesg(jrKanjiError);
122}
123
124/*
125 * ¤«¤Ê´Á»úÊÑ´¹¤Î¤¿¤á¤Î½é´ü½èÍý
126 *
127 * ¡¦RkwInitialize¤ò¸Æ¤ó¤Ç¡¢defaultContext ¤òºîÀ®¤¹¤ë
128 * ¡¦defaultBushuContext ¤òºîÀ®¤¹¤ë
129 * ¡¦¼­½ñ¤Î¥µ¡¼¥Á¥Ñ¥¹¤òÀßÄꤹ¤ë
130 * ¡¦¥·¥¹¥Æ¥à¼­½ñ¡¢Éô¼óÍѼ­½ñ¡¢¥æ¡¼¥¶¼­½ñ¤ò¥Þ¥¦¥ó¥È¤¹¤ë
131 *
132 * °ú¤­¿ô	¤Ê¤·
133 * Ìá¤êÃÍ	0:¤Þ¤¢Àµ¾ï¡¢ -1:¤È¤³¤È¤óÉÔÎÉ
134 */
135int KanjiInit()
136{
137char			*ptr, *getenv(), *kodmesg = ""/* ¼­½ñ¤Î¼ïÊÌËè¤Î¥á¥Ã¥»¡¼¥¸ */;
138int				con;
139static int		mountnottry = 1; /* ¥Þ¥¦¥ó¥È½èÍý¤ò¹Ô¤Ã¤Æ¤¤¤ë¤«¤É¤¦¤« */
140struct			dicname *stp;
141extern struct	dicname *kanjidicnames;
142extern			int FirstTime;
143extern			jrUserInfoStruct *uinfo;
144extern char		*RkGetServerHost(void);
145extern char		basepath[];
146int 			ret = -1;
147char 			dichomedir[256];
148
149#if defined(DEBUG) && !defined(WIN)
150  if (iroha_debug) {
151    fprintf(stderr,"\n¥µ¡¼¥Ð¤ËÀܳ¤·¤¿ strokelimit = %d (default:%d)\n",
152              cannaconf.strokelimit, STROKE_LIMIT);
153  }
154#endif
155  /* ϢʸÀá¥é¥¤¥Ö¥é¥ê¤ò½é´ü²½¤¹¤ë */
156  if (uinfo) {
157    RkwSetUserInfo(uinfo->uname, uinfo->gname, uinfo->topdir);
158  }
159
160    sprintf(dichomedir, "%s%s", basepath, "dic");
161//    puts(dichomedir);
162	fputs( dichomedir, stderr );
163  if ((defaultContext = RkwInitialize(dichomedir)) == -1) {
164    RkwInitError();
165    ret = -1;
166    goto return_ret;
167  }
168
169  if (defaultContext != -1) {
170    if((defaultBushuContext = RkwCreateContext()) == -1) {
171      jrKanjiError = "\311\364\274\363\315\321\244\316\245\263\245\363\245\306"
172	"\245\257\245\271\245\310\244\362\272\356\300\256\244\307\244\255"
173	"\244\336\244\273\244\363\244\307\244\267\244\277";
174                     /* Éô¼óÍѤΥ³¥ó¥Æ¥¯¥¹¥È¤òºîÀ®¤Ç¤­¤Þ¤»¤ó¤Ç¤·¤¿ */
175      addWarningMesg(jrKanjiError);
176      defaultContext = -1;
177      RkwFinalize();
178      ret = -1;
179      goto return_ret;
180    }
181  } else {
182    defaultBushuContext = -1;
183  }
184
185  debug_message("\245\307\245\325\245\251\245\353\245\310\245\263\245\363"
186	"\245\306\245\255\245\271\245\310(%d), \311\364\274\363\245\263"
187	"\245\363\245\306\245\255\245\271\245\310(%d)\n",
188		defaultContext, defaultBushuContext, 0);
189               /* ¥Ç¥Õ¥©¥ë¥È¥³¥ó¥Æ¥­¥¹¥È(%d), Éô¼ó¥³¥ó¥Æ¥­¥¹¥È(%d)\n */
190
191      if((RkwSetDicPath(defaultContext, "canna")) == -1) {
192	jrKanjiError = "¼­½ñ¤Î¥Ç¥£¥ì¥¯¥È¥ê¤òÀßÄê¤Ç¤­¤Þ¤»¤ó¤Ç¤·¤¿";
193	RkwFinalize();
194	return(NG);
195      }
196      if((RkwSetDicPath(defaultBushuContext, "canna")) == -1) {
197	jrKanjiError = "¼­½ñ¤Î¥Ç¥£¥ì¥¯¥È¥ê¤òÀßÄê¤Ç¤­¤Þ¤»¤ó¤Ç¤·¤¿";
198	RkwFinalize();
199	return(NG);
200      }
201
202
203  if (defaultContext != -1) {
204
205    if (saveapname[0]) {
206      RkwSetAppName(defaultContext, saveapname);
207    }
208
209    if (!FirstTime && !mountnottry) { /* KC_INITIALIZE ¤Ç¸Æ¤Ó½Ð¤µ¤ì¤Æ¤¤¤Ê¤¯¤Æ¡¢
210					 ´û¤Ë¥Þ¥¦¥ó¥È½èÍý¤ò¹Ô¤Ã¤Æ¤¤¤ë¾ì¹ç */
211      /* ʸˡ¼­½ñ¤Î¥Þ¥¦¥ó¥È */
212      for (stp = kanjidicnames; stp ; stp = stp->next) {
213	if (stp->dictype == DIC_GRAMMAR) {
214	  if (stp->dicflag == DIC_MOUNTED) {
215	    if (RkwMountDic(defaultContext, stp->name,
216			    cannaconf.kojin ? PL_ALLOW : PL_INHIBIT) == -1) {
217	      stp->dicflag = DIC_MOUNT_FAILED;
218	      mountError(stp->name);
219	    }
220	    else {
221	      stp->dicflag = DIC_MOUNTED;
222	      dicMesg("\312\270\313\241\274\255\275\361", stp->name);
223                      /* ʸˡ¼­½ñ */
224	    }
225	  }
226	}
227      }
228      /* ¥·¥¹¥Æ¥à¼­½ñ¤Î¥Þ¥¦¥ó¥È */
229      for (stp = kanjidicnames ; stp ; stp = stp->next) {
230        if (stp->dictype != DIC_GRAMMAR) {
231          if (stp->dicflag == DIC_MOUNTED) {
232            if (stp->dictype == DIC_BUSHU) {
233              con = defaultBushuContext;
234            }
235            else {
236              con = defaultContext;
237            }
238            if (RkwMountDic(con, stp->name,
239			    cannaconf.kojin ? PL_ALLOW : PL_INHIBIT)
240              == -1) {
241#if defined(DEBUG) && !defined(WIN)
242            if (iroha_debug) {
243              fprintf(stderr, "saveddicname = %s\n", stp->name);
244            }
245#endif
246	      stp->dicflag = DIC_MOUNT_FAILED;
247	      mountError(stp->name);
248	    }
249	    dicMesg("saveddicname\244\316\274\255\275\361", stp->name);
250                    /* saveddicname¤Î¼­½ñ */
251	  }
252	}
253      }
254    }
255    else { /* KC_INITIALIZE ¤«¤é¸Æ¤Ó½Ð¤µ¤ì¤Æ¤¤¤ë¾ì¹ç¡£
256              ¤Þ¤¿¤Ï¡¢¥Þ¥¦¥ó¥È½èÍý¤ò¹Ô¤Ã¤Æ¤¤¤Ê¤¤¾ì¹ç */
257#if defined(DEBUG) && !defined(WIN)
258      if (iroha_debug) {
259        fprintf(stderr, "¼­½ñ¤Ï.canna¤ÎÄ̤ê¤Ë¥Þ¥¦¥ó¥È¤¹¤ë\n");
260      }
261#endif
262
263      mountnottry = 0; /* ¥Þ¥¦¥ó¥È½èÍý¤ò¹Ô¤¦¤Î¤Ç mountnottry = 0 ¤Ë¤¹¤ë */
264      /* ʸˡ¼­½ñ¤Î¥Þ¥¦¥ó¥È */
265      for (stp = kanjidicnames; stp ; stp = stp->next) {
266	if (stp->dictype == DIC_GRAMMAR) {
267	  if (RkwMountDic(defaultContext, stp->name,
268			  cannaconf.kojin ? PL_ALLOW : PL_INHIBIT) == -1) {
269	    stp->dicflag = DIC_MOUNT_FAILED;
270	    mountError(stp->name);
271	  }
272	  else {
273	    stp->dicflag = DIC_MOUNTED;
274	    dicMesg("\312\270\313\241\274\255\275\361", stp->name);
275                    /* ʸˡ¼­½ñ */
276	  }
277	}
278      }
279
280      /* ¥·¥¹¥Æ¥à¼­½ñ¤Î¥Þ¥¦¥ó¥È */
281      for (stp = kanjidicnames ; stp ; stp = stp->next) {
282        if (stp->dictype != DIC_GRAMMAR) {
283          con = defaultContext;
284          if (stp->dictype == DIC_PLAIN) {
285            kodmesg = "\245\267\245\271\245\306\245\340\274\255\275\361";
286                      /* "¥·¥¹¥Æ¥à¼­½ñ"; */
287          }
288          else if (stp->dictype == DIC_USER) {
289            /* ¥æ¡¼¥¶¼­½ñ¤Î¥Þ¥¦¥ó¥È */
290           kodmesg = "\303\261\270\354\305\320\317\277\315\321\274\255\275\361";
291                     /* "ñ¸ìÅÐÏ¿ÍѼ­½ñ"; */
292          }
293          else if (stp->dictype == DIC_RENGO) {
294            /* Ï¢¸ì¼­½ñ¤Î¥Þ¥¦¥ó¥È */
295            RengoGakushu = stp;
296            kodmesg = "\317\242\270\354\274\255\275\361";
297                      /* "Ï¢¸ì¼­½ñ"; */
298          }
299          else if (stp->dictype == DIC_KATAKANA) {
300            KatakanaGakushu = stp;
301            kodmesg = "\274\253\306\260\305\320\317\277\315\321\274\255\275\361";
302                      /* "¼«Æ°ÅÐÏ¿ÍѼ­½ñ"; */
303          }
304          else if (stp->dictype == DIC_HIRAGANA) {
305            HiraganaGakushu = stp;
306#ifdef HIRAGANAAUTO
307            kodmesg = "\274\253\306\260\305\320\317\277\315\321\274\255\275\361";
308                      /* "¼«Æ°ÅÐÏ¿ÍѼ­½ñ"; */
309#else
310            kodmesg = "\317\242\270\354\274\255\275\361";
311                      /* "Ï¢¸ì¼­½ñ"; */
312#endif
313          }
314          else if (stp->dictype == DIC_BUSHU) {
315            kodmesg = "\311\364\274\363\274\255\275\361";
316                      /* "Éô¼ó¼­½ñ"; */
317            con = defaultBushuContext;
318          }
319          if (RkwMountDic(con, stp->name,
320			  cannaconf.kojin ? PL_ALLOW : PL_INHIBIT) == -1) {
321            extern int auto_define;
322
323            stp->dicflag = DIC_MOUNT_FAILED;
324            if (stp->dictype == DIC_KATAKANA
325#ifdef HIRAGANAAUTO
326                || stp->dictype == DIC_HIRAGANA
327#endif
328               ) {
329              /* ¼«Æ°ÅÐÏ¿¼­½ñ¤À¤Ã¤¿¤é¡¢¼«Æ°ÅÐÏ¿¤·¤Ê¤¤ */
330              auto_define = 0;
331            }
332            if (stp->dictype != DIC_USER || strcmp(stp->name, "user")) {
333              /* ¥æ¡¼¥¶¼­½ñ¤Ç user ¤È¤¤¤¦Ì¾Á°¤Î¾ì¹ç¤Ï¥¨¥é¡¼É½¼¨ *
334               * ¤·¤Ê¤¤¤è¤¦¤Ë¤¹¤ë¤¿¤á                           */
335              int majv, minv;
336
337              RkwGetServerVersion(&majv, &minv);
338              if (!(canna_version(majv, minv) < canna_version(3, 4))
339                  || ((stp->dictype != DIC_KATAKANA ||
340                         strcmp(stp->name, "katakana"))
341#ifdef HIRAGANAAUTO
342                     && (stp->dictype != DIC_HIRAGANA ||
343                           strcmp(stp->name, "hiragana"))
344#endif
345                  )) {
346                /* V3.3 °ÊÁ°¤Ç¡¢¥«¥¿¥«¥Ê¼­½ñ¤¬ katakana¡¢¤Ò¤é¤¬¤Ê¼­½ñ¤¬
347                   hiragana ¤Î¾ì¹ç¤Ï¥¨¥é¡¼¤Ë¤·¤Ê¤¤¤¿¤á                  */
348                extern char *kataautodic;
349#ifdef HIRAGANAAUTO
350                extern char *hiraautodic;
351#endif
352
353                if (!auto_define ||
354                    ((kataautodic && strcmp(stp->name, kataautodic))
355#ifdef HIRAGANAAUTO
356                    && (hiraautodic && strcmp(stp->name, hiraautodic))
357#endif
358                   )) {
359                  if (stp->dictype == DIC_KATAKANA
360#ifdef HIRAGANAAUTO
361                      || stp->dictype == DIC_HIRAGANA
362#endif
363                     ) {
364                    autodicError();
365                  }
366                  else {
367                    mountError(stp->name);
368                  }
369                }
370              }
371            }
372          }
373          else {
374            stp->dicflag = DIC_MOUNTED;
375            dicMesg(kodmesg, stp->name);
376          }
377        }
378      }
379    }
380    ret = 0;
381    goto return_ret;
382  }
383  ret = -1;
384 return_ret:
385#ifdef WIN
386  free(buf);
387#endif
388  return ret;
389}
390/*
391 * ¤«¤Ê´Á»úÊÑ´¹¤Î¤¿¤á¤Î¸å½èÍý
392 *
393 * ¡¦¥·¥¹¥Æ¥à¼­½ñ¡¢Éô¼óÍѼ­½ñ¡¢¥æ¡¼¥¶¼­½ñ¤ò¥¢¥ó¥Þ¥¦¥ó¥È¤¹¤ë
394 * ¡¦RkwFinalize¤ò¸Æ¤Ö
395 *
396 * °ú¤­¿ô	¤Ê¤·
397 * Ìá¤êÃÍ	¤Ê¤·
398 */
399int KanjiFin(void)
400{
401  struct dicname *dp, *np;
402  int con;
403
404  for (dp = kanjidicnames ; dp ;) {
405    if (dp->dictype == DIC_BUSHU) {
406      con = defaultBushuContext;
407    }
408    else {
409      con = defaultContext;
410    }
411    if (dp->dicflag == DIC_MOUNTED) {
412      if (RkwUnmountDic(con, dp->name) == -1) {
413#ifdef WIN
414	char *buf = malloc(128);
415	if (buf) {
416	  sprintf(buf, "%s \244\362\245\242\245\363\245\336\245\246\245\363"
417	  "\245\310\244\307\244\255\244\336\244\273\244\363\244\307\244\267"
418	  "\244\277", dp->name);
419	  addWarningMesg(buf);
420	  free(buf);
421	}
422#else
423        char buf[256];
424	sprintf(buf, "%s ¤ò¥¢¥ó¥Þ¥¦¥ó¥È¤Ç¤­¤Þ¤»¤ó¤Ç¤·¤¿¡£", dp->name);
425	addWarningMesg(buf);
426#endif
427      }
428    }
429    np = dp->next;
430    free(dp->name);
431    free(dp);
432    dp = np;
433  }
434  kanjidicnames = (struct dicname *)0;
435
436  /* ϢʸÀá¥é¥¤¥Ö¥é¥ê¤ò½ªÎ»¤µ¤»¤ë */
437  RkwFinalize();
438
439  return(0);
440}
441
442static tanContext
443newTanContext(int majo, int mino)
444{
445  tanContext tan;
446
447  tan = (tanContext)malloc(sizeof(tanContextRec));
448  if (tan) {
449    bzero(tan, sizeof(tanContextRec));
450    tan->id = TAN_CONTEXT;
451    tan->majorMode = majo;
452    tan->minorMode = mino;
453    tan->left = tan->right = (tanContext)0;
454    tan->next = (mode_context)0;
455    tan->curMode = &tankouho_mode;
456  }
457  return tan;
458}
459
460void
461freeTanContext(tanContext tan)
462{
463  if (tan->kanji) free(tan->kanji);
464  if (tan->yomi) free(tan->yomi);
465  if (tan->roma) free(tan->roma);
466  if (tan->kAttr) free(tan->kAttr);
467  if (tan->rAttr) free(tan->rAttr);
468  free(tan);
469}
470
471static WCHAR_T *
472DUpwstr(WCHAR_T *w, int l)
473{
474  WCHAR_T *res;
475
476  res = (WCHAR_T *)malloc((l + 1) * sizeof(WCHAR_T));
477  if (res) {
478    WStrncpy(res, w, l);
479    res[l] = (WCHAR_T)0;
480  }
481  return res;
482}
483
484static BYTE *
485DUpattr(BYTE *a, int l)
486{
487  BYTE *res;
488
489  res = (BYTE *)malloc((l + 1) * sizeof(BYTE));
490  if (res) {
491    bcopy(a, res, (l + 1) * sizeof(BYTE));
492  }
493  return res;
494}
495
496static void
497copyYomiinfo2Tan(yomiContext yc, tanContext tan)
498{
499  tan->next = yc->next;
500  tan->prevMode = yc->prevMode;
501  tan->generalFlags = yc->generalFlags;
502  tan->savedFlags = yc->savedFlags;
503
504  tan->romdic = yc->romdic;
505  tan->myMinorMode = yc->myMinorMode;
506  tan->myEmptyMode = yc->myEmptyMode;
507  tan->savedMinorMode = yc->savedMinorMode;
508  tan->allowedChars = yc->allowedChars;
509  tan->henkanInhibition = yc->henkanInhibition;
510}
511
512static void
513copyTaninfo2Yomi(tanContext tan, yomiContext yc)
514{
515  /* next ¤È prevMode ¤Ï´û¤ËÀßÄêºÑ¤ß */
516  yc->generalFlags = tan->generalFlags;
517  yc->savedFlags = tan->savedFlags;
518
519  yc->romdic = tan->romdic;
520  yc->myMinorMode = tan->myMinorMode;
521  yc->myEmptyMode = tan->myEmptyMode;
522  yc->savedMinorMode = tan->savedMinorMode;
523  yc->allowedChars = tan->allowedChars;
524  yc->henkanInhibition = tan->henkanInhibition;
525}
526
527extern yomiContext dupYomiContext (yomiContext);
528extern void setMode (uiContext, tanContext, int);
529
530extern void trimYomi (uiContext, int, int, int, int);
531
532/*
533  Á´Ê¸Àá¤ò tanContext ¤ËÊÑ´¹¤¹¤ë
534 */
535
536int
537doTanConvertTb(uiContext d, yomiContext yc)
538{
539  int cur = yc->curbun, i, len, ylen = 0, rlen = 0, ret = 0;
540  int scuryomi, ecuryomi, scurroma, ecurroma;
541  tanContext tan, prevLeft = yc->left, curtan = (tanContext)0;
542  BYTE *p, *q, *r;
543#ifndef WIN
544  WCHAR_T xxx[ROMEBUFSIZE];
545#else
546  WCHAR_T *xxx = (WCHAR_T *)malloc(sizeof(WCHAR_T) * ROMEBUFSIZE);
547  if (!xxx) {
548    return ret;
549  }
550#endif
551
552  yc->kouhoCount = 0;
553  scuryomi = ecuryomi = scurroma = ecurroma = 0;
554
555/*  jrKanjiError = "¥á¥â¥ê¤¬Â­¤ê¤Þ¤»¤ó"; */
556  jrKanjiError = "malloc (doTanBubunMuhenkan) \244\307\244\255\244\336\244\273"
557	"\244\363\244\307\244\267\244\277\241\243";
558                 /* malloc (doTanBubunMuhenkan) ¤Ç¤­¤Þ¤»¤ó¤Ç¤·¤¿ */
559  for (i = 0 ; i < yc->nbunsetsu ; i++) {
560    tan = newTanContext(yc->majorMode, CANNA_MODE_TankouhoMode);
561    if (tan) {
562      copyYomiinfo2Tan(yc, tan);
563      RkwGoTo(yc->context, i);
564      len = RkwGetKanji(yc->context, xxx, ROMEBUFSIZE);
565      if (len >= 0) {
566	tan->kanji = DUpwstr(xxx, len);
567	if (tan->kanji) {
568	  len = RkwGetYomi(yc->context, xxx, ROMEBUFSIZE);
569	  if (len >= 0) {
570	    tan->yomi = DUpwstr(xxx, len);
571	    if (tan->yomi) {
572	      tan->kAttr = DUpattr(yc->kAttr + ylen, len);
573	      if (tan->kAttr) {
574		r = yc->rAttr + rlen;
575		for (p = yc->kAttr + ylen, q = p + len ; p < q ; p++) {
576		  if (*p & SENTOU) {
577		    r++;
578		    while (!(*r & SENTOU)) {
579		      r++;
580		    }
581		  }
582		}
583		ylen += len;
584		len = r - yc->rAttr - rlen; /* ¥í¡¼¥Þ»ú¤ÎŤµ */
585		tan->roma = DUpwstr(yc->romaji_buffer + rlen, len);
586		if (tan->roma) {
587		  tan->rAttr = DUpattr(yc->rAttr + rlen, len);
588		  if (tan->rAttr) {
589		    rlen += len;
590		    /* ¤È¤ê¤¢¤¨¤ºº¸¤Ë¤Ä¤Ê¤²¤ë */
591		    tan->right = (tanContext)yc;
592		    tan->left = yc->left;
593		    if (yc->left) {
594		      yc->left->right = tan;
595		    }
596		    yc->left = tan;
597		    if (i == cur) {
598		      curtan = tan;
599		    }
600		    continue;
601		  }
602		  free(tan->roma);
603		}
604		free(tan->kAttr);
605	      }
606	      free(tan->yomi);
607	    }
608	  }
609	  else {
610	    makeRkError(d, KanjiInitError());
611	  }
612	  free(tan->kanji);
613	}
614      }else{
615	makeRkError(d, KanjiInitError());
616      }
617      freeTanContext(tan);
618    }
619    /* ¥¨¥é¡¼½èÍý¤ò¤¹¤ë */
620  procerror:
621    while ((tan = yc->left) != prevLeft) {
622      yc->left = tan->left;
623      freeTanContext(tan);
624    }
625    ret = -1;
626    goto return_ret;
627  }
628
629  if (chikujip(yc) && chikujiyomiremain(yc)) {
630    int rpos;
631    yomiContext lyc = dupYomiContext(yc);
632
633    if (!lyc) { /* ¥¨¥é¡¼½èÍý¤ò¤¹¤ë */
634      goto procerror;
635    }
636
637    if (yc->right) { /* Ã༡¤Î¾ì¹ç¤Ê¤¤¤Ï¤º¤À¤¬Ç°¤Î¤¿¤á */
638      yc->right->left = (tanContext)lyc;
639    }
640    lyc->right = yc->right;
641    yc->right = (tanContext)lyc;
642    lyc->left = (tanContext)yc;
643
644    kPos2rPos(lyc, 0, yc->cStartp, (int *)0, &rpos);
645    d->modec = (mode_context)lyc;
646    moveToChikujiYomiMode(d);
647    trimYomi(d, yc->cStartp, yc->kEndp, rpos, yc->rEndp);
648    d->modec = (mode_context)yc;
649    yc->status = lyc->status;
650    lyc->cStartp = lyc->cRStartp = lyc->ys = lyc->ye = 0;
651  }
652
653  RkwGoTo(yc->context, cur);
654  if (RkwEndBun(yc->context, cannaconf.Gakushu ? 1 : 0) == -1) {
655    jrKanjiError = "\244\253\244\312\264\301\273\372\312\321\264\271\244\316"
656	"\275\252\316\273\244\313\274\272\307\324\244\267\244\336\244\267"
657	"\244\277";
658                   /* ¤«¤Ê´Á»úÊÑ´¹¤Î½ªÎ»¤Ë¼ºÇÔ¤·¤Þ¤·¤¿ */
659    if (errno == EPIPE) {
660      jrKanjiPipeError();
661    }
662  }
663
664  d->modec = (mode_context)curtan;
665  setMode(d, curtan, 1);
666  makeKanjiStatusReturn(d, (yomiContext)curtan);
667
668  /* yc ¤ò¥ê¥ó¥¯¤«¤éÈ´¤¯ */
669  if (yc->left) {
670    yc->left->right = yc->right;
671  }
672  if (yc->right) {
673    yc->right->left = yc->left;
674  }
675  abandonContext(d, yc);
676  freeYomiContext(yc);
677
678 return_ret:
679#ifdef WIN
680  free(xxx);
681#endif
682
683  return ret;
684}
685
686static int
687doTanBubunMuhenkan(uiContext d, yomiContext yc)
688{
689  int cur = yc->curbun, i, len, ylen = 0, rlen = 0, ret = 0;
690  int scuryomi, ecuryomi, scurroma, ecurroma;
691  tanContext tan, prevLeft = yc->left;
692  BYTE *p, *q, *r;
693#ifndef WIN
694  WCHAR_T xxx[ROMEBUFSIZE];
695#else
696  WCHAR_T *xxx = (WCHAR_T *)malloc(sizeof(WCHAR_T) * ROMEBUFSIZE);
697  if (!xxx) {
698    return ret;
699  }
700#endif
701
702  yc->kouhoCount = 0;
703  scuryomi = ecuryomi = scurroma = ecurroma = 0;
704
705/*  jrKanjiError = "¥á¥â¥ê¤¬Â­¤ê¤Þ¤»¤ó"; */
706  jrKanjiError = "malloc (doTanBubunMuhenkan) \244\307\244\255\244\336\244\273"
707	"\244\363\244\307\244\267\244\277\241\243";
708                 /* malloc (doTanBubunMuhenkan) ¤Ç¤­¤Þ¤»¤ó¤Ç¤·¤¿ */
709  for (i = 0 ; i < yc->nbunsetsu ; i++) {
710    tan = (tanContext)0;
711    if (i == cur ||
712	(tan = newTanContext(yc->majorMode, CANNA_MODE_TankouhoMode))) {
713      if (tan) {
714	copyYomiinfo2Tan(yc, tan);
715      }
716      RkwGoTo(yc->context, i);
717      len = RkwGetKanji(yc->context, xxx, ROMEBUFSIZE);
718      if (len >= 0) {
719	if (!tan || (tan->kanji = DUpwstr(xxx, len))) {
720	  len = RkwGetYomi(yc->context, xxx, ROMEBUFSIZE);
721	  if (len >= 0) {
722	    if (!tan || (tan->yomi = DUpwstr(xxx, len))) {
723	      if (!tan || (tan->kAttr = DUpattr(yc->kAttr + ylen, len))) {
724		r = yc->rAttr + rlen;
725		for (p = yc->kAttr + ylen, q = p + len ; p < q ; p++) {
726		  if (*p & SENTOU) {
727		    r++;
728		    while (!(*r & SENTOU)) {
729		      r++;
730		    }
731		  }
732		}
733		if (i == cur) {
734		  scuryomi = ylen;
735		  ecuryomi = ylen + len;
736		}
737		ylen += len;
738		len = r - yc->rAttr - rlen; /* ¥í¡¼¥Þ»ú¤ÎŤµ */
739		if (!tan ||
740		    (tan->roma = DUpwstr(yc->romaji_buffer + rlen, len))) {
741		  if (!tan || (tan->rAttr = DUpattr(yc->rAttr + rlen, len))) {
742		    if (i == cur) {
743		      scurroma = rlen;
744		      ecurroma = rlen + len;
745		    }
746		    rlen += len;
747		    if (tan) {
748		      if (i != cur) {
749			/* ¤È¤ê¤¢¤¨¤ºº¸¤Ë¤Ä¤Ê¤²¤ë */
750			tan->right = (tanContext)yc;
751			tan->left = yc->left;
752			if (yc->left) {
753			  yc->left->right = tan;
754			}
755			yc->left = tan;
756		      }
757#if defined(DEBUG) && !defined(WIN)
758		      {
759			char yyy[ROMEBUFSIZE];
760			WCstombs(yyy, tan->kanji, ROMEBUFSIZE);
761			printf("%s/", yyy);
762			WCstombs(yyy, tan->yomi, ROMEBUFSIZE);
763			printf("%s/", yyy);
764			WCstombs(yyy, tan->roma, ROMEBUFSIZE);
765			printf("%s\n", yyy);
766		      }
767#endif
768		    }
769		    continue;
770		  }
771		  if (tan) free(tan->roma);
772		}
773		if (tan) free(tan->kAttr);
774	      }
775	      if (tan) free(tan->yomi);
776	    }
777	  }
778	  else {
779	    makeRkError(d, KanjiInitError());
780	  }
781	  if (tan) free(tan->kanji);
782	}
783      }else{
784	makeRkError(d, KanjiInitError());
785      }
786      if (tan) freeTanContext(tan);
787    }
788    /* ¥¨¥é¡¼½èÍý¤ò¤¹¤ë */
789    while ((tan = yc->left) != prevLeft) {
790      yc->left = tan->left;
791      freeTanContext(tan);
792    }
793    ret = -1;
794    goto return_ret;
795  }
796
797  if (chikujip(yc) && chikujiyomiremain(yc)) {
798    int rpos;
799    yomiContext lyc = dupYomiContext(yc);
800
801    if (!lyc) { /* ¥¨¥é¡¼½èÍý¤ò¤¹¤ë */
802      while ((tan = yc->left) != prevLeft) {
803	yc->left = tan->left;
804	freeTanContext(tan);
805      }
806      ret = -1;
807      goto return_ret;
808    }
809
810    if (yc->right) { /* ¤Ê¤¤¤Ï¤º */
811      yc->right->left = (tanContext)lyc;
812    }
813    lyc->right = yc->right;
814    yc->right = (tanContext)lyc;
815    lyc->left = (tanContext)yc;
816
817    kPos2rPos(lyc, 0, yc->cStartp, (int *)0, &rpos);
818    d->modec = (mode_context)lyc;
819    moveToChikujiYomiMode(d);
820    trimYomi(d, yc->cStartp, yc->kEndp, rpos, yc->rEndp);
821    d->modec = (mode_context)yc;
822    yc->status = lyc->status;
823    lyc->cStartp = lyc->cRStartp = lyc->ys = lyc->ye = 0;
824  }
825
826  if (cur + 1 < yc->nbunsetsu) { /* yc ¤¬ºÇ¸å¤¸¤ã¤Ê¤¤¾ì¹ç */
827    int n = yc->nbunsetsu - cur - 1;
828    tan = yc->left;
829    tan->right = yc->right;
830    if (yc->right) {
831      yc->right->left = tan;
832    }
833    for (i = 1 ; i < n ; i++) { /* yomi ¤Î right ¤ËÍè¤ë¤Ù¤­ tan ¤òÆÀ¤¿¤¤ */
834      tan = tan->left;
835    }
836    if (tan->left) {
837      tan->left->right = (tanContext)yc;
838    }
839    yc->left = tan->left;
840    tan->left = (tanContext)yc;
841    yc->right = tan;
842  }
843  RkwGoTo(yc->context, cur);
844  if (RkwEndBun(yc->context, cannaconf.Gakushu ? 1 : 0) == -1) {
845    jrKanjiError = "\244\253\244\312\264\301\273\372\312\321\264\271\244\316"
846	"\275\252\316\273\244\313\274\272\307\324\244\267\244\336\244\267"
847	"\244\277";
848                   /* ¤«¤Ê´Á»úÊÑ´¹¤Î½ªÎ»¤Ë¼ºÇÔ¤·¤Þ¤·¤¿ */
849    if (errno == EPIPE) {
850      jrKanjiPipeError();
851    }
852  }
853
854  trimYomi(d, scuryomi, ecuryomi, scurroma, ecurroma);
855
856  yc->cRStartp = yc->rCurs = yc->rStartp = 0;
857  yc->cStartp = yc->kCurs = yc->kRStartp =
858    yc->ys = yc->ye = 0;
859  yc->status &= CHIKUJI_NULL_STATUS;
860  /* ¤Ê¤ó¤ÈÃ༡¤Ç¤Ê¤¯¤Ê¤ë */
861  if (chikujip(yc)) {
862    yc->generalFlags &= ~CANNA_YOMI_CHIKUJI_MODE;
863    yc->generalFlags |= CANNA_YOMI_BASE_CHIKUJI;
864  }
865
866  d->current_mode = yc->curMode = &yomi_mode;
867  yc->minorMode = getBaseMode(yc);
868
869  /* Á´Éô̵ÊÑ´¹¤Ë¤¹¤ë */
870  yc->nbunsetsu = 0;
871
872  /* ñ¸õÊä¾õÂÖ¤«¤éÆɤߤËÌá¤ë¤È¤­¤Ë¤Ï̵¾ò·ï¤Ëmark¤òÀèƬ¤ËÌ᤹ */
873  yc->cmark = yc->pmark = 0;
874
875  abandonContext(d, yc);
876  ret = 0;
877
878 return_ret:
879#ifdef WIN
880  free(xxx);
881#endif
882
883  return ret;
884}
885
886extern void restoreChikujiIfBaseChikuji (yomiContext);
887extern void ReCheckStartp (yomiContext);
888extern void fitmarks (yomiContext);
889
890int YomiBubunKakutei (uiContext);
891
892int
893YomiBubunKakutei(uiContext d)
894{
895  yomiContext yc = (yomiContext)d->modec;
896  tanContext tan;
897  int len;
898
899  if (yc->id != YOMI_CONTEXT) {
900    /* ¤¢¤êÆÀ¤Ê¤¤¤Î¤Ç¤Ï? */
901  }
902  else /* if (yc->left) */ {
903    /* yomiContext ¤Çºï½ü¤¹¤ëÉôʬ¤ò¤Þ¤º tanContext ¤ËÀÚ¤ê½Ð¤·¡¢yc ¤Îº¸
904       ¦¤ËÁÞÆþ¤¹¤ë¡£¼¡¤Ë yc ¤Îº¸¤ò¤Ð¤Ã¤µ¤ê¤È³ÎÄꤹ¤ë¡£
905       Á´¤Æ¤³¤Î¥í¥¸¥Ã¥¯¤Ç¤ä¤í¤¦¤«¤·¤é¡£
906       */
907    tan = newTanContext(yc->majorMode, CANNA_MODE_TankouhoMode);
908    if (tan) {
909      copyYomiinfo2Tan(yc, tan);
910      /* ¤«¤Ê¤ò¥³¥Ô¡¼¤¹¤ë */
911      tan->kanji = DUpwstr(yc->kana_buffer, yc->kCurs);
912      if (tan->kanji) {
913	/* ¤³¤³¤âƱ¤¸¤«¤Ê¤ò¥³¥Ô¡¼¤¹¤ë */
914	tan->yomi = DUpwstr(yc->kana_buffer, yc->kCurs);
915	if (tan->yomi) {
916	  tan->kAttr = DUpattr(yc->kAttr, yc->kCurs);
917	  if (tan->kAttr) {
918	    tan->roma = DUpwstr(yc->romaji_buffer, yc->rCurs);
919	    if (tan->roma) {
920	      tan->rAttr = DUpattr(yc->rAttr, yc->rCurs);
921	      if (tan->rAttr) {
922		WCHAR_T *sb = d->buffer_return, *eb = sb + d->n_buffer;
923
924		tan->left = yc->left;
925		tan->right = (tanContext)yc;
926		if (yc->left) {
927		  yc->left->right = tan;
928		}
929		yc->left = tan;
930		while (tan->left) {
931		  tan = tan->left;
932		}
933
934		trimYomi(d, yc->kCurs, yc->kEndp, yc->rCurs, yc->rEndp);
935
936		len = doKakutei(d, tan, (tanContext)yc, sb, eb,
937				(yomiContext *)0);
938		d->modec = (mode_context)yc;
939		yc->left = (tanContext)0;
940		goto done;
941	      }
942	      free(tan->roma);
943	    }
944	    free(tan->kAttr);
945	  }
946	  free(tan->yomi);
947	}
948	free(tan->kanji);
949      }
950      free(tan); /* not freeTanContext(tan); */
951    }
952  }
953#if 0
954  /* ËÜÍ褳¤³¤Î½èÍý¤ò¤¤¤ì¤¿Êý¤¬¸úΨ¤¬Îɤ¤¤È»×¤ï¤ì¤ë¤¬¡¢ÆɤߤΰìÉô¤ò³Î
955  Äꤵ¤»¤Æ¡¢¤·¤«¤â¥í¡¼¥Þ»ú¾ðÊó¤Ê¤É¤â¤¤¤ì¤ë¤Î¤ÏÌÌÅݤʤΤǤ¢¤È¤Þ¤ï¤·¤È¤¹¤ë */
956  else {
957
958    /* ³ÎÄꤵ¤»¤ë¡£
959       ¼¡¤Ë trim ¤¹¤ë*/
960  }
961#endif
962
963 done:
964  if (!yc->kEndp) {
965    if (yc->savedFlags & CANNA_YOMI_MODE_SAVED) {
966      restoreFlags(yc);
967    }
968    if (yc->right) {
969      removeCurrentBunsetsu(d, (tanContext)yc);
970      yc = (yomiContext)0;
971    }
972    else {
973      /* ̤³ÎÄêʸ»úÎó¤¬Á´¤¯¤Ê¤¯¤Ê¤Ã¤¿¤Î¤Ê¤é¡¢¦Õ¥â¡¼¥É¤ËÁ«°Ü¤¹¤ë */
974      restoreChikujiIfBaseChikuji(yc);
975      d->current_mode = yc->curMode = yc->myEmptyMode;
976      d->kanji_status_return->info |= KanjiEmptyInfo;
977    }
978    currentModeInfo(d);
979  }
980  else {
981    if (yc->kCurs != yc->kRStartp) {
982      ReCheckStartp(yc);
983    }
984  }
985
986  if (yc) {
987    fitmarks(yc);
988  }
989
990  makeYomiReturnStruct(d);
991  return len;
992}
993
994yomiContext
995newFilledYomiContext(mode_context next, KanjiMode prev)
996{
997  yomiContext yc;
998
999  yc = newYomiContext((WCHAR_T *)NULL, 0, /* ·ë²Ì¤Ï³ÊǼ¤·¤Ê¤¤ */
1000		      CANNA_NOTHING_RESTRICTED,
1001		      (int)!CANNA_YOMI_CHGMODE_INHIBITTED,
1002		      (int)!CANNA_YOMI_END_IF_KAKUTEI,
1003		      CANNA_YOMI_INHIBIT_NONE);
1004  if (yc) {
1005    yc->majorMode = yc->minorMode = CANNA_MODE_HenkanMode;
1006    yc->curMode = &yomi_mode;
1007    yc->myEmptyMode = &empty_mode;
1008    yc->romdic = romajidic;
1009    yc->next = next;
1010    yc->prevMode = prev;
1011  }
1012  return yc;
1013}
1014
1015#ifdef DO_MERGE
1016static
1017yomiContext
1018mergeYomiContext(yomiContext yc)
1019{
1020  yomiContext res, a, b;
1021
1022  res = yc;
1023  while (res->left && res->left->id == YOMI_CONTEXT) {
1024    res = (yomiContext)res->left;
1025  }
1026  for (a = (yomiContext)res->right ; a && a->id == YOMI_CONTEXT ; a = b) {
1027    b = (yomiContext)a->right;
1028    appendYomi2Yomi(a, res);
1029    if (yc == a) {
1030      res->kCurs = res->kRStartp = res->kEndp;
1031      res->rCurs = res->rStartp = res->rEndp;
1032      res->cmark = res->kCurs;
1033    }
1034    res->right = a->right;
1035    if (res->right) {
1036      res->right->left = (tanContext)res;
1037    }
1038    /* yc->context ¤Î close ¤Ï¤¤¤é¤Ê¤¤¤Î¤«¤Ê¤¢¡£1996.10.30 º£ */
1039    freeYomiContext(a);
1040  }
1041  return res;
1042}
1043#endif
1044
1045/*
1046  tanContext ¤ò yomiContext ¤Ë¤·¤Æ¡¢ÆɤßÆþÎϾõÂ֤ˤ¹¤ë
1047
1048   0          ¼ºÇÔ
1049   otherwise  ¤¢¤¿¤é¤·¤¤Æɤߥ³¥ó¥Æ¥­¥¹¥È¤¬ÊÖ¤ë
1050
1051 */
1052
1053static yomiContext
1054tanbunUnconvert(uiContext d, tanContext tan)
1055{
1056  yomiContext yc;
1057
1058  yc = newFilledYomiContext(tan->next, tan->prevMode);
1059  if (yc) {
1060    extern KanjiModeRec yomi_mode, empty_mode;
1061
1062    appendTan2Yomi(tan, yc);
1063    copyTaninfo2Yomi(tan, yc);
1064    yc->right = tan->right;
1065    yc->left = tan->left;
1066    if (yc->myMinorMode) {
1067      yc->minorMode = yc->myMinorMode;
1068    }
1069
1070    if (chikujip(yc)) { /* Ã༡¤Ë¤Ï¤·¤Ê¤¤ */
1071      yc->generalFlags &= ~CANNA_YOMI_CHIKUJI_MODE;
1072      yc->generalFlags |= CANNA_YOMI_BASE_CHIKUJI;
1073    }
1074
1075    if (yc->left) {
1076      yc->left->right = (tanContext)yc;
1077    }
1078    if (yc->right) {
1079      yc->right->left = (tanContext)yc;
1080    }
1081    freeTanContext(tan);
1082#ifdef DO_MERGE /* ÄêµÁ¤·¤Æ¤¤¤Ê¤¤ */
1083    yc = mergeYomiContext(yc);
1084#endif
1085    d->current_mode = yc->curMode;
1086    d->modec = (mode_context)yc;
1087    return yc;
1088  }
1089  jrKanjiError = "\245\341\245\342\245\352\244\254\302\255\244\352\244\336"
1090	"\244\273\244\363";
1091                 /* ¥á¥â¥ê¤¬Â­¤ê¤Þ¤»¤ó */
1092  return (yomiContext)0;
1093}
1094
1095static int
1096TbBubunMuhenkan(uiContext d)
1097{
1098  tanContext tan = (tanContext)d->modec;
1099  yomiContext yc;
1100
1101  yc = tanbunUnconvert(d, tan);
1102  if (yc) {
1103    currentModeInfo(d);
1104    makeKanjiStatusReturn(d, yc);
1105    return 0;
1106  }
1107  makeGLineMessageFromString(d, jrKanjiError);
1108  return NothingChangedWithBeep(d);
1109}
1110
1111/*
1112  TanBubunMuhenkan -- ÊÑ´¹Ãæ¤Îʸ»úÎó¤òʸÀáËè¤Ëʬ³ä¤¹¤ë¡£
1113
1114    ¤½¤ÎºÝ¡¢Æɤߤä¥í¡¼¥Þ»ú¤âʬ³ä¤¹¤ë
1115 */
1116
1117int
1118TanBubunMuhenkan(uiContext d)
1119{
1120  yomiContext yc = (yomiContext)d->modec;
1121
1122  if (yc->id != YOMI_CONTEXT) {
1123    return TbBubunMuhenkan(d);
1124  }
1125
1126  if (!yc->right && !yc->left && yc->nbunsetsu == 1) {
1127    return TanMuhenkan(d);
1128  }
1129
1130  if (doTanBubunMuhenkan(d, yc) < 0) {
1131    makeGLineMessageFromString(d, jrKanjiError);
1132    return TanMuhenkan(d);
1133  }
1134  makeYomiReturnStruct(d);
1135  currentModeInfo(d);
1136  return 0;
1137}
1138
1139int
1140prepareHenkanMode(uiContext d)
1141{
1142  yomiContext yc = (yomiContext)d->modec;
1143
1144  if (confirmContext(d, yc) < 0) {
1145    return 0;
1146  }
1147  d->current_mode = yc->curMode = &tankouho_mode;
1148
1149  return 1;
1150}
1151
1152int doHenkan(uiContext d, int len, WCHAR_T *kanji)
1153{
1154  /* ¤è¤ß¤ò´Á»ú¤ËÊÑ´¹¤¹¤ë */
1155  if(doYomiHenkan(d, len, kanji) == NG) {
1156    return -1;
1157  }
1158
1159  /* kanji_status_return¤òºî¤ë */
1160  makeKanjiStatusReturn(d, (yomiContext)d->modec);
1161  return 0;
1162}
1163
1164
1165/*
1166 * ¤«¤Ê´Á»úÊÑ´¹¤ò¹Ô¤¦
1167 * ¡¦d->yomi_buffer¤Ë¤è¤ß¤ò¼è¤ê½Ð¤·¡¢RkwBgnBun¤ò¸Æ¤ó¤Ç¤«¤Ê´Á»úÊÑ´¹¤ò³«»Ï¤¹¤ë
1168 * ¡¦¥«¥ì¥ó¥ÈʸÀá¤òÀèƬʸÀá¤Ë¤·¤Æ¡¢¥¨¥³¡¼Ê¸»úÎó¤òºî¤ë
1169 *
1170 * °ú¤­¿ô	uiContext
1171 *		len       len ¤¬»ØÄꤵ¤ì¤Æ¤¤¤¿¤éʸÀáŤò¤½¤ÎŤµ¤Ë¤¹¤ë¡£
1172 *		kanji	  kanji ¤¬»ØÄꤵ¤ì¤Æ¤¤¤¿¤éñʸÀáÊÑ´¹¤·¤Æ¡¢
1173 *			  ¥«¥ì¥ó¥È¸õÊä¤ò kanji ¤Ç¼¨¤µ¤ì¤¿¸õÊä¤Ë¹ç¤ï¤»¤ë¡£
1174 * Ìá¤êÃÍ	Àµ¾ï½ªÎ»»þ 0	°Û¾ï½ªÎ»»þ -1
1175 */
1176static int
1177doYomiHenkan(uiContext d, int len, WCHAR_T *kanji)
1178{
1179  unsigned int mode;
1180  yomiContext yc = (yomiContext)d->modec;
1181  extern int defaultContext;
1182
1183#if defined(DEBUG) && !defined(WIN)
1184  if (iroha_debug) {
1185/*    printf("yomi     => "); Wprintf(hc->yomi_buffer); putchar('\n');*/
1186    printf("yomi len => %d\n", hc->yomilen);
1187  }
1188#endif
1189
1190  /* ϢʸÀáÊÑ´¹¤ò³«»Ï¤¹¤ë *//* ¼­½ñ¤Ë¤Ê¤¤ ¥«¥¿¥«¥Ê ¤Ò¤é¤¬¤Ê ¤òÉղ乤ë */
1191  mode = 0;
1192  mode = (RK_XFER<<RK_XFERBITS) | RK_KFER;
1193  if (kanji) {
1194    mode |= RK_HENKANMODE(RK_TANBUN |
1195			  RK_MAKE_WORD |
1196			  RK_MAKE_EISUUJI |
1197			  RK_MAKE_KANSUUJI) << (2 * RK_XFERBITS);
1198  }
1199
1200  if (confirmContext(d, yc) < 0) {
1201    return NG;
1202  }
1203
1204#ifdef MEASURE_TIME
1205  {
1206    struct tms timebuf;
1207    long RkTime, times();
1208
1209    RkTime = times(&timebuf);
1210#endif /* MEASURE_TIME */
1211
1212    if ((yc->nbunsetsu =
1213	 RkwBgnBun(yc->context, yc->kana_buffer, yc->kEndp, mode)) == -1) {
1214      yc->nbunsetsu = 0;
1215      return kanakanError(d);
1216    }
1217
1218    if (len > 0 && (yc->nbunsetsu = RkwResize(yc->context, len)) == -1) {
1219      RkwEndBun(yc->context, 0);
1220      yc->nbunsetsu = 0;
1221      return kanakanError(d);
1222    }
1223
1224    if (kanji) {
1225      /* kanji ¤¬»ØÄꤵ¤ì¤Æ¤¤¤¿¤é¡¢Æ±¤¸¸õÊ䤬¤Ç¤ë¤Þ¤Ç RkwNext ¤ò¤¹¤ë */
1226      int i, n;
1227
1228      n = RkwGetKanjiList(yc->context, d->genbuf, ROMEBUFSIZE);
1229      if (n < 0) {
1230	return kanakanError(d);
1231      }
1232      for (i = 0 ; i < n ; i++) {
1233	RkwXfer(yc->context, i);
1234	len = RkwGetKanji(yc->context, d->genbuf, ROMEBUFSIZE);
1235	if (len < 0) {
1236	  return kanakanError(d);
1237	}
1238	d->genbuf[len] = (WCHAR_T)'\0';
1239	if (!WStrcmp(kanji, d->genbuf)) {
1240	  break;
1241	}
1242      }
1243      if (i == n) {
1244	RkwXfer(yc->context, 0);
1245      }
1246    }
1247
1248#ifdef MEASURE_TIME
1249    yc->rktime = times(&timebuf);
1250    yc->rktime -= RkTime;
1251  }
1252#endif /* MEASURE_TIME */
1253
1254  /* ¥«¥ì¥ó¥ÈʸÀá¤ÏÀèƬʸÀá */
1255  yc->curbun = 0;
1256
1257  return(0);
1258}
1259
1260int
1261TanNop(uiContext d)
1262{
1263  yomiContext yc = (yomiContext)d->modec;
1264
1265  /* currentModeInfo ¤Ç¥â¡¼¥É¾ðÊó¤¬É¬¤ºÊÖ¤ë¤è¤¦¤Ë¥À¥ß¡¼¤Î¥â¡¼¥É¤òÆþ¤ì¤Æ¤ª¤¯ */
1266  d->majorMode = d->minorMode = CANNA_MODE_AlphaMode;
1267  currentModeInfo(d);
1268
1269  makeKanjiStatusReturn(d, yc);
1270  return 0;
1271}
1272
1273static int
1274doGoTo(uiContext d, yomiContext yc)
1275{
1276  if (RkwGoTo(yc->context, yc->curbun) == -1) {
1277    return makeRkError(d, "\312\270\300\341\244\316\260\334\306\260\244\313"
1278	"\274\272\307\324\244\267\244\336\244\267\244\277");
1279                          /* ʸÀá¤Î°ÜÆ°¤Ë¼ºÇÔ¤·¤Þ¤·¤¿ */
1280  }
1281  yc->status |= CHIKUJI_OVERWRAP;
1282
1283  /* kanji_status_return¤òºî¤ë */
1284  makeKanjiStatusReturn(d, yc);
1285  return 0;
1286}
1287
1288/*
1289 * ¼¡Ê¸Àá¤Ë°ÜÆ°¤¹¤ë
1290 *
1291 * °ú¤­¿ô	uiContext
1292 * Ìá¤êÃÍ	Àµ¾ï½ªÎ»»þ 0	°Û¾ï½ªÎ»»þ -1
1293 */
1294
1295int
1296TanForwardBunsetsu(uiContext d)
1297{
1298  yomiContext yc = (yomiContext)d->modec;
1299
1300  if (yc->id != YOMI_CONTEXT) {
1301    return TbForward(d);
1302  }
1303
1304  yc->kouhoCount = 0;
1305  if (yc->curbun + 1 < yc->nbunsetsu) {
1306    yc->curbun++;
1307  }
1308  else if (yc->cStartp && yc->cStartp < yc->kEndp) { /* Ã༡¤ÎÆɤߤ¬±¦¤Ë¤¢¤ë */
1309    yc->kRStartp = yc->kCurs = yc->cStartp;
1310    yc->rStartp = yc->rCurs = yc->cRStartp;
1311    moveToChikujiYomiMode(d);
1312  }
1313  else if (yc->right) {
1314    return TbForward(d);
1315  }
1316  else if (cannaconf.kakuteiIfEndOfBunsetsu) {
1317    d->nbytes = TanKakutei(d);
1318    d->kanji_status_return->length
1319     = d->kanji_status_return->revPos
1320       = d->kanji_status_return->revLen = 0;
1321    return d->nbytes;
1322  }
1323  else if (!cannaconf.CursorWrap) {
1324    return NothingForGLine(d);
1325  }
1326  else if (yc->left) {
1327    return TbBeginningOfLine(d);
1328  }
1329  else {
1330    yc->curbun = 0;
1331  }
1332
1333  /* ¥«¥ì¥ó¥ÈʸÀá¤ò£±¤Ä±¦¤Ë°Ü¤¹ */
1334  /* ¥«¥ì¥ó¥ÈʸÀ᤬ºÇ±¦¤À¤Ã¤¿¤é¡¢
1335     ºÇº¸¤ò¥«¥ì¥ó¥ÈʸÀá¤Ë¤¹¤ë   */
1336  return doGoTo(d, yc);
1337}
1338
1339/*
1340 * Á°Ê¸Àá¤Ë°ÜÆ°¤¹¤ë
1341 *
1342 * °ú¤­¿ô	uiContext
1343 * Ìá¤êÃÍ	Àµ¾ï½ªÎ»»þ 0	°Û¾ï½ªÎ»»þ -1
1344 */
1345int
1346TanBackwardBunsetsu(uiContext d)
1347{
1348  yomiContext yc = (yomiContext)d->modec;
1349
1350  if (yc->id != YOMI_CONTEXT) {
1351    return TbBackward(d);
1352  }
1353
1354  yc->kouhoCount = 0;
1355  if (yc->curbun) {
1356    yc->curbun--;
1357  }
1358  else if (yc->left) {
1359    return TbBackward(d);
1360  }
1361  else if (!cannaconf.CursorWrap) {
1362    return NothingForGLine(d);
1363  }
1364  else if (yc->right) {
1365    return TbEndOfLine(d);
1366  }
1367  else if (yc->cStartp && yc->cStartp < yc->kEndp) { /* Ã༡¤ÎÆɤߤ¬±¦¤Ë¤¢¤ë */
1368    yc->kCurs = yc->kRStartp = yc->kEndp;
1369    yc->rCurs = yc->rStartp = yc->rEndp;
1370    moveToChikujiYomiMode(d);
1371  }
1372  else {
1373    yc->curbun = yc->nbunsetsu - 1;
1374  }
1375
1376  return doGoTo(d, yc);
1377}
1378
1379/*
1380 * ¼¡¸õÊä¤ò¥«¥ì¥ó¥È¸õÊä¤Ë¤¹¤ë
1381 *
1382 * °ú¤­¿ô	uiContext
1383 * Ìá¤êÃÍ	Àµ¾ï½ªÎ»»þ 0	°Û¾ï½ªÎ»»þ -1
1384 */
1385
1386static int
1387tanNextKouho(uiContext d, yomiContext yc)
1388{
1389#ifdef MEASURE_TIME
1390  struct tms timebuf;
1391  long time, times(;
1392
1393  time = times(&timebuf;
1394#endif /* MEASURE_TIME */
1395
1396  /* ¼¡¤Î¸õÊä¤ò¥«¥ì¥ó¥È¸õÊä¤È¤¹¤ë */
1397  if (RkwNext(yc->context) == -1) {
1398    makeRkError(d, "\245\253\245\354\245\363\245\310\270\365\312\344\244\362"
1399	"\274\350\244\352\275\320\244\273\244\336\244\273\244\363\244\307"
1400	"\244\267\244\277");
1401                   /* ¥«¥ì¥ó¥È¸õÊä¤ò¼è¤ê½Ð¤»¤Þ¤»¤ó¤Ç¤·¤¿ */
1402    return TanMuhenkan(d);
1403  }
1404
1405#ifdef MEASURE_TIME
1406  yc->rktime = times(&timebuf);
1407  yc->rktime -= proctime;
1408#endif /* MEASURE_TIME */
1409
1410  /* kanji_status_return¤òºî¤ë */
1411  makeKanjiStatusReturn(d, yc);
1412
1413#ifdef MEASURE_TIME
1414  yc->time = times(&timebuf;
1415  yc->proctime -= proctime;
1416#endif /* MEASURE_TIME */
1417
1418  return(0);
1419}
1420
1421/*
1422  tanbunHenkan -- ÊÑ´¹¤¹¤ë¡£
1423
1424    ¤ß¤½¤Ï¡¢kanji ¤Ç¼¨¤µ¤ì¤¿¸õÊä¤ÈƱ¤¸¸õÊ䤬½Ð¤ë¤Þ¤Ç RkwNext ¤ò¤¹¤ë¤³¤È
1425    ¤Ç¤¢¤ë¡£°ì¼þ¤·¤¿¤³¤È¤â¸¡½Ð¤·¤Ê¤±¤ì¤Ð¤Ê¤ë¤Þ¤¤¡£
1426 */
1427
1428static int
1429tanbunHenkan(uiContext d, yomiContext yc, WCHAR_T *kanji)
1430{
1431  if (!prepareHenkanMode(d)) {
1432    makeGLineMessageFromString(d, jrKanjiError);
1433    makeYomiReturnStruct(d);
1434    return 0;
1435  }
1436  yc->minorMode = CANNA_MODE_TankouhoMode;
1437  yc->kouhoCount = 1;
1438  if (doHenkan(d, 0, kanji) < 0) {
1439    makeGLineMessageFromString(d, jrKanjiError);
1440    makeYomiReturnStruct(d);
1441    return 0;
1442  }
1443  if (cannaconf.kouho_threshold > 0 &&
1444      yc->kouhoCount >= cannaconf.kouho_threshold) {
1445    return tanKouhoIchiran(d, 0);
1446  }
1447
1448  currentModeInfo(d);
1449  makeKanjiStatusReturn(d, yc);
1450  return 0;
1451}
1452
1453/*
1454  enterTanHenkanMode -- tanContext ¤ò yomiContext ¤Ë¤·¤ÆÊÑ´¹¤Î½àÈ÷¤ò¤¹¤ë
1455
1456 */
1457
1458static int
1459enterTanHenkanMode(uiContext d, int fnum)
1460{
1461  tanContext tan = (tanContext)d->modec;
1462  yomiContext yc;
1463  WCHAR_T *prevkanji;
1464
1465  prevkanji = tan->kanji;
1466  tan->kanji = (WCHAR_T *)0;
1467
1468  yc = tanbunUnconvert(d, tan);
1469  if (yc) {
1470    tanbunHenkan(d, yc, prevkanji);
1471    free(prevkanji);
1472
1473    /*¤³¤³¤Ç
1474      ñ¸õÊä¥â¡¼¥É¤Î·Á¤Ë¤¹¤ë
1475      */
1476
1477    d->more.todo = 1;
1478    d->more.ch = d->ch;
1479    d->more.fnum = fnum;
1480    return 0;
1481  }
1482  else { /* Æó½Å¥Õ¥ê¡¼¤ò¤·¤Ê¤¤¤¿¤á¶¯Ä´Åª¤Ë else ¤ò½ñ¤¯ */
1483    free(prevkanji);
1484  }
1485  makeGLineMessageFromString(d, jrKanjiError);
1486  return NothingChangedWithBeep(d);
1487}
1488
1489/*
1490 * ¸õÊä°ìÍ÷¹Ô¤òɽ¼¨¤¹¤ë
1491 *
1492 * ¡¦¸õÊä°ìÍ÷ɽ¼¨¤Î¤¿¤á¤Î¥Ç¡¼¥¿¤ò¥Æ¡¼¥Ö¥ë¤ËºîÀ®¤¹¤ë
1493 * ¡¦¸õÊä°ìÍ÷ɽ¼¨¹Ô¤¬¶¹¤¤¤È¤­¤Ï¡¢°ìÍ÷¤òɽ¼¨¤·¤Ê¤¤¤Ç¼¡¸õÊä¤ò¤½¤Î¾ì¤Ëɽ¼¨¤¹¤ë
1494 *
1495 * °ú¤­¿ô	uiContext
1496 * Ìá¤êÃÍ	Àµ¾ï½ªÎ»»þ 0	°Û¾ï½ªÎ»»þ -1
1497 */
1498
1499int TanKouhoIchiran(uiContext d)
1500{
1501  if (d->modec->id != YOMI_CONTEXT) {
1502    return enterTanHenkanMode(d, CANNA_FN_KouhoIchiran);
1503  }
1504  return tanKouhoIchiran(d, 1);
1505}
1506
1507int TanNextKouho(uiContext d)
1508{
1509  yomiContext yc = (yomiContext)d->modec;
1510
1511  if (yc->id != YOMI_CONTEXT) {
1512    return enterTanHenkanMode(d, CANNA_FN_Next);
1513  }
1514  yc->status |= CHIKUJI_OVERWRAP;
1515  yc->kouhoCount = 0;
1516  return tanNextKouho(d, yc);
1517}
1518
1519/*
1520
1521  TanHenkan -- ²ó¿ô¤ò¥Á¥§¥Ã¥¯¤¹¤ë°Ê³°¤Ï TanNextKouho ¤È¤Û¤ÜƱ¤¸
1522
1523 */
1524static int TanHenkan (uiContext);
1525
1526static int
1527TanHenkan(uiContext d)
1528{
1529  yomiContext yc = (yomiContext)d->modec;
1530
1531  if (yc->id != YOMI_CONTEXT) {
1532    return enterTanHenkanMode(d, CANNA_FN_Henkan);
1533  }
1534
1535  if (cannaconf.kouho_threshold &&
1536      ++yc->kouhoCount >= cannaconf.kouho_threshold) {
1537    return TanKouhoIchiran(d);
1538  }
1539  else {
1540    return tanNextKouho(d, yc);
1541  }
1542}
1543
1544/*
1545 * Á°¸õÊä¤ò¥«¥ì¥ó¥È¸õÊä¤Ë¤¹¤ë
1546 *
1547 * °ú¤­¿ô	uiContext
1548 * Ìá¤êÃÍ	Àµ¾ï½ªÎ»»þ 0	°Û¾ï½ªÎ»»þ -1
1549 */
1550int TanPreviousKouho(uiContext d)
1551{
1552  yomiContext yc = (yomiContext)d->modec;
1553
1554  if (yc->id != YOMI_CONTEXT) {
1555    return enterTanHenkanMode(d, CANNA_FN_Prev);
1556  }
1557
1558  yc->status |= CHIKUJI_OVERWRAP;
1559  yc->kouhoCount = 0;
1560  /* Á°¤Î¸õÊä¤ò¥«¥ì¥ó¥È¸õÊä¤È¤¹¤ë */
1561  if (RkwPrev(yc->context) == -1) {
1562    makeRkError(d, "\245\253\245\354\245\363\245\310\270\365\312\344\244\362"
1563	"\274\350\244\352\275\320\244\273\244\336\244\273\244\363\244\307"
1564	"\244\267\244\277");
1565                   /* ¥«¥ì¥ó¥È¸õÊä¤ò¼è¤ê½Ð¤»¤Þ¤»¤ó¤Ç¤·¤¿ */
1566    return TanMuhenkan(d);
1567  }
1568
1569  /* kanji_status_return¤òºî¤ë */
1570  makeKanjiStatusReturn(d, yc);
1571
1572  return 0;
1573}
1574
1575/*
1576  tanJishuHenkan -- ÆÃÄê¤ÎʸÀá¤À¤±»ú¼ïÊÑ´¹¤¹¤ë
1577 */
1578
1579static int tanJishuHenkan (uiContext, int);
1580
1581static int
1582tanJishuHenkan(uiContext d, int fn)
1583{
1584  d->nbytes = TanBubunMuhenkan(d);
1585  d->more.todo = 1;
1586  d->more.ch = d->ch;
1587  d->more.fnum = fn;
1588  return d->nbytes;
1589}
1590
1591int TanHiragana(uiContext d)
1592{
1593  return tanJishuHenkan(d, CANNA_FN_Hiragana);
1594}
1595
1596int TanKatakana(uiContext d)
1597{
1598  return tanJishuHenkan(d, CANNA_FN_Katakana);
1599}
1600
1601int TanRomaji(uiContext d)
1602{
1603  return tanJishuHenkan(d, CANNA_FN_Romaji);
1604}
1605
1606int TanUpper(uiContext d)
1607{
1608  return tanJishuHenkan(d, CANNA_FN_ToUpper);
1609}
1610
1611int TanCapitalize(uiContext d)
1612{
1613  return tanJishuHenkan(d, CANNA_FN_Capitalize);
1614}
1615
1616int TanZenkaku(uiContext d)
1617{
1618  return tanJishuHenkan(d, CANNA_FN_Zenkaku);
1619}
1620
1621int TanHankaku(uiContext d)
1622{
1623  return tanJishuHenkan(d, CANNA_FN_Hankaku);
1624}
1625
1626int TanKanaRotate (uiContext);
1627
1628int TanKanaRotate(uiContext d)
1629{
1630  return tanJishuHenkan(d, CANNA_FN_KanaRotate);
1631}
1632
1633int TanRomajiRotate (uiContext);
1634
1635int TanRomajiRotate(uiContext d)
1636{
1637  return tanJishuHenkan(d, CANNA_FN_RomajiRotate);
1638}
1639
1640int TanCaseRotateForward (uiContext);
1641
1642int TanCaseRotateForward(uiContext d)
1643{
1644  return tanJishuHenkan(d, CANNA_FN_CaseRotate);
1645}
1646
1647static int
1648gotoBunsetsu(yomiContext yc, int n)
1649{
1650  /* ¥«¥ì¥ó¥ÈʸÀá¤ò°ÜÆ°¤¹¤ë */
1651  if (RkwGoTo(yc->context, n) == -1) {
1652    if (errno == EPIPE) {
1653      jrKanjiPipeError();
1654    }
1655    jrKanjiError = "\312\270\300\341\244\316\260\334\306\260\244\313\274\272"
1656	"\307\324\244\267\244\336\244\267\244\277";
1657                   /* ʸÀá¤Î°ÜÆ°¤Ë¼ºÇÔ¤·¤Þ¤·¤¿ */
1658    return NG;
1659  }
1660  yc->curbun = n;
1661  return 0;
1662}
1663
1664/*
1665 * ºÇº¸Ê¸Àá¤Ë°ÜÆ°¤¹¤ë
1666 *
1667 * °ú¤­¿ô	uiContext
1668 * Ìá¤êÃÍ	Àµ¾ï½ªÎ»»þ 0	°Û¾ï½ªÎ»»þ -1
1669 */
1670int
1671TanBeginningOfBunsetsu(uiContext d)
1672{
1673  yomiContext yc = (yomiContext)d->modec;
1674
1675  if (yc->id != YOMI_CONTEXT || yc->left) {
1676    return TbBeginningOfLine(d);
1677  }
1678  yc->kouhoCount = 0;
1679  if (gotoBunsetsu(yc, 0) < 0) {
1680    return NG;
1681  }
1682  makeKanjiStatusReturn(d, yc);
1683  return 0;
1684}
1685
1686/*
1687 * ºÇ±¦Ê¸Àá¤Ë°ÜÆ°¤¹¤ë
1688 *
1689 * °ú¤­¿ô	uiContext
1690 * Ìá¤êÃÍ	Àµ¾ï½ªÎ»»þ 0	°Û¾ï½ªÎ»»þ -1
1691 */
1692int
1693TanEndOfBunsetsu(uiContext d)
1694{
1695  yomiContext yc = (yomiContext)d->modec;
1696
1697  if (yc->id != YOMI_CONTEXT || yc->right) {
1698    return TbEndOfLine(d);
1699  }
1700
1701  yc->kouhoCount = 0;
1702  if (yc->cStartp && yc->cStartp < yc->kEndp) {
1703    yc->kRStartp = yc->kCurs = yc->kEndp;
1704    yc->rStartp = yc->rCurs = yc->rEndp;
1705    moveToChikujiYomiMode(d);
1706  }
1707  if (gotoBunsetsu(yc, yc->nbunsetsu - 1) < 0) {
1708    return NG;
1709  }
1710  yc->status |= CHIKUJI_OVERWRAP;
1711  makeKanjiStatusReturn(d, yc);
1712  return 0;
1713}
1714
1715int
1716tanMuhenkan(uiContext d, int kCurs)
1717{
1718  extern KanjiModeRec yomi_mode;
1719  yomiContext yc = (yomiContext)d->modec;
1720  int autoconvert = (yc->generalFlags & CANNA_YOMI_CHIKUJI_MODE);
1721
1722  if (RkwEndBun(yc->context, 0) == -1) {
1723    if (errno == EPIPE) {
1724      jrKanjiPipeError();
1725    }
1726  }
1727
1728  if (autoconvert) {
1729    yc->status &= CHIKUJI_NULL_STATUS;
1730    d->current_mode = yc->curMode = &cy_mode;
1731    yc->ys = yc->ye = yc->cStartp = yc->cRStartp = 0;
1732    yc->rCurs = yc->rStartp = yc->rEndp;
1733    yc->kCurs = yc->kRStartp = yc->kEndp;
1734    clearHenkanContext(yc);
1735  }
1736  else {
1737    d->current_mode = yc->curMode = &yomi_mode;
1738  }
1739  yc->minorMode = getBaseMode(yc);
1740
1741  if (kCurs >= 0) {
1742    int rpos;
1743
1744    kPos2rPos(yc, 0, kCurs, (int *)0, &rpos);
1745    yc->kCurs = yc->kRStartp = kCurs;
1746    yc->rCurs = yc->rStartp = rpos;
1747  }
1748
1749  /* Á´Éô̵ÊÑ´¹¤Ë¤¹¤ë */
1750  yc->nbunsetsu = 0;
1751
1752  /* ñ¸õÊä¾õÂÖ¤«¤éÆɤߤËÌá¤ë¤È¤­¤Ë¤Ï̵¾ò·ï¤Ëmark¤òÀèƬ¤ËÌ᤹ */
1753  yc->cmark = yc->pmark = 0;
1754
1755  abandonContext(d, yc);
1756
1757  return 0;
1758}
1759
1760/*
1761 * Á´¤Æ¤ÎʸÀá¤òÆɤߤËÌᤷ¡¢YomiInputMode ¤ËÌá¤ë
1762 *
1763 * °ú¤­¿ô	uiContext
1764 * Ìá¤êÃÍ	Àµ¾ï½ªÎ»»þ 0	°Û¾ï½ªÎ»»þ -1
1765 */
1766
1767int TanMuhenkan(uiContext d)
1768{
1769  yomiContext yc = (yomiContext)d->modec, newyc;
1770  tanContext tan;
1771
1772  if (yc->id != YOMI_CONTEXT || yc->left || yc->right) {
1773    tan = (tanContext)yc;
1774    while (tan->left) {
1775      tan = tan->left;
1776    }
1777    if (tan->id == YOMI_CONTEXT) {
1778      newyc = (yomiContext)tan;
1779    }
1780    else {
1781      newyc = newFilledYomiContext(yc->next, yc->prevMode);
1782      if (newyc) {
1783	tan->left = (tanContext)newyc;
1784	newyc->right = tan;
1785	newyc->generalFlags = tan->generalFlags;
1786	newyc->savedFlags = tan->savedFlags;
1787	if (chikujip(newyc)) {
1788	  newyc->curMode = &cy_mode;
1789	}
1790	newyc->minorMode = getBaseMode(newyc);
1791      }else{
1792	jrKanjiError = "\245\341\245\342\245\352\244\254\302\255\244\352"
1793	"\244\336\244\273\244\363";
1794                       /* ¥á¥â¥ê¤¬Â­¤ê¤Þ¤»¤ó */
1795	makeGLineMessageFromString(d, jrKanjiError);
1796	return NothingChangedWithBeep(d);
1797      }
1798    }
1799    d->modec = (mode_context)newyc;
1800    d->current_mode = newyc->curMode;
1801
1802    doMuhenkan(d, newyc);
1803
1804    if (newyc->generalFlags &
1805	(CANNA_YOMI_CHIKUJI_MODE | CANNA_YOMI_BASE_CHIKUJI)) {
1806      /* ¡Ö¿´¤ÏÃ༡¤À¤Ã¤¿¡×¤Î¤Ç¤¢¤ì¤Ð¡¢Ã༡¥â¡¼¥É¤ËÌ᤹ */
1807      newyc->generalFlags |= CANNA_YOMI_CHIKUJI_MODE;
1808      newyc->generalFlags &= ~CANNA_YOMI_BASE_CHIKUJI;
1809      newyc->minorMode = getBaseMode(newyc);
1810      d->current_mode = newyc->curMode = &cy_mode;
1811    }
1812
1813    makeYomiReturnStruct(d);
1814    currentModeInfo(d);
1815    return 0;
1816  }
1817
1818  if (yc->generalFlags &
1819      (CANNA_YOMI_CHIKUJI_MODE | CANNA_YOMI_BASE_CHIKUJI)) {
1820    /* ¡Ö¿´¤ÏÃ༡¤À¤Ã¤¿¡×¤Î¤Ç¤¢¤ì¤Ð¡¢Ã༡¥â¡¼¥É¤ËÌ᤹ */
1821    yc->generalFlags |= CANNA_YOMI_CHIKUJI_MODE;
1822    yc->generalFlags &= ~CANNA_YOMI_BASE_CHIKUJI;
1823    /* ¥Ì¥ë¥¹¥Æ¡¼¥¿¥¹¤ËÌ᤹ */
1824    yc->status &= CHIKUJI_NULL_STATUS;
1825  }
1826
1827  tanMuhenkan(d, -1);
1828  makeYomiReturnStruct(d);
1829  currentModeInfo(d);
1830  return 0;
1831}
1832
1833int
1834TanDeletePrevious(uiContext d)
1835{
1836  yomiContext yc = (yomiContext)d->modec;
1837  int i, j, l = -1, ret = 0;
1838#ifndef WIN
1839  WCHAR_T tmpbuf[ROMEBUFSIZE];
1840#else
1841  WCHAR_T *tmpbuf = (WCHAR_T *)malloc(sizeof(WCHAR_T) * ROMEBUFSIZE);
1842  if (!tmpbuf) {
1843    return ret;
1844  }
1845#endif
1846
1847  if (yc->id != YOMI_CONTEXT) {
1848    ret = TanMuhenkan(d);
1849    goto return_ret;
1850  }
1851
1852  if ((yc->generalFlags & CANNA_YOMI_CHIKUJI_MODE) &&
1853      !cannaconf.BackspaceBehavesAsQuit) {
1854    ret = ChikujiTanDeletePrevious(d);
1855    goto return_ret;
1856  }
1857  else {
1858    if (cannaconf.keepCursorPosition) {
1859      for (i = 0, l = 0; i <= yc->curbun; i++) {
1860	if (RkwGoTo(yc->context, i) == -1
1861	    || (j = RkwGetYomi(yc->context, tmpbuf, ROMEBUFSIZE)) == -1) {
1862	  l = -1;
1863	  break;
1864	}
1865	l += j;
1866      }
1867    }
1868    yc->status &= CHIKUJI_NULL_STATUS;
1869    tanMuhenkan(d, l);
1870    makeYomiReturnStruct(d);
1871    currentModeInfo(d);
1872    ret = 0;
1873  }
1874 return_ret:
1875#ifdef WIN
1876  free(tmpbuf);
1877#endif
1878  return ret;
1879}
1880
1881#if 0
1882/*
1883  doTanKakutei -- ³ÎÄꤵ¤»¤ëÆ°ºî¤ò¤¹¤ë
1884
1885  retval 0 -- ÌäÂê̵¤¯³ÎÄꤷ¤¿¡£
1886         1 -- ³ÎÄꤷ¤¿¤é¤Ê¤¯¤Ê¤Ã¤¿¡£
1887        -1 -- ¥¨¥é¡¼¡©
1888 */
1889
1890static
1891doTanKakutei(uiContext d, yomiContext yc)
1892{
1893  if ((yc->generalFlags & CANNA_YOMI_CHIKUJI_MODE) &&
1894      (yc->cStartp < yc->kEndp)) {
1895    (void)RomajiFlushYomi(d, (WCHAR_T *)0, 0);
1896  }
1897
1898  return 0;
1899}
1900#endif /* 0 */
1901
1902void
1903finishTanKakutei(uiContext d)
1904{
1905  yomiContext yc = (yomiContext)d->modec;
1906  int autoconvert = yc->generalFlags & CANNA_YOMI_CHIKUJI_MODE;
1907
1908#ifdef DO_RENGO_LEARNING
1909#define RENGOBUFSIZE 256
1910
1911  /* This will not be defined when WIN is defined.  So I don't care
1912     about the local array located below.  1996.6.5 kon */
1913
1914  if (RengoGakushu && hc->nbunsetsu > 1) { /* Ï¢¸ì³Ø½¬¤ò¤·¤è¤¦¤«¤Ê¤¡ */
1915    RkLex  lex[2][RENGOBUFSIZE];
1916    WCHAR_T yomi[2][RENGOBUFSIZE];
1917    WCHAR_T kanji[2][RENGOBUFSIZE];
1918    WCHAR_T word[1024], *w;
1919    unsigned char xxxx[ROMEBUFSIZE];
1920    int    nword[2], wlen;
1921
1922    *(w = word) = (WCHAR_T) '\0';
1923    wlen = 1024;
1924
1925    RkwGoTo(hc->context, 0);
1926    nword[0] = RkwGetLex(hc->context, lex[0], RENGOBUFSIZE);
1927    yomi[0][0] =
1928      (WCHAR_T) '\0'; /* yomi[current][0]¤Î¿¿ÍýÃÍ ¢á RkwGetYomi¤·¤¿¤« */
1929
1930    for (i = 1 ; i < hc->nbunsetsu ; i++) {
1931      int current, previous, mighter;
1932
1933      current = i % 2;
1934      previous = 1 - current;
1935
1936      nword[current] = 0;
1937      if ( !nword[previous] ) {
1938	nword[previous] = RkwGetLex(hc->context, lex[previous], RENGOBUFSIZE);
1939      }
1940      RkwRight(hc->context);
1941
1942      if (nword[previous] == 1) {
1943	nword[current] = RkwGetLex(hc->context, lex[current], RENGOBUFSIZE);
1944	yomi[current][0] = (WCHAR_T) '\0';
1945	if (((lex[previous][0].ylen <= 3 && lex[previous][0].klen == 1) ||
1946	     (lex[current][0].ylen <= 3 && lex[current][0].klen == 1)) &&
1947	    (lex[current][0].rownum < R_K5 ||
1948	     R_NZX < lex[current][0].rownum)) {
1949	  if ( !yomi[previous][0] ) {
1950	    RkwLeft(hc->context);
1951	    RkwGetYomi(hc->context, yomi[previous], RENGOBUFSIZE);
1952	    RkwGetKanji(hc->context, kanji[previous], RENGOBUFSIZE);
1953	    RkwRight(hc->context);
1954	  }
1955	  RkwGetYomi(hc->context, yomi[current], RENGOBUFSIZE);
1956	  RkwGetKanji(hc->context, kanji[current], RENGOBUFSIZE);
1957
1958	  WStrncpy(yomi[previous] + lex[previous][0].ylen,
1959		   yomi[current], lex[current][0].ylen);
1960	  yomi[previous][lex[previous][0].ylen + lex[current][0].ylen] =
1961	    (WCHAR_T) '\0';
1962
1963	  WStrncpy(kanji[previous] + lex[previous][0].klen,
1964		   kanji[current], lex[current][0].klen);
1965	  kanji[previous][lex[previous][0].klen + lex[current][0].klen] =
1966	    (WCHAR_T) '\0';
1967
1968#ifdef NAGASADEBUNPOUWOKIMEYOU
1969	  if (lex[previous][0].klen >= lex[current][0].klen) {
1970	    /* Á°¤Î´Á»ú¤ÎŤµ       >=    ¸å¤í¤Î´Á»ú¤ÎŤµ */
1971	    mighter = previous;
1972	  }
1973	  else {
1974	    mighter = current;
1975	  }
1976#else /* !NAGASADEBUNPOUWOKIMEYOU */
1977	  mighter = current;
1978#endif /* !NAGASADEBUNPOUWOKIMEYOU */
1979	  WStrcpy(w, yomi[previous]);
1980	  printf(xxxx, " #%d#%d ", lex[mighter][0].rownum,
1981		 lex[mighter][0].colnum);
1982	  MBstowcs(w + WStrlen(w), xxxx, wlen - WStrlen(w));
1983	  WStrcat(w, kanji[previous]);
1984	  wlen -= (WStrlen(w) + 1); w += WStrlen(w) + 1; *w = (WCHAR_T) '\0';
1985	}
1986      }
1987    }
1988  }
1989#endif /* DO_RENGO_LEARNING */
1990
1991  if (RkwEndBun(yc->context, cannaconf.Gakushu ? 1 : 0) == -1) {
1992    if (errno == EPIPE) {
1993      jrKanjiPipeError();
1994    }
1995  }
1996
1997#ifdef DO_RENGO_LEARNING
1998  if (RengoGakushu && yc->nbunsetsu > 1) { /* Ï¢¸ì³Ø½¬¤ò¤·¤è¤¦¤«¤Ê¤¡ */
1999    for (w = word ; *w ; w += WStrlen(w) + 1) {
2000      RkwDefineDic(yc->context, RengoGakushu, w);
2001    }
2002  }
2003#endif /* DO_RENGO_LEARNING */
2004
2005  if (autoconvert) {
2006    yc->status &= CHIKUJI_NULL_STATUS;
2007    yc->ys = yc->ye = yc->cStartp = yc->cRStartp = 0;
2008    clearHenkanContext(yc);
2009    yc->kEndp = yc->rEndp = yc->kCurs = yc->rCurs =
2010      yc->cStartp = yc->cRStartp =
2011	yc->rStartp = yc->kRStartp = 0;
2012    yc->kAttr[0] = yc->rAttr[0] = SENTOU;
2013    yc->kana_buffer[0] = yc->romaji_buffer[0] = 0;
2014/*    d->kanji_status_return->info |= KanjiEmptyInfo; ¿ʬÍפé¤Ê¤¤¤Î¤Ç.. */
2015    d->current_mode = yc->curMode = yc->myEmptyMode;
2016  }
2017  yc->minorMode = getBaseMode(yc);
2018
2019  /* ñ¸õÊä¾õÂÖ¤«¤éÆɤߤËÌá¤ë¤È¤­¤Ë¤Ï̵¾ò·ï¤Ëmark¤òÀèƬ¤ËÌ᤹ */
2020  yc->nbunsetsu = 0;
2021  yc->cmark = yc->pmark = 0;
2022
2023  abandonContext(d, yc);
2024
2025  if (yc->savedFlags & CANNA_YOMI_MODE_SAVED) {
2026    restoreFlags(yc);
2027  }
2028}
2029
2030int TanKakutei(uiContext d)
2031{
2032  return YomiKakutei(d);
2033}
2034
2035/*
2036 * ´Á»ú¸õÊä¤ò³ÎÄꤵ¤»¡¢¥í¡¼¥Þ»ú¤ò¥¤¥ó¥µ¡¼¥È¤¹¤ë
2037 *
2038 * renbun-continue ¤¬ t ¤Î¤È¤­¤Ï¡¢¼ÂºÝ¤Ë¤Ï³ÎÄꤷ¤Ê¤¤¤Î¤Ç½èÍý¤¬
2039 * ÌÌÅݤÀ¤Ã¤¿¤ê¤¹¤ë¡£
2040 *
2041 * °ú¤­¿ô	uiContext
2042 * Ìá¤êÃÍ	Àµ¾ï½ªÎ»»þ 0	°Û¾ï½ªÎ»»þ -1
2043 */
2044
2045static int TanKakuteiYomiInsert (uiContext);
2046
2047static int
2048TanKakuteiYomiInsert(uiContext d)
2049{
2050  yomiContext yc = (yomiContext)d->modec;
2051  tanContext tan;
2052
2053  if (cannaconf.RenbunContinue || cannaconf.ChikujiContinue) {
2054    d->nbytes = 0;
2055    for (tan = (tanContext)yc ; tan->right ; tan = tan->right)
2056      /* bodyless 'for' */;
2057    yc = (yomiContext)0; /* Ç°¤Î¤¿¤á */
2058    d->modec = (mode_context)tan;
2059    setMode(d, tan, 1);
2060
2061    if (tan->id == YOMI_CONTEXT) {
2062      yc = (yomiContext)tan;
2063
2064      if (yc->generalFlags & CANNA_YOMI_CHIKUJI_MODE) {
2065	/* Ã༡¤Ê¤éÉáÄ̤˳¤±¤ë¤À¤±¤À¤«¤é¤Ê¤¢ */
2066	yc->minorMode = CANNA_MODE_ChikujiTanMode;
2067	d->current_mode = yc->curMode = &cb_mode;
2068	currentModeInfo(d);
2069	yc->status &= ~CHIKUJI_OVERWRAP;
2070	if (yc->kCurs != yc->kEndp) {
2071	  yc->rStartp = yc->rCurs = yc->rEndp;
2072	  yc->kRStartp = yc->kCurs = yc->kEndp;
2073	}
2074	yc->ys = yc->ye = yc->cStartp;
2075	return YomiInsert(d);
2076      }else{ /* Ã༡¤¸¤ã¤Ê¤¤¾ì¹ç */
2077	extern int nKouhoBunsetsu;
2078
2079	yc->curbun = yc->nbunsetsu;
2080	if (doTanBubunMuhenkan(d, yc) < 0) {
2081	  makeGLineMessageFromString(d, jrKanjiError);
2082	  return NothingChangedWithBeep(d);
2083	}
2084	if (nKouhoBunsetsu) {
2085	  (void)cutOffLeftSide(d, yc, nKouhoBunsetsu);
2086	}
2087      }
2088    }
2089    else {
2090      yc = newFilledYomiContext(tan->next, tan->prevMode);
2091      /* ¤¢¤êÆÀ¤Ê¤¤ if (tan->right) yc->right = tan->right;
2092	 yc->right->left = yc; */
2093      tan->right = (tanContext)yc;
2094      yc->left = tan;
2095      d->modec = (mode_context)yc;
2096      /* d->current_mode = yc->curMode = yc->myEmptyMode; */
2097    }
2098  }
2099  else {
2100    d->nbytes = YomiKakutei(d);
2101  }
2102  /* YomiKakutei(d) ¤Ç d->modec ¤¬Êѹ¹¤µ¤ì¤¿²ÄǽÀ­¤¬¤¢¤ë¤Î¤ÇºÆÆɤ߹þ¤ß¤¹¤ë */
2103  yc = (yomiContext)d->modec;
2104
2105  if (yc->id == YOMI_CONTEXT) {
2106    yc->minorMode = getBaseMode(yc);
2107  }
2108  currentModeInfo(d);
2109  d->more.todo = 1;
2110  d->more.ch = d->ch;
2111  d->more.fnum = 0;    /* ¾å¤Î ch ¤Ç¼¨¤µ¤ì¤ë½èÍý¤ò¤»¤è */
2112  return d->nbytes;
2113}
2114
2115
2116/* cfuncdef
2117
2118  pos ¤Ç»ØÄꤵ¤ì¤¿Ê¸Àᤪ¤è¤Ó¤½¤ì¤è¤ê¸å¤ÎʸÀá¤Î»ú¼ïÊÑ´¹¾ðÊó¤ò
2119  ¥¯¥ê¥¢¤¹¤ë¡£
2120*/
2121
2122static int
2123doTbResize(uiContext d, yomiContext yc, int n)
2124{
2125  int len;
2126
2127  if (doTanBubunMuhenkan(d, yc) < 0) {
2128    makeGLineMessageFromString(d, jrKanjiError);
2129    return NothingChangedWithBeep(d);
2130  }
2131  len = yc->kEndp;
2132  doMuhenkan(d, yc); /* yc ¤«¤é±¦¤ò¤ß¤ó¤Ê̵ÊÑ´¹¤Ë¤·¤Æ yc ¤Ë¤Ä¤Ê¤²¤ë */
2133  if (!prepareHenkanMode(d)) {
2134    makeGLineMessageFromString(d, jrKanjiError);
2135    makeYomiReturnStruct(d);
2136    currentModeInfo(d);
2137    return 0;
2138  }
2139  yc->minorMode = CANNA_MODE_TankouhoMode;
2140  yc->kouhoCount = 0;
2141  if (doHenkan(d, len + n, (WCHAR_T *)0) < 0) {
2142    makeGLineMessageFromString(d, jrKanjiError);
2143    makeYomiReturnStruct(d);
2144    currentModeInfo(d);
2145    return 0;
2146  }
2147  currentModeInfo(d);
2148  makeKanjiStatusReturn(d, yc);
2149  return 0;
2150}
2151
2152/*
2153 * ʸÀá¤ò¿­¤Ð¤¹
2154 *
2155 * °ú¤­¿ô	uiContext
2156 * Ìá¤êÃÍ	Àµ¾ï½ªÎ»»þ 0	°Û¾ï½ªÎ»»þ -1
2157 */
2158static int TanExtendBunsetsu (uiContext);
2159
2160static int
2161TanExtendBunsetsu(uiContext d)
2162{
2163  yomiContext yc = (yomiContext)d->modec;
2164
2165  if (yc->id != YOMI_CONTEXT) {
2166    return enterTanHenkanMode(d, CANNA_FN_Extend);
2167  }
2168
2169  d->nbytes = 0;
2170  yc->kouhoCount = 0;
2171  if (yc->right) {
2172    return doTbResize(d, yc, 1);
2173  }
2174  if ((yc->nbunsetsu = RkwEnlarge(yc->context)) <= 0) {
2175    makeRkError(d, "\312\270\300\341\244\316\263\310\302\347\244\313\274\272"
2176	"\307\324\244\267\244\336\244\267\244\277");
2177                   /* ʸÀá¤Î³ÈÂç¤Ë¼ºÇÔ¤·¤Þ¤·¤¿ */
2178    return TanMuhenkan(d);
2179  }
2180  makeKanjiStatusReturn(d, yc);
2181  return(d->nbytes);
2182}
2183
2184/*
2185 * ʸÀá¤ò½Ì¤á¤ë
2186 *
2187 * °ú¤­¿ô	uiContext
2188 * Ìá¤êÃÍ	Àµ¾ï½ªÎ»»þ 0	°Û¾ï½ªÎ»»þ -1
2189 */
2190static int TanShrinkBunsetsu (uiContext);
2191
2192static int
2193TanShrinkBunsetsu(uiContext d)
2194{
2195  yomiContext yc = (yomiContext)d->modec;
2196
2197  if (yc->id != YOMI_CONTEXT) {
2198    return enterTanHenkanMode(d, CANNA_FN_Shrink);
2199  }
2200
2201  d->nbytes = 0;
2202  yc->kouhoCount = 0;
2203
2204  if (yc->right) {
2205    return doTbResize(d, yc, -1);
2206  }
2207
2208  /* ʸÀá¤ò½Ì¤á¤ë */
2209  if ((yc->nbunsetsu = RkwShorten(yc->context)) <= 0) {
2210    makeRkError(d, "\312\270\300\341\244\316\275\314\276\256\244\313\274\272"
2211	"\307\324\244\267\244\336\244\267\244\277");
2212                   /* ʸÀá¤Î½Ì¾®¤Ë¼ºÇÔ¤·¤Þ¤·¤¿ */
2213    return TanMuhenkan(d);
2214  }
2215  makeKanjiStatusReturn(d, yc);
2216
2217  return(d->nbytes);
2218}
2219
2220#define BUNPOU_DISPLAY
2221
2222#ifdef BUNPOU_DISPLAY
2223/*
2224 * ʸˡ¾ðÊó¤ò¥×¥ê¥ó¥È¤¹¤ë
2225 *
2226 * °ú¤­¿ô	uiContext
2227 * Ìá¤êÃÍ	Àµ¾ï½ªÎ»»þ 0	°Û¾ï½ªÎ»»þ -1
2228 */
2229int TanPrintBunpou(uiContext d)
2230{
2231  yomiContext yc = (yomiContext)d->modec;
2232  static WCHAR_T mesg[512]; /* static! */
2233
2234  if (yc->id != YOMI_CONTEXT) {
2235    return enterTanHenkanMode(d, CANNA_FN_ConvertAsHex);
2236  }
2237
2238#ifdef notdef
2239#ifdef DO_GETYOMI
2240  if (RkwGetYomi(yc->context, buf, 256) == -1) {
2241    if (errno == EPIPE) {
2242      jrKanjiPipeError();
2243      TanMuhenkan(d);
2244    }
2245    fprintf(stderr, "¥«¥ì¥ó¥È¸õÊä¤ÎÆɤߤò¼è¤ê½Ð¤»¤Þ¤»¤ó¤Ç¤·¤¿¡£\n");
2246  }
2247  Wfprintf(stderr, "%s\n", buf);
2248#endif /* DO_GETYOMI */
2249
2250  if(RkwGetKanji(yc->context, buf, 256) == -1) {
2251    if(errno == EPIPE) {
2252      jrKanjiPipeError();
2253    }
2254    jrKanjiError = "\245\253\245\354\245\363\245\310\270\365\312\344\244\362"
2255	"\274\350\244\352\275\320\244\273\244\336\244\273\244\363\244\307"
2256	"\244\267\244\277";
2257                   /* ¥«¥ì¥ó¥È¸õÊä¤ò¼è¤ê½Ð¤»¤Þ¤»¤ó¤Ç¤·¤¿ */
2258    return NG;
2259  }
2260#endif
2261
2262  if (RkwGetHinshi(yc->context, mesg, sizeof(mesg) / sizeof(WCHAR_T)) < 0) {
2263    jrKanjiError = "\311\312\273\354\276\360\312\363\244\362\274\350\244\352"
2264	"\275\320\244\273\244\336\244\273\244\363\244\307\244\267\244\277";
2265                   /* ÉÊ»ì¾ðÊó¤ò¼è¤ê½Ð¤»¤Þ¤»¤ó¤Ç¤·¤¿ */
2266    makeGLineMessageFromString(d, jrKanjiError);
2267    makeKanjiStatusReturn(d, yc);
2268    return 0;
2269  }
2270
2271  makeKanjiStatusReturn(d, yc);
2272  d->kanji_status_return->info |= KanjiGLineInfo;
2273  d->kanji_status_return->gline.line = mesg;
2274  d->kanji_status_return->gline.length = WStrlen(mesg);
2275  d->kanji_status_return->gline.revPos = 0;
2276  d->kanji_status_return->gline.revLen = 0;
2277  d->flags |= PLEASE_CLEAR_GLINE;
2278  return 0;
2279}
2280#endif /* BUNPOU_DISPLAY */
2281
2282#ifdef MEASURE_TIME
2283static
2284TanPrintTime(uiContext d)
2285{
2286  /* MEASURE_TIME will not be defined when WIN is defined.  So I will not
2287     care about arrays located on stack below.  1996.6.5 kon */
2288  unsgined char tmpbuf[1024];
2289  static WCHAR_T buf[256];
2290  yomiContext yc = (yomiContext)d->modec;
2291
2292  ycc->kouhoCount = 0;
2293  sprintf(tmpbuf, "\312\321\264\271\273\376\264\326 %d [ms]¡¢\244\246\244\301"
2294	" UI \311\364\244\317 %d [ms]",
2295	   (yc->time * 50 / 3,
2296	   (yc->time - yc->rktime) * 50 / 3;
2297               /* ÊÑ´¹»þ´Ö %d [ms]¡¢¤¦¤Á UI Éô¤Ï %d [ms] */
2298  MBstowcs(buf, tmpbuf, 1024);
2299  d->kanji_status_return->info |= KanjiGLineInfo;
2300  d->kanji_status_return->gline.line = buf;
2301  d->kanji_status_return->gline.length = WStrlen(buf);
2302  d->kanji_status_return->gline.revPos = 0;
2303  d->kanji_status_return->gline.revLen = 0;
2304  d->kanji_status_return->length = -1;
2305  d->flags |= PLEASE_CLEAR_GLINE;
2306  return 0;
2307}
2308#endif /* MEASURE_TIME */
2309
2310void
2311jrKanjiPipeError(void)
2312{
2313  extern int defaultContext, defaultBushuContext;
2314
2315  defaultContext = -1;
2316  defaultBushuContext = -1;
2317
2318  makeAllContextToBeClosed(0);
2319
2320  RkwFinalize();
2321#if defined(DEBUG) && !defined(WIN)
2322  if (iroha_debug) {
2323    fprintf(stderr, "\300\334\302\263\244\254\300\332\244\354\244\277\n");
2324                    /* Àܳ¤¬Àڤ줿 */
2325  }
2326#endif
2327}
2328
2329/* cfuncdef
2330
2331  TanBunsetsuMode -- ñ¸õÊä¥â¡¼¥É¤«¤éʸÀá¿­¤Ð¤·½Ì¤á¥â¡¼¥É¤Ø°Ü¹Ô¤¹¤ë
2332
2333 */
2334
2335static int TanBunsetsuMode (uiContext);
2336
2337static int
2338TanBunsetsuMode(uiContext d)
2339{
2340  yomiContext yc = (yomiContext)d->modec;
2341
2342  if (yc->id != YOMI_CONTEXT) {
2343    return enterTanHenkanMode(d, CANNA_FN_AdjustBunsetsu);
2344  }
2345  if (yc->right) {
2346    doTbResize(d, yc, 0);
2347    yc = (yomiContext)d->modec;
2348  }
2349  if (enterAdjustMode(d, yc) < 0) {
2350    return TanMuhenkan(d);
2351  }
2352  makeKanjiStatusReturn(d, yc);
2353  currentModeInfo(d);
2354  return 0;
2355}
2356
2357static void
2358chikujiSetCursor(uiContext d, int forw)
2359{
2360  yomiContext yc = (yomiContext)d->modec;
2361
2362  if (forw) { /* °ìÈÖº¸¤Ø¹Ô¤¯ */
2363    if (yc->nbunsetsu) { /* ʸÀ᤬¤¢¤ë¡© */
2364      gotoBunsetsu(yc, 0);
2365      moveToChikujiTanMode(d);
2366    }
2367    else {
2368      yc->kRStartp = yc->kCurs = yc->cStartp;
2369      yc->rStartp = yc->rCurs = yc->cRStartp;
2370      moveToChikujiYomiMode(d);
2371    }
2372  }
2373  else { /* °ìÈÖ±¦¤Ø¹Ô¤¯ */
2374    if (yc->cStartp < yc->kEndp) { /* Æɤߤ¬¤¢¤ë¡© */
2375      yc->kRStartp = yc->kCurs = yc->kEndp;
2376      yc->rStartp = yc->rCurs = yc->rEndp;
2377      moveToChikujiYomiMode(d);
2378    }
2379    else {
2380      gotoBunsetsu(yc, yc->nbunsetsu - 1);
2381      moveToChikujiTanMode(d);
2382    }
2383  }
2384}
2385
2386
2387void
2388setMode(uiContext d, tanContext tan, int forw)
2389{
2390  yomiContext yc = (yomiContext)tan;
2391
2392  d->current_mode = yc->curMode;
2393  currentModeInfo(d);
2394  if (tan->id == YOMI_CONTEXT) {
2395    if (yc->generalFlags & CANNA_YOMI_CHIKUJI_MODE) {
2396      chikujiSetCursor(d, forw);
2397    }
2398    else if (yc->nbunsetsu) {
2399      if (forw) {
2400	gotoBunsetsu(yc, 0);
2401      }else{
2402	gotoBunsetsu(yc, yc->nbunsetsu - 1);
2403      }
2404    }
2405    else /* Æɤߥ⡼¥É */ if (forw) {
2406      yc->kCurs = yc->kRStartp = yc->cStartp;
2407      yc->rCurs = yc->rStartp = yc->cRStartp;
2408    }
2409    else {
2410      yc->kCurs = yc->kRStartp = yc->kEndp;
2411      yc->rCurs = yc->rStartp = yc->rEndp;
2412    }
2413  }
2414}
2415
2416int
2417TbForward(uiContext d)
2418{
2419  tanContext tan = (tanContext)d->modec;
2420
2421  if (tan->right) {
2422    d->modec = (mode_context)tan->right;
2423    tan = (tanContext)d->modec;
2424  }
2425  else if (cannaconf.CursorWrap && tan->left) {
2426    while (tan->left) {
2427      tan = tan->left;
2428    }
2429    d->modec = (mode_context)tan;
2430  }
2431  else {
2432    return NothingChanged(d);
2433  }
2434  setMode(d, tan, 1);
2435  makeKanjiStatusReturn(d, (yomiContext)d->modec);
2436  return 0;
2437}
2438
2439int
2440TbBackward(uiContext d)
2441{
2442  tanContext tan = (tanContext)d->modec;
2443
2444  if (tan->left) {
2445    d->modec = (mode_context)tan->left;
2446    tan = (tanContext)d->modec;
2447  }
2448  else if (cannaconf.CursorWrap && tan->right) {
2449    while (tan->right) {
2450      tan = tan->right;
2451    }
2452    d->modec = (mode_context)tan;
2453  }
2454  else {
2455    return NothingChanged(d);
2456  }
2457  setMode(d, tan, 0);
2458  makeKanjiStatusReturn(d, (yomiContext)d->modec);
2459  return 0;
2460}
2461
2462int
2463TbBeginningOfLine(uiContext d)
2464{
2465  tanContext tan = (tanContext)d->modec;
2466
2467  while (tan->left) {
2468    tan = tan->left;
2469  }
2470  d->modec = (mode_context)tan;
2471  setMode(d, tan, 1);
2472  makeKanjiStatusReturn(d, (yomiContext)d->modec);
2473  return 0;
2474}
2475
2476int
2477TbEndOfLine(uiContext d)
2478{
2479  tanContext tan = (tanContext)d->modec;
2480
2481  while (tan->right) {
2482    tan = tan->right;
2483  }
2484  d->modec = (mode_context)tan;
2485  setMode(d, tan, 0);
2486  makeKanjiStatusReturn(d, (yomiContext)d->modec);
2487  return 0;
2488}
2489
2490
2491inline int
2492TbChooseChar(uiContext d, int head)
2493{
2494  tanContext tan = (tanContext)d->modec;
2495
2496  if (!head) {
2497    int len = WStrlen(tan->kanji);
2498    tan->kanji[0] = tan->kanji[len - 1];
2499  }
2500  tan->yomi[0] = tan->roma[0] = tan->kanji[0];
2501  tan->yomi[1] = tan->roma[1] = tan->kanji[1] = (WCHAR_T)0;
2502  tan->rAttr[0] = SENTOU;
2503  tan->kAttr[0] = SENTOU | HENKANSUMI;
2504  tan->rAttr[1] = tan->kAttr[1] = 0;
2505
2506  makeKanjiStatusReturn(d, (yomiContext)tan);
2507  return 0;
2508}
2509
2510static int
2511TanChooseChar(uiContext d, int head)
2512{
2513  int retval, len;
2514  yomiContext yc = (yomiContext)d->modec;
2515#ifndef WIN
2516  WCHAR_T xxx[ROMEBUFSIZE];
2517#else
2518  WCHAR_T *xxx;
2519#endif
2520
2521  if (yc->id != YOMI_CONTEXT) {
2522    return TbChooseChar(d, head);
2523  }
2524#ifdef WIN
2525  xxx = (WCHAR_T *)malloc(sizeof(WCHAR_T) * ROMEBUFSIZE);
2526  if (!xxx) {
2527    return 0;
2528  }
2529#endif
2530  RkwGoTo(yc->context, yc->curbun);
2531  len = RkwGetKanji(yc->context, xxx, ROMEBUFSIZE);
2532  if (len >= 0) {
2533    retval = TanBubunMuhenkan(d);
2534    if (retval >= 0) {
2535      tanContext tan;
2536      yc = (yomiContext)d->modec;
2537      tan = newTanContext(yc->majorMode, CANNA_MODE_TankouhoMode);
2538      if (tan) {
2539	copyYomiinfo2Tan(yc, tan);
2540	tan->kanji = DUpwstr(xxx + (head ? 0 : len - 1), 1);
2541	tan->yomi = DUpwstr(yc->kana_buffer, yc->kEndp);
2542	tan->roma = DUpwstr(yc->romaji_buffer, yc->rEndp);
2543	tan->kAttr = DUpattr(yc->kAttr, yc->kEndp);
2544	tan->rAttr = DUpattr(yc->rAttr, yc->rEndp);
2545	tan->right = yc->right;
2546	if (tan->right) tan->right->left = tan;
2547	yc->right = tan;
2548	tan->left = (tanContext)yc;
2549	removeCurrentBunsetsu(d, (tanContext)yc);
2550	makeKanjiStatusReturn(d, (yomiContext)tan);
2551	goto done;
2552      }
2553    }
2554  }
2555  retval = NothingChangedWithBeep(d);
2556 done:
2557#ifdef WIN
2558  free(xxx);
2559#endif
2560  return retval;
2561}
2562
2563static int TanChooseHeadChar (uiContext);
2564static int TanChooseTailChar (uiContext);
2565
2566static int
2567TanChooseHeadChar(uiContext d)
2568{
2569  return TanChooseChar(d, 1);
2570}
2571
2572static int
2573TanChooseTailChar(uiContext d)
2574{
2575  return TanChooseChar(d, 0);
2576}
2577
2578#include	"tanmap.h"
2579