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: romaji.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 <ctype.h>
37#include <errno.h>
38#ifdef MEASURE_TIME
39#include <sys/types.h>
40#include <sys/times.h>
41#endif
42
43#define DEFAULT_ROMKANA_TABLE "/dic/default.cbp"
44extern struct RkRxDic *romajidic, *englishdic;
45
46static struct RkRxDic *OpenRoma(char *table);
47static int makePhonoOnBuffer(uiContext d, yomiContext yc, unsigned char key, int flag, int english);
48static int growDakuonP(WCHAR_T ch);
49static int KanaYomiInsert(uiContext d);
50static int howFarToGoBackward(yomiContext yc);
51static int howFarToGoForward(yomiContext yc);
52static int YomiBackward(uiContext d);
53static int YomiNop(uiContext d);
54static int YomiForward(uiContext d);
55static int YomiBeginningOfLine(uiContext d);
56static int YomiEndOfLine(uiContext d);
57static int appendYomi2Yomi(yomiContext yom, yomiContext yc);
58static int YomiDeletePrevious(uiContext d);
59static int YomiDeleteNext(uiContext d);
60static int YomiKillToEndOfLine(uiContext d);
61static int YomiQuit(uiContext d);
62static int simplePopCallback(uiContext d, int retval, mode_context env);
63static int exitYomiQuotedInsert(uiContext d, int retval, mode_context env);
64static int YomiInsertQuoted(uiContext d);
65static int yomiquotedfunc(uiContext d, KanjiMode mode, int whattodo, int key, int fnum);
66static int ConvertAsHex(uiContext d);
67static int everySupkey(uiContext d, int retval, mode_context env);
68static int exitSupkey(uiContext d, int retval, mode_context env);
69static int quitSupkey(uiContext d, int retval, mode_context env);
70static int YomiHenkan(uiContext d);
71static int YomiHenkanNaive(uiContext d);
72static int YomiHenkanOrNothing(uiContext d);
73static int YomiBaseHira(uiContext d);
74static int YomiBaseKata(uiContext d);
75static int YomiBaseEisu(uiContext d);
76static int YomiBaseZen(uiContext d);
77static int YomiBaseHan(uiContext d);
78static int YomiBaseKana(uiContext d);
79static int YomiBaseKakutei(uiContext d);
80static int YomiBaseHenkan(uiContext d);
81static int YomiJishu(uiContext d, int fn);
82static int chikujiEndBun(uiContext d);
83static void replaceEnglish(uiContext d, yomiContext yc, int start, int end, int RKflag, int engflag);
84static int YomiNextJishu(uiContext d);
85static int YomiPreviousJishu(uiContext d);
86static int YomiKanaRotate(uiContext d);
87static int YomiRomajiRotate(uiContext d);
88static int YomiCaseRotateForward(uiContext d);
89static int YomiZenkaku(uiContext d);
90static int YomiHankaku(uiContext d);
91static int YomiHiraganaJishu(uiContext d);
92static int YomiKatakanaJishu(uiContext d);
93static int YomiRomajiJishu(uiContext d);
94static int YomiToLower(uiContext d);
95static int YomiToUpper(uiContext d);
96static int YomiCapitalize(uiContext d);
97
98int forceRomajiFlushYomi (uiContext);
99static int chikujiEndBun (uiContext);
100extern void EWStrcat (WCHAR_T *, char *);
101
102extern int yomiInfoLevel;
103
104extern struct RkRxDic *englishdic;
105
106/*
107 * int d->rStartp;     ro shu c|h    shi f   ���������������� ���������������� ������������������������
108 * int d->rEndp;       ro shu ch     shi f|  ���������������� ���������������� ������������������������
109 * int d->rCurs;       ro shu ch|    shi f   ���������������� ������������   ������������������������
110 * int d->rAttr[1024]; 10 100 11     100 1   ��������������������������������������������������������������������
111 * int d->kEndp;       ���� ����  ch  ���� ����  f|  ��������     ���������������� ������������������������
112 * int d->kRStartp;    ���� ����  c|h ���� ����  f   ���������������� ���������������� ������������������������
113 * int d->kCurs;      ���� ����  ch| ���� ����  f   ���������������� ������������   ������������������������
114 * int d->kAttr[1024]; 11 11  00  11 11  0   ����������������������������������������������������
115 * int d->nrf;                1              ����������������������������������������������������
116 */
117
118/*
119 * ��������������������������������������������
120 *
121 *           ������������           hyaku
122 *  ����       100010           10010
123 *  ����       111111
124 *  ����       000000
125 * rStartp                         1
126 * rCurs                           1
127 * rEndp                           1
128 * kRstartp        1
129 * kCurs           1
130 * kEndp           1
131 *
132 * ����
133 *           ������������           hyaku
134 *  ����       100010           10010
135 *  ����       111111
136 *  ����       000000
137 * rStartp                       1
138 * rCurs                         1
139 * rEndp                           1
140 * kRstartp      1
141 * kCurs         1
142 * kEndp           1
143 *
144 * ����
145 *           ������������           hyaku
146 *  ����       100010           10010
147 *  ����       111111
148 *  ����       000000
149 * rStartp                       1
150 * rCurs                         1
151 * rEndp                           1
152 * kRstartp    1
153 * kCurs       1
154 * kEndp           1
155 *
156 * ����
157 *           ������������           hyaku
158 *  ����       100010           10010
159 *  ����       111111
160 *  ����       000000
161 * rStartp                    1
162 * rCurs                      1
163 * rEndp                           1
164 * kRstartp  1
165 * kCurs     1
166 * kEndp           1
167 *
168 * ����
169 *           ������������           hyaku
170 *  ����       100010           10010
171 *  ����       111111
172 *  ����       000000
173 * rStartp                       1
174 * rCurs                         1
175 * rEndp                           1
176 * kRstartp    1
177 * kCurs       1
178 * kEndp           1
179 *
180 * 'k'
181 *           ����k��������           hyakku
182 *  ����       1010010           100110
183 *  ����       1101111
184 *  ����       0010000
185 * rStartp                        1
186 * rCurs                           1
187 * rEndp                             1
188 * kRstartp    1
189 * kCurs        1
190 * kEndp            1
191 *
192 * 'i'
193 *           ����������������           hyakiku
194 *  ����       10100010           1001010
195 *  ����       11111111
196 *  ����       00110000
197 * rStartp                           1
198 * rCurs                             1
199 * rEndp                               1
200 * kRstartp      1
201 * kCurs         1
202 * kEndp             1
203 */
204
205#ifdef WIN
206#define KANALIMIT 127 /* This is caused by the Canna IME coding */
207#endif
208
209#ifndef KANALIMIT
210#define KANALIMIT 255
211#endif
212#define ROMAJILIMIT 255
213
214#define  doubleByteP(x) ((x) & 0x80)
215
216#ifdef DEBUG
217
218void debug_yomi(yomiContext x)
219{
220  char foo[1024];
221  int len, i;
222
223#ifndef WIN
224  if (iroha_debug) {
225    len = WCstombs(foo, x->romaji_buffer, 1024);
226    foo[len] = '\0';
227    printf("    %s\n����: ", foo);
228    for (i = 0 ; i <= x->rEndp ; i++) {
229      printf("%s", (x->rAttr[i] & SENTOU) ? "1" : " ");
230    }
231    printf("\n����: ");
232    for (i = 0 ; i < x->rStartp ; i++) {
233      printf(" ");
234    }
235    printf("^\n");
236
237    len = WCstombs(foo, x->kana_buffer, 1024);
238    foo[len] = '\0';
239    printf("    %s\n����: ", foo);
240    for (i = 0 ; i <= x->kEndp ; i++) {
241      printf("%s ", (x->kAttr[i] & SENTOU) ? "1" : " ");
242    }
243    printf("\n����: ");
244    for (i = 0 ; i <= x->kEndp ; i++) {
245      printf("%s", (x->kAttr[i] & HENKANSUMI) ? "����" : "����");
246    }
247    printf("\n����: ");
248    for (i = 0 ; i < x->kRStartp ; i++) {
249      printf("  ");
250    }
251    printf("����\n");
252
253  }
254#endif
255}
256#else /* !DEBUG */
257# define debug_yomi(x)
258#endif /* !DEBUG */
259
260#ifndef CALLBACK
261#define kanaReplace(where, insert, insertlen, mask) \
262kanaRepl(d, where, insert, insertlen, mask)
263
264inline void
265kanaRepl(uiContext d, int where, WCHAR_T *insert, int insertlen, int mask)
266{
267  yomiContext yc = (yomiContext)d->modec;
268
269  generalReplace(yc->kana_buffer, yc->kAttr, &yc->kRStartp,
270		 &yc->kCurs, &yc->kEndp,
271		 where, insert, insertlen, mask);
272}
273#else /* CALLBACK */
274#define kanaReplace(where, insert, insertlen, mask) \
275kanaRepl(d, where, insert, insertlen, mask)
276
277static void
278kanaRepl(uiContext d, int where, WCHAR_T *insert, int insertlen, int mask)
279{
280  yomiContext yc = (yomiContext)d->modec;
281#ifndef WIN
282  WCHAR_T buf[256];
283#else
284  WCHAR_T *buf = (WCHAR_T *)malloc(sizeof(WCHAR_T) * 256);
285  if (!buf) {
286    return;
287  }
288#endif
289
290  WStrncpy(buf, insert, insertlen);
291  buf[insertlen] = '\0';
292
293  generalReplace(yc->kana_buffer, yc->kAttr, &yc->kRStartp,
294		 &yc->kCurs, &yc->kEndp,
295		 where, insert, insertlen, mask);
296#ifdef WIN
297  free(buf);
298#endif
299}
300#endif /* CALLBACK */
301
302#define  romajiReplace(where, insert, insertlen, mask) \
303romajiRepl(d, where, insert, insertlen, mask)
304
305inline void
306romajiRepl(uiContext d, int where, WCHAR_T *insert, int insertlen, int mask)
307{
308  yomiContext yc = (yomiContext)d->modec;
309
310  generalReplace(yc->romaji_buffer, yc->rAttr,
311		 &yc->rStartp, &yc->rCurs, &yc->rEndp,
312		 where, insert, insertlen, mask);
313}
314
315/* cfuncdef
316
317   kPos2rPos -- ����������������������������������������������������������������������������������������������������������������������������
318
319   yc : ��������������������������������
320   s  : ��������������������������������������������������������������������
321   e  : ��������������������������������������������������������������������
322   rs : ������������������������������������������������������������������������������������������������������������������������
323   rs : ������������������������������������������������������������������������������������������������������������������������
324 */
325
326void
327kPos2rPos(yomiContext yc, int s, int e, int *rs, int *re)
328{
329  int i, j, k;
330
331  for (i = 0, j = 0 ; i < s ; i++) {
332    if (yc->kAttr[i] & SENTOU) {
333      do {
334	j++;
335      } while (!(yc->rAttr[j] & SENTOU));
336    }
337  }
338  for (i = s, k = j ; i < e ; i++) {
339    if (yc->kAttr[i] & SENTOU) {
340      do {
341	k++;
342      } while (!(yc->rAttr[k] & SENTOU));
343    }
344  }
345  if (rs) *rs = j;
346  if (re) *re = k;
347}
348
349/*
350  makeYomiReturnStruct-- ������������������������������������������������������������������������������������������������
351
352  makeYomiReturnStruct ���� kana_buffer ����������������������������������������������������������������
353  ��������������������������������������������������������������������������������������������������������������������������������
354  ReverseWidely ����������������������������������������������������
355
356  */
357
358void
359makeYomiReturnStruct(uiContext d)
360{
361  yomiContext yc = (yomiContext)d->modec;
362
363  makeKanjiStatusReturn(d, yc);
364}
365
366extern int ckverbose;
367
368static struct RkRxDic *
369OpenRoma(char *table)
370{
371struct RkRxDic *retval = (struct RkRxDic *)0;
372char *p;
373char rdic[1024];
374extern char basepath[];
375
376  if (table || *table) {
377    retval = RkwOpenRoma(table);
378
379    if (ckverbose == CANNA_FULL_VERBOSE) {
380      if (retval != (struct RkRxDic *)NULL) { /* ���������������������������������������� */
381        printf("���������������������������������������������������� \"%s\" ������������������������\n", table);
382      }
383    }
384
385    if (retval == (struct RkRxDic *)NULL) {
386      /* ������������������������������������������������������������������������ */
387      extern jrUserInfoStruct *uinfo;
388
389      rdic[0] = '\0';
390      if (uinfo && uinfo->topdir && uinfo->uname) {
391	sprintf(rdic, "%sdic/user/%s/%s", uinfo->topdir, uinfo->uname, table);
392	retval = RkwOpenRoma(rdic);
393      }else{
394        p = getenv("HOME");
395        if (p) {
396          sprintf(rdic, "%s/%s", p, table);
397          retval = RkwOpenRoma(rdic);
398        }
399      }
400
401      if (ckverbose == CANNA_FULL_VERBOSE) {
402	if (retval != (struct RkRxDic *)NULL) {
403#ifndef WIN
404          printf("���������������������������������������������������� \"%s\" ������������������������\n", rdic);
405#endif
406	}
407      }
408
409      if (retval == (struct RkRxDic *)NULL) { /* �������������������������������������������� */
410        extern jrUserInfoStruct *uinfo;
411
412        rdic[0] = '\0';
413        if (uinfo && uinfo->topdir) {
414	  strcpy(rdic, uinfo->topdir);
415        }
416        else {
417          strcpy(rdic, basepath);
418        }
419	strcat(rdic, "dic/");	/*******************/
420	strcat(rdic, table);
421	retval = RkwOpenRoma(rdic);
422
423	if (ckverbose) {
424	  if (retval != (struct RkRxDic *)NULL) {
425	    if (ckverbose == CANNA_FULL_VERBOSE) {
426              printf("���������������������������������������������������� \"%s\" ������������������������\n", rdic);
427	    }
428	  }
429	}
430
431	if (retval == (struct RkRxDic *)NULL) { /* ���������������������������������������� */
432	  sprintf(rdic,
433#ifndef WIN
434		  "������������������������������������������������(%s)��������������������������������������������",
435#else
436	"\245\355\241\274\245\336\273\372\244\253\244\312"
437	"\312\321\264\271\245\306\241\274\245\326\245\353\50\45\163\51\244\254"
438	"\245\252\241\274\245\327\245\363\244\307\244\255\244\336\244\273"
439	"\244\363\241\243",
440#endif
441		  table);
442           /* ������������������������������������������������(%s)�������������������������������������������� */
443	  addWarningMesg(rdic);
444	  retval = (struct RkRxDic *)0;
445	  goto return_ret;
446	}
447      }
448    }
449  }
450 return_ret:
451  return retval;
452}
453
454int RomkanaInit(void)
455{
456  extern char *RomkanaTable, *EnglishTable;
457  extern extraFunc *extrafuncp;
458  extern char basepath[];
459
460  extraFunc *extrafunc1, *extrafunc2;
461
462  /* �������������������������������������������������������������������� */
463  if (RomkanaTable) {
464    romajidic = OpenRoma(RomkanaTable);
465  }
466  else {
467    char buf[1024];
468
469    sprintf(buf, "%sdic/default.kp", basepath);
470    romajidic = RkwOpenRoma(buf);
471
472    if (romajidic != NULL) {
473      int len = strlen(buf);
474      RomkanaTable = (char *)malloc(len + 1);
475      if (RomkanaTable) {
476	strcpy(RomkanaTable, buf);
477      }
478      if (ckverbose == CANNA_FULL_VERBOSE) {
479	printf("���������������������������������������������������� \"%s\" ������������������������\n", buf);
480      }
481    }
482    else { /* ���������������������������������������� */
483      if (ckverbose) {
484	printf("������������������������������������������������ \"%s\" ��������������������������������������������\n",
485	       buf);
486      }
487      sprintf(buf,
488	      "����������������������������������������������������������������������������������������������������������������");
489      addWarningMesg(buf);
490    }
491  }
492
493  if (EnglishTable && (!RomkanaTable || strcmp(RomkanaTable, EnglishTable))) {
494    /* RomkanaTable ���� EnglishTable ������������������������������������ */
495    englishdic = OpenRoma(EnglishTable);
496  }
497
498  /* ���������������������������������������� */
499  for (extrafunc1 = extrafuncp ; extrafunc1 ; extrafunc1 = extrafunc1->next) {
500    /* �������������������������������������������������������������������� */
501    if (extrafunc1->keyword == EXTRA_FUNC_DEFMODE) {
502      if (extrafunc1->u.modeptr->romaji_table) {
503        if (RomkanaTable &&
504            !strcmp(RomkanaTable,
505		    (char *)extrafunc1->u.modeptr->romaji_table)) {
506	  extrafunc1->u.modeptr->romdic = romajidic;
507	  extrafunc1->u.modeptr->romdic_owner = 0;
508        }
509        else if (EnglishTable &&
510	         !strcmp(EnglishTable,
511			 (char *)extrafunc1->u.modeptr->romaji_table)) {
512	  extrafunc1->u.modeptr->romdic = englishdic;
513	  extrafunc1->u.modeptr->romdic_owner = 0;
514        }
515        else {
516	  for (extrafunc2 = extrafuncp ; extrafunc1 != extrafunc2 ;
517					extrafunc2 = extrafunc2->next) {
518	    if (extrafunc2->keyword == EXTRA_FUNC_DEFMODE &&
519		extrafunc2->u.modeptr->romaji_table) {
520	      if (!strcmp((char *)extrafunc1->u.modeptr->romaji_table,
521			  (char *)extrafunc2->u.modeptr->romaji_table)) {
522	        extrafunc1->u.modeptr->romdic = extrafunc2->u.modeptr->romdic;
523	        extrafunc1->u.modeptr->romdic_owner = 0;
524	        break;
525	      }
526	    }
527	  }
528	  if (extrafunc2 == extrafunc1) {
529	    extrafunc1->u.modeptr->romdic =
530              OpenRoma(extrafunc1->u.modeptr->romaji_table);
531	    extrafunc1->u.modeptr->romdic_owner = 1;
532	  }
533        }
534      }else{
535        extrafunc1->u.modeptr->romdic = (struct RkRxDic *)0; /* nil���������������� */
536        extrafunc1->u.modeptr->romdic_owner = 0;
537      }
538    }
539  }
540
541  return 0;
542}
543#if 0
544RomkanaInit(void)
545{
546  extern char *RomkanaTable, *EnglishTable;
547  extern extraFunc *extrafuncp;
548  extraFunc *extrafunc1, *extrafunc2;
549  extern jrUserInfoStruct *uinfo;
550
551  /* �������������������������������������������������������������������� */
552  if (uinfo) {
553    if (uinfo->romkanatable) {
554      if (RomkanaTable) {
555        free(RomkanaTable);
556      }
557      RomkanaTable = (char *)malloc(strlen(uinfo->romkanatable) + 1);
558      if (RomkanaTable) {
559        strcpy(RomkanaTable, uinfo->romkanatable);
560      }
561    }
562  }
563  if (RomkanaTable) {
564    romajidic = OpenRoma(RomkanaTable);
565  }
566  else {
567#ifndef WIN
568    char buf[1024];
569#else
570    char *buf = malloc(1024);
571    if (!buf) {
572      return 0;
573    }
574#endif
575
576    buf[0] = '\0';
577    if (uinfo && uinfo->topdir) {
578      strcpy(buf, uinfo->topdir);
579    }
580    else {
581      strcpy(buf, basepath);
582    }
583    strcat(buf, DEFAULT_ROMKANA_TABLE);
584    romajidic = RkwOpenRoma(buf);
585
586    if (romajidic != (struct RkRxDic *)NULL) {
587      int len = strlen(buf);
588      RomkanaTable = (char *)malloc(len + 1);
589      if (RomkanaTable) {
590	strcpy(RomkanaTable, buf);
591      }
592      if (ckverbose == CANNA_FULL_VERBOSE) {
593#ifndef WIN
594        printf("���������������������������������������������������� \"%s\" ������������������������\n", buf);
595#endif
596      }
597    }
598    else { /* ���������������������������������������� */
599      if (ckverbose) {
600#ifndef WIN
601        printf("������������������������������������������������ \"%s\" ��������������������������������������������\n",
602               buf);
603#endif
604      }
605      sprintf(buf, "\245\267\245\271\245\306\245\340\244\316\245\355\241\274"
606	"\245\336\273\372\244\253\244\312\312\321\264\271\245\306\241\274"
607	"\245\326\245\353\244\254\245\252\241\274\245\327\245\363\244\307"
608	"\244\255\244\336\244\273\244\363\241\243");
609         /* ���������������������������������������������������������������������������������������������������������������� */
610      addWarningMesg(buf);
611    }
612#ifdef WIN
613    free(buf);
614#endif
615  }
616
617#ifndef NOT_ENGLISH_TABLE
618  if (EnglishTable && (!RomkanaTable || strcmp(RomkanaTable, EnglishTable))) {
619    /* RomkanaTable ���� EnglishTable ������������������������������������ */
620    englishdic = OpenRoma(EnglishTable);
621  }
622#endif
623
624  /* ���������������������������������������� */
625  for (extrafunc1 = extrafuncp ; extrafunc1 ; extrafunc1 = extrafunc1->next) {
626    /* �������������������������������������������������������������������� */
627    if (extrafunc1->keyword == EXTRA_FUNC_DEFMODE) {
628      if (extrafunc1->u.modeptr->romaji_table) {
629        if (RomkanaTable &&
630            !strcmp(RomkanaTable,
631		    (char *)extrafunc1->u.modeptr->romaji_table)) {
632	  extrafunc1->u.modeptr->romdic = romajidic;
633	  extrafunc1->u.modeptr->romdic_owner = 0;
634        }
635#ifndef NOT_ENGLISH_TABLE
636        else if (EnglishTable &&
637	         !strcmp(EnglishTable,
638			 (char *)extrafunc1->u.modeptr->romaji_table)) {
639	  extrafunc1->u.modeptr->romdic = englishdic;
640	  extrafunc1->u.modeptr->romdic_owner = 0;
641        }
642#endif
643        else {
644	  for (extrafunc2 = extrafuncp ; extrafunc1 != extrafunc2 ;
645					extrafunc2 = extrafunc2->next) {
646	    if (extrafunc2->keyword == EXTRA_FUNC_DEFMODE &&
647		extrafunc2->u.modeptr->romaji_table) {
648	      if (!strcmp((char *)extrafunc1->u.modeptr->romaji_table,
649			  (char *)extrafunc2->u.modeptr->romaji_table)) {
650	        extrafunc1->u.modeptr->romdic = extrafunc2->u.modeptr->romdic;
651	        extrafunc1->u.modeptr->romdic_owner = 0;
652	        break;
653	      }
654	    }
655	  }
656	  if (extrafunc2 == extrafunc1) {
657	    extrafunc1->u.modeptr->romdic =
658              OpenRoma(extrafunc1->u.modeptr->romaji_table);
659	    extrafunc1->u.modeptr->romdic_owner = 1;
660	  }
661        }
662      }else{
663        extrafunc1->u.modeptr->romdic = (struct RkRxDic *)0; /* nil���������������� */
664        extrafunc1->u.modeptr->romdic_owner = 0;
665      }
666    }
667  }
668
669  return 0;
670}
671#endif
672
673/* �������������������������������������������������������������������� */
674
675extern keySupplement keysup[];
676extern void RkwCloseRoma (struct RkRxDic *);
677
678void
679RomkanaFin(void)
680{
681  extern char *RomkanaTable, *EnglishTable;
682  extern int nkeysup;
683  int i;
684
685  /* �������������������������������������������������������������������� */
686  if (romajidic != (struct RkRxDic *)NULL) {
687    RkwCloseRoma(romajidic);
688  }
689  if (RomkanaTable) {
690    free(RomkanaTable);
691    RomkanaTable = (char *)NULL;
692  }
693#ifndef NOT_ENGLISH_TABLE
694  if (englishdic != (struct RkRxDic *)NULL) {
695    RkwCloseRoma(englishdic);
696  }
697  if (EnglishTable) {
698    free(EnglishTable);
699    EnglishTable = (char *)NULL;
700  }
701#endif
702  /* �������������������������������������������������������������������������������������������� */
703  for (i = 0 ; i < nkeysup ; i++) {
704    if (keysup[i].cand) {
705      free(keysup[i].cand);
706      keysup[i].cand = (WCHAR_T **)NULL;
707    }
708    if (keysup[i].fullword) {
709      free(keysup[i].fullword);
710      keysup[i].fullword = (WCHAR_T *)NULL;
711    }
712  }
713  nkeysup = 0;
714}
715
716/* cfunc newYomiContext
717
718  yomiContext ��������������������������������������������
719
720 */
721
722yomiContext
723newYomiContext(WCHAR_T *buf, int bufsize, int allowedc, int chmodinhibit, int quitTiming, int hinhibit)
724{
725  yomiContext ycxt;
726
727  ycxt = (yomiContext)malloc(sizeof(yomiContextRec));
728  if (ycxt) {
729    bzero(ycxt, sizeof(yomiContextRec));
730    ycxt->id = YOMI_CONTEXT;
731    ycxt->allowedChars = allowedc;
732    ycxt->generalFlags = chmodinhibit ? CANNA_YOMI_CHGMODE_INHIBITTED : 0;
733    ycxt->generalFlags |= quitTiming ? CANNA_YOMI_END_IF_KAKUTEI : 0;
734    ycxt->savedFlags = (long)0;
735    ycxt->henkanInhibition = hinhibit;
736    ycxt->n_susp_chars = 0;
737    ycxt->retbufp = ycxt->retbuf = buf;
738    ycxt->romdic = (struct RkRxDic *)0;
739    ycxt->myEmptyMode = (KanjiMode)0;
740    ycxt->last_rule = 0;
741    if ((ycxt->retbufsize = bufsize) == 0) {
742      ycxt->retbufp = 0;
743    }
744    ycxt->right = ycxt->left = (tanContext)0;
745    ycxt->next = (mode_context)0;
746    ycxt->prevMode = 0;
747
748    /* ���������������� */
749    ycxt->nbunsetsu = 0;  /* �������������������������������������������������������������������������������������������� */
750    ycxt->context = -1;
751    ycxt->kouhoCount = 0;
752    ycxt->allkouho = (WCHAR_T **)0;
753    ycxt->curbun = 0;
754    ycxt->curIkouho = 0;  /* ������������������������ */
755    ycxt->proctime = ycxt->rktime = 0;
756
757    /* ���������������� */
758    ycxt->ys = ycxt->ye = ycxt->cStartp = ycxt->cRStartp = ycxt->status = 0;
759  }
760  return ycxt;
761}
762
763/*
764
765  GetKanjiString ����������������������������������������������������������������������������������������������������
766  empty ���������������������������������������������������������������������������������������������������� buf ������������
767  ������������������������������������������������ exitCallback ������������������������������������������������������������
768  ��������������������������������������������������������������������������������������������
769
770  �������������������� ycxt ��������������������������������������������������������������������������������������������������������
771  ���������������������������������������������������������������� uiContext ������������������������������������������������
772  ��������������������������������������������������������������������������������������������������������������������������������������������
773  ���������������������������������������������������� push/pop ����������������������������������������������������������������
774  ����������������������������������������������������������������
775
776  ������������ Callback ����������������exitCallback ������������������������������������������������������������
777  everyTimeCallback ���� quitCallback ����������������������������������������������������
778
779 */
780
781yomiContext
782GetKanjiString(uiContext d, WCHAR_T *buf, int bufsize, int allowedc, int chmodinhibit, int quitTiming, int hinhibit, canna_callback_t everyTimeCallback, canna_callback_t exitCallback, canna_callback_t quitCallback)
783{
784  extern KanjiModeRec empty_mode;
785  yomiContext yc;
786
787  if ((pushCallback(d, d->modec, everyTimeCallback, exitCallback, quitCallback,
788		    NO_CALLBACK)) == (struct callback *)0) {
789    return (yomiContext)0;
790  }
791
792  yc = newYomiContext(buf, bufsize, allowedc, chmodinhibit,
793		      quitTiming, hinhibit);
794  if (yc == (yomiContext)0) {
795    popCallback(d);
796    return (yomiContext)0;
797  }
798  yc->romdic = romajidic;
799  yc->majorMode = d->majorMode;
800  yc->minorMode = CANNA_MODE_HenkanMode;
801  yc->next = d->modec;
802  d->modec = (mode_context)yc;
803  /* �������������������������������� */
804  yc->prevMode = d->current_mode;
805  /* �������������������� */
806  d->current_mode = yc->curMode = yc->myEmptyMode = &empty_mode;
807  return yc;
808}
809
810/* cfuncdef
811
812   popYomiMode -- ������������������������������������������������������������
813
814 */
815
816void
817popYomiMode(uiContext d)
818{
819  yomiContext yc = (yomiContext)d->modec;
820
821  d->modec = yc->next;
822  d->current_mode = yc->prevMode;
823
824  if (yc->context >= 0) {
825    RkwCloseContext(yc->context);
826    yc->context = -1;
827  }
828
829  freeYomiContext(yc);
830}
831
832/* cfuncdef
833
834  checkIfYomiExit -- ������������������������������������������������������������������������������������������������
835
836  ����������������������������������������������������������������������������������������������������������������������������������������
837  ����������������������������������������������������������������������������������������������������������������uiContext ����
838  ����������������������������������������������������������������������������������������������������������������������������
839
840  �������������������������������� exitCallback ����������������������������������������������������������������������������
841  ��������������������������������������������������������������������
842
843  ��������������������������������������������������������������������������������������������������������������������
844
845  (1) C-m ��������������������������������������������������������������������������������(������������������������)
846
847  (2) ����������������������������������������������������(������������������������)
848
849  quit ����������������������������������������������������?����������������?����������������
850
851 */
852
853inline
854int checkIfYomiExit(uiContext d, int retval)
855{
856  yomiContext yc = (yomiContext)d->modec;
857
858  if (retval <= 0) {
859    /* ������������������������������������������������������������ ���� exit ���������������� */
860    return retval;
861  }
862  if (yc->retbufp && yc->retbufsize - (yc->retbufp - yc->retbuf) > retval) {
863    /* ����������������������������������������������������������������������������������������������������������������������������
864       �������������������������������������������������������������������������������������������������������������������� */
865    WStrncpy(yc->retbufp, d->buffer_return, retval);
866    yc->retbufp[retval] = (WCHAR_T)0;
867    yc->retbufp += retval;
868  }
869  if (yc->generalFlags & CANNA_YOMI_END_IF_KAKUTEI
870      || d->buffer_return[retval - 1] == '\n') {
871    /* �������������������������������������������������������� exit */
872    /* ������������������������������������\n ���������������������������� exit */
873    d->status = EXIT_CALLBACK;
874    if (!(d->cb && d->cb->func[EXIT_CALLBACK] == NO_CALLBACK)) {
875      d->status = EXIT_CALLBACK;
876      popYomiMode(d);
877    }
878  }
879  return retval;
880}
881
882static
883int checkIfYomiQuit(uiContext d, int retval)
884/* ARGSUSED */
885{
886#ifdef QUIT_IN_YOMI /* ������������������������������������������������ ifdef */
887  yomiContext yc = (yomiContext)d->modec;
888
889  if (d->cb && d->cb->func[QUIT_CALLBACK] == NO_CALLBACK) {
890    /* ��������������������������������������������
891
892       ��������������������������������������������������������������������������������������������������������������������������������
893       ������������������������������������������������������������������������������������������������������������������������������������
894       ����������������������������������������������������������������������������������������������������
895
896     */
897  }
898  else {
899    d->status = QUIT_CALLBACK;
900    popYomiMode(d);
901  }
902#endif /* QUIT_IN_YOMI */
903  return retval;
904}
905
906void fitmarks(yomiContext);
907
908void
909fitmarks(yomiContext yc)
910{
911  if (yc->kRStartp < yc->pmark) {
912    yc->pmark = yc->kRStartp;
913  }
914  if (yc->kRStartp < yc->cmark) {
915    yc->cmark = yc->kRStartp;
916  }
917}
918
919/* ������������������������������������������������������������������������ */
920void
921ReCheckStartp(yomiContext yc)
922{
923  int r = yc->rStartp, k = yc->kRStartp, i;
924
925  do {
926    yc->kRStartp--;
927    yc->rStartp--;
928  } while ( yc->kRStartp >= 0
929	   && !(yc->kAttr[yc->kRStartp] & HENKANSUMI)
930	   );
931  yc->kRStartp++;
932  yc->rStartp++;
933
934  /* ��������������������������������������������������������������������������������������������������������������������
935
936     ������������������������������������������������������������������������������������������������
937     ����������������������������������������(kRStartp < k)��������������������kCurs ������������
938     ���������������������������������������������������������������� */
939
940  if (yc->kRStartp < k && k < yc->kCurs) {
941    yc->kAttr[k] &= ~SENTOU;
942    yc->rAttr[r] &= ~SENTOU;
943  }
944  for (i = yc->kRStartp + 1 ; i < k ; i++) {
945    yc->kAttr[i] &= ~SENTOU;
946  }
947  for (i = yc->rStartp + 1 ; i < r ; i++) {
948    yc->rAttr[i] &= ~SENTOU;
949  }
950}
951
952extern void setMode (uiContext d, tanContext tan, int forw);
953
954void
955removeCurrentBunsetsu(uiContext d, tanContext tan)
956{
957  if (tan->left) {
958    tan->left->right = tan->right;
959    d->modec = (mode_context)tan->left;
960    d->current_mode = tan->left->curMode;
961    setMode(d, tan->left, 0);
962  }
963  if (tan->right) {
964    tan->right->left = tan->left;
965    d->modec = (mode_context)tan->right;
966    d->current_mode = tan->right->curMode;
967    setMode(d, tan->right, 1);
968  }
969  switch (tan->id) {
970  case YOMI_CONTEXT:
971    freeYomiContext((yomiContext)tan);
972    break;
973  case TAN_CONTEXT:
974    freeTanContext(tan);
975    break;
976  }
977}
978
979/* tabledef
980
981 charKind -- ����������������������������������������������������
982
983 0x20 �������� 0x7f ����������������������������������������������������������������������������������������
984
985 3: ��������
986 2: ��������������������������������������������������������
987 1: ����������������������������
988 0: ������������
989
990 ����������������
991
992 */
993
994static BYTE charKind[] = {
995/*sp !  "  #  $  %  &  '  (  )  *  +  ,  -  .  / */
996  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
997/*0  1  2  3  4  5  6  7  8  9  :  ;  <  =  >  ? */
998  4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1, 1, 1, 1, 1, 1,
999/*@  A  B  C  D  E  F  G  H  I  J  K  L  M  N  O */
1000  1, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2,
1001/*P  Q  R  S  T  U  V  W  X  Y  X  [  \  ]  ^  _ */
1002  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1,
1003/*`  a  b  c  d  e  f  g  h  i  j  k  l  m  n  o */
1004  1, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2,
1005/*p  q  r  s  t  u  v  w  x  y  z  {  |  }  ~  DEL */
1006  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1,
1007};
1008
1009/*
1010  YomiInsert -- ��������������������������������������������������������
1011
1012  */
1013
1014void
1015restoreChikujiIfBaseChikuji(yomiContext yc)
1016{
1017  if (!chikujip(yc) && (yc->generalFlags & CANNA_YOMI_BASE_CHIKUJI)) {
1018    yc->generalFlags &= ~CANNA_YOMI_BASE_CHIKUJI;
1019    yc->generalFlags |= CANNA_YOMI_CHIKUJI_MODE;
1020    yc->minorMode = getBaseMode(yc);
1021  }
1022}
1023
1024int YomiInsert (uiContext);
1025
1026int YomiInsert(uiContext d)
1027{
1028  yomiContext yc = (yomiContext)d->modec;
1029  int subst, autoconvert = (yc->generalFlags & CANNA_YOMI_CHIKUJI_MODE);
1030  int kugiri = 0;
1031#ifdef USE_ROMKANATABLE_FOR_KANAKEY
1032  WCHAR_T key = 0;
1033#endif
1034
1035  d->nbytes = 0;
1036  if (autoconvert) {
1037    if (yc->status & CHIKUJI_ON_BUNSETSU) {
1038      yc->status &= ~CHIKUJI_OVERWRAP;
1039      if (yc->kCurs != yc->kEndp) {
1040	yc->rStartp = yc->rCurs = yc->rEndp;
1041	yc->kRStartp = yc->kCurs = yc->kEndp;
1042      }
1043    }
1044    else {
1045      if (yc->rEndp == yc->rCurs) {
1046	yc->status &= ~CHIKUJI_OVERWRAP;
1047      }
1048      if (yc->kCurs < yc->ys) {
1049	yc->ys = yc->kCurs;
1050      }
1051    }
1052  }
1053
1054  if (yc->allowedChars == CANNA_NOTHING_ALLOWED)/* ���������������������������������������� */
1055    return NothingChangedWithBeep(d);
1056  if  (yc->rEndp >= ROMAJILIMIT
1057       || yc->kEndp >= KANALIMIT
1058       /* ������������������������������������
1059       || (chc && yc->rEndp + chc->hc->ycx->rEndp > ROMAJILIMIT)*/) {
1060    return NothingChangedWithBeep(d);
1061  }
1062
1063  fitmarks(yc);
1064
1065  if (0xa0 < d->ch && d->ch < 0xe0) {
1066#ifdef USE_ROMKANATABLE_FOR_KANAKEY
1067    key = d->buffer_return[0];
1068#else
1069    if (yc->allowedChars == CANNA_NOTHING_RESTRICTED) {
1070      return KanaYomiInsert(d); /* callback ������������������������ KanaYomiInsert ����! */
1071    }
1072    else {
1073      return NothingChangedWithBeep(d);
1074    }
1075#endif
1076  }
1077
1078  /*   (d->ch & ~0x1f) == 0x1f < (unsigned char)d->ch */
1079  if (!(d->ch & ~0x1f) && yc->allowedChars != CANNA_NOTHING_RESTRICTED
1080      || (d->ch < 0x80 ? charKind[d->ch - 0x20] : 1) < yc->allowedChars) {
1081    /* ����������������USE_ROMKANATABLE_FOR_KANAKEY ���������������������������� */
1082    /* 0x20 �������������������������������������������������������� */
1083    return NothingChangedWithBeep(d);
1084  }
1085
1086  if (yc->allowedChars != CANNA_NOTHING_RESTRICTED) {
1087    /* allowed all �������������������������������������������������������������������� */
1088    WCHAR_T romanBuf[4]; /* �������������������������������������������������������� */
1089    int len;
1090#ifdef USE_ROMKANATABLE_FOR_KANAKEY
1091    WCHAR_T tempc = key ? key : (WCHAR_T)d->ch;
1092#else
1093    WCHAR_T tempc = (WCHAR_T)d->ch;
1094#endif
1095    romajiReplace(0, &tempc, 1, SENTOU);
1096
1097    len = RkwCvtNone(romanBuf, 4, &tempc, 1);
1098
1099    if (yc->generalFlags & CANNA_YOMI_KAKUTEI) { /* ������������������������ */
1100      WStrncpy(d->buffer_return + d->nbytes, yc->kana_buffer, yc->kCurs);
1101      /* ������������������������������������������������������������������������������������yc->kRStartp ��������������������
1102	 yc->kCurs ���������������� */
1103      d->nbytes += yc->kCurs;
1104      romajiReplace(-yc->rCurs, (WCHAR_T *)0, 0, 0);
1105      kanaReplace(-yc->kCurs, (WCHAR_T *)0, 0, 0);
1106
1107      WStrncpy(d->buffer_return + d->nbytes, romanBuf, len);
1108      d->nbytes += len;
1109      len = 0;
1110    }
1111
1112    kanaReplace(0, romanBuf, len, HENKANSUMI);
1113    yc->kAttr[yc->kRStartp] |= SENTOU;
1114    yc->rStartp = yc->rCurs;
1115    yc->kRStartp = yc->kCurs;
1116  }
1117  else { /* ������������������������������������������������ */
1118#ifdef USE_ROMKANATABLE_FOR_KANAKEY
1119    WCHAR_T tempc = key ? key : (WCHAR_T)d->ch;
1120#else
1121    WCHAR_T tempc = (WCHAR_T)d->ch;
1122#endif
1123    int ppos;
1124    if (cannaconf.BreakIntoRoman)
1125      yc->generalFlags |= CANNA_YOMI_BREAK_ROMAN;
1126
1127    /* ������������������������������������������������������������������������ */
1128
1129    if (yc->kCurs == yc->kRStartp) {
1130      ReCheckStartp(yc);
1131    }
1132
1133    /* �������������������������������������������������������������������������������� */
1134
1135    romajiReplace(0, &tempc, 1, (yc->rStartp == yc->rCurs) ? SENTOU : 0);
1136
1137    ppos = yc->kRStartp;
1138    kanaReplace(0, &tempc, 1, (yc->kRStartp == yc->kCurs) ? SENTOU : 0);
1139
1140#ifdef USE_ROMKANATABLE_FOR_KANAKEY
1141    kugiri = makePhonoOnBuffer(d, yc, key ? key : (unsigned char)d->ch, 0, 0);
1142#else
1143    kugiri = makePhonoOnBuffer(d, yc, (unsigned char)d->ch, 0, 0);
1144#endif
1145
1146    if (kugiri && autoconvert) {
1147      if (ppos < yc->ys) {
1148	yc->ys = ppos;
1149      }
1150      if ((subst = ChikujiSubstYomi(d)) < 0) {
1151	makeGLineMessageFromString(d, jrKanjiError);
1152	if (subst == -2) {
1153	  TanMuhenkan(d);
1154	}
1155	else {
1156	  makeYomiReturnStruct(d);
1157	}
1158	return 0; /* �������������������������������������������������������� */
1159      }
1160    }
1161  }
1162
1163  debug_yomi(yc);
1164  makeYomiReturnStruct(d);
1165
1166  if (!yc->kEndp && !(autoconvert && yc->nbunsetsu)) {
1167    if (yc->left || yc->right) {
1168      removeCurrentBunsetsu(d, (tanContext)yc);
1169    }
1170    else {
1171      /* ������������������������������������������������������������������������������������������������������������ */
1172      restoreChikujiIfBaseChikuji(yc);
1173      d->current_mode = yc->curMode = yc->myEmptyMode;
1174      d->kanji_status_return->info |= KanjiEmptyInfo;
1175    }
1176    currentModeInfo(d);
1177  }
1178
1179  return d->nbytes;
1180}
1181
1182/* cfuncdef
1183
1184   findSup -- supkey ��������������������������������������������������������������������
1185
1186   ���������������� supkey ������������ key ����������������������������������������������������������������������������������������
1187   ����������������������������������������������������������������
1188
1189   ����������������������������������������������������
1190 */
1191
1192int findSup (WCHAR_T);
1193
1194int findSup(WCHAR_T key)
1195{
1196  int i;
1197  extern int nkeysup;
1198
1199  for (i = 0 ; i < nkeysup ; i++) {
1200    if (key == keysup[i].key) {
1201      return i + 1;
1202    }
1203  }
1204  return 0;
1205}
1206
1207/* cfuncdef
1208
1209   makePhonoOnBuffer -- yomiContext ����������������������������������������������������������������������������
1210   ��������
1211
1212   ������������������������������������������������������������ 1 ���������������������������������������������������� 0 ����������������
1213
1214   �������������������������������� flag ���� RkwMapPhonogram ��������������������������������
1215   ������������ english ����������������������������������������������������������������������������������������������������
1216
1217 */
1218
1219static
1220int makePhonoOnBuffer(uiContext d, yomiContext yc, unsigned char key, int flag, int english)
1221{
1222  int i, n, m, t, sm, henkanflag, prevflag, cond;
1223  int retval = 0;
1224  int sup = 0;
1225  int engflag = (english && englishdic);
1226  int engdone = 0;
1227  WCHAR_T *subp;
1228#ifndef WIN
1229  WCHAR_T kana_char[1024], sub_buf[1024];
1230#else
1231  WCHAR_T *kana_char, *sub_buf;
1232
1233  kana_char = (WCHAR_T *)malloc(sizeof(WCHAR_T) * 1024);
1234  sub_buf = (WCHAR_T *)malloc(sizeof(WCHAR_T) * 1024);
1235  if (!kana_char || !sub_buf) {
1236    if (kana_char) {
1237      free(kana_char);
1238    }
1239    if (sub_buf) {
1240      free(sub_buf);
1241    }
1242    return 0;
1243  }
1244#endif
1245
1246  if (cannaconf.ignore_case) flag |= RK_IGNORECASE;
1247
1248  /* �������������������������������������������������������� */
1249  for (;;) {
1250#ifndef USE_ROMKANATABLE_FOR_KANAKEY
1251    if ((flag & RK_FLUSH) &&
1252	yc->kRStartp != yc->kCurs &&
1253	!WIsG0(yc->kana_buffer[yc->kCurs - 1])) {
1254      /* �������������������������������������������������������������������������������� */
1255      kana_char[0] = yc->kana_buffer[yc->kRStartp];
1256      n = m = 1; t = 0;
1257      henkanflag = HENKANSUMI;
1258    }
1259    /* ���������������������������������������� */
1260    else
1261#endif
1262      if ((cond = (!(yc->generalFlags & CANNA_YOMI_ROMAJI) &&
1263		   !(yc->generalFlags & CANNA_YOMI_IGNORE_USERSYMBOLS) &&
1264		   (yc->kCurs - yc->kRStartp) == 1 &&
1265		   (sup = findSup(yc->kana_buffer[yc->kRStartp]))) )
1266	  && keysup[sup - 1].ncand > 0) {
1267      n = 1; t = 0;
1268      WStrcpy(kana_char, keysup[sup - 1].cand[0]);
1269      m = WStrlen(kana_char);
1270      /* defsymbol ���������������������������������������������������� */
1271      yc->romaji_buffer[yc->rStartp] = keysup[sup - 1].xkey;
1272      henkanflag = HENKANSUMI | SUPKEY;
1273    }
1274    else {
1275      if (cond) { /* && keysup[sup - 1].ncand == 0 */
1276      /* defsymbol �������������������������������������������������������������������������������������������������������� */
1277	yc->kana_buffer[yc->kRStartp] =
1278	  yc->romaji_buffer[yc->rStartp] = keysup[sup - 1].xkey;
1279      }
1280      if (yc->romdic != (struct RkRxDic *)NULL
1281	  && !(yc->generalFlags & CANNA_YOMI_ROMAJI)) {
1282	if (engflag &&
1283	    RkwMapPhonogram(englishdic, kana_char, 1024,
1284			    yc->kana_buffer + yc->kRStartp,
1285			    yc->kCurs - yc->kRStartp,
1286			    (WCHAR_T)key,
1287			    flag, &n, &m, &t, &yc->last_rule) &&
1288	    n > 0) {
1289	  henkanflag = HENKANSUMI | GAIRAIGO;
1290	  engdone = 1;
1291	}
1292	else if (engflag && 0 == n /* �������� RkwMapPhonogram ���������������� */ &&
1293		 RkwMapPhonogram(englishdic, kana_char, 1024,
1294				 yc->kana_buffer + yc->kRStartp,
1295				 yc->kCurs - yc->kRStartp,
1296				 (WCHAR_T)key,
1297				 flag | RK_FLUSH,
1298				 &n, &m, &t, &yc->last_rule) &&
1299		 n > 0) {
1300	  henkanflag = HENKANSUMI | GAIRAIGO;
1301	  engdone = 1;
1302	}
1303	else {
1304	  engflag = 0;
1305	  if (RkwMapPhonogram(yc->romdic, kana_char, 1024,
1306			      yc->kana_buffer + yc->kRStartp,
1307			      yc->kCurs - yc->kRStartp,
1308			      (WCHAR_T) key,
1309			      flag | RK_SOKON, &n, &m, &t, &yc->last_rule)) {
1310	    /* RK_SOKON ���������������������������������������� */
1311	    henkanflag = HENKANSUMI;
1312	  }
1313	  else {
1314	    henkanflag = 0;
1315	  }
1316	  if (n > 0 && !engdone) {
1317	    engflag = (english && englishdic);
1318	  }
1319	}
1320	if (n == yc->kCurs - yc->kRStartp) {
1321	  key = (unsigned char)0;
1322	}
1323      }else{
1324	t = 0;
1325	henkanflag = (yc->generalFlags & CANNA_YOMI_ROMAJI) ?
1326	  (HENKANSUMI | STAYROMAJI) : 0;
1327	m = n = (yc->kCurs - yc->kRStartp) ? 1 : 0;
1328	WStrncpy(kana_char, yc->kana_buffer + yc->kRStartp, n);
1329      }
1330    }
1331
1332    /* ���������������������������� n �������������������������������������������� */
1333
1334    if (n <= 0) {
1335      break;
1336    }
1337    else {
1338      int unchanged;
1339
1340      /* ���������������������������������������������������������������� */
1341      if (cannaconf.abandonIllegalPhono && !henkanflag && !yc->n_susp_chars) {
1342	/* ���������������������������������������� */
1343	sm = 0; subp = sub_buf;
1344	/* t �������������������� henkanflag ���� 0 ������������������������������������������������ */
1345	/* WStrncpy(subp, kana_char + m, t); */
1346      }else{
1347	sm = m; subp = kana_char;
1348	if (yc->generalFlags & (CANNA_YOMI_KATAKANA | CANNA_YOMI_HIRAGANA)) {
1349	  int tempm;
1350
1351	  if (yc->generalFlags & CANNA_YOMI_KATAKANA) {
1352	    tempm = RkwCvtKana(sub_buf, 1024, subp, sm);
1353	  }
1354	  else {
1355	    tempm = RkwCvtHira(sub_buf, 1024, subp, sm);
1356	  }
1357	  /* �������������������������������������������������������������������������������������������������������������������� */
1358	  WStrncpy(sub_buf + tempm, subp + sm, t);
1359	  subp = sub_buf;
1360	  sm = tempm;
1361	}
1362	if (yc->generalFlags & (CANNA_YOMI_ZENKAKU | CANNA_YOMI_HANKAKU)) {
1363	  int tempm;
1364	  WCHAR_T *otherp = (subp == sub_buf) ? kana_char : sub_buf;
1365
1366	  if (yc->generalFlags & CANNA_YOMI_ZENKAKU) {
1367	    tempm = RkwCvtZen(otherp, 1024, subp, sm);
1368	  }
1369	  else {
1370	    tempm = RkwCvtHan(otherp, 1024, subp, sm);
1371	  }
1372	  WStrncpy(otherp + tempm, subp + sm, t);
1373	  subp = otherp;
1374	  sm = tempm;
1375	}
1376
1377	if (yc->generalFlags & CANNA_YOMI_KAKUTEI) { /* ������������������������ */
1378	  int off;
1379
1380	  chikujiEndBun(d);
1381	  WStrncpy(d->buffer_return + d->nbytes,
1382		   yc->kana_buffer, yc->kRStartp);
1383	  d->nbytes += yc->kRStartp;
1384
1385	  off = yc->kCurs - yc->kRStartp;
1386	  yc->kRStartp = 0;
1387	  yc->kCurs -= off;
1388	  kanaReplace(-yc->kCurs, (WCHAR_T *)0, 0, 0);
1389	  yc->kCurs += off;
1390
1391	  WStrncpy(d->buffer_return + d->nbytes, subp, sm);
1392	  d->nbytes += sm;
1393	  subp += sm;
1394	  sm = 0;
1395	}
1396      }
1397      /* �������������������������������������������������������������������������������������������� */
1398
1399      unchanged = yc->kCurs - yc->kRStartp - n;
1400      yc->kCurs -= unchanged;
1401      prevflag = (yc->kAttr[yc->kRStartp] & SENTOU);
1402      kanaReplace(-n, subp, sm + t, henkanflag);
1403      if ( prevflag ) {
1404	yc->kAttr[yc->kRStartp] |= SENTOU;
1405      }
1406      yc->kRStartp += sm;
1407      if (t == 0 && m > 0 && unchanged) {
1408	yc->kAttr[yc->kRStartp] |= SENTOU;
1409      }
1410      for (i = yc->kRStartp ; i < yc->kCurs ; i++) {
1411	yc->kAttr[i] &= ~HENKANSUMI; /* HENKANSUMI �������������������������������� */
1412      }
1413      yc->kCurs += unchanged;
1414
1415      if (t > 0) {
1416	/* suspend ����������������������������������������������������������������������������������������������������
1417           ������������������������������������������������������������������������������������������������������������ */
1418
1419	if (yc->n_susp_chars) {
1420	  yc->n_susp_chars += t - n;
1421	}
1422	else {
1423	  yc->n_susp_chars = SUSPCHARBIAS + t - n;
1424	}
1425
1426	/* ���������������������������������������������������������������� key ���������������������������� */
1427	key = (unsigned char)yc->kana_buffer[yc->kRStartp + t];
1428      }
1429      else if (m > 0) { /* ���������������������������������������������������������������������������� */
1430	int n_cor_keys = n -
1431	  (yc->n_susp_chars ? yc->n_susp_chars - SUSPCHARBIAS : 0);
1432
1433	retval = 1; /* ������������������������������������ */
1434	yc->rStartp += n_cor_keys;
1435	if (cannaconf.abandonIllegalPhono &&
1436	    !henkanflag && !yc->n_susp_chars) {
1437	  yc->rStartp -= n;
1438	  unchanged = yc->rCurs - yc->rStartp - n;
1439	  yc->rCurs -= unchanged;
1440	  romajiReplace(-n, (WCHAR_T *)0, 0, 0);
1441	  yc->rCurs += unchanged;
1442	  retval = 0; /* �������������������������������������������������������� */
1443	}
1444	else if (yc->generalFlags & CANNA_YOMI_KAKUTEI) {
1445	  int offset = yc->rCurs - yc->rStartp;
1446
1447	  yc->rCurs -= offset;
1448	  romajiReplace(-yc->rCurs, (WCHAR_T *)0, 0, 0);
1449	  yc->rCurs += offset;
1450	  retval = 0; /* �������������������������������������������������������� */
1451	}
1452	yc->rAttr[yc->rStartp] |= SENTOU;
1453	yc->n_susp_chars = /* t ? SUSPCHARBIAS + t : (t ������������ 0)*/ 0;
1454      }
1455    }
1456  }
1457#ifdef WIN
1458  free(kana_char);
1459  free(sub_buf);
1460#endif
1461  return retval;
1462}
1463
1464#define KANAYOMIINSERT_BUFLEN 10
1465
1466/* ����������������������������������������������������������������������������������������������������
1467   ������������������������������������������������������������������������������������������������������������
1468   ���������������������������������������������������� */
1469
1470/*
1471  dakuonP -- predicate for Japanese voiced sounds (Japanese specific)
1472
1473  argument:
1474            ch(WCHAR_T): character to be inspected
1475
1476  return value:
1477            0: Not a voiced sound.
1478	    1: Semi voiced sound.
1479	    2: Full voiced sound.
1480 */
1481
1482#define DAKUON_HV 1
1483#define DAKUON_FV 2
1484
1485inline
1486int dakuonP(WCHAR_T ch)
1487{
1488  static int dakuon_first_time = 1;
1489  static WCHAR_T hv, fv;
1490
1491  if (dakuon_first_time) { /* �������������������������������� */
1492    WCHAR_T buf[2];
1493
1494    dakuon_first_time = 0;
1495
1496    MBstowcs(buf, "\216\336"/* �������� */, 2);
1497    fv = buf[0];
1498    MBstowcs(buf, "\216\337"/* ������������ */, 2);
1499    hv = buf[0];
1500  }
1501
1502  if (ch == hv) {
1503    return DAKUON_HV;
1504  }
1505  else if (ch == fv) {
1506    return DAKUON_FV;
1507  }
1508  else {
1509    return 0;
1510  }
1511}
1512
1513/*
1514  growDakuonP -- ������������������������������������
1515
1516  ��������:
1517       ch(WCHAR_T): ��������������������������������
1518
1519  ������������:
1520       0: ����������������
1521       1: ������������
1522       2: ����������������������������
1523       3: ������������������������������������
1524 */
1525
1526#define GROW_U  1
1527#define GROW_FV 2
1528#define GROW_HV 3
1529
1530static
1531int growDakuonP(WCHAR_T ch)
1532{
1533  /* ���������������������������������������������������������������� (������������������������������������) */
1534  static int dakuon_first_time = 1;
1535  static WCHAR_T wu, wka, wto, wha, who;
1536
1537  if (dakuon_first_time) { /* �������������������������������� */
1538    WCHAR_T buf[2];
1539
1540    dakuon_first_time = 0;
1541
1542    MBstowcs(buf, "\216\263"/* ���� */, 2);
1543    wu = buf[0];
1544    MBstowcs(buf, "\216\266"/* ���� */, 2);
1545    wka = buf[0];
1546    MBstowcs(buf, "\216\304"/* ���� */, 2);
1547    wto = buf[0];
1548    MBstowcs(buf, "\216\312"/* ���� */, 2);
1549    wha = buf[0];
1550    MBstowcs(buf, "\216\316"/* ���� */, 2);
1551    who = buf[0];
1552  }
1553
1554  if (ch == wu) {
1555    return GROW_U;
1556  }
1557  else if (wka <= ch && ch <= wto) {
1558    return GROW_FV;
1559  }
1560  else if (wha <= ch && ch <= who) {
1561    return GROW_HV;
1562  }
1563  else {
1564    return 0;
1565  }
1566}
1567
1568static
1569int KanaYomiInsert(uiContext d)
1570{
1571  static WCHAR_T kana[3], *kanap;
1572  WCHAR_T buf1[KANAYOMIINSERT_BUFLEN], buf2[KANAYOMIINSERT_BUFLEN];
1573  /* The array above is not so big (10 WCHAR_T length) 1996.6.5 kon */
1574  WCHAR_T *bufp, *nextbufp;
1575  int len, replacelen, spos;
1576  yomiContext yc = (yomiContext)d->modec;
1577  int dakuon, grow_dakuon;
1578
1579  yc->generalFlags &= ~CANNA_YOMI_BREAK_ROMAN;
1580  kana[0] = (WCHAR_T)0;
1581  kana[1] = d->buffer_return[0];
1582  kana[2] = (WCHAR_T)0;
1583  kanap = kana + 1;
1584  replacelen = 0; len = 1;
1585  romajiReplace(0, kanap, 1, SENTOU);
1586  yc->rStartp = yc->rCurs;
1587  if ((dakuon = dakuonP(kanap[0])) != 0) { /* �������������������� */
1588    if (yc->rCurs > 1) {
1589      kana[0] = yc->romaji_buffer[yc->rCurs - 2];
1590      if ((grow_dakuon = growDakuonP(kana[0])) == GROW_HV ||
1591	  (grow_dakuon && dakuon == DAKUON_FV)) {
1592	kanap = kana; len = 2; replacelen = -1;
1593	yc->rAttr[yc->rCurs - 1] &= ~SENTOU;
1594      }
1595    }
1596  }
1597#ifdef DEBUG
1598  if (iroha_debug) {
1599    WCHAR_T aho[200];
1600
1601    WStrncpy(aho, kana, len);
1602    aho[len] = 0;
1603    fprintf(stderr, "\312\321\264\271\301\260(%s)", aho);
1604                   /* ������������ */
1605  }
1606#endif
1607  bufp = kanap; nextbufp = buf1;
1608  if (yc->generalFlags & CANNA_YOMI_ZENKAKU ||
1609      !(yc->generalFlags & (CANNA_YOMI_ROMAJI | CANNA_YOMI_HANKAKU))) {
1610    len = RkwCvtZen(nextbufp, KANAYOMIINSERT_BUFLEN, bufp, len);
1611    bufp = nextbufp;
1612    if (bufp == buf1) {
1613      nextbufp = buf2;
1614    }
1615    else {
1616      nextbufp = buf1;
1617    }
1618  }
1619  if (!(yc->generalFlags & (CANNA_YOMI_ROMAJI | CANNA_YOMI_KATAKANA))) {
1620    /* ���������������������������� */
1621    len = RkwCvtHira(nextbufp, KANAYOMIINSERT_BUFLEN, bufp, len);
1622    bufp = nextbufp;
1623    if (bufp == buf1) {
1624      nextbufp = buf2;
1625    }
1626    else {
1627      nextbufp = buf1;
1628    }
1629  }
1630
1631  spos = yc->kCurs + replacelen;
1632  kanaReplace(replacelen, bufp, len, HENKANSUMI);
1633  yc->kAttr[spos] |= SENTOU;
1634
1635  yc->kRStartp = yc->kCurs;
1636  yc->rStartp = yc->rCurs;
1637  if (growDakuonP(yc->romaji_buffer[yc->rCurs - 1])) {
1638    yc->kRStartp--;
1639    yc->rStartp--;
1640  }
1641
1642  if (yc->generalFlags & CANNA_YOMI_KAKUTEI) { /* ���������������������������� */
1643    int off, i;
1644
1645    for (i = len = 0 ; i < yc->kRStartp ; i++) {
1646      if (yc->kAttr[i] & SENTOU) {
1647	do {
1648	  len++;
1649	} while (!(yc->rAttr[len] & SENTOU));
1650      }
1651    }
1652
1653    if (yc->kRStartp < d->n_buffer) {
1654      WStrncpy(d->buffer_return, yc->kana_buffer, yc->kRStartp);
1655      d->nbytes = yc->kRStartp;
1656    }
1657    else {
1658      d->nbytes = 0;
1659    }
1660    off = yc->kCurs - yc->kRStartp;
1661    yc->kCurs -= off;
1662    kanaReplace(-yc->kCurs, (WCHAR_T *)0, 0, 0);
1663    yc->kCurs += off;
1664    off = yc->rCurs - len;
1665    yc->rCurs -= off;
1666    romajiReplace(-yc->rCurs, (WCHAR_T *)0, 0, 0);
1667    yc->rCurs += off;
1668  }
1669  else {
1670    d->nbytes = 0;
1671  }
1672
1673  if (yc->rStartp == yc->rCurs && yc->generalFlags & CANNA_YOMI_CHIKUJI_MODE &&
1674      ChikujiSubstYomi(d) == -1) {
1675    makeRkError(d, "\303\340\274\241\312\321\264\271\244\313\274\272\307\324"
1676	"\244\267\244\336\244\267\244\277");
1677                   /* �������������������������������������������� */
1678    return 0;
1679  }
1680
1681  makeYomiReturnStruct(d);
1682
1683  if (yc->kEndp <= yc->cStartp &&
1684      !((yc->generalFlags & CANNA_YOMI_CHIKUJI_MODE) && yc->nbunsetsu)) {
1685    if (yc->left || yc->right) {
1686      removeCurrentBunsetsu(d, (tanContext)yc);
1687    }
1688    else {
1689      /* ������������������������������������������������������������������������������������������������������������ */
1690      restoreChikujiIfBaseChikuji(yc);
1691      d->current_mode = yc->curMode = yc->myEmptyMode;
1692      d->kanji_status_return->info |= KanjiEmptyInfo;
1693    }
1694    currentModeInfo(d);
1695  }
1696
1697  return d->nbytes;
1698}
1699
1700#undef KANAYOMIINSERT_BUFLEN
1701
1702void
1703moveStrings(WCHAR_T *str, BYTE *attr, int start, int end, int distance)
1704{
1705  int i;
1706
1707  if (distance > 0) { /* ���������������������������� */
1708    for (i = end ; start <= i ; i--) { /* ���������������������������� */
1709      str[i + distance]  = str[i];
1710      attr[i + distance] = attr[i];
1711    }
1712  }
1713  else if (distance < 0) { /* ������������������������ */
1714    for (i = start ; i <= end ; i++) {     /* ������������������������ */
1715      str[i + distance]  = str[i];
1716      attr[i + distance] = attr[i];
1717    }
1718  }
1719  /* else { ������������������������ } */
1720}
1721
1722static
1723int howFarToGoBackward(yomiContext yc)
1724{
1725  if (yc->kCurs <= yc->cStartp) {
1726    return 0;
1727  }
1728  if (!cannaconf.ChBasedMove) {
1729    BYTE *st = yc->kAttr;
1730    BYTE *cur = yc->kAttr + yc->kCurs;
1731    BYTE *p = cur;
1732
1733    for (--p ; p > st && !(*p & SENTOU) ;) {
1734      --p;
1735    }
1736    if (yc->kAttr + yc->cStartp > p) {
1737      p = yc->kAttr + yc->cStartp;
1738    }
1739    return cur - p;
1740  }
1741  return 1;
1742}
1743
1744static
1745int howFarToGoForward(yomiContext yc)
1746{
1747  if (yc->kCurs == yc->kEndp) {
1748    return 0;
1749  }
1750  if (!cannaconf.ChBasedMove) {
1751    BYTE *end = yc->kAttr + yc->kEndp;
1752    BYTE *cur = yc->kAttr + yc->kCurs;
1753    BYTE *p = cur;
1754
1755    for (++p ; p < end && !(*p & SENTOU) ;) {
1756      p++;
1757    }
1758    return p - cur;
1759  }
1760  return 1;
1761}
1762
1763
1764static int
1765YomiBackward(uiContext d)
1766{
1767  yomiContext yc = (yomiContext)d->modec;
1768  int howManyMove;
1769
1770  d->nbytes = 0;
1771  if (forceRomajiFlushYomi(d))
1772    return(d->nbytes);
1773
1774  if ((yc->generalFlags & CANNA_YOMI_CHIKUJI_MODE) &&
1775      !(yc->status & CHIKUJI_OVERWRAP) && yc->nbunsetsu) {
1776    /* ������������������������������������������������ */
1777    yc->status |= CHIKUJI_OVERWRAP;
1778    moveToChikujiTanMode(d);
1779    return TanBackwardBunsetsu(d);
1780  }
1781
1782  howManyMove = howFarToGoBackward(yc);
1783  if (howManyMove) {
1784    yc->kCurs -= howManyMove;
1785
1786    if (yc->kCurs < yc->kRStartp)
1787      yc->kRStartp = yc->kCurs;   /* ������������������������������������������������������������ */
1788
1789    /* ������������������������������������������������������������������������������������������������������������
1790       (����������������������������������������������������������������������������)����������������������������
1791       �������������������������������� */
1792
1793    if (yc->kAttr[yc->kCurs] & SENTOU) {
1794      while ( yc->rCurs > 0 && !(yc->rAttr[--yc->rCurs] & SENTOU) )
1795	/* EMPTY */
1796	;
1797      if (yc->rCurs < yc->rStartp)
1798	yc->rStartp = yc->rCurs;
1799    }
1800  }
1801  else if (yc->nbunsetsu) { /* ����������������������������(��������) */
1802    yc->curbun = yc->nbunsetsu - 1;
1803    if (RkwGoTo(yc->context, yc->nbunsetsu - 1) == -1) { /* ������������������������ */
1804      return makeRkError(d, "\312\270\300\341\244\316\260\334\306\260\244\313"
1805	"\274\272\307\324\244\267\244\336\244\267\244\277");
1806                            /* ������������������������������������������������ */
1807    }
1808    yc->kouhoCount = 0;
1809    moveToChikujiTanMode(d);
1810  }
1811  else if (yc->left) {
1812    return TbBackward(d);
1813  }
1814  else if (!cannaconf.CursorWrap) {
1815    return NothingChanged(d);
1816  }
1817  else if (yc->right) {
1818    return TbEndOfLine(d);
1819  }
1820  else {
1821    yc->kCurs = yc->kRStartp = yc->kEndp;
1822    yc->rCurs = yc->rStartp = yc->rEndp;
1823  }
1824  yc->status |= CHIKUJI_OVERWRAP;
1825  makeYomiReturnStruct(d);
1826
1827  return 0;
1828}
1829
1830static
1831int YomiNop(uiContext d)
1832{
1833  /* currentModeInfo ������������������������������������������������������������������������������������������������������������ */
1834  d->majorMode = d->minorMode = CANNA_MODE_AlphaMode;
1835  currentModeInfo(d);
1836  makeYomiReturnStruct(d);
1837  return 0;
1838}
1839
1840static
1841int YomiForward(uiContext d)
1842{
1843  yomiContext yc = (yomiContext)d->modec;
1844  int howManyMove;
1845
1846  d->nbytes = 0;
1847  if (forceRomajiFlushYomi(d))
1848    return(d->nbytes);
1849
1850  if ((yc->generalFlags & CANNA_YOMI_CHIKUJI_MODE) &&
1851      !(yc->status & CHIKUJI_OVERWRAP) && yc->nbunsetsu) {
1852    yc->status |= CHIKUJI_OVERWRAP;
1853    moveToChikujiTanMode(d);
1854    return TanForwardBunsetsu(d);
1855  }
1856
1857  howManyMove = howFarToGoForward(yc);
1858  if (howManyMove) {
1859    if (yc->kAttr[yc->kCurs] & SENTOU) { /* �������������������������������������������������������� */
1860      while ( !yc->rAttr[++yc->rCurs] )
1861	/* EMPTY */
1862	; /* ������������������������������������ */
1863      yc->rStartp = yc->rCurs;
1864    }
1865
1866    yc->kCurs += howManyMove;   /* ���������������������������� ���������������������������������������� */
1867    yc->kRStartp = yc->kCurs;
1868    yc->status &= ~CHIKUJI_ON_BUNSETSU;
1869  }
1870  else if (yc->right) {
1871    return TbForward(d);
1872  }
1873  else if (!cannaconf.CursorWrap) {
1874    return NothingChanged(d);
1875  }
1876  else if (yc->left) {
1877    return TbBeginningOfLine(d);
1878  }
1879  else if (yc->nbunsetsu) { /* ��������������������(��������) */
1880    yc->kouhoCount = 0;
1881    yc->curbun = 0;
1882    if (RkwGoTo(yc->context, 0) == -1) {
1883      return makeRkError(d, "\312\270\300\341\244\316\260\334\306\260\244\313"
1884	"\274\272\307\324\244\267\244\336\244\267\244\277");
1885                            /* ������������������������������������������������ */
1886    }
1887    moveToChikujiTanMode(d);
1888  }
1889  else {
1890    yc->kRStartp = yc->kCurs = yc->rStartp = yc->rCurs = 0;
1891  }
1892
1893  yc->status |= CHIKUJI_OVERWRAP;
1894  makeYomiReturnStruct(d);
1895  return 0;
1896}
1897
1898int static YomiBeginningOfLine (uiContext);
1899
1900static
1901int YomiBeginningOfLine(uiContext d)
1902{
1903  yomiContext yc = (yomiContext)d->modec;
1904
1905  d->nbytes = 0;
1906  if (forceRomajiFlushYomi(d))
1907    return(d->nbytes);
1908
1909  if (yc->left) {
1910    return TbBeginningOfLine(d);
1911  }
1912  else if (yc->nbunsetsu) { /* ���������������������������������������������������� */
1913    yc->kouhoCount = 0;
1914    if (RkwGoTo(yc->context, 0) < 0) {
1915      return makeRkError(d, "\312\270\300\341\244\316\260\334\306\260\244\313"
1916	"\274\272\307\324\244\267\244\336\244\267\244\277");
1917                            /* ������������������������������������������������ */
1918    }
1919    yc->curbun = 0;
1920    moveToChikujiTanMode(d);
1921  }
1922  else {
1923    yc->kRStartp = yc->kCurs = yc->cStartp;
1924    yc->rStartp = yc->rCurs = yc->cRStartp;
1925  }
1926  yc->status |= CHIKUJI_OVERWRAP;
1927  makeYomiReturnStruct(d);
1928  return(0);
1929}
1930
1931
1932static
1933int YomiEndOfLine(uiContext d)
1934{
1935  yomiContext yc = (yomiContext)d->modec;
1936
1937  d->nbytes = 0;
1938  if (forceRomajiFlushYomi(d))
1939    return(d->nbytes);
1940
1941  if (yc->right) {
1942    return TbEndOfLine(d);
1943  }
1944  else {
1945    yc->kRStartp = yc-> kCurs = yc->kEndp;
1946    yc->rStartp = yc-> rCurs = yc->rEndp;
1947    yc->status &= ~CHIKUJI_ON_BUNSETSU;
1948    yc->status |= CHIKUJI_OVERWRAP;
1949  }
1950  makeYomiReturnStruct(d);
1951  return 0;
1952}
1953
1954int
1955forceRomajiFlushYomi(uiContext d)
1956{
1957  yomiContext yc = (yomiContext)d->modec;
1958
1959  if (yc->kCurs != yc->kRStartp) {
1960    d->nbytes = 0;
1961    if (RomajiFlushYomi(d, (WCHAR_T *)NULL, 0) == 0) { /* empty mode */
1962      d->more.todo = 1;
1963      d->more.ch = d->ch;
1964      d->more.fnum = 0;    /* �������� ch ���������������������������������������� */
1965      return(1);
1966    }
1967  }
1968  return(0);
1969}
1970
1971/* RomajiFlushYomi(d, buffer, bufsize) ������������������������������������
1972 *
1973 * ������������������������(uiContext)d ����������������������������������������������������
1974 * (yc->romaji_buffer ���� yc->kana_buffer)��������������������buffer ����������������������������
1975 * ������������������������������������������������������������������������������������������������������������������������������������
1976 * ��������������������������������������������������������������������
1977 *
1978 * buffer ������������ NULL ������������������������������������������������������������������������������������������������
1979 *
1980 * ����������������
1981 *
1982 *    ����������������������������
1983 *
1984 * ����������������
1985 *
1986 *    d  (uiContext)  ������������������������������������
1987 *    buffer (char *)    ������������������������������������������������ (NULL ����)
1988 *
1989 * ��������������������
1990 *
1991 *    buffer ��������������������������������������������(����������������)
1992 *
1993 * ��������������������
1994 *
1995 */
1996
1997int RomajiFlushYomi(uiContext d, WCHAR_T *b, int bsize)
1998{
1999  int ret;
2000  yomiContext yc = (yomiContext)d->modec;
2001
2002  yc->generalFlags &= ~CANNA_YOMI_BREAK_ROMAN;
2003
2004  makePhonoOnBuffer(d, yc, (unsigned char)0, RK_FLUSH, 0);
2005  yc->n_susp_chars = 0; /* ������������������������������������������������������������ */
2006  yc->last_rule = 0;
2007
2008  ret = yc->kEndp - yc->cStartp; /* ���������������������������������������������������������������� */
2009  if (b) {
2010    if (bsize > ret) {
2011      WStrncpy(b, yc->kana_buffer + yc->cStartp, ret);
2012      b[ret] = '\0';
2013    }
2014    else {
2015      WStrncpy(b, yc->kana_buffer + yc->cStartp, bsize);
2016      ret = bsize;
2017    }
2018  }
2019  if (ret == 0) { /* �������������������������������������������������������������������������������� */
2020    d->current_mode = yc->curMode = yc->myEmptyMode;
2021    /* ���������������������������������������������������������������������������������������� */
2022  }
2023  return ret;
2024}
2025
2026inline int
2027saveFlags(yomiContext yc)
2028{
2029  if (!(yc->savedFlags & CANNA_YOMI_MODE_SAVED)) {
2030    yc->savedFlags = (yc->generalFlags &
2031		      (CANNA_YOMI_ATTRFUNCS | CANNA_YOMI_BASE_HANKAKU)) |
2032			CANNA_YOMI_MODE_SAVED;
2033    yc->savedMinorMode = yc->minorMode;
2034    return 1;
2035  }
2036  else {
2037    return 0;
2038  }
2039}
2040
2041void
2042restoreFlags(yomiContext yc)
2043{
2044  yc->generalFlags &= ~(CANNA_YOMI_ATTRFUNCS | CANNA_YOMI_BASE_HANKAKU);
2045  yc->generalFlags |= yc->savedFlags
2046    & (CANNA_YOMI_ATTRFUNCS | CANNA_YOMI_BASE_HANKAKU);
2047  yc->savedFlags = (long)0;
2048  yc->minorMode = yc->savedMinorMode;
2049}
2050
2051/*
2052 doYomiKakutei -- ��������������������������������������������������������
2053
2054  retval 0 -- ������������������������������������
2055         1 -- ��������������������������������������������
2056        -1 -- ����������������
2057 */
2058
2059inline int
2060doYomiKakutei(uiContext d)
2061{
2062  int len;
2063
2064  len = RomajiFlushYomi(d, (WCHAR_T *)0, 0);
2065  if (len == 0) {
2066    return 1;
2067  }
2068
2069  return 0;
2070}
2071
2072int
2073xString(WCHAR_T *str, int len, WCHAR_T *s, WCHAR_T *e)
2074{
2075  if (e < s + len) {
2076    len = e - s;
2077  }
2078  WStrncpy(s, str, len);
2079  return len;
2080}
2081
2082inline int
2083xYomiKakuteiString(yomiContext yc, WCHAR_T *s, WCHAR_T *e)
2084{
2085  return xString(yc->kana_buffer + yc->cStartp, yc->kEndp - yc->cStartp, s, e);
2086}
2087
2088inline int
2089xYomiYomi(yomiContext yc, WCHAR_T *s, WCHAR_T *e)
2090{
2091  return xString(yc->kana_buffer, yc->kEndp, s, e);
2092}
2093
2094inline int
2095xYomiRomaji(yomiContext yc, WCHAR_T *s, WCHAR_T *e)
2096{
2097  return xString(yc->romaji_buffer, yc->rEndp, s, e);
2098}
2099
2100inline void
2101finishYomiKakutei(uiContext d)
2102{
2103  yomiContext yc = (yomiContext)d->modec;
2104
2105  if (yc->savedFlags & CANNA_YOMI_MODE_SAVED) {
2106    restoreFlags(yc);
2107  }
2108}
2109
2110int
2111appendTan2Yomi(tanContext tan, yomiContext yc)
2112{
2113  int klen, rlen;
2114
2115  klen = WStrlen(tan->yomi);
2116  rlen = WStrlen(tan->roma);
2117
2118  if (yc->kEndp + klen < ROMEBUFSIZE && yc->rEndp + rlen < ROMEBUFSIZE) {
2119    WStrcpy(yc->kana_buffer + yc->kEndp, tan->yomi);
2120    WStrcpy(yc->romaji_buffer + yc->rEndp, tan->roma);
2121    bcopy(tan->kAttr, yc->kAttr + yc->kEndp, (klen + 1) * sizeof(BYTE));
2122    bcopy(tan->rAttr, yc->rAttr + yc->rEndp, (rlen + 1) * sizeof(BYTE));
2123    yc->rEndp += rlen;
2124    yc->kEndp += klen;
2125    return 1;
2126  }
2127  return 0;
2128}
2129
2130static
2131int appendYomi2Yomi(yomiContext yom, yomiContext yc)
2132{
2133  int rlen, klen;
2134
2135  rlen = yom->rEndp;
2136  klen = yom->kEndp;
2137  if (yc->kEndp + klen < ROMEBUFSIZE && yc->rEndp + rlen < ROMEBUFSIZE) {
2138    yom->romaji_buffer[rlen] = (WCHAR_T)'\0';
2139    yom->kana_buffer[klen] = (WCHAR_T)'\0';
2140    WStrcpy(yc->romaji_buffer + yc->rEndp, yom->romaji_buffer);
2141    WStrcpy(yc->kana_buffer + yc->kEndp, yom->kana_buffer);
2142    bcopy(yom->kAttr, yc->kAttr + yc->kEndp, (klen + 1) * sizeof(BYTE));
2143    bcopy(yom->rAttr, yc->rAttr + yc->rEndp, (rlen + 1) * sizeof(BYTE));
2144    yc->rEndp += rlen;
2145    yc->kEndp += klen;
2146    return 1;
2147  }
2148  return 0;
2149}
2150
2151yomiContext
2152dupYomiContext(yomiContext yc)
2153{
2154  yomiContext res;
2155
2156  res = newYomiContext((WCHAR_T *)NULL, 0, /* �������������������������������� */
2157		       CANNA_NOTHING_RESTRICTED,
2158		       (int)!CANNA_YOMI_CHGMODE_INHIBITTED,
2159		       (int)!CANNA_YOMI_END_IF_KAKUTEI,
2160		       CANNA_YOMI_INHIBIT_NONE);
2161  if (res) {
2162    res->generalFlags = yc->generalFlags;
2163    res->status = yc->status;
2164    res->majorMode = yc->majorMode;
2165    res->minorMode = yc->minorMode;
2166    res->myMinorMode = yc->myMinorMode;
2167    res->curMode = yc->curMode;
2168    res->myEmptyMode = yc->myEmptyMode;
2169    res->romdic = yc->romdic;
2170    res->next = yc->next;
2171    res->prevMode = yc->prevMode;
2172    appendYomi2Yomi(yc, res);
2173  }
2174  return res;
2175}
2176
2177
2178/*
2179  doMuhenkan -- ������������������������������������
2180
2181  yc ���������������� tanContext/yomiContext ����������������������������������������������������������������������������
2182  ������������ yc ����������������������������
2183 */
2184
2185void
2186doMuhenkan(uiContext d, yomiContext yc)
2187{
2188  tanContext tan, netan, st = (tanContext)yc;
2189  yomiContext yom;
2190
2191  /* ������������������������������������������������ */
2192  for (tan = st ; tan ; tan = tan->right) {
2193    if (tan->id == YOMI_CONTEXT) {
2194      yom = (yomiContext)tan;
2195      d->modec = (mode_context)yom;
2196      if (yom->nbunsetsu || (yom->generalFlags & CANNA_YOMI_CHIKUJI_MODE)) {
2197	tanMuhenkan(d, -1);
2198      }
2199      if (yom->jishu_kEndp) {
2200	leaveJishuMode(d, yom);
2201      }
2202      /* else ������������������������������������������������������������������������ */
2203    }
2204  }
2205
2206  /* �������������������������������������������������������� */
2207  for (tan = st ; tan ; tan = netan) {
2208    netan = tan->right;
2209    if (tan->id == TAN_CONTEXT) {
2210      appendTan2Yomi(tan, yc);
2211      freeTanContext(tan);
2212    }
2213    else if (tan->id == YOMI_CONTEXT) {
2214      if ((yomiContext)tan != yc) {
2215	appendYomi2Yomi((yomiContext)tan, yc);
2216	freeYomiContext((yomiContext)tan);
2217      }
2218    }
2219  }
2220  yc->rCurs = yc->rStartp = yc->rEndp;
2221  yc->kCurs = yc->kRStartp = yc->kEndp;
2222  yc->right = (tanContext)0;
2223  d->modec = (mode_context)yc;
2224}
2225
2226inline int
2227xTanKakuteiString(yomiContext yc, WCHAR_T *s, WCHAR_T *e)
2228{
2229  WCHAR_T *ss = s;
2230  int i, len, nbun;
2231
2232  nbun = yc->bunlen ? yc->curbun : yc->nbunsetsu;
2233
2234  for (i = 0 ; i < nbun ; i++) {
2235    RkwGoTo(yc->context, i);
2236    len = RkwGetKanji(yc->context, s, (int)(e - s));
2237    if (len < 0) {
2238      if (errno == EPIPE) {
2239	jrKanjiPipeError();
2240      }
2241      jrKanjiError = "\245\253\245\354\245\363\245\310\270\365\312\344\244\362"
2242	"\274\350\244\352\275\320\244\273\244\336\244\273\244\363\244\307"
2243	"\244\267\244\277";
2244                    /* �������������������������������������������������������������������� */
2245    }
2246    else {
2247      s += len;
2248    }
2249  }
2250  RkwGoTo(yc->context, yc->curbun);
2251
2252  if (yc->bunlen) {
2253    len = yc->kEndp - yc->kanjilen;
2254    if (((int)(e - s)) < len) {
2255      len = (int)(e - s);
2256    }
2257    WStrncpy(s, yc->kana_buffer + yc->kanjilen, len);
2258    s += len;
2259  }
2260
2261  if ((yc->generalFlags & CANNA_YOMI_CHIKUJI_MODE) &&
2262      yc->cStartp < yc->kEndp) {
2263    len = xYomiKakuteiString(yc, s, e);
2264    s += len;
2265  }
2266  return (int)(s - ss);
2267}
2268
2269inline int
2270doJishuKakutei(uiContext d, yomiContext yc)
2271{
2272  exitJishu(d);
2273  yc->jishu_kEndp = 0;
2274  return 0;
2275}
2276
2277
2278/*
2279  doKakutei -- ��������������������������������
2280
2281    st �������� et ������������������������ tanContext/yomiContext ������������������������
2282    s �������� e ������������������������������������������������������������
2283    yc_return ���� yomiContext ���������������������������������������������������������������� yomiContext
2284    ������������������������������������������������������������yc_return �������������������������������������������� free
2285    ������������
2286    et->left ���������������������������������������� 0 ������������������������
2287
2288    ������������������������������������������������������������
2289
2290    ������������������������������������ d->modec ��������������������������������������������������������������������������������
2291
2292 */
2293
2294int
2295doKakutei(uiContext d, tanContext st, tanContext et, WCHAR_T *s, WCHAR_T *e, yomiContext *yc_return)
2296{
2297  tanContext tan, netan;
2298  yomiContext yc;
2299  int len, res;
2300  WCHAR_T *ss = s;
2301  int katakanadef = 0, hiraganadef = 0;
2302  extern int auto_define;
2303#ifndef WIN
2304  WCHAR_T ytmpbuf[256];
2305#else
2306  WCHAR_T *ytmpbuf = (WCHAR_T *)malloc(sizeof(WCHAR_T) * 256);
2307  if (!ytmpbuf) {
2308    return 0;
2309  }
2310#endif
2311
2312  /* �������������������������������������������� */
2313  for (tan = st ; tan != et ; tan = tan->right) {
2314    if (tan->id == YOMI_CONTEXT) {
2315      yc = (yomiContext)tan;
2316      d->modec = (mode_context)yc;
2317      if (yc->jishu_kEndp) {
2318        if (auto_define) {
2319          if (yc->jishu_kc == JISHU_ZEN_KATA)
2320            katakanadef = 1;
2321#ifdef HIRAGANAAUTO
2322          if (yc->jishu_kc == JISHU_HIRA)
2323            hiraganadef = 1;
2324#endif
2325          WStrcpy(ytmpbuf, yc->kana_buffer);
2326        }
2327	doJishuKakutei(d, yc);
2328      }
2329      else if (!yc->bunlen && /* �������������������������������� */
2330	       (!yc->nbunsetsu || /* ������������������������... */
2331		(yc->generalFlags & CANNA_YOMI_CHIKUJI_MODE &&
2332		 yc->cStartp < yc->kEndp))) { /* ���������������������������� .. */
2333	long savedFlag = yc->generalFlags;
2334	yc->generalFlags &= ~CANNA_YOMI_KAKUTEI;
2335	/* base-kakutei �������� doYomiKakutei() ��������������������������������
2336	   RomajiFlushYomi() ����������������������������������������������������
2337	   ������������������������������������������������������������ base-kakutei ���������������� */
2338	doYomiKakutei(d);
2339	yc->generalFlags = savedFlag;
2340      }
2341    }
2342  }
2343
2344  /* �������������������������������������������� */
2345  for (tan = st ; tan != et ; tan = tan->right) {
2346    if (tan->id == TAN_CONTEXT) {
2347      len = extractTanString(tan, s, e);
2348    }
2349    else if (tan->id == YOMI_CONTEXT) {
2350      yc = (yomiContext)tan;
2351      d->modec = (mode_context)yc;
2352      if (yc->nbunsetsu || (yc->generalFlags & CANNA_YOMI_CHIKUJI_MODE)) {
2353	len = xTanKakuteiString(yc, s, e);
2354      }else{ /* else �������������������������������������������������������� */
2355	len = xYomiKakuteiString(yc, s, e);
2356      }
2357    }
2358    s += len;
2359  }
2360  res = (int)(s - ss);
2361  if (s < e) {
2362    *s++ = (WCHAR_T)'\0';
2363  }
2364
2365  /* yomiInfo ������������������������ */
2366  if (yomiInfoLevel > 0) {
2367    d->kanji_status_return->info |= KanjiYomiInfo;
2368    for (tan = st ; tan != et ; tan = tan->right) {
2369      if (tan->id == TAN_CONTEXT) {
2370	len = extractTanYomi(tan, s, e);
2371      }
2372      else if (tan->id == YOMI_CONTEXT) {
2373	len = xYomiYomi((yomiContext)tan, s, e);
2374      }
2375      s += len;
2376    }
2377    if (s < e) {
2378      *s++ = (WCHAR_T)'\0';
2379    }
2380
2381    if (yomiInfoLevel > 1) {
2382      for (tan = st ; tan != et ; tan = tan->right) {
2383	if (tan->id == TAN_CONTEXT) {
2384	  len = extractTanRomaji(tan, s, e);
2385	}
2386	else if (tan->id == YOMI_CONTEXT) {
2387	  len = xYomiRomaji((yomiContext)tan, s, e);
2388	}
2389	s += len;
2390      }
2391    }
2392    if (s < e) {
2393      *s++ = (WCHAR_T)'\0';
2394    }
2395  }
2396
2397  /* ������������������������������������ */
2398  if (yc_return) {
2399    *yc_return = (yomiContext)0;
2400  }
2401  for (tan = st ; tan != et ; tan = netan) {
2402    netan = tan->right;
2403    if (tan->id == TAN_CONTEXT) {
2404      freeTanContext(tan);
2405    }
2406    else { /* tan->id == YOMI_CONTEXT */
2407      yc = (yomiContext)tan;
2408      d->modec = (mode_context)yc;
2409
2410      if (yc->nbunsetsu || (yc->generalFlags & CANNA_YOMI_CHIKUJI_MODE)) {
2411	if (yc->bunlen) {
2412	  leaveAdjustMode(d, yc);
2413	}
2414	finishTanKakutei(d);
2415      }else{ /* �������������������������������������������������������� */
2416	finishYomiKakutei(d);
2417      }
2418      if (yc_return && !*yc_return) {
2419	*yc_return = yc;
2420      }else{
2421	/* ������������������������������������������������������������������������������������������������������������ */
2422	/* yc->context ���� close ����������������������������������������1996.10.30 ���� */
2423	freeYomiContext(yc);
2424      }
2425    }
2426  }
2427
2428  if (yc_return) {
2429    yc = *yc_return;
2430    if (yc) {
2431      yc->left = yc->right = (tanContext)0;
2432    }
2433  }
2434  d->modec = (mode_context)0;
2435  /* ���������������������������������������������������������������������������������������������������������������������������� */
2436
2437  /* ������������������������������������������������������������������������������������������������ */
2438  if (katakanadef || hiraganadef) {
2439    WCHAR_T line[ROMEBUFSIZE];
2440    int cnt;
2441    extern int defaultContext;
2442    extern char *kataautodic;
2443#ifdef HIRAGANAAUTO
2444    extern char *hiraautodic;
2445#endif
2446
2447    WStraddbcpy(line, ytmpbuf, ROMEBUFSIZE);
2448    EWStrcat(line, " ");
2449    EWStrcat(line, "#T30");
2450    EWStrcat(line, " ");
2451    cnt = WStrlen(line);
2452    WStraddbcpy(line + cnt, ss, ROMEBUFSIZE - cnt);
2453
2454    if (defaultContext == -1) {
2455      if ((KanjiInit() < 0) || (defaultContext == -1)) {
2456	jrKanjiError = KanjiInitError();
2457        makeGLineMessageFromString(d, jrKanjiError);
2458        goto return_res;
2459      }
2460    }
2461
2462    if (katakanadef) {
2463      if (RkwDefineDic(defaultContext, kataautodic, line) != 0) {
2464        jrKanjiError = "\274\253\306\260\305\320\317\277\244\307\244\255"
2465                       "\244\336\244\273\244\363\244\307\244\267\244\277";
2466                         /* ������������������������������������������������ */
2467        makeGLineMessageFromString(d, jrKanjiError);
2468      }else{
2469        if (cannaconf.auto_sync) {
2470          (void)RkwSync(defaultContext, kataautodic);
2471        }
2472      }
2473    }
2474    if (hiraganadef) {
2475#ifdef HIRAGANAAUTO
2476      if (RkwDefineDic(defaultContext, hiraautodic, line) != 0) {
2477        jrKanjiError = "\274\253\306\260\305\320\317\277\244\307\244\255"
2478                       "\244\336\244\273\244\363\244\307\244\267\244\277";
2479                         /* ������������������������������������������������ */
2480        makeGLineMessageFromString(d, jrKanjiError);
2481      }else{
2482        if (cannaconf.auto_sync) {
2483          (void)RkwSync(defaultContext, hiraautodic);
2484        }
2485      }
2486#endif
2487    }
2488  }
2489 return_res:
2490#ifdef WIN
2491  free(ytmpbuf);
2492#endif
2493  return res;
2494}
2495
2496/*
2497  cutOffLeftSide -- ���������������� tanContext ����������������������������
2498
2499  n -- �������� n ������������������������������������
2500
2501 */
2502
2503int
2504cutOffLeftSide(uiContext d, yomiContext yc, int n)
2505{
2506  int i;
2507  tanContext tan = (tanContext)yc, st;
2508
2509  for (i = 0 ; i < n && tan ; i++) {
2510    tan = tan->left;
2511  }
2512  if (tan && tan->left) {
2513    st = tan->left;
2514    while (st->left) {
2515      st = st->left;
2516    }
2517    d->nbytes = doKakutei(d, st, tan, d->buffer_return,
2518			  d->buffer_return + d->n_buffer, (yomiContext *)0);
2519    d->modec = (mode_context)yc;
2520    tan->left = (tanContext)0;
2521    return 1;
2522  }
2523  return 0;
2524}
2525
2526extern KanjiModeRec cy_mode;
2527
2528int YomiKakutei (uiContext);
2529
2530int
2531YomiKakutei(uiContext d)
2532{
2533  yomiContext yc = (yomiContext)d->modec;
2534  tanContext leftmost;
2535  int len, res;
2536  WCHAR_T *s = d->buffer_return, *e = s + d->n_buffer;
2537  mode_context next = yc->next;
2538  KanjiMode prev = yc->prevMode;
2539  long prevflags;
2540
2541  prevflags = (yc->id == YOMI_CONTEXT) ?
2542    yc->generalFlags : ((tanContext)yc)->generalFlags;
2543
2544  d->kanji_status_return->length = 0;
2545  d->nbytes = 0;
2546
2547  leftmost = (tanContext)yc;
2548  while (leftmost->left) {
2549    leftmost = leftmost->left;
2550  }
2551
2552  len = doKakutei(d, leftmost, (tanContext)0, s, e, &yc);
2553
2554  if (!yc) {
2555    yc = newFilledYomiContext(next, prev);
2556    yc->generalFlags = prevflags;
2557    yc->minorMode = getBaseMode(yc);
2558  }
2559  d->modec = (mode_context)yc;
2560  if (!yc) {
2561    freeRomeStruct(d);
2562    return -1; /* �������������������������������������������������������� 1994.2.23 kon */
2563  }
2564  d->current_mode = yc->curMode;
2565  d->nbytes = len;
2566
2567  res = YomiExit(d, d->nbytes);
2568  currentModeInfo(d);
2569  return res;
2570}
2571
2572/* �������� 0 ���������������������������������������������������� */
2573
2574void
2575clearYomiContext(yomiContext yc)
2576{
2577  yc->rStartp = 0;
2578  yc->rCurs = 0;
2579  yc->rEndp = 0;
2580  yc->romaji_buffer[0] = (WCHAR_T)0;
2581  yc->rAttr[0] = SENTOU;
2582  yc->kRStartp = 0;
2583  yc->kCurs = 0;
2584  yc->kEndp = 0;
2585  yc->kana_buffer[0] = (WCHAR_T)0;
2586  yc->kAttr[0] = SENTOU;
2587  yc->pmark = yc->cmark = 0;
2588  yc->englishtype = CANNA_ENG_KANA;
2589  yc->cStartp = yc->cRStartp = 0;
2590  yc->jishu_kEndp = 0;
2591}
2592
2593inline int
2594clearChikujiContext(yomiContext yc)
2595{
2596  clearYomiContext(yc);
2597  yc->status &= CHIKUJI_NULL_STATUS;
2598  yc->ys = yc->ye = yc->cStartp;
2599  clearHenkanContext(yc);
2600  return 0;
2601}
2602
2603
2604/* RomajiClearYomi(d) ������������������������������������
2605 *
2606 * ������������������������(uiContext)d ����������������������������������������������������
2607 * ����������������������������
2608 *
2609 * ����������������
2610 *
2611 *    ������������������������������������
2612 *
2613 * ����������������
2614 *
2615 *    d  (uiContext)  ������������������������������������
2616 *
2617 * ��������������������
2618 *
2619 *    ������������
2620 *
2621 * ��������������������
2622 *
2623 *    yc->rEndp = 0;
2624 *    yc->kEndp = 0; ����
2625 */
2626
2627void
2628RomajiClearYomi(uiContext d)
2629{
2630  yomiContext yc = (yomiContext)d->modec;
2631
2632  if (yc->generalFlags & CANNA_YOMI_CHIKUJI_MODE) {
2633    if (yc->context >= 0) {
2634      RkwEndBun(yc->context, 0);
2635      abandonContext(d, yc);
2636    }
2637    clearChikujiContext(yc);
2638  }
2639  else {
2640    clearYomiContext(yc);
2641  }
2642}
2643
2644int YomiExit(uiContext d, int retval)
2645{
2646  yomiContext yc = (yomiContext)d->modec;
2647
2648  RomajiClearYomi(d);
2649
2650  /* �������������������������������������������������������������������������������������������������������������������� */
2651  restoreChikujiIfBaseChikuji(yc);
2652  d->current_mode = yc->curMode = yc->myEmptyMode;
2653  d->kanji_status_return->info |= KanjiEmptyInfo;
2654
2655  return checkIfYomiExit(d, retval);
2656}
2657
2658/* RomajiStoreYomi(d, kana) ������������������������������������
2659 *
2660 * ������������������������(uiContext)d ����������������������������������������������������
2661 *
2662 * ����������������
2663 *
2664 *    ��������������������������������
2665 *
2666 * ����������������
2667 *
2668 *    d    (uiContext)  ������������������������������������
2669 *    kana (WCHAR_T *) ��������������������
2670 *    roma (WCHAR_T *) ����������������������������
2671 * ��������������������
2672 *
2673 *    ������������
2674 *
2675 * ��������������������
2676 *
2677 *    yc->rEndp = WStrlen(kana);
2678 *    yc->kEndp = WStrlen(kana); ����
2679 */
2680
2681void
2682RomajiStoreYomi(uiContext d, WCHAR_T *kana, WCHAR_T *roma)
2683{
2684  int i, ylen, rlen, additionalflag;
2685  yomiContext yc = (yomiContext)d->modec;
2686
2687  rlen = ylen = WStrlen(kana);
2688  if (roma) {
2689    rlen = WStrlen(roma);
2690    additionalflag = 0;
2691  }
2692  else {
2693    additionalflag = SENTOU;
2694  }
2695  WStrcpy(yc->romaji_buffer, (roma ? roma : kana));
2696  yc->rStartp = rlen;
2697  yc->rCurs = rlen;
2698  yc->rEndp = rlen;
2699  WStrcpy(yc->kana_buffer, kana);
2700  yc->kRStartp = ylen;
2701  yc->kCurs = ylen;
2702  yc->kEndp = ylen;
2703  for (i = 0 ; i < rlen ; i++) {
2704    yc->rAttr[i] = additionalflag;
2705  }
2706  yc->rAttr[0] |= SENTOU;
2707  yc->rAttr[i] = SENTOU;
2708  for (i = 0 ; i < ylen ; i++) {
2709    yc->kAttr[i] = HENKANSUMI | additionalflag;
2710  }
2711  yc->kAttr[0] |= SENTOU;
2712  yc->kAttr[i] = SENTOU;
2713}
2714
2715/*
2716  KanaDeletePrevious -- ����������������������������������������������������
2717
2718*/
2719
2720int KanaDeletePrevious(uiContext d)
2721{
2722  int howManyDelete;
2723  int prevflag;
2724  yomiContext yc = (yomiContext)d->modec;
2725
2726  /* ������������������������������������������������������������������������������������������������
2727
2728    (1) ������������������������������������������������������������������������������������������������������������������������������������
2729    (2) ����������������������������
2730
2731    ������������������������������������(����������������������������������������������������������������������������)
2732   */
2733
2734  if (!yc->kCurs) { /* �������������������� */
2735    d->kanji_status_return->length = -1;
2736    return 0;
2737  }
2738  yc->last_rule = 0;
2739  howManyDelete = howFarToGoBackward(yc);
2740  if (howManyDelete > 0 && (yc->generalFlags & CANNA_YOMI_BREAK_ROMAN)) {
2741    yc->generalFlags &= ~CANNA_YOMI_BREAK_ROMAN;
2742    yc->rStartp = yc->rCurs - 1;
2743    while ( yc->rStartp > 0 && !(yc->rAttr[yc->rStartp] & SENTOU) ) {
2744      yc->rStartp--;
2745    }
2746    romajiReplace (-1, (WCHAR_T *)NULL, 0, 0);
2747    yc->kRStartp = yc->kCurs - 1;
2748    while ( yc->kRStartp > 0 && !(yc->kAttr[yc->kRStartp] & SENTOU) )
2749      yc->kRStartp--;
2750    prevflag = (yc->kAttr[yc->kRStartp] & SENTOU);
2751    kanaReplace(yc->kRStartp - yc->kCurs,
2752		yc->romaji_buffer + yc->rStartp,
2753		yc->rCurs - yc->rStartp,
2754		0);
2755    yc->kAttr[yc->kRStartp] |= prevflag;
2756    yc->n_susp_chars = 0; /* ������������������������������������������������ */
2757    makePhonoOnBuffer(d, yc, (unsigned char)0, 0, 0);
2758  }
2759  else {
2760    if ( yc->kAttr[yc->kCurs - howManyDelete] & HENKANSUMI ) {
2761      if (yc->kAttr[yc->kCurs - howManyDelete] & SENTOU) {
2762	/* ������������������������������������������������������������ */
2763	if (yc->kAttr[yc->kCurs] & SENTOU) {
2764	  int n;
2765
2766	  /* �������������������������������������������������������������������������������������������������������������������� */
2767
2768	  for (n = 1 ; yc->rCurs > 0 && !(yc->rAttr[--yc->rCurs] & SENTOU) ;) {
2769	    n++;
2770	  }
2771	  moveStrings(yc->romaji_buffer, yc->rAttr,
2772		      yc->rCurs + n, yc->rEndp,-n);
2773	  if (yc->rCurs < yc->rStartp) {
2774	    yc->rStartp = yc->rCurs;
2775	  }
2776	  yc->rEndp -= n;
2777	}
2778	else {
2779	  yc->kAttr[yc->kCurs] |= SENTOU;
2780	}
2781      }
2782    }
2783    else {
2784      romajiReplace(-howManyDelete, (WCHAR_T *)NULL, 0, 0);
2785    }
2786    kanaReplace(-howManyDelete, (WCHAR_T *)NULL, 0, 0);
2787  }
2788  debug_yomi(yc);
2789  return(0);
2790}
2791
2792
2793static int
2794YomiDeletePrevious(uiContext d)
2795{
2796  yomiContext yc = (yomiContext)d->modec;
2797
2798  KanaDeletePrevious(d);
2799  if (!yc->kEndp) {
2800    if (yc->savedFlags & CANNA_YOMI_MODE_SAVED) {
2801      restoreFlags(yc);
2802    }
2803    if (yc->left || yc->right) {
2804      removeCurrentBunsetsu(d, (tanContext)yc);
2805      yc = (yomiContext)0;
2806    }
2807    else {
2808      /* ������������������������������������������������������������������������������������������������������������ */
2809      restoreChikujiIfBaseChikuji(yc);
2810      d->current_mode = yc->curMode = yc->myEmptyMode;
2811      d->kanji_status_return->info |= KanjiEmptyInfo;
2812    }
2813    currentModeInfo(d);
2814  }
2815  else {
2816    if (yc->kCurs != yc->kRStartp) {
2817      ReCheckStartp(yc);
2818    }
2819  }
2820
2821  if (yc) {
2822    fitmarks(yc);
2823  }
2824
2825  makeYomiReturnStruct(d);
2826  return 0;
2827}
2828
2829static int YomiDeleteNext (uiContext);
2830
2831static int
2832YomiDeleteNext(uiContext d)
2833{
2834  int howManyDelete;
2835  yomiContext yc = (yomiContext)d->modec;
2836
2837  if (chikujip(yc) && (yc->status & CHIKUJI_ON_BUNSETSU)) {
2838    return NothingChangedWithBeep(d);
2839  }
2840
2841  if (yc->kCurs == yc->kEndp) {
2842    /* ������������������������������������������������������������������������ */
2843    d->kanji_status_return->length = -1;
2844    return 0;
2845  }
2846
2847  fitmarks(yc);
2848
2849  yc->last_rule = 0;
2850  howManyDelete = howFarToGoForward(yc);
2851
2852  if (yc->kAttr[yc->kCurs] & SENTOU) {
2853    if (yc->kAttr[yc->kCurs + howManyDelete] & SENTOU) {
2854      int n = 1;
2855      while ( !(yc->rAttr[++yc->rCurs] & SENTOU) )
2856	n++;
2857      moveStrings(yc->romaji_buffer, yc->rAttr, yc->rCurs, yc->rEndp, -n);
2858      yc->rCurs -= n;
2859      yc->rEndp -= n;
2860    }
2861    else {
2862      yc->kAttr[yc->kCurs + howManyDelete] |= SENTOU;
2863    }
2864  }
2865  kanaReplace(howManyDelete, (WCHAR_T *)NULL, 0, 0);
2866  /* �������������������������������� */
2867
2868  if (yc->cStartp < yc->kEndp) { /* ���������������������������� */
2869    if (yc->kCurs < yc->ys) {
2870      yc->ys = yc->kCurs; /* ������������������������������������������������������������ */
2871    }
2872  }
2873  else if (yc->nbunsetsu) { /* �������������������������������������������� */
2874    if (RkwGoTo(yc->context, yc->nbunsetsu - 1) == -1) {
2875      return makeRkError(d, "\312\270\300\341\244\316\260\334\306\260\244\313"
2876	"\274\272\307\324\244\267\244\336\244\267\244\277");
2877                            /* ������������������������������������������������ */
2878    }
2879    yc->kouhoCount = 0;
2880    yc->curbun = yc->nbunsetsu - 1;
2881    moveToChikujiTanMode(d);
2882  }
2883  else { /* �������������������������������� */
2884    if (yc->savedFlags & CANNA_YOMI_MODE_SAVED) {
2885      restoreFlags(yc);
2886    }
2887    if (yc->left || yc->right) {
2888      removeCurrentBunsetsu(d, (tanContext)yc);
2889    }
2890    else {
2891      /* ������������������������������������������������������������������������������������������������������������ */
2892      restoreChikujiIfBaseChikuji(yc);
2893      d->current_mode = yc->curMode = yc->myEmptyMode;
2894      d->kanji_status_return->info |= KanjiEmptyInfo;
2895    }
2896    currentModeInfo(d);
2897  }
2898  makeYomiReturnStruct(d);
2899  return 0;
2900}
2901
2902static int YomiKillToEndOfLine (uiContext);
2903
2904static int
2905YomiKillToEndOfLine(uiContext d)
2906{
2907  yomiContext yc = (yomiContext)d->modec;
2908
2909  romajiReplace (yc->rEndp - yc->rCurs, (WCHAR_T *)NULL, 0, 0);
2910  kanaReplace   (yc->kEndp - yc->kCurs, (WCHAR_T *)NULL, 0, 0);
2911
2912  fitmarks(yc);
2913
2914  if (!yc->kEndp) {
2915    if (yc->savedFlags & CANNA_YOMI_MODE_SAVED) {
2916      restoreFlags(yc);
2917    }
2918    if (yc->left || yc->right) {
2919      removeCurrentBunsetsu(d, (tanContext)yc);
2920    }
2921    else {
2922      /* ������������������������������������������������������������������������������������������������������������ */
2923      restoreChikujiIfBaseChikuji(yc);
2924      d->current_mode = yc->curMode = yc->myEmptyMode;
2925      d->kanji_status_return->info |= KanjiEmptyInfo;
2926    }
2927    currentModeInfo(d);
2928  }
2929  makeYomiReturnStruct(d);
2930  return 0;
2931}
2932
2933static int YomiQuit (uiContext);
2934
2935static int
2936YomiQuit(uiContext d)
2937{
2938  yomiContext yc = (yomiContext)d->modec;
2939
2940  /* �������������������������������������������� */
2941  RomajiClearYomi(d);
2942
2943  if (yc->left || yc->right) {
2944    removeCurrentBunsetsu(d, (tanContext)yc);
2945  }
2946  else {
2947    /* �������������������������������������������������������������������������������������������������������� */
2948    restoreChikujiIfBaseChikuji(yc);
2949    d->current_mode = yc->curMode = yc->myEmptyMode;
2950    d->kanji_status_return->info |= KanjiEmptyInfo;
2951  }
2952  makeYomiReturnStruct(d);
2953  currentModeInfo(d);
2954  return checkIfYomiQuit(d, 0);
2955}
2956
2957coreContext
2958newCoreContext(void)
2959{
2960  coreContext cc;
2961
2962  cc = (coreContext)malloc(sizeof(coreContextRec));
2963  if (cc) {
2964    cc->id = CORE_CONTEXT;
2965  }
2966  return cc;
2967}
2968
2969static
2970int simplePopCallback(uiContext d, int retval, mode_context env)
2971/* ARGSUSED */
2972{
2973  popCallback(d);
2974  currentModeInfo(d);
2975  return retval;
2976}
2977
2978int alphaMode(uiContext d)
2979{
2980  extern KanjiModeRec alpha_mode;
2981  coreContext cc;
2982  char *bad = "\245\341\245\342\245\352\244\254\302\255\244\352\244\336"
2983	"\244\273\244\363";
2984              /* ������������������������������������ */
2985
2986  cc = newCoreContext();
2987  if (cc == (coreContext)0) {
2988    makeGLineMessageFromString(d, bad);
2989    return 0;
2990  }
2991  if (pushCallback(d, d->modec,
2992		   NO_CALLBACK, simplePopCallback,
2993                   simplePopCallback, NO_CALLBACK) == 0) {
2994    freeCoreContext(cc);
2995    makeGLineMessageFromString(d, bad);
2996    return 0;
2997  }
2998  cc->prevMode = d->current_mode;
2999  cc->next = d->modec;
3000  cc->majorMode =
3001    cc->minorMode = CANNA_MODE_AlphaMode;
3002  d->current_mode = &alpha_mode;
3003  d->modec = (mode_context)cc;
3004  return 0;
3005}
3006
3007/* Quoted Insert Mode -- ��������������������������������
3008
3009   ����������������������������������������������������������������������������������������������������������������
3010
3011 */
3012
3013static int exitYomiQuotedInsert (uiContext, int, mode_context);
3014
3015static
3016int exitYomiQuotedInsert(uiContext d, int retval, mode_context env)
3017/* ARGSUSED */
3018{
3019  popCallback(d);
3020  return retval;
3021}
3022
3023static
3024int YomiInsertQuoted(uiContext d)
3025{
3026  unsigned char ch;
3027  coreContext cc = (coreContext)d->modec;
3028  yomiContext yc;
3029
3030  ch = (unsigned char)*(d->buffer_return);
3031
3032  if (IrohaFunctionKey(ch)) {
3033    d->kanji_status_return->length = -1;
3034    d->kanji_status_return->info = 0;
3035    return 0;
3036  } else {
3037    d->current_mode = cc->prevMode;
3038    d->modec = cc->next;
3039    free(cc);
3040
3041    yc = (yomiContext)d->modec;
3042
3043    romajiReplace (0, d->buffer_return, d->nbytes, 0);
3044    kanaReplace   (0, d->buffer_return, d->nbytes, HENKANSUMI);
3045    yc->rStartp = yc->rCurs;
3046    yc->kRStartp = yc->kCurs;
3047    makeYomiReturnStruct(d);
3048    currentModeInfo(d);
3049    d->status = EXIT_CALLBACK;
3050    return 0;
3051  }
3052}
3053
3054static int yomiquotedfunc (uiContext, KanjiMode, int, int, int);
3055
3056static
3057int yomiquotedfunc(uiContext d, KanjiMode mode, int whattodo, int key, int fnum)
3058     /* ARGSUSED */
3059{
3060  switch (whattodo) {
3061  case KEY_CALL:
3062    return YomiInsertQuoted(d);
3063  case KEY_CHECK:
3064    return 1;
3065  case KEY_SET:
3066    return 0;
3067  }
3068  /* NOTREACHED */
3069}
3070
3071static KanjiModeRec yomi_quoted_insert_mode = {
3072  yomiquotedfunc,
3073  0, 0, 0,
3074};
3075
3076inline void
3077yomiQuotedInsertMode(uiContext d)
3078{
3079  coreContext cc;
3080
3081  cc = newCoreContext();
3082  if (cc == 0) {
3083    NothingChangedWithBeep(d);
3084    return;
3085  }
3086  cc->prevMode = d->current_mode;
3087  cc->next = d->modec;
3088  cc->majorMode = d->majorMode;
3089  cc->minorMode = CANNA_MODE_QuotedInsertMode;
3090  if (pushCallback(d, d->modec,
3091                   NO_CALLBACK, exitYomiQuotedInsert,
3092                   NO_CALLBACK, NO_CALLBACK) == (struct callback *)0) {
3093    freeCoreContext(cc);
3094    NothingChangedWithBeep(d);
3095    return;
3096  }
3097  d->modec = (mode_context)cc;
3098  d->current_mode = &yomi_quoted_insert_mode;
3099  currentModeInfo(d);
3100  return;
3101}
3102
3103int YomiQuotedInsert(uiContext d)
3104{
3105  yomiContext yc = (yomiContext)d->modec;
3106
3107  d->nbytes = 0;
3108
3109  if (yc->generalFlags & CANNA_YOMI_CHIKUJI_MODE) {
3110    if (yc->status & CHIKUJI_ON_BUNSETSU) {
3111      if (yc->kEndp != yc->kCurs) {
3112	yc->rStartp = yc->rCurs = yc->rEndp;
3113	yc->kRStartp = yc->kCurs = yc->kEndp;
3114      }
3115      yc->status &= ~CHIKUJI_ON_BUNSETSU;
3116      yc->status |= CHIKUJI_OVERWRAP;
3117    }
3118    else if (yc->rEndp == yc->rCurs) {
3119      yc->status &= ~CHIKUJI_OVERWRAP;
3120    }
3121  }
3122
3123  if (forceRomajiFlushYomi(d))
3124    return(d->nbytes);
3125
3126  fitmarks(yc);
3127
3128  yomiQuotedInsertMode(d);
3129  d->kanji_status_return->length = -1;
3130  return 0;
3131}
3132
3133inline int
3134mapAsKuten(uiContext d)
3135{
3136  yomiContext yc = (yomiContext)d->modec;
3137  int i, j, ch, len, clen, kanalen, pos;
3138  char tmpbuf[4];
3139  WCHAR_T *hexbuf;
3140  WCHAR_T buf[2];
3141  static int allowTwoByte = 1;
3142
3143  tmpbuf[0] = tmpbuf[1] = tmpbuf[2] = tmpbuf[3] = '\0';
3144
3145  if (yc->kCurs < yc->cmark) {
3146    int tmp = yc->kCurs;
3147    yc->kCurs = yc->cmark;
3148    yc->cmark = tmp;
3149    kPos2rPos(yc, 0, yc->kCurs, (int *) 0, &tmp);
3150    yc->rCurs = tmp;
3151  }
3152  else if (yc->kCurs == yc->cmark) {
3153    yc->kCurs = yc->kRStartp = yc->kEndp;
3154    yc->rCurs = yc->rStartp = yc->rEndp;
3155  }
3156
3157  if (*yc->romaji_buffer == 'x' || *yc->romaji_buffer == 'X')
3158    len = yc->rCurs - 1;
3159  else
3160    len = yc->rCurs;
3161  if (len > 6) {
3162    return 0;
3163  }
3164  hexbuf = yc->romaji_buffer + yc->rCurs - len;
3165
3166  kPos2rPos(yc, 0, yc->cmark, (int *) 0, &pos);
3167
3168  if (hexbuf < yc->romaji_buffer + pos) {
3169    if (hexbuf + 6 < yc->romaji_buffer + pos) {
3170      return 0;
3171    }
3172  }
3173  for (i = 0, j = 1; i < len; i++) {
3174    ch = *(hexbuf + i);
3175    if ('0' <= ch && ch <= '9')
3176      tmpbuf[j] = tmpbuf[j] * 10 + (ch - '0');
3177    else if (ch == '-' && j == 1)
3178      j++;
3179    else
3180      return 0;
3181  }
3182  tmpbuf[2] = (char)((0x80 | tmpbuf[2]) + 0x20);
3183  if (tmpbuf[1] < 0x5f) {
3184    tmpbuf[1] = (char)((0x80 | tmpbuf[1]) + 0x20);
3185  }
3186  else {
3187    tmpbuf[1] = (char)((0x80 | tmpbuf[1]) - 0x5e + 0x20);
3188    tmpbuf[0] = (char)0x8f; /* SS3 */
3189  }
3190  if ((unsigned char)tmpbuf[1] < 0xa1 ||
3191      0xfe < (unsigned char)tmpbuf[1] ||
3192      (len > 2 && ((unsigned char)tmpbuf[2] < 0xa1 ||
3193                   0xfe < (unsigned char)tmpbuf[2]))) {
3194    return 0;
3195  }
3196  if (hexbuf[-1] == 'x' || hexbuf[-1] == 'X') {
3197    tmpbuf[0] = (char)0x8f;/*SS3*/
3198    len++;
3199  }
3200  if (tmpbuf[0]) {
3201    clen = MBstowcs(buf, tmpbuf, 2);
3202  }
3203  else {
3204    clen = MBstowcs(buf, tmpbuf + 1, 2);
3205  }
3206  for (i = 0, kanalen = 0 ; i < len ; i++) {
3207    if (yc->rAttr[yc->rCurs - len + i] & SENTOU) {
3208      do {
3209	kanalen++;
3210      } while (!(yc->kAttr[yc->kCurs - kanalen] & SENTOU));
3211      yc->rAttr[yc->rCurs - len + i] &= ~SENTOU;
3212    }
3213  }
3214  yc->rAttr[yc->rCurs - len] |= SENTOU;
3215  kanaReplace(-kanalen, buf, clen, HENKANSUMI);
3216  yc->kAttr[yc->kCurs - clen] |= SENTOU;
3217  yc->kRStartp = yc->kCurs;
3218  yc->rStartp = yc->rCurs;
3219  yc->pmark = yc->cmark;
3220  yc->cmark = yc->kCurs;
3221  yc->n_susp_chars = 0; /* ������������������������������������������������������������������������������������������������ */
3222  return 1;
3223}
3224
3225inline int
3226mapAsHex(uiContext d)
3227{
3228  yomiContext yc = (yomiContext)d->modec;
3229  int i, ch, len = 4, clen, kanalen, pos;
3230  char tmpbuf[8], *a;
3231  WCHAR_T *hexbuf;
3232  WCHAR_T buf[2];
3233  static int allowTwoByte = 1;
3234  extern struct CannaConfig cannaconf;
3235
3236  if (yc->kCurs < yc->cmark) {
3237    int tmp = yc->kCurs;
3238    yc->kCurs = yc->cmark;
3239    yc->cmark = tmp;
3240    kPos2rPos(yc, 0, yc->kCurs, (int *)0, &tmp);
3241    yc->rCurs = tmp;
3242  }
3243  else if (yc->kCurs == yc->cmark) {
3244    yc->kCurs = yc->kRStartp = yc->kEndp;
3245    yc->rCurs = yc->rStartp = yc->rEndp;
3246  }
3247
3248  hexbuf = yc->romaji_buffer + yc->rCurs - 4;
3249
3250  kPos2rPos(yc, 0, yc->cmark, (int *)0, &pos);
3251
3252  if (hexbuf < yc->romaji_buffer + pos) {
3253    if (!allowTwoByte || hexbuf + 2 < yc->romaji_buffer + pos) {
3254      return 0;
3255    }
3256    hexbuf += 2;
3257    len = 2;
3258  }
3259 retry:
3260  for (i = 0, a = tmpbuf + 1; i < len ; i++) {
3261    ch = *(hexbuf + i);
3262    if ('0' <= ch && ch <= '9')
3263      ch -= '0';
3264    else if ('A' <= ch && ch <= 'F')
3265      ch -= 'A' - 10;
3266    else if ('a' <= ch && ch <= 'f')
3267      ch -= 'a' - 10;
3268    else if (allowTwoByte && i < 2 && 2 < len) {
3269      hexbuf += 2;
3270      len = 2;
3271      goto retry;
3272    }
3273    else {
3274      return 0;
3275    }
3276    *a++ = ch;
3277  }
3278  if (cannaconf.code_input == CANNA_CODE_SJIS) { /* sjis ���������������������������� */
3279    char eucbuf[4];  /* SS3 �������������������������������� */
3280
3281    tmpbuf[1] = tmpbuf[1] * 16 + tmpbuf[2];
3282    if (len > 2) {
3283      tmpbuf[2] = tmpbuf[3] * 16 + tmpbuf[4];
3284      tmpbuf[3] = '\0';
3285    }
3286    else {
3287      tmpbuf[2] = '\0';
3288    }
3289    if ((unsigned char)tmpbuf[1] < 0x81 ||
3290        (0x9f < (unsigned char)tmpbuf[1] && (unsigned char)tmpbuf[1] < 0xe0) ||
3291        0xfc < (unsigned char)tmpbuf[1] ||
3292        (len > 2 && ((unsigned char)tmpbuf[2] < 0x40 ||
3293                     0xfc < (unsigned char)tmpbuf[2] ||
3294                     (unsigned char)tmpbuf[2] == 0x7f))) {
3295      return 0;
3296    }
3297    RkCvtEuc((unsigned char *)eucbuf, sizeof(eucbuf),
3298                        (unsigned char *)tmpbuf + 1, 2);
3299    clen = MBstowcs(buf, eucbuf, 2);
3300  }
3301  else {
3302    tmpbuf[1] = 0x80 | (tmpbuf[1] * 16 + tmpbuf[2]);
3303    if (len > 2) {
3304      tmpbuf[2] = 0x80 | (tmpbuf[3] * 16 + tmpbuf[4]);
3305      tmpbuf[3] = '\0';
3306    }
3307    else {
3308      tmpbuf[2] = '\0';
3309    }
3310    if ((unsigned char)tmpbuf[1] < 0xa1 ||
3311        0xfe < (unsigned char)tmpbuf[1] ||
3312        (len > 2 && ((unsigned char)tmpbuf[2] < 0xa1 ||
3313                      0xfe < (unsigned char)tmpbuf[2]))) {
3314      return 0;
3315    }
3316    if (len == 2) {
3317      tmpbuf[1] &= 0x7f;
3318    }
3319    if (hexbuf > yc->romaji_buffer
3320        && len > 2 && (hexbuf[-1] == 'x' || hexbuf[-1] == 'X')) {
3321      tmpbuf[0] = (char)0x8f;/*SS3*/
3322      len++;
3323      clen = MBstowcs(buf, tmpbuf, 2);
3324    }
3325    else {
3326      clen = MBstowcs(buf, tmpbuf + 1, 2);
3327    }
3328  }
3329  for (i = 0, kanalen = 0 ; i < len ; i++) {
3330    if (yc->rAttr[yc->rCurs - len + i] & SENTOU) {
3331      do {
3332	kanalen++;
3333      } while (!(yc->kAttr[yc->kCurs - kanalen] & SENTOU));
3334      yc->rAttr[yc->rCurs - len + i] &= ~SENTOU;
3335    }
3336  }
3337  yc->rAttr[yc->rCurs - len] |= SENTOU;
3338  kanaReplace(-kanalen, buf, clen, HENKANSUMI);
3339  yc->kAttr[yc->kCurs - clen] |= SENTOU;
3340  yc->kRStartp = yc->kCurs;
3341  yc->rStartp = yc->rCurs;
3342  yc->pmark = yc->cmark;
3343  yc->cmark = yc->kCurs;
3344  yc->n_susp_chars = 0; /* ������������������������������������������������������������������������������������������������ */
3345  return 1;
3346}
3347
3348/* ConvertAsHex -- ��������������������������������������������
3349
3350  ����������������������������������������������������������������������������������������������������������������������������������������������������
3351  ������������������������������������
3352
3353  (MSB������������������������������������)
3354
3355  */
3356
3357static int ConvertAsHex (uiContext);
3358
3359static
3360int ConvertAsHex(uiContext d)
3361{
3362  yomiContext yc = (yomiContext)d->modec;
3363  extern struct CannaConfig cannaconf;
3364
3365  if (yc->henkanInhibition & CANNA_YOMI_INHIBIT_ASHEX) {
3366    return NothingChangedWithBeep(d);
3367  }
3368  if (yc->savedFlags & CANNA_YOMI_MODE_SAVED) {
3369    restoreFlags(yc);
3370    currentModeInfo(d);
3371  }
3372  if (cannaconf.code_input != CANNA_CODE_KUTEN) {
3373    if (!mapAsHex(d)) {
3374      return NothingChangedWithBeep(d);
3375    }
3376  }
3377  else {
3378    if (!mapAsKuten(d)) {
3379      return NothingChangedWithBeep(d);
3380    }
3381  }
3382  if (yc->kCurs - 1 < yc->ys) {
3383    yc->ys = yc->kCurs - 1;
3384  }
3385  makeYomiReturnStruct(d);
3386  return 0;
3387}
3388
3389/*
3390  convertAsHex  ��������������������������������������������������������
3391
3392  ����������������������������������������������������������������������������������������d->romaji_buffer ������������
3393  ����������������������������������������������������������������������������������������������������������������������������������������
3394  �������������������������������������������������������������������������������������������������������� buffer_return
3395  �������������������������������������������������������������������������������� buffer_return ������������������������
3396  ��������������������������������(����������������������������)������������������������������������������������������������������������
3397  ����������������
3398
3399  ��������������������������������������������������������������������������������������������
3400
3401  ��������������������������������������������������������������������������������������������������������������������
3402
3403  <������������>
3404    ����������������������������������������������������������������������������������������������������������������
3405*/
3406
3407#ifdef WIN
3408static
3409#endif
3410int cvtAsHex(uiContext d, WCHAR_T *buf, WCHAR_T *hexbuf, int hexlen)
3411{
3412  int i;
3413  char tmpbuf[5], *a, *b;
3414  WCHAR_T rch;
3415
3416  if (hexlen != 4) { /* ����������������������������������������������������������������������������������������������������
3417			������������������������ */
3418    d->kanji_status_return->length = -1;
3419    return 0;
3420  }
3421  for (i = 0, a = tmpbuf; i < 4 ; i++) {
3422    rch = hexbuf[i]; /* �������������������������������������������������������������������������������� */
3423    if ('0' <= rch && rch <= '9') {
3424      rch -= '0';
3425    }
3426    else if ('A' <= rch && rch <= 'F') {
3427      rch -= 'A' - 10;
3428    }
3429    else if ('a' <= rch && rch <= 'f') {
3430      rch -= 'a' - 10;
3431    }
3432    else {
3433      d->kanji_status_return->length = -1;
3434      return 0;
3435    }
3436    *a++ = (char)rch; /* �������������������������������������������� */
3437  }
3438  b = (a = tmpbuf) + 1;
3439  *a = (char)(0x80 | (*a * 16 + *b));
3440  *(tmpbuf+1) = 0x80 | (*(a += 2) * 16 + *(b += 2));
3441  *a = '\0';
3442  if ((unsigned char)*tmpbuf < 0xa1 ||
3443      0xfe < (unsigned char)*tmpbuf ||
3444      (unsigned char)*--a < 0xa1 ||
3445      0xfe < (unsigned char)*a) {
3446    return 0;
3447  } else {
3448    MBstowcs(buf, tmpbuf, 2);
3449    return 1;
3450  }
3451}
3452
3453int convertAsHex(uiContext d)
3454{
3455  yomiContext yc = (yomiContext)d->modec;
3456
3457  return cvtAsHex(d, d->buffer_return, yc->romaji_buffer, yc->rEndp);
3458}
3459
3460/*
3461   ����������������������������������������������������������������
3462 */
3463
3464inline void
3465replaceSup2(int ind, int n)
3466{
3467  int i;
3468  WCHAR_T *temp, **p;
3469
3470  if (ind < 0)
3471    return;
3472
3473  temp = (p = keysup[ind].cand)[n];
3474  for (i = n ; i > 0 ; i--) {
3475    p[i] = p[i - 1];
3476  }
3477  p[0] = temp;
3478}
3479
3480inline void
3481replaceSup(int ind, int n)
3482{
3483  int i, group;
3484  extern int nkeysup;
3485
3486  group = keysup[ind].groupid;
3487  for (i = 0 ; i < nkeysup ; i++) {
3488    if (keysup[i].groupid == group) {
3489      replaceSup2(i, n);
3490    }
3491  }
3492}
3493
3494static int everySupkey (uiContext, int, mode_context);
3495
3496static
3497int everySupkey(uiContext d, int retval, mode_context env)
3498/* ARGSUSED */
3499{
3500  ichiranContext ic = (ichiranContext)d->modec;
3501  WCHAR_T *cur;
3502
3503  cur = ic->allkouho[*(ic->curIkouho)];
3504  d->kanji_status_return->revPos = 0;
3505  d->kanji_status_return->revLen = 0;
3506  d->kanji_status_return->echoStr = cur;
3507  d->kanji_status_return->length = WStrlen(cur);
3508
3509  return retval;
3510}
3511
3512static int exitSupkey (uiContext, int, mode_context);
3513
3514static
3515int exitSupkey(uiContext d, int retval, mode_context env)
3516/* ARGSUSED */
3517{
3518  yomiContext yc;
3519
3520  popCallback(d); /* ������������������������ */
3521
3522  yc = (yomiContext)d->modec;
3523
3524  replaceSup(findSup(yc->romaji_buffer[0]) - 1, yc->cursup);
3525
3526#ifdef NOT_KAKUTEI
3527  yc->rCurs = yc->rStartp = yc->rEndp;
3528  yc->kCurs = yc->kEndp;
3529  kanaReplace(-yc->kEndp, d->buffer_return, retval, HENKANSUMI | SUPKEY);
3530  yc->kRStartp = yc->kCurs;
3531  yc->kAttr[0] |= SENTOU;
3532  yc->rAttr[0] |= SENTOU | HENKANSUMI;
3533  for (i = 1 ; i < retval ; i++) {
3534    yc->kAttr[i] &= ~SENTOU;
3535  }
3536  currentModeInfo(d);
3537  makeYomiReturnStruct(d);
3538  return 0;
3539#else
3540  /* �������������������������������������������� */
3541  RomajiClearYomi(d);
3542
3543  /* �������������������������������������������������������������������������������������������������������� */
3544  restoreChikujiIfBaseChikuji(yc);
3545  d->current_mode = yc->curMode = yc->myEmptyMode;
3546  d->kanji_status_return->info |= KanjiEmptyInfo;
3547  currentModeInfo(d);
3548  makeYomiReturnStruct(d);
3549  return checkIfYomiQuit(d, retval);
3550#endif
3551}
3552
3553static int quitSupkey (uiContext, int, mode_context);
3554
3555static
3556int quitSupkey(uiContext d, int retval, mode_context env)
3557/* ARGSUSED */
3558{
3559  popCallback(d); /* ������������������������ */
3560  makeYomiReturnStruct(d);
3561  currentModeInfo(d);
3562  return retval;
3563}
3564
3565int selectKeysup(uiContext d, yomiContext yc, int ind)
3566{
3567  int retval;
3568  ichiranContext ic;
3569  extern int nkeysup;
3570
3571  yc->cursup = 0;
3572  retval = selectOne(d, keysup[ind].cand, &(yc->cursup), keysup[ind].ncand,
3573		     BANGOMAX,
3574		     (unsigned)(!cannaconf.HexkeySelect ? NUMBERING : 0),
3575		     0, WITH_LIST_CALLBACK,
3576		     everySupkey, exitSupkey, quitSupkey, NO_CALLBACK);
3577
3578  ic = (ichiranContext)d->modec;
3579  ic->majorMode = CANNA_MODE_IchiranMode;
3580  ic->minorMode = CANNA_MODE_IchiranMode;
3581
3582  currentModeInfo(d);
3583  *(ic->curIkouho) = 0;
3584
3585  /* ������������������������������������������������������������������������ */
3586  if(ic->tooSmall) {
3587    d->status = AUX_CALLBACK;
3588    return(retval);
3589  }
3590
3591  if ( !(ic->flags & ICHIRAN_ALLOW_CALLBACK) ) {
3592    makeGlineStatus(d);
3593  }
3594
3595  return retval;
3596}
3597
3598/*
3599  ������������������������������������������������������������������������������������������������
3600
3601  ����������������������������������������������������������������������������������������������������������������������������������������
3602  ����������������������������������������������������������������������������������������������������������������������������������������
3603  ��������������������������������������������������������������������������������������������
3604
3605  �������������������������������������������������������������������� mark ��������������������������������������������������������
3606  ��������������������������������������������
3607
3608 */
3609
3610inline
3611int regionGairaigo(yomiContext yc, int s, int e)
3612{
3613  if ((yc->kAttr[s] & SENTOU) && (yc->kAttr[e] & SENTOU)) {
3614    return 1;
3615  }
3616  else {
3617    return 0;
3618  }
3619}
3620
3621
3622/*
3623  ����������������������������������������������������������������
3624 */
3625
3626inline int
3627containGairaigo(yomiContext yc)
3628{
3629  int i;
3630
3631  for (i = 0 ; i < yc->kEndp ; i++) {
3632    if (yc->kAttr[i] & GAIRAIGO) {
3633      return 1;
3634    }
3635  }
3636  return 0;
3637}
3638
3639int containUnconvertedKey(yomiContext yc)
3640{
3641  int i, s, e;
3642
3643  if (containGairaigo(yc)) {
3644    return 0;
3645  }
3646
3647  if ((s = yc->cmark) > yc->kCurs) {
3648    e = s;
3649    s = yc->kCurs;
3650  }
3651  else {
3652    e = yc->kCurs;
3653  }
3654
3655  for (i = s ; i < e ; i++) {
3656    if ( !(yc->kAttr[i] & HENKANSUMI) ) {
3657      return 1;
3658    }
3659  }
3660  return 0;
3661}
3662
3663/*
3664 * ������������������������������������(������������������������������������������������)����TanKouhoMode��������������������
3665 *
3666 * ������������	uiContext
3667 * ������������	�������������������� 0	�������������������� -1
3668 */
3669
3670static int YomiHenkan (uiContext);
3671
3672static int
3673YomiHenkan(uiContext d)
3674{
3675  yomiContext yc = (yomiContext)d->modec;
3676  int len, idx;
3677
3678#ifdef MEASURE_TIME
3679  struct tms timebuf;
3680  long   currenttime, times();
3681
3682  currenttime = times(&timebuf);
3683#endif
3684
3685  if (yc->henkanInhibition & CANNA_YOMI_INHIBIT_HENKAN) {
3686    return NothingChangedWithBeep(d);
3687  }
3688
3689  d->nbytes = 0;
3690  len = RomajiFlushYomi(d, d->genbuf, ROMEBUFSIZE);
3691
3692  if (containUnconvertedKey(yc)) {
3693    YomiMark(d);
3694    len = RomajiFlushYomi(d, d->genbuf, ROMEBUFSIZE);
3695  }
3696
3697  yc->kRStartp = yc->kCurs = yc->kEndp;
3698  yc->rStartp  = yc->rCurs = yc->rEndp;
3699
3700  if (len == 0) { /* empty �������������������������������������������� */
3701    d->more.todo = 1;
3702    d->more.ch = d->ch;
3703    d->more.fnum = 0;    /* �������� ch ���������������������������������������� */
3704    return d->nbytes;
3705  }
3706
3707  if (yc->rEndp == 1 && (yc->kAttr[0] & SUPKEY) &&
3708      !yc->left && !yc->right &&
3709      (idx = findSup(yc->romaji_buffer[0])) &&
3710      keysup[idx - 1].ncand > 1) {
3711    return selectKeysup(d, yc, idx - 1);
3712  }
3713
3714  if (!prepareHenkanMode(d)) {
3715    makeGLineMessageFromString(d, jrKanjiError);
3716    makeYomiReturnStruct(d);
3717    return 0;
3718  }
3719  yc->minorMode = CANNA_MODE_TankouhoMode;
3720  yc->kouhoCount = 1;
3721  if (doHenkan(d, 0, (WCHAR_T *)0) < 0) {
3722    makeGLineMessageFromString(d, jrKanjiError);
3723    return TanMuhenkan(d);
3724  }
3725  if (cannaconf.kouho_threshold > 0 &&
3726      yc->kouhoCount >= cannaconf.kouho_threshold) {
3727    return tanKouhoIchiran(d, 0);
3728  }
3729  currentModeInfo(d);
3730
3731#ifdef MEASURE_TIME
3732  hc->time = times(&timebuf;
3733  hc->proctime -= currenttime;
3734#endif
3735
3736  return 0;
3737}
3738
3739static int YomiHenkanNaive (uiContext);
3740
3741static int
3742YomiHenkanNaive(uiContext d)
3743{
3744  yomiContext yc = (yomiContext)d->modec;
3745
3746  if (yc->generalFlags &
3747      (CANNA_YOMI_HANKAKU | CANNA_YOMI_ROMAJI | CANNA_YOMI_BASE_HANKAKU)) {
3748    return YomiInsert(d);
3749  }
3750  else {
3751    return YomiHenkan(d);
3752  }
3753}
3754
3755static int YomiHenkanOrNothing (uiContext);
3756
3757static int
3758YomiHenkanOrNothing(uiContext d)
3759{
3760  yomiContext yc = (yomiContext)d->modec;
3761
3762  if (yc->generalFlags &
3763      (CANNA_YOMI_HANKAKU | CANNA_YOMI_ROMAJI | CANNA_YOMI_BASE_HANKAKU)) {
3764    return NothingChanged(d);
3765  }
3766  else {
3767    return YomiHenkan(d);
3768  }
3769}
3770
3771/* ���������������������������������������� */
3772
3773extern int EmptyBaseHira (uiContext);
3774extern int EmptyBaseKata (uiContext);
3775extern int EmptyBaseEisu (uiContext);
3776extern int EmptyBaseZen (uiContext);
3777extern int EmptyBaseHan (uiContext);
3778
3779static int YomiBaseHira (uiContext);
3780
3781static
3782int YomiBaseHira(uiContext d)
3783{
3784  (void)RomajiFlushYomi(d, d->genbuf, ROMEBUFSIZE);
3785  (void)EmptyBaseHira(d);
3786  makeYomiReturnStruct(d);
3787  return 0;
3788}
3789
3790static int YomiBaseKata (uiContext);
3791
3792static
3793int YomiBaseKata(uiContext d)
3794{
3795  (void)RomajiFlushYomi(d, d->genbuf, ROMEBUFSIZE);
3796  (void)EmptyBaseKata(d);
3797  makeYomiReturnStruct(d);
3798  return 0;
3799}
3800
3801static int YomiBaseEisu (uiContext);
3802
3803static
3804int YomiBaseEisu(uiContext d)
3805{
3806  (void)RomajiFlushYomi(d, d->genbuf, ROMEBUFSIZE);
3807  (void)EmptyBaseEisu(d);
3808  makeYomiReturnStruct(d);
3809  return 0;
3810}
3811
3812static int YomiBaseZen (uiContext);
3813
3814static
3815int YomiBaseZen(uiContext d)
3816{
3817  (void)RomajiFlushYomi(d, d->genbuf, ROMEBUFSIZE);
3818  (void)EmptyBaseZen(d);
3819  makeYomiReturnStruct(d);
3820  return 0;
3821}
3822
3823static int YomiBaseHan (uiContext);
3824
3825static
3826int YomiBaseHan(uiContext d)
3827{
3828  (void)RomajiFlushYomi(d, d->genbuf, ROMEBUFSIZE);
3829  (void)EmptyBaseHan(d);
3830  makeYomiReturnStruct(d);
3831  return 0;
3832}
3833
3834static int YomiBaseKana (uiContext);
3835
3836static
3837int YomiBaseKana(uiContext d)
3838{
3839  (void)RomajiFlushYomi(d, d->genbuf, ROMEBUFSIZE);
3840  (void)EmptyBaseKana(d);
3841  makeYomiReturnStruct(d);
3842  return 0;
3843}
3844
3845static int YomiBaseKakutei (uiContext);
3846
3847static
3848int YomiBaseKakutei(uiContext d)
3849{
3850  (void)RomajiFlushYomi(d, d->genbuf, ROMEBUFSIZE);
3851  (void)EmptyBaseKakutei(d);
3852  makeYomiReturnStruct(d);
3853  return 0;
3854}
3855
3856static int YomiBaseHenkan (uiContext);
3857
3858static
3859int YomiBaseHenkan(uiContext d)
3860{
3861  (void)RomajiFlushYomi(d, d->genbuf, ROMEBUFSIZE);
3862  (void)EmptyBaseHenkan(d);
3863  makeYomiReturnStruct(d);
3864  return 0;
3865}
3866
3867int YomiBaseHiraKataToggle (uiContext);
3868
3869int YomiBaseHiraKataToggle(uiContext d)
3870{
3871  yomiContext yc = (yomiContext)d->modec;
3872
3873  (void)RomajiFlushYomi(d, d->genbuf, ROMEBUFSIZE);
3874
3875  if (yc->generalFlags & CANNA_YOMI_KATAKANA) {
3876    (void)EmptyBaseHira(d);
3877  }
3878  else {
3879    (void)EmptyBaseKata(d);
3880  }
3881  makeYomiReturnStruct(d);
3882  return 0;
3883}
3884
3885int YomiBaseZenHanToggle (uiContext);
3886
3887int YomiBaseZenHanToggle(uiContext d)
3888{
3889  yomiContext yc = (yomiContext)d->modec;
3890
3891  (void)RomajiFlushYomi(d, d->genbuf, ROMEBUFSIZE);
3892
3893  if (yc->generalFlags & CANNA_YOMI_BASE_HANKAKU) {
3894    (void)EmptyBaseZen(d);
3895  }
3896  else {
3897    (void)EmptyBaseHan(d);
3898  }
3899  makeYomiReturnStruct(d);
3900  return 0;
3901}
3902
3903int YomiBaseRotateForw (uiContext);
3904
3905int YomiBaseRotateForw(uiContext d)
3906{
3907  yomiContext yc = (yomiContext)d->modec;
3908
3909  (void)RomajiFlushYomi(d, d->genbuf, ROMEBUFSIZE);
3910
3911  if (!(yc->generalFlags & CANNA_YOMI_BASE_HANKAKU) &&
3912      ((yc->generalFlags & CANNA_YOMI_ROMAJI) ||
3913       ((yc->generalFlags & CANNA_YOMI_KATAKANA) &&
3914	!cannaconf.InhibitHankakuKana) )) {
3915    (void)EmptyBaseHan(d);
3916  }
3917  else {
3918    yc->generalFlags &= ~CANNA_YOMI_BASE_HANKAKU;
3919    if (yc->generalFlags & CANNA_YOMI_ROMAJI) {
3920      (void)EmptyBaseHira(d);
3921    }
3922    else if (yc->generalFlags & CANNA_YOMI_KATAKANA) {
3923      (void)EmptyBaseEisu(d);
3924    }
3925    else {
3926      (void)EmptyBaseKata(d);
3927    }
3928  }
3929  makeYomiReturnStruct(d);
3930  return 0;
3931}
3932
3933int YomiBaseRotateBack (uiContext);
3934
3935int YomiBaseRotateBack(uiContext d)
3936{
3937  yomiContext yc = (yomiContext)d->modec;
3938
3939  (void)RomajiFlushYomi(d, d->genbuf, ROMEBUFSIZE);
3940
3941  if (yc->generalFlags & CANNA_YOMI_BASE_HANKAKU) {
3942    (void)EmptyBaseZen(d);
3943  }
3944  else if (yc->generalFlags & CANNA_YOMI_KATAKANA) {
3945    (void)EmptyBaseHira(d);
3946  }
3947  else if (yc->generalFlags & CANNA_YOMI_ROMAJI) {
3948    if (!cannaconf.InhibitHankakuKana) {
3949      yc->generalFlags |= CANNA_YOMI_BASE_HANKAKU;
3950    }
3951    (void)EmptyBaseKata(d);
3952  }
3953  else {
3954    yc->generalFlags &= ~CANNA_YOMI_ZENKAKU;
3955    yc->generalFlags |= CANNA_YOMI_BASE_HANKAKU;
3956    (void)EmptyBaseEisu(d);
3957  }
3958  makeYomiReturnStruct(d);
3959  return 0;
3960}
3961
3962int YomiBaseKanaEisuToggle (uiContext);
3963
3964int YomiBaseKanaEisuToggle(uiContext d)
3965{
3966  yomiContext yc = (yomiContext)d->modec;
3967
3968  (void)RomajiFlushYomi(d, d->genbuf, ROMEBUFSIZE);
3969
3970  if (yc->generalFlags & CANNA_YOMI_ROMAJI) {
3971    (void)EmptyBaseKana(d);
3972  }
3973  else {
3974    (void)EmptyBaseEisu(d);
3975  }
3976  makeYomiReturnStruct(d);
3977  return 0;
3978}
3979
3980int YomiBaseKakuteiHenkanToggle (uiContext);
3981
3982int YomiBaseKakuteiHenkanToggle(uiContext d)
3983{
3984  yomiContext yc = (yomiContext)d->modec;
3985
3986  (void)RomajiFlushYomi(d, d->genbuf, ROMEBUFSIZE);
3987
3988  if (yc->generalFlags & CANNA_YOMI_KAKUTEI) {
3989    (void)EmptyBaseHenkan(d);
3990  }
3991  else { /* ������������������������������������������������ */
3992    (void)EmptyBaseKakutei(d);
3993  }
3994  makeYomiReturnStruct(d);
3995  return 0;
3996}
3997
3998int YomiModeBackup (uiContext);
3999
4000int YomiModeBackup(uiContext d)
4001{
4002  yomiContext yc = (yomiContext)d->modec;
4003
4004  (void)saveFlags(yc);
4005  return NothingChanged(d);
4006}
4007
4008/* ������������������������ */
4009
4010/* cfuncdef
4011
4012   exitJishu -- ����������������������������������������
4013
4014   ������������������������������������������������������������������������������������������������������������������������������������
4015   ������������������������
4016
4017   ������������������������������������������������
4018
4019   �������������������� jishu.c ������������������������ JishuKakutei ��������������������������������
4020   ����������������������������������������������������������������JishuKakutei ��������������������������������
4021   ����������������������������������������������������������������������������������������������������������������������������
4022   ����������������������������������������������������������������������������������������������������������������������������
4023   �������������������������������������������������������������������������������� JishuKakutei ����������������
4024   ������������������������������������
4025
4026   (1) ���������������������������� yc ��������������������������������������������������������
4027   (2) ��������������������������������������������
4028       jishu_kc    ������������������������������������ (JISHU_ZEN_KATA ��������)
4029       jishu_case  ���������������������������������������� (CANNA_JISHU_UPPER ��������)
4030       jishu_kEndp ������������������������������������
4031       jishu_rEndp ����������������������������������������������������������������������������������������
4032   (3) yc->cmark ��������������������������������������������������������������������������������
4033   (4) yc->kana_buffer ������������������������ exitJishu ����������������
4034   (5) yc->kana_buffer ���������������������������������������������������� yc->romaji_buffer
4035       ��������������������������������������������������������������������������������������������������������������������������������
4036   (6) ����������������yc->kRStartp == yc->jishu_kEndp ������������������������������������������������
4037       ��������
4038   (7) ���������������������������������������������������������������� yc->jishu_rEndp ������������������������
4039   (8) exitJishu ������������������������ yc->kana_buffer ������������������������������������������������
4040       ��������������������������������
4041 */
4042
4043int exitJishu(uiContext d)
4044{
4045  yomiContext yc;
4046  int len, srclen, i, pos;
4047  BYTE jishu, jishu_case, head = 1;
4048  int jishu_kEndp, jishu_rEndp;
4049  int (*func1)(...), (*func2)(...);
4050  long savedgf;
4051  WCHAR_T *buf, *p;
4052#ifndef WIN
4053  WCHAR_T xxxx[1024];
4054#else
4055  WCHAR_T *xxxx = (WCHAR_T *)malloc(sizeof(WCHAR_T) * 1024);
4056  if (!xxxx) {
4057    return 0;
4058  }
4059#endif
4060
4061  /* ���������������������������������������������������������������� */
4062
4063  yc = (yomiContext)d->modec;
4064
4065  jishu = yc->jishu_kc;
4066  jishu_case = yc->jishu_case;
4067  jishu_kEndp = yc->jishu_kEndp;
4068  jishu_rEndp = yc->jishu_rEndp;
4069
4070  leaveJishuMode(d, yc);
4071
4072  /* ���������������������������������������������������������������� */
4073  if (yc->savedFlags & CANNA_YOMI_MODE_SAVED) {
4074    restoreFlags(yc);
4075  }
4076  /* ���������������������������������������������������� */
4077  yc->ys = yc->cStartp;
4078
4079  /* ������������������������������������������������������������ */
4080  buf = d->genbuf;
4081  switch (jishu) {
4082  case JISHU_ZEN_KATA: /* �������������������������������������������� */
4083    func1 = (int (*)(...))RkwCvtZen;
4084    func2 = (int (*)(...))RkwCvtKana;
4085    goto jishuKakuteiKana;
4086
4087  case JISHU_HAN_KATA: /* �������������������������������������������� */
4088    func1 = (int (*)(...))RkwCvtKana;
4089    func2 = (int (*)(...))RkwCvtHan;
4090    goto jishuKakuteiKana;
4091
4092  case JISHU_HIRA: /* ������������������������������������ */
4093    func1 = (int (*)(...))RkwCvtZen;
4094    func2 = (int (*)(...))RkwCvtHira;
4095
4096  jishuKakuteiKana:
4097    /* ������������������������������������������������������������������������������������������������������������������������������������ */
4098    savedgf = yc->generalFlags;
4099    yc->generalFlags = savedgf & CANNA_YOMI_IGNORE_USERSYMBOLS;
4100    for (i = yc->cmark ; i < jishu_kEndp ;) {
4101      int j = i;
4102      while (i < jishu_kEndp && yc->kAttr[i] & STAYROMAJI) {
4103	yc->kAttr[i++] &= ~(HENKANSUMI | STAYROMAJI);
4104      }
4105      if (j < i) {
4106	kPos2rPos(yc, j, i, &yc->rStartp, &yc->rCurs);
4107	yc->kRStartp = j;
4108	yc->kCurs = i;
4109	makePhonoOnBuffer(d, yc, (unsigned char)0, RK_FLUSH, 0);
4110	jishu_kEndp += yc->kCurs - i;
4111	i = yc->kCurs;
4112      }else{
4113	i++;
4114      }
4115    }
4116    yc->generalFlags = savedgf;
4117
4118    /* ������������������������������������������������������������������������������������ */
4119    for (i = yc->cmark ; i < jishu_kEndp ; i = yc->kCurs) {
4120      int j;
4121
4122      for (j = i + 1 ; !(yc->kAttr[j] & SENTOU) ;) {
4123	j++;
4124      }
4125      if(j > jishu_kEndp) {
4126	j = jishu_kEndp;
4127      }
4128      srclen = j - i;
4129
4130      len = (*func1)(xxxx, 1024, yc->kana_buffer + i, srclen);
4131      len = (*func2)(buf, ROMEBUFSIZE, xxxx, len);
4132      yc->kCurs = j;
4133      kanaReplace(-srclen, buf, len, 0);
4134      jishu_kEndp += len - srclen; /* yc->kCurs - j ���������������� */
4135
4136      for (j = yc->kCurs - len ; j < yc->kCurs ; j++) {
4137	yc->kAttr[j] = HENKANSUMI;
4138      }
4139      yc->kAttr[yc->kCurs - len] |= SENTOU;
4140    }
4141    break;
4142
4143  case JISHU_ZEN_ALPHA: /* ������������������������������������ */
4144  case JISHU_HAN_ALPHA: /* ������������������������������������ */
4145    p = yc->romaji_buffer;
4146    kPos2rPos(yc, 0, yc->cmark, (int *)0, &pos);
4147
4148    for (i = pos ; i < jishu_rEndp ; i++) {
4149      xxxx[i - pos] =
4150	(jishu_case == CANNA_JISHU_UPPER) ? WToupper(p[i]) :
4151        (jishu_case == CANNA_JISHU_LOWER) ? WTolower(p[i]) : p[i];
4152      if (jishu_case == CANNA_JISHU_CAPITALIZE) {
4153	if (p[i] <= ' ') {
4154	  head = 1;
4155	}
4156	else if (head) {
4157	  head = 0;
4158	  xxxx[i - pos] = WToupper(p[i]);
4159	}
4160      }
4161    }
4162    xxxx[i - pos] = (WCHAR_T)0;
4163#if 0
4164    if (jishu_case == CANNA_JISHU_CAPITALIZE) {
4165      xxxx[0] = WToupper(xxxx[0]);
4166    }
4167#endif
4168    if (jishu == JISHU_ZEN_ALPHA) {
4169      len = RkwCvtZen(buf, ROMEBUFSIZE, xxxx, jishu_rEndp - pos);
4170    }
4171    else {
4172      len = RkwCvtNone(buf, ROMEBUFSIZE, xxxx, jishu_rEndp - pos);
4173    }
4174    yc->rCurs = jishu_rEndp;
4175    yc->kCurs = jishu_kEndp;
4176    kanaReplace(yc->cmark - yc->kCurs, buf, len, 0);
4177    jishu_kEndp = yc->kCurs;
4178
4179    /* ������������������������������������������������ */
4180    for (i = pos ; i < yc->rCurs ; i++) {
4181      yc->rAttr[i] = SENTOU;
4182    }
4183
4184    len = yc->kCurs;
4185    for (i = yc->cmark ; i < len ; i++) {
4186      yc->kAttr[i] = HENKANSUMI | SENTOU;
4187    }
4188
4189    /* �������������������� */
4190    for (i = jishu_rEndp ; i < yc->rEndp ; i++) {
4191      yc->rAttr[i] = 0;
4192    }
4193    yc->rAttr[jishu_rEndp] = SENTOU;
4194
4195    kanaReplace(yc->kEndp - jishu_kEndp, yc->romaji_buffer + jishu_rEndp,
4196		yc->rEndp - jishu_rEndp, 0);
4197    yc->rAttr[jishu_rEndp] |= SENTOU;
4198    yc->kAttr[jishu_kEndp] |= SENTOU;
4199    yc->rStartp = jishu_rEndp;
4200    yc->kRStartp = jishu_kEndp;
4201
4202    for (yc->kCurs = jishu_kEndp, yc->rCurs = jishu_rEndp ;
4203	 yc->kCurs < yc->kEndp ;) {
4204      yc->kCurs++; yc->rCurs++;
4205      if (yc->kRStartp == yc->kCurs - 1) {
4206	yc->kAttr[yc->kRStartp] |= SENTOU;
4207      }
4208      makePhonoOnBuffer(d, yc,
4209                          (unsigned char)yc->kana_buffer[yc->kCurs - 1], 0, 0);
4210    }
4211    if (yc->kRStartp != yc->kEndp) {
4212      if (yc->kRStartp == yc->kCurs - 1) {
4213	yc->kAttr[yc->kRStartp] |= SENTOU;
4214      }
4215      makePhonoOnBuffer(d, yc, (unsigned char)0, RK_FLUSH, 0);
4216    }
4217    break;
4218
4219  default:/* ���������������������������������������������������������������������������������������� */
4220    jishu_rEndp = jishu_kEndp = 0;
4221    break;
4222  }
4223  yc->kCurs = yc->kRStartp = yc->kEndp;
4224  yc->rCurs = yc->rStartp = yc->rEndp;
4225  yc->pmark = yc->cmark;
4226  yc->cmark = yc->kCurs;
4227  yc->jishu_kEndp = 0;
4228#ifdef WIN
4229  free(xxxx);
4230#endif
4231  return 0;
4232}
4233
4234static
4235int YomiJishu(uiContext d, int fn)
4236{
4237  yomiContext yc = (yomiContext)d->modec;
4238
4239  if (yc->henkanInhibition & CANNA_YOMI_INHIBIT_JISHU) {
4240    return NothingChangedWithBeep(d);
4241  }
4242  d->nbytes = 0;
4243  if ((yc->generalFlags & CANNA_YOMI_CHIKUJI_MODE) &&
4244      !(yc->status & CHIKUJI_OVERWRAP) && yc->nbunsetsu) {
4245    yc->status |= CHIKUJI_OVERWRAP;
4246    moveToChikujiTanMode(d);
4247  }
4248  else if (! RomajiFlushYomi(d, (WCHAR_T *)NULL, 0)) {
4249    d->more.todo = 1;
4250    d->more.ch = d->ch;
4251    d->more.fnum = 0;    /* �������� ch ���������������������������������������� */
4252    return d->nbytes;
4253  }
4254  else {
4255    enterJishuMode(d, yc);
4256    yc->minorMode = CANNA_MODE_JishuMode;
4257  }
4258  currentModeInfo(d);
4259  d->more.todo = 1;
4260  d->more.ch = d->ch;
4261  d->more.fnum = fn;
4262  return 0;
4263}
4264
4265static int
4266chikujiEndBun(uiContext d)
4267{
4268  yomiContext yc = (yomiContext)d->modec;
4269  int ret = 0;
4270
4271  if ((yc->generalFlags & CANNA_YOMI_CHIKUJI_MODE) && yc->nbunsetsu) {
4272    KanjiMode mdsv;
4273#ifndef WIN
4274    yomiContextRec ycsv;
4275#else
4276    yomiContext ycsv;
4277
4278    ycsv = (yomiContext)malloc(sizeof(yomiContextRec));
4279    if (ycsv) {
4280#endif
4281
4282    /* ���������������������������� */
4283#ifdef WIN
4284    * /* This is a little bit tricky source code */
4285#endif
4286    ycsv = *yc;
4287    yc->kEndp = yc->rEndp = 0;
4288    mdsv = d->current_mode;
4289    ret = TanKakutei(d);
4290    d->current_mode = mdsv;
4291    *yc =
4292#ifdef WIN
4293      * /* this is also a little bit trick source code */
4294#endif
4295      ycsv;
4296  }
4297#ifdef WIN
4298    free(ycsv);
4299  }
4300#endif
4301  return(ret);
4302}
4303
4304/* cfuncdef
4305
4306   replaceEnglish -- ��������������������������������������������������������������������������������������������������������
4307
4308   d, yc      : ������������������������
4309   start, end : ������������������������������������
4310   RKflag     : RkwMapPhonogram ����������������������������
4311   engflag    : ��������������������������������������������������������������������������������
4312
4313 */
4314
4315inline void
4316replaceEnglish(uiContext d, yomiContext yc, int start, int end, int RKflag, int engflag)
4317{
4318  int i;
4319
4320  kanaReplace(yc->pmark - yc->cmark,
4321	      yc->romaji_buffer + start, end - start, 0);
4322  yc->kRStartp = yc->pmark;
4323  yc->rStartp = start;
4324  for (i = start ; i < end ; i++) {
4325    yc->rAttr[i] &= ~SENTOU;
4326  }
4327  yc->rAttr[start] |= SENTOU;
4328  for (i = yc->pmark ; i < yc->kCurs ; i++) {
4329    yc->kAttr[i] &= ~(SENTOU | HENKANSUMI);
4330  }
4331  yc->kAttr[yc->pmark] |= SENTOU;
4332
4333  yc->n_susp_chars = 0; /* �������������������������������������������������������������������������������� */
4334  makePhonoOnBuffer(d, yc, 0, (unsigned char)RKflag, engflag);
4335  yc->kRStartp = yc->kCurs;
4336  yc->rStartp = yc->rCurs;
4337}
4338
4339int YomiMark (uiContext);
4340
4341int
4342YomiMark(uiContext d)
4343{
4344#ifndef NOT_ENGLISH_TABLE
4345  int rc, rp, i;
4346#endif
4347  yomiContext yc = (yomiContext)d->modec;
4348
4349#if defined(DEBUG) && !defined(WIN)
4350  if (iroha_debug) {
4351    fprintf(stderr,"yc->kCurs=%d yc->cmark=%d\n", yc->kCurs,yc->cmark);
4352  }
4353#endif /* DEBUG */
4354
4355  if (yc->kCurs != yc->cmark) { /* �������� */
4356
4357    if (yc->cmark < yc->kCurs) {
4358      yc->pmark = yc->cmark;
4359      yc->cmark = yc->kCurs;
4360    }
4361    else {
4362      /* ������������pmark < cmark ������������������������������������������������������������
4363	 cmark < pmark ���������������� pmark ���� cmark ��������������������������������������������
4364	 �������������������������������� pmark ���� cmark ����������������������������������������������������
4365	 ����������������������������������������������������������������������������������������������������������������������������
4366	 ���������������������������������������������������� */
4367      yc->pmark = yc->cmark = yc->kCurs;
4368    }
4369    yc->englishtype = CANNA_ENG_NO;
4370  }
4371#ifndef NOT_ENGLISH_TABLE
4372  if (englishdic) {
4373    if (regionGairaigo(yc, yc->pmark, yc->cmark)) {
4374      yc->englishtype++;
4375      yc->englishtype = (BYTE)((int)yc->englishtype % (int)(CANNA_ENG_NO + 1));
4376      if (yc->englishtype == CANNA_ENG_KANA) {
4377	kPos2rPos(yc, yc->pmark, yc->cmark, &rp, &rc);
4378	replaceEnglish(d, yc, rp, rc, RK_FLUSH, 1);
4379	yc->cmark = yc->kCurs;
4380      }
4381    }
4382    else {
4383      makeYomiReturnStruct(d);
4384      return 0;
4385    }
4386
4387    /* �������������������������������������������������������������������������������������������������������� */
4388    rp = rc = 0;
4389    for (i = yc->pmark ; i < yc->cmark ; i++) {
4390      if (yc->kAttr[i] & GAIRAIGO) {
4391	rp = i;
4392	do {
4393	  i++;
4394	} while (!(yc->kAttr[i] & SENTOU));
4395	rc = i;
4396	break;
4397      }
4398    }
4399    if (rp || rc) {
4400      int rs, re, offset;
4401      WCHAR_T space2[2];
4402
4403      kPos2rPos(yc, rp, rc, &rs, &re);
4404      switch (yc->englishtype) {
4405      case CANNA_ENG_KANA:
4406	break;
4407      case CANNA_ENG_ENG1:
4408	offset = yc->kCurs - rc;
4409	yc->kCurs -= offset;
4410	kanaReplace(rp - rc, yc->romaji_buffer + rs, re - rs,
4411		    HENKANSUMI | GAIRAIGO);
4412	yc->kAttr[yc->kCurs - re + rs] |= SENTOU;
4413	yc->kCurs += offset;
4414	yc->cmark = yc->kRStartp = yc->kCurs;
4415	break;
4416      case CANNA_ENG_ENG2:
4417	offset = yc->kCurs - rc;
4418	yc->kCurs -= offset;
4419	space2[0] = (WCHAR_T)' ';
4420	space2[1] = (WCHAR_T)' ';
4421	kanaReplace(rp - rc, space2, 2, HENKANSUMI | GAIRAIGO);
4422	yc->kAttr[yc->kCurs - 2] |= SENTOU;
4423	yc->kCurs--;
4424	kanaReplace(0, yc->romaji_buffer + rs, re - rs, HENKANSUMI | GAIRAIGO);
4425	yc->kAttr[yc->kCurs - re + rs] &= ~SENTOU;
4426	yc->kCurs += offset + 1;
4427	yc->cmark = yc->kRStartp = yc->kCurs;
4428	break;
4429      case CANNA_ENG_NO:
4430	kPos2rPos(yc, yc->pmark, yc->cmark, &rs, &re);
4431	replaceEnglish(d, yc, rs, re, 0, 0);
4432	yc->cmark = yc->kRStartp = yc->kCurs;
4433	break;
4434      }
4435    }
4436  }
4437#endif
4438  makeYomiReturnStruct(d);
4439  debug_yomi(yc);
4440  return 0;
4441}
4442
4443int
4444Yomisearchfunc(uiContext d, KanjiMode mode, int whattodo, int key, int fnum)
4445{
4446  yomiContext yc = (yomiContext)0;
4447  int len;
4448  extern KanjiModeRec yomi_mode;
4449
4450  if (d) {
4451    yc = (yomiContext)d->modec;
4452  }
4453
4454  if (yc && yc->id != YOMI_CONTEXT) {
4455    /* �������������������������������������������������������������������������������������������� core ��������������������
4456       ������������������������������������������������������������������������������������������������������������ */
4457    yc = (yomiContext)0;
4458  }
4459
4460  if (cannaconf.romaji_yuusen && yc) { /* ���������������������������� */
4461    len = yc->kCurs - yc->kRStartp;
4462    if (fnum == 0) {
4463      fnum = mode->keytbl[key];
4464    }
4465    if (fnum != CANNA_FN_FunctionalInsert && len > 0) {
4466      int n, m, t, flag, prevrule;
4467      WCHAR_T kana[128], roma[128];
4468      flag = cannaconf.ignore_case ? RK_IGNORECASE : 0;
4469
4470      WStrncpy(roma, yc->kana_buffer + yc->kRStartp, len);
4471      roma[len++] = (WCHAR_T)key;
4472
4473      prevrule = yc->last_rule;
4474      if ((RkwMapPhonogram(yc->romdic, kana, 128, roma, len, (WCHAR_T)key,
4475			   flag | RK_SOKON, &n, &m, &t, &prevrule) &&
4476	   n == len) || n == 0) {
4477	/* RK_SOKON ���������������������������������������� */
4478	fnum = CANNA_FN_FunctionalInsert;
4479      }
4480    }
4481  }
4482  return searchfunc(d, mode, whattodo, key, fnum);
4483}
4484
4485/*
4486  trimYomi -- ����������������������������������������������������������������
4487
4488   sy ey  ������������������������������������������������������������������������������������
4489   sr er  ����������������             ����
4490 */
4491
4492void
4493trimYomi(uiContext d, int sy, int ey, int sr, int er)
4494{
4495  yomiContext yc = (yomiContext)d->modec;
4496
4497  yc->kCurs = ey;
4498  yc->rCurs = er;
4499
4500  romajiReplace (yc->rEndp - er, (WCHAR_T *)NULL, 0, 0);
4501  kanaReplace   (yc->kEndp - ey, (WCHAR_T *)NULL, 0, 0);
4502
4503  yc->kCurs = sy;
4504  yc->rCurs = sr;
4505
4506  romajiReplace (-sr, (WCHAR_T *)NULL, 0, 0);
4507  kanaReplace   (-sy, (WCHAR_T *)NULL, 0, 0);
4508}
4509
4510inline int
4511TbBubunKakutei(uiContext d)
4512{
4513  tanContext tan, tc = (tanContext)d->modec;
4514  WCHAR_T *s = d->buffer_return, *e = s + d->n_buffer;
4515  int len;
4516
4517  tan = tc;
4518  while (tan->left) {
4519    tan = tan->left;
4520  }
4521
4522  len = doKakutei(d, tan, tc, s, e, (yomiContext *)0);
4523  d->modec = (mode_context)tc;
4524  tc->left = (tanContext)0;
4525  s += len;
4526  (void)TanMuhenkan(d);
4527  return len;
4528}
4529
4530int doTanConvertTb (uiContext, yomiContext);
4531
4532int TanBubunKakutei (uiContext);
4533
4534int
4535TanBubunKakutei(uiContext d)
4536{
4537  int len;
4538  tanContext tan;
4539  yomiContext yc = (yomiContext)d->modec;
4540  WCHAR_T *s = d->buffer_return, *e = s + d->n_buffer;
4541
4542  if (yc->id == YOMI_CONTEXT) {
4543    doTanConvertTb(d, yc);
4544    yc = (yomiContext)d->modec;
4545  }
4546  tan = (tanContext)yc;
4547  while (tan->left) {
4548    tan = tan->left;
4549  }
4550  len = doKakutei(d, tan, (tanContext)yc, s, e, (yomiContext *)0);
4551  d->modec = (mode_context)yc;
4552  yc->left = (tanContext)0;
4553
4554  makeYomiReturnStruct(d);
4555  currentModeInfo(d);
4556  return len;
4557}
4558
4559#if 0
4560/*
4561 * ��������������������������������������������������������������������������������������������������������������������
4562 *
4563 * ������������	uiContext
4564 * ������������	�������������������� 0	�������������������� -1
4565 */
4566TanBubunKakutei(uiContext d)
4567{
4568  extern KanjiModeRec cy_mode, yomi_mode;
4569  WCHAR_T *ptr = d->buffer_return, *eptr = ptr + d->n_buffer;
4570  yomiContext yc = (yomiContext)d->modec;
4571  tanContext tan;
4572  int i, j, n, l = 0, len, con, ret = 0;
4573#ifndef WIN
4574  WCHAR_T tmpbuf[ROMEBUFSIZE];
4575#else
4576  WCHAR_T *tmpbuf = (WCHAR_T *)malloc(sizeof(WCHAR_T) * ROMEBUFSIZE);
4577  if (!tmpbuf) {
4578    return 0;
4579  }
4580#endif
4581
4582  if (yc->id != YOMI_CONTEXT) {
4583    ret = TbBubunKakutei(d);
4584    goto return_ret;
4585  }
4586
4587  tan = (tanContext)yc;
4588  while (tan->left) {
4589    tan = tan->left;
4590  }
4591
4592  len = doKakutei(d, tan, (tanContext)yc, ptr, eptr, (yomiContext *)0);
4593  d->modec = (mode_context)yc;
4594  yc->left = (tanContext)0;
4595  ptr += len;
4596
4597  if (yomiInfoLevel > 0) {  /* �������������������� yomiInfo ���������������� */
4598    d->kanji_status_return->info &= ~KanjiYomiInfo;
4599  }
4600
4601  con = yc->context;
4602
4603  /* �������������������� ������������ */
4604  for (i = 0, n = yc->curbun ; i < n ; i++) {
4605    if (RkwGoTo(con, i) < 0) {
4606      ret = makeRkError(d, "\312\270\300\341\244\316\260\334\306\260\244\313"
4607	"\274\272\307\324\244\267\244\336\244\267\244\277");
4608                            /* ������������������������������������������������ */
4609      goto return_ret;
4610    }
4611    len = RkwGetKanji(con, ptr, (int)(eptr - ptr));
4612    if (len < 0) {
4613      (void)makeRkError(d, "\264\301\273\372\244\316\274\350\244\352\275\320"
4614	"\244\267\244\313\274\272\307\324\244\267\244\336\244\267\244\277");
4615                           /* �������������������������������������������������������� */
4616      ret = TanMuhenkan(d);
4617      goto return_ret;
4618    }
4619    ptr += len;
4620    j = RkwGetYomi(yc->context, tmpbuf, ROMEBUFSIZE);
4621    if (j < 0) {
4622      (void)makeRkError(d, "\245\271\245\306\245\244\245\277\245\271\244\362"
4623	"\274\350\244\352\275\320\244\273\244\336\244\273\244\363\244\307"
4624	"\244\267\244\277");
4625                           /* ���������������������������������������������������������������� */
4626      ret = TanMuhenkan(d);
4627      goto return_ret;
4628    }
4629    l += j;
4630  }
4631  d->nbytes = ptr - d->buffer_return;
4632
4633  for (i = j = 0 ; i < l ; i++) {
4634    if (yc->kAttr[i] & SENTOU) {
4635      do {
4636	++j;
4637      } while (!(yc->rAttr[j] & SENTOU));
4638    }
4639  }
4640  yc->rStartp = yc->rCurs = j;
4641  romajiReplace(-j, (WCHAR_T *)NULL, 0, 0);
4642  yc->kRStartp = yc->kCurs = i;
4643  kanaReplace(-i, (WCHAR_T *)NULL, 0, 0);
4644
4645  if (RkwEndBun(yc->context, cannaconf.Gakushu ? 1 : 0) == -1) {
4646    jrKanjiError = "\244\253\244\312\264\301\273\372\312\321\264\271\244\316"
4647	"\275\252\316\273\244\313\274\272\307\324\244\267\244\336\244\267"
4648	"\244\277";
4649                   /* ���������������������������������������������������������������� */
4650    if (errno == EPIPE) {
4651      jrKanjiPipeError();
4652    }
4653  }
4654
4655  if (yc->generalFlags & CANNA_YOMI_CHIKUJI_MODE) {
4656    yc->status &= CHIKUJI_NULL_STATUS;
4657    yc->cStartp = yc->cRStartp = 0;
4658    yc->kCurs = yc->kRStartp = yc->kEndp;
4659    yc->rCurs = yc->rStartp = yc->rEndp;
4660    yc->ys = yc->ye = yc->cStartp;
4661    clearHenkanContext(yc);
4662    d->current_mode = yc->curMode = yc->rEndp ? &cy_mode : yc->myEmptyMode;
4663  }
4664  else {
4665    d->current_mode = yc->curMode = &yomi_mode;
4666  }
4667  yc->minorMode = getBaseMode(yc);
4668
4669  yc->nbunsetsu = 0;
4670
4671  /* ��������������������������������������������������������������������������������mark������������������������ */
4672  yc->cmark = yc->pmark = 0;
4673
4674  abandonContext(d, yc);
4675
4676  doMuhenkan(d, yc);
4677
4678  makeYomiReturnStruct(d);
4679  currentModeInfo(d);
4680
4681  ret = d->nbytes;
4682
4683 return_ret:
4684#ifdef WIN
4685  free(tmpbuf);
4686#endif
4687  return ret;
4688}
4689#endif /* 0 */
4690
4691/*
4692  removeKana -- yomiContext ������������������������������������(��������������������)
4693
4694  k -- ������������������������
4695  r -- ��������������������������������
4696  d ����������������������������������������������������������������������������������������������������������������
4697
4698 */
4699
4700void
4701removeKana(uiContext d, yomiContext yc, int k, int r)
4702{
4703  int offs;
4704
4705  offs = yc->kCurs - k;
4706  yc->kCurs = k;
4707  kanaReplace(-k, (WCHAR_T *)NULL, 0, 0);
4708  if (offs > 0) {
4709    yc->kCurs = offs;
4710  }
4711  yc->cmark = yc->kRStartp = yc->kCurs;
4712  offs = yc->rCurs - r;
4713  yc->rCurs = r;
4714  romajiReplace(-r, (WCHAR_T *)NULL, 0, 0);
4715  if (offs > 0) {
4716    yc->rCurs = offs;
4717  }
4718  yc->rStartp = yc->rCurs;
4719}
4720
4721static int YomiNextJishu (uiContext);
4722
4723static
4724int YomiNextJishu(uiContext d)
4725{
4726  return YomiJishu(d, CANNA_FN_Next);
4727}
4728
4729static int YomiPreviousJishu (uiContext);
4730
4731static
4732int YomiPreviousJishu(uiContext d)
4733{
4734  return YomiJishu(d, CANNA_FN_Prev);
4735}
4736
4737static int YomiKanaRotate (uiContext);
4738
4739static
4740int YomiKanaRotate(uiContext d)
4741{
4742  return YomiJishu(d, CANNA_FN_KanaRotate);
4743}
4744
4745static int YomiRomajiRotate (uiContext);
4746
4747static
4748int YomiRomajiRotate(uiContext d)
4749{
4750  return YomiJishu(d, CANNA_FN_RomajiRotate);
4751}
4752
4753static int YomiCaseRotateForward (uiContext);
4754
4755static
4756int YomiCaseRotateForward(uiContext d)
4757{
4758  return YomiJishu(d, CANNA_FN_CaseRotate);
4759}
4760
4761static int YomiZenkaku (uiContext);
4762
4763static
4764int YomiZenkaku(uiContext d)
4765{
4766  return YomiJishu(d, CANNA_FN_Zenkaku);
4767}
4768
4769static int YomiHankaku (uiContext);
4770
4771static
4772int YomiHankaku(uiContext d)
4773{
4774  if (cannaconf.InhibitHankakuKana)
4775    return NothingChangedWithBeep(d);
4776  else
4777    return YomiJishu(d, CANNA_FN_Hankaku);
4778}
4779
4780static int YomiHiraganaJishu (uiContext);
4781
4782static
4783int YomiHiraganaJishu(uiContext d)
4784{
4785  return YomiJishu(d, CANNA_FN_Hiragana);
4786}
4787
4788static int YomiKatakanaJishu (uiContext);
4789
4790static
4791int YomiKatakanaJishu(uiContext d)
4792{
4793  return YomiJishu(d, CANNA_FN_Katakana);
4794}
4795
4796static int YomiRomajiJishu (uiContext);
4797
4798static
4799int YomiRomajiJishu(uiContext d)
4800{
4801  return YomiJishu(d, CANNA_FN_Romaji);
4802}
4803
4804static int YomiToLower (uiContext);
4805static
4806int YomiToLower(uiContext d)
4807{
4808  return YomiJishu(d, CANNA_FN_ToLower);
4809}
4810
4811static int YomiToUpper (uiContext);
4812
4813static
4814int YomiToUpper(uiContext d)
4815{
4816  return YomiJishu(d, CANNA_FN_ToUpper);
4817}
4818
4819static int YomiCapitalize (uiContext);
4820
4821static
4822int YomiCapitalize(uiContext d)
4823{
4824  return YomiJishu(d, CANNA_FN_Capitalize);
4825}
4826
4827/* ����������������������������������������������������
4828
4829 ������������������������������������������������������������������������
4830
4831   ����������������������������������������������������������������������������
4832
4833 ��������������������������������������������������������������������������������������������������������������������������������
4834 ��������������������������������������������
4835
4836 */
4837
4838#include "yomimap.h"
4839