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 #if !defined(lint) && !defined(__CODECENTER__)
24 static char rcs_id[] = "$Id: chikuji.c,v 1.3 2003/09/17 08:50:53 aida_s Exp $";
25 #endif
26 
27 #include	"canna.h"
28 
29 #ifdef MEASURE_TIME
30 #include	<sys/types.h>
31 #include <sys/times.h>
32 #endif /* MEASURE_TIME */
33 
34 /*********************************************************************
35  *                      wchar_t replace begin                        *
36  *********************************************************************/
37 #ifdef wchar_t
38 # error "wchar_t is already defined"
39 #endif
40 #define wchar_t cannawc
41 
42 extern int yomiInfoLevel, nKouhoBunsetsu, KeepCursorPosition;
43 extern int defaultContext;
44 extern KanjiModeRec tankouho_mode, cy_mode, cb_mode;
45 extern void makeYomiReturnStruct pro((uiContext));
46 extern exp(int) RkwGetServerVersion pro((int *, int *));
47 extern exp(int) RkwGetProtocolVersion pro((int *, int *));
48 
49 int forceRomajiFlushYomi pro((uiContext));
50 void moveToChikujiTanMode pro((uiContext));
51 void moveToChikujiYomiMode pro((uiContext));
52 
53 static void clearHenkanContent pro((yomiContext));
54 
55 static void
clearHenkanContent(yc)56 clearHenkanContent(yc)
57 yomiContext yc;
58 {
59   yc->allkouho = 0;
60   yc->kouhoCount = yc->curIkouho = 0;
61   return;
62 }
63 
64 void
clearHenkanContext(yc)65 clearHenkanContext(yc)
66 yomiContext yc;
67 {
68   if (yc->context >= 0) {
69     RkwCloseContext(yc->context);
70     yc->context = -1;
71   }
72   yc->nbunsetsu = yc->curbun = 0;
73   clearHenkanContent(yc);
74   return;
75 }
76 
77 extern NothingChanged pro((uiContext));
78 
79 /*
80   restoreChikujiYomi
81 
82   ����:
83     d   : uiContext
84     old : ����ʸ���
85 
86   ��뤳��:
87    (1) ʸ������������鵬����ʾ��ʸ�����ꤵ���롣
88    (2) ���ΤȤ���RkwRemoveBun �⤹�롣
89    (3) ����ʬ���ɤߤ��롣
90    (4) ʸ��ˤʤä�ʬ���ɤߤ�����ȡ�
91  */
92 
93 static int
restoreChikujiYomi(d,old)94 restoreChikujiYomi(d, old)
95      uiContext d;
96      int old;
97 {
98   yomiContext yc = (yomiContext)d->modec;
99   wchar_t *s = d->buffer_return, *e = s + d->n_buffer;
100   RkStat stat;
101   int len, i, j, yomilen, ll = 0, m = 0, n = 0, recalc = 0;
102 
103   d->nbytes = 0;
104   yomilen = yc->kEndp - yc->cStartp;
105   if (yc->nbunsetsu) {
106     yc->status |= CHIKUJI_ON_BUNSETSU;
107     if (yc->nbunsetsu > old) {
108       recalc = 1;
109     }
110     if (nKouhoBunsetsu) {
111       (void)cutOffLeftSide(d, yc, nKouhoBunsetsu - yc->nbunsetsu);
112       if (nKouhoBunsetsu < yc->nbunsetsu) {
113 	n = yc->nbunsetsu - nKouhoBunsetsu;
114 	if (n > old) {
115 	  n = old; /* ���ˤޤ������ˤʤäƤ��ʤ��ä�ʬ�ޤǤϳ��ꤵ���ʤ� */
116 	}
117       }
118     }
119     if (n > 0) { /* ���ꤵ����ʸ��� */
120 
121       recalc = 1;
122       for (i = 0 ; i < n ; i++) {
123 	if (RkwGoTo(yc->context, i) < 0 ||
124 	    (len = RkwGetKanji(yc->context, s, (int)(e - s))) < 0 ||
125 	    RkwGetStat(yc->context, &stat) == -1) {
126 	  return -1;
127 	}
128 	s += len;
129 
130 	ll += stat.ylen;
131 	m += stat.klen;
132       }
133       d->nbytes = s - d->buffer_return;
134       if (s < e) {
135 	*s++ = (wchar_t)'\0';
136       }
137 
138       if (RkwRemoveBun(yc->context, cannaconf.Gakushu ? 1 : 0) == -1) {
139 	return -1;
140       }
141 
142       /* ���ʥХåե��Ȥ����� */
143       kPos2rPos(yc, 0, ll, (int *)0, &j);
144 
145       if (yomiInfoLevel > 0) {
146 	d->kanji_status_return->info |= KanjiYomiInfo;
147 	len = xString(yc->kana_buffer, ll, s, e);
148 	s += len;
149 	if (s < e) {
150 	  *s++ = (wchar_t)'\0';
151 	}
152 	if (yomiInfoLevel > 1) {
153 	  len = xString(yc->romaji_buffer, j, s, e);
154 	  s += len;
155 	}
156 	if (s < e) {
157 	  *s++ = (wchar_t)'\0';
158 	}
159       }
160 
161       removeKana(d, yc, ll, j);
162 
163       yc->nbunsetsu -= n;
164     }
165     if (RkwGoTo(yc->context, yc->nbunsetsu - 1) == -1)
166       return(-1);
167     yc->curbun = yc->nbunsetsu - 1;
168     if (old < yc->curbun) { /* ��������Τ�Ĥα��˹Ԥ� */
169       yc->curbun = old;
170     }
171   }
172 
173   if (recalc) {
174     yomilen = RkwGetLastYomi(yc->context, d->genbuf, ROMEBUFSIZE);
175     if (yomilen == -1) {
176       return -1;
177     }
178     if (yomilen < yc->kEndp) { /* ɬ�����Ǥϡ� */
179       kPos2rPos(yc, 0, yc->kEndp - yomilen, (int *)0, &j);
180       yc->cStartp = yc->kEndp - yomilen;
181       yc->cRStartp = j;
182     }
183     yc->ys = yc->ye = yc->kEndp;
184   }
185 
186   if (yc->nbunsetsu) {
187     moveToChikujiTanMode(d);
188   }
189   return(0);
190 }
191 
192 static int
doesSupportChikuji()193 doesSupportChikuji()
194 {
195   int a, b;
196 
197   if (defaultContext == -1) {
198     if (KanjiInit() < 0 || defaultContext == -1) {
199       jrKanjiError = KanjiInitError();
200       return(-1);
201     }
202   }
203   RkwGetProtocolVersion(&a, &b);
204   return(a > 1);
205 }
206 
207 #ifndef NO_EXTEND_MENU
208 int
chikujiInit(d)209 chikujiInit(d)
210 uiContext d;
211 {
212   int chikuji_f;
213   yomiContext yc = (yomiContext)d->modec;
214 
215   if (yc->generalFlags & CANNA_YOMI_CHGMODE_INHIBITTED) {
216     return NothingChangedWithBeep(d);
217   }
218 
219   d->status = 0;
220   killmenu(d);
221 
222   chikuji_f = doesSupportChikuji();
223 
224   if (ToggleChikuji(d, 1) == -1) {
225     if(!chikuji_f)
226       jrKanjiError = "\245\265\241\274\245\320\244\254\303\340\274\241\274\253"
227 	"\306\260\312\321\264\271\244\362\245\265\245\335\241\274\245\310"
228 	"\244\267\244\306\244\244\244\336\244\273\244\363";
229                      /* �����Ф��༡��ư�Ѵ����ݡ��Ȥ��Ƥ��ޤ��� */
230     else
231       jrKanjiError = "\303\340\274\241\274\253\306\260\312\321\264\271\244\313"
232 	"\300\332\302\330\244\250\244\353\244\263\244\310\244\254\244\307"
233 	"\244\255\244\336\244\273\244\363";
234                      /* �༡��ư�Ѵ������ؤ��뤳�Ȥ��Ǥ��ޤ��� */
235     makeGLineMessageFromString(d, jrKanjiError);
236     currentModeInfo(d);
237     return(-1);
238   }
239   else {
240     if(!chikuji_f)
241       makeGLineMessageFromString(d, "\245\265\241\274\245\320\244\254\303\340"
242 	"\274\241\274\253\306\260\312\321\264\271\244\362\245\265\245\335"
243 	"\241\274\245\310\244\267\244\306\244\244\244\336\244\273\244\363");
244                 /* �����Ф��༡��ư�Ѵ����ݡ��Ȥ��Ƥ��ޤ��� */
245     else
246       makeGLineMessageFromString(d, "\303\340\274\241\274\253\306\260\312\321"
247 	"\264\271\244\313\300\332\302\330\244\250\244\336\244\267\244\277");
248                 /* �༡��ư�Ѵ������ؤ��ޤ��� */
249     currentModeInfo(d);
250     return 0;
251   }
252 }
253 #endif /* not NO_EXTEND_MENU */
254 
255 static int
chikujiSubstYomi(d)256 chikujiSubstYomi(d)
257 uiContext d;
258 {
259   yomiContext yc = (yomiContext)d->modec;
260   int n = yc->nbunsetsu, ret;
261 
262   if (yc->context == -1) { /* �ֽФ������ä���פΰ�̣�⤢�� */
263     if (confirmContext(d, yc) < 0) {
264       return -1;
265     }
266     if (!doesSupportChikuji()) {
267       jrKanjiError = "\245\265\241\274\245\320\244\254\303\340\274\241\274\253"
268 	"\306\260\312\321\264\271\244\362\245\265\245\335\241\274\245\310"
269 	"\244\267\244\306\244\244\244\336\244\273\244\363";
270                      /* �����Ф��༡��ư�Ѵ����ݡ��Ȥ��Ƥ��ޤ��� */
271       abandonContext(d, yc);
272       return(-1);
273     }
274     if (RkwBgnBun(yc->context, (wchar_t *)0, 1,
275                     RK_XFER << RK_XFERBITS | RK_KFER) == NG) {
276     substError:
277       jrKanjiError = "\303\340\274\241\274\253\306\260\312\321\264\271\244\313"
278 	"\274\272\307\324\244\267\244\336\244\267\244\277";
279                      /* �༡��ư�Ѵ��˼��Ԥ��ޤ��� */
280       /* �ʲ��ϲ����äƤ���Τ����顩 */
281       if (TanMuhenkan(d) == -1) {
282 	return -2;
283       }
284       return(-1);
285     }
286   }
287   yc->nbunsetsu = RkwSubstYomi(yc->context,
288 			       yc->ys - yc->cStartp, yc->ye - yc->cStartp,
289 			       yc->kana_buffer + yc->ys, yc->kEndp - yc->ys);
290   yc->ys = yc->ye = yc->kEndp;
291   if (yc->nbunsetsu < 0 || (ret = restoreChikujiYomi(d, n)) < 0) {
292     goto substError;
293   }
294   return(ret);
295 }
296 
ChikujiSubstYomi(d)297 ChikujiSubstYomi(d)
298   uiContext d;
299 {
300   yomiContext yc = (yomiContext)d->modec;
301 
302   if ((yc->ys == yc->ye && yc->kEndp == yc->ye)
303       || yc->kEndp != yc->kCurs
304       || !(yc->kAttr[yc->kEndp - 1] & HENKANSUMI)) {
305     /* ���������Ϥ��ʤ��ä��ꡢ
306        �Ǹ�ؤ����Ϥ���ʤ��ä��ꡢ
307        �Ǹ�λ������޻������Ѵ�����Ĥ����Ƥ��ʤ��ä��ꤷ���� */
308     return 0; /* �ʤˤ⤷�ʤ� */
309   }
310   return chikujiSubstYomi(d);
311 }
312 
313 int
ChikujiTanDeletePrevious(d)314 ChikujiTanDeletePrevious(d)
315      uiContext d;
316 {
317   yomiContext yc = (yomiContext)d->modec;
318   int i, j, l = 0, flg = 0;
319   RkStat stat;
320 
321   if (yc->cRStartp < yc->rEndp) { /* ���޻������äƤ��� */
322     flg = 1;
323   }
324   d->nbytes = 0;
325 
326   /* �ޤ�������ʸ�ᤫ������ɤߤ��᤹ */
327   if (forceRomajiFlushYomi(d)) {
328     return d->nbytes;
329   }
330   if (RkwSubstYomi(yc->context, 0, yc->ye - yc->cStartp,
331                                     (wchar_t *)0, 0) == NG) {
332     /* �ɤߤǻĤäƤ���ʬ���༡�Υǡ�������ä� */
333     (void)makeRkError(d, "\306\311\244\337\244\313\314\341\244\271\244\263"
334 	"\244\310\244\254\244\307\244\255\244\336\244\273\244\363");
335                          /* �ɤߤ��᤹���Ȥ��Ǥ��ޤ��� */
336     (void)TanMuhenkan(d); /* �����פ�Ρ� */
337     return 0;
338   }
339   yc->ys = yc->ye = yc->cStartp;
340   for (i = yc->nbunsetsu - 1 ; i >= yc->curbun ; i--) {
341     /* ������ʸ�ᤫ������ɤߤ��᤹����ν��� */
342     if (RkwGoTo(yc->context, i) == NG
343 	|| RkwGetStat(yc->context, &stat) == NG
344 	|| RkwStoreYomi(yc->context, (wchar_t *)0, 0) == NG) {
345       (void)makeRkError(d, "\306\311\244\337\244\313\314\341\244\271\244\263"
346 	"\244\310\244\254\244\307\244\255\244\336\244\273\244\363");
347                            /* �ɤߤ��᤹���Ȥ��Ǥ��ޤ��� */
348       TanMuhenkan(d); /* ���졢�פ�Ρ� */
349       return 0;
350     }
351     l += stat.ylen;
352   }
353   yc->nbunsetsu = yc->curbun;
354   if (l) {
355     i = j = 0;
356     do {
357       ++i;
358       if (yc->kAttr[yc->cStartp - i] & SENTOU) {
359 	for (j++ ;
360 	     j < yc->cRStartp && !(yc->rAttr[yc->cRStartp - j] & SENTOU) ;) {
361 	  j++;
362 	}
363       }
364     } while (i < l);
365     yc->cStartp = (i < yc->cStartp) ? yc->cStartp - i : 0;
366     yc->cRStartp = (j < yc->cRStartp) ? yc->cRStartp - j : 0;
367   }
368   if (KeepCursorPosition && yc->kCurs != yc->kEndp) {
369     yc->kRStartp = yc->kCurs = yc->cStartp;
370     yc->rStartp = yc->rCurs = yc->cRStartp;
371   }
372   else {
373     yc->kRStartp = yc->kCurs = yc->kEndp;
374     yc->rStartp = yc->rCurs = yc->rEndp;
375   }
376   yc->ys = yc->ye = yc->cStartp;
377   clearHenkanContent(yc);
378   if (yc->curbun) {
379     yc->curbun--;
380   }
381   yc->status |= CHIKUJI_OVERWRAP;
382   moveToChikujiYomiMode(d);
383   makeKanjiStatusReturn(d, yc);
384   if (flg && cannaconf.chikujiRealBackspace && !KeepCursorPosition) {
385     d->more.todo = 1;
386     d->more.ch = 0;
387     d->more.fnum = CANNA_FN_DeletePrevious;
388     /* Ʊ�����Ȥ�ޤ����äƴ������� */
389   }
390   return 0;
391 }
392 
393 /*
394   chikuji_restore_yomi
395 
396     cStartp, cRStartp ��Ĵ������
397  */
398 
399 static int
chikuji_restore_yomi(d)400 chikuji_restore_yomi(d)
401      uiContext d;
402 {
403   yomiContext yc = (yomiContext)d->modec;
404   int l, j;
405 
406   if ((l = RkwGetLastYomi(yc->context, d->genbuf, ROMEBUFSIZE)) == -1) {
407     return makeRkError(d, "\314\244\267\350\312\270\300\341\244\362\274\350"
408 	"\244\352\275\320\244\273\244\336\244\273\244\363\244\307\244\267"
409 	"\244\277");
410                           /* ̤��ʸ�����Ф��ޤ���Ǥ��� */
411   }
412   if (l != yc->kEndp - yc->cStartp) { /* �Ѥ�ä��� */
413     kPos2rPos(yc, 0, yc->kEndp - l, (int *)0, &j);
414     yc->cStartp = yc->kEndp - l;
415     yc->cRStartp = j;
416   }
417 
418   yc->ys = yc->ye = yc->cStartp;
419   return 0;
420 }
421 
422 static int
chikuji_subst_yomi(d)423 chikuji_subst_yomi(d)
424      uiContext d;
425 {
426   yomiContext yc = (yomiContext)d->modec;
427   int l, n = yc->nbunsetsu;
428 
429   /* �ɤߤ��������碌�� */
430   l = RkwSubstYomi(yc->context, yc->ys - yc->cStartp, yc->ye - yc->cStartp,
431 		   yc->kana_buffer + yc->ys, yc->kEndp - yc->ys);
432   yc->ys = yc->ye = yc->kEndp;
433   if (l == -1) {
434     jrKanjiError = "\312\321\264\271\244\313\274\272\307\324\244\267\244\336"
435 	"\244\267\244\277";
436                    /* �Ѵ��˼��Ԥ��ޤ��� */
437     (void)TanMuhenkan(d);
438     return -1;
439   }
440   yc->nbunsetsu = l;
441   if (l > n) {
442     yc->curbun = n; /* ����ʸ�᤬������ */
443   }
444   return chikuji_restore_yomi(d);
445 }
446 
447 static ChikujiTanExtend pro((uiContext));
448 
449 static int
ChikujiTanExtend(d)450 ChikujiTanExtend(d)
451      uiContext d;
452 {
453   yomiContext yc = (yomiContext)d->modec;
454   int i;
455 
456   d->nbytes = 0;
457   yc->kouhoCount = 0;
458 
459   if (yc->ys < yc->kEndp || yc->ye != yc->kEndp) {
460     i = yc->curbun; /* �ȤäȤ� */
461     if (chikuji_subst_yomi(d) == -1) {
462       makeGLineMessageFromString(d, jrKanjiError);
463       return TanMuhenkan(d);
464     }
465     if (RkwGoTo(yc->context, i) == -1) {
466       (void)makeRkError(d, "\312\270\300\341\244\316\260\334\306\260\244\313"
467 	"\274\272\307\324\244\267\244\336\244\267\244\277");
468                            /* ʸ��ΰ�ư�˼��Ԥ��ޤ��� */
469       return TanMuhenkan(d);
470     }
471     yc->curbun = i;
472   }
473   if ((yc->nbunsetsu = RkwEnlarge(yc->context)) <= 0) {
474     (void)makeRkError(d, "\312\270\300\341\244\316\263\310\302\347\244\313"
475 	"\274\272\307\324\244\267\244\336\244\267\244\277");
476                          /* ʸ��γ���˼��Ԥ��ޤ��� */
477     return TanMuhenkan(d);
478   }
479   if (chikuji_restore_yomi(d) == NG) {
480     return TanMuhenkan(d);
481   }
482   yc->status |= CHIKUJI_OVERWRAP;
483   makeKanjiStatusReturn(d, yc);
484   return d->nbytes;
485 }
486 
487 static ChikujiTanShrink pro((uiContext));
488 
489 static int
ChikujiTanShrink(d)490 ChikujiTanShrink(d)
491      uiContext d;
492 {
493   yomiContext yc = (yomiContext)d->modec;
494   RkStat stat;
495   int i;
496 
497   d->nbytes = 0;
498   yc->kouhoCount = 0;
499   if (yc->ys < yc->kEndp || yc->ye != yc->kEndp) {
500     i = yc->curbun;
501     if (chikuji_subst_yomi(d) == -1) {
502       makeGLineMessageFromString(d, jrKanjiError);
503       return TanMuhenkan(d);
504     }
505     if (RkwGoTo(yc->context, i) == -1) {
506       (void)makeRkError(d, "\312\270\300\341\244\316\275\314\276\256\244\313"
507 	"\274\272\307\324\244\267\244\336\244\267\244\277");
508                            /* ʸ��ν̾��˼��Ԥ��ޤ��� */
509       return TanMuhenkan(d);
510     }
511     yc->curbun = i;
512   }
513 
514   if (RkwGetStat(yc->context, &stat) < 0 || stat.ylen == 1) {
515     /* ����ʾ�û���Ǥ��뤫�ɤ�����ǧ���פ롩 */
516     return NothingForGLine(d);
517   }
518   yc->nbunsetsu = RkwShorten(yc->context);
519   if (yc->nbunsetsu <= 0) { /* 0 �äƤ��Ȥ���Τ��ʤ��� */
520     (void)makeRkError(d, "\312\270\300\341\244\316\275\314\276\256\244\313"
521 	"\274\272\307\324\244\267\244\336\244\267\244\277");
522                          /* ʸ��ν̾��˼��Ԥ��ޤ��� */
523     return TanMuhenkan(d);
524   }
525   if (chikuji_restore_yomi(d) == NG) {
526     return TanMuhenkan(d);
527   }
528   yc->status |= CHIKUJI_OVERWRAP;
529   makeKanjiStatusReturn(d, yc);
530   return d->nbytes;
531 }
532 
533 static ChikujiYomiDeletePrevious pro((uiContext));
534 
535 static int
ChikujiYomiDeletePrevious(d)536 ChikujiYomiDeletePrevious(d)
537      uiContext d;
538 {
539   yomiContext yc = (yomiContext)d->modec;
540   RkStat stat;
541   int i, j, l = 0;
542 
543   d->nbytes = 0;
544   if (!(yc->cStartp < yc->kCurs)) { /* �ɤߤ��ʤ��ʤ� */
545     if (!yc->nbunsetsu) { /* ʸ���ʤ� */
546       return NothingChanged(d);
547     }
548     else {
549       if (RkwSubstYomi(yc->context, 0, yc->ye - yc->cStartp,
550                                         (wchar_t *)0, 0) == NG) {
551 	(void)makeRkError(d, "\306\311\244\337\244\313\314\341\244\271\244\263"
552 	"\244\310\244\254\244\307\244\255\244\336\244\273\244\363");
553                              /* �ɤߤ��᤹���Ȥ��Ǥ��ޤ��� */
554 	(void)TanMuhenkan(d);
555 	return 0;
556       }
557       yc->ys = yc->ye = yc->cStartp;
558       yc->curbun = yc->nbunsetsu - 1; /* �ҤȤ��ɤߤ��᤹ */
559       for (i = yc->nbunsetsu - 1; i >= yc->curbun; i--) {
560 	if (RkwGoTo(yc->context, i) == NG ||
561 	    RkwGetStat(yc->context, &stat) == NG ||
562 	    RkwStoreYomi(yc->context, (wchar_t *)0, 0) == NG) {
563 	  return makeRkError(d, "\306\311\244\337\244\313\314\341\244\271"
564 	"\244\263\244\310\244\254\244\307\244\255\244\336\244\273\244\363");
565                                 /* �ɤߤ��᤹���Ȥ��Ǥ��ޤ��� */
566 	}
567 	l += stat.ylen;
568 	yc->nbunsetsu--;
569       }
570       i = j = 0;
571       do {
572 	++i;
573 	if (yc->kAttr[yc->cStartp - i] & SENTOU) {
574 	  for (j++ ;
575 	       j < yc->cRStartp && !(yc->rAttr[yc->cRStartp - j] & SENTOU) ;) {
576 	    j++;
577 	  }
578 	}
579       } while (i < l);
580       yc->kCurs = yc->kRStartp = yc->cStartp;
581       yc->rCurs = yc->rStartp = yc->cRStartp;
582       yc->cStartp = (i < yc->cStartp) ? yc->cStartp - i : 0;
583       yc->cRStartp = (j < yc->cRStartp) ? yc->cRStartp - j : 0;
584       yc->ys = yc->ye = yc->cStartp;
585       clearHenkanContent(yc);
586       if (yc->curbun) {
587 	yc->curbun--;
588       }
589 
590       makeKanjiStatusReturn(d, yc);
591       return 0;
592     }
593   }
594   if (yc->kCurs - 1 < yc->ys) {
595     yc->ys = yc->kCurs - 1;
596   }
597   if (yc->ys < 0) {
598     yc->ys = 0;
599   }
600   KanaDeletePrevious(d);
601   yc->status |= CHIKUJI_OVERWRAP;
602   if (yc->kCurs <= yc->cStartp && yc->kEndp <= yc->cStartp && yc->nbunsetsu) {
603     /* ʸ��Ϥ���Τ��ɤߤ��ʤ��ʤ� */
604     if (RkwGoTo(yc->context, yc->nbunsetsu - 1) == -1) {
605       return makeRkError(d, "\312\270\300\341\244\316\260\334\306\260\244\313"
606 	"\274\272\307\324\244\267\244\336\244\267\244\277");
607                             /* ʸ��ΰ�ư�˼��Ԥ��ޤ��� */
608     }
609     yc->kouhoCount = 0;
610     yc->curbun = yc->nbunsetsu - 1;
611     moveToChikujiTanMode(d);
612     makeKanjiStatusReturn(d, yc);
613   }
614   else {
615     moveToChikujiYomiMode(d);
616     makeYomiReturnStruct(d);
617     if (yc->kEndp <= yc->cStartp && !yc->nbunsetsu) {
618       /* ���ˤ�ʤ� */
619       d->current_mode = yc->curMode = yc->myEmptyMode;
620       d->kanji_status_return->info |= KanjiEmptyInfo;
621     }
622   }
623   return 0;
624 }
625 
626 static ChikujiHenkan pro((uiContext));
627 
628 static int
ChikujiHenkan(d)629 ChikujiHenkan(d)
630      uiContext d;
631 {
632   yomiContext yc = (yomiContext)d->modec;
633   int n, tmp, idx;
634 
635   if (!yc->nbunsetsu && yc->rEndp == /* yc->cRStartp(== 0) + */ 1 &&
636       (yc->kAttr[0] & SUPKEY) &&
637       (idx = findSup(yc->romaji_buffer[0]))) {
638     return selectKeysup(d, yc, idx - 1);
639   }
640   if (!doesSupportChikuji()) {
641     jrKanjiError = "\245\265\241\274\245\320\244\254\303\340\274\241\274\253"
642 	"\306\260\312\321\264\271\244\362\245\265\245\335\241\274\245\310"
643 	"\244\267\244\306\244\244\244\336\244\273\244\363";
644                    /* �����Ф��༡��ư�Ѵ����ݡ��Ȥ��Ƥ��ޤ��� */
645     makeGLineMessageFromString(d, jrKanjiError);
646     makeKanjiStatusReturn(d, yc);
647     d->nbytes = 0;
648     return 0;
649   }
650   if (yc->status & CHIKUJI_ON_BUNSETSU) {
651     tmp = yc->curbun;
652   }
653   else {
654     tmp = yc->nbunsetsu;
655   }
656   d->nbytes = 0;
657   if (yc->kCurs < yc->ys) {
658     yc->ys = yc->kCurs;
659   }
660   if (forceRomajiFlushYomi(d)) {
661     return d->nbytes;
662   }
663 
664   if (containUnconvertedKey(yc)) {
665     if (yc->cmark < yc->cStartp) {
666       yc->cmark = yc->cStartp;
667     }
668     YomiMark(d);
669     yc->ys = yc->pmark;
670     if (forceRomajiFlushYomi(d)) {
671       return d->nbytes;
672     }
673   }
674 
675   yc->kRStartp = yc->kCurs = yc->kEndp;
676   yc->rStartp  = yc->rCurs = yc->rEndp;
677 
678   if (yc->cStartp < yc->kEndp) { /* �ɤߤ������ */
679     yc->kCurs = yc->kEndp;
680     if (chikujiSubstYomi(d) < 0) {
681       makeGLineMessageFromString(d, jrKanjiError);
682       TanMuhenkan(d);
683       return 0;
684     }
685     n = RkwFlushYomi(yc->context);
686     if (n == -1) {
687       (void)makeRkError(d, "\312\321\264\271\244\313\274\272\307\324\244\267"
688 	"\244\336\244\267\244\277");
689                            /* �Ѵ��˼��Ԥ��ޤ��� */
690       (void)TanMuhenkan(d);
691       return 0;
692     }
693     yc->cStartp = yc->kEndp;
694     yc->cRStartp = yc->rEndp;
695     yc->kouhoCount = 1;
696     yc->status |= CHIKUJI_ON_BUNSETSU;
697     if (n > yc->nbunsetsu) {
698       yc->curbun = yc->nbunsetsu;
699       yc->nbunsetsu = n;
700     }
701   }
702   if (RkwGoTo(yc->context, tmp) == -1) {
703     makeRkError(d, "\303\340\274\241\312\321\264\271\244\313\274\272\307\324"
704 	"\244\267\244\336\244\267\244\277");
705                    /* �༡�Ѵ��˼��Ԥ��ޤ��� */
706     return 0;
707   }
708   yc->curbun = tmp;
709   yc->ys = yc->ye = yc->cStartp;
710   d->current_mode = yc->curMode = &tankouho_mode;
711   yc->minorMode = CANNA_MODE_TankouhoMode;
712   if (cannaconf.kouho_threshold > 0 &&
713       yc->kouhoCount >= cannaconf.kouho_threshold) {
714     return tanKouhoIchiran(d, 0);
715   }
716   currentModeInfo(d);
717   makeKanjiStatusReturn(d, yc);
718   return d->nbytes;
719 }
720 
721 void
moveToChikujiTanMode(d)722 moveToChikujiTanMode(d)
723      uiContext d;
724 {
725   yomiContext yc = (yomiContext)d->modec;
726 
727   yc->status |= CHIKUJI_ON_BUNSETSU;
728   yc->minorMode = CANNA_MODE_ChikujiTanMode;
729   d->current_mode = yc->curMode = &cb_mode;
730   currentModeInfo(d);
731 }
732 
733 void
moveToChikujiYomiMode(d)734 moveToChikujiYomiMode(d)
735      uiContext d;
736 {
737   yomiContext yc = (yomiContext)d->modec;
738 
739   yc->status &= ~CHIKUJI_ON_BUNSETSU;
740   d->current_mode = yc->curMode = &cy_mode;
741   EmptyBaseModeInfo(d, yc);
742 }
743 
744 static int
generalNaive(d,fn)745 generalNaive(d, fn)
746 uiContext d;
747 int (*fn)();
748 {
749   if ((((yomiContext)d->modec)->generalFlags) &
750       (CANNA_YOMI_HANKAKU | CANNA_YOMI_ROMAJI | CANNA_YOMI_BASE_HANKAKU)) {
751     return (*fn)(d);
752   }
753   else {
754     return ChikujiHenkan(d);
755   }
756 }
757 
758 extern int YomiInsert();
759 
760 static ChikujiHenkanNaive pro((uiContext));
761 
762 static int
ChikujiHenkanNaive(d)763 ChikujiHenkanNaive(d)
764 uiContext d;
765 {
766   return generalNaive(d, YomiInsert);
767 }
768 
769 static ChikujiHenkanOrNothing pro((uiContext));
770 
771 static int
ChikujiHenkanOrNothing(d)772 ChikujiHenkanOrNothing(d)
773      uiContext d;
774 {
775   return generalNaive(d, NothingChanged);
776 }
777 
778 static ChikujiMuhenkan pro((uiContext));
779 
780 static int
ChikujiMuhenkan(d)781 ChikujiMuhenkan(d)
782 uiContext d;
783 {
784   yomiContext yc = (yomiContext)d->modec;
785 
786   if (yc->nbunsetsu) {
787     return TanMuhenkan(d);
788   }
789   else if (yc->left || yc->right) {
790     removeCurrentBunsetsu(d, (tanContext)yc);
791     yc = (yomiContext)d->modec;
792   }
793   else {
794     RomajiClearYomi(d);
795     d->current_mode = yc->curMode = yc->myEmptyMode;
796     d->kanji_status_return->info |= KanjiEmptyInfo;
797   }
798   makeKanjiStatusReturn(d, yc);
799   return 0;
800 }
801 
802 #ifndef wchar_t
803 # error "wchar_t is already undefined"
804 #endif
805 #undef wchar_t
806 /*********************************************************************
807  *                       wchar_t replace end                         *
808  *********************************************************************/
809 
810 #include "chikujimap.h"
811