1 /*
2  * Copyright (c) 1994  Sony Corporation
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining
5  * a copy of this software and associated documentation files (the
6  * "Software"), to deal in the Software without restriction, including
7  * without limitation the rights to use, copy, modify, merge, publish,
8  * distribute, sublicense, and/or sell copies of the Software, and to
9  * permit persons to whom the Software is furnished to do so, subject to
10  * the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be
13  * included in all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18  * IN NO EVENT SHALL SONY CORPORATION BE LIABLE FOR ANY CLAIM,
19  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
21  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22  *
23  * Except as contained in this notice, the name of Sony Corporation
24  * shall not be used in advertising or otherwise to promote the sale, use
25  * or other dealings in this Software without prior written authorization
26  * from Sony Corporation.
27  *
28  */
29 
30 /*
31  * $SonyRCSfile: douon.c,v $
32  * $SonyRevision: 1.2 $
33  * $SonyDate: 1996/02/23 11:04:02 $
34  */
35 
36 
37 
38 #include <stdlib.h>
39 #include <string.h>
40 #include "common.h"
41 #include "key.h"
42 #include "wchar16.h"
43 
44 #include "sj3.h"
45 
46 #define DNUM		5
47 
48 static int		Dcount;
49 static int		Dpoint;
50 static struct douon_sj3	HenkanDouon[DOUON_N];
51 static wchar16_t		Dkanji[BUFFLENGTH * 2];
52 
53 int
SJ_getdouon(wchar16_t * s,struct douon_sj3 * d,int n,int choice,int reconv)54 SJ_getdouon(wchar16_t *s, struct douon_sj3 *d, int n, int choice, int reconv)
55 {
56 	int	len;
57 
58         Dcount = SJ2_getdouon (s, d, n, choice, reconv);
59 
60 
61         if (Dcount < 0 && !dconnect(1))
62                 Dcount = SJ2_getdouon (s, d, n, choice, reconv);
63 
64 	if (Dcount <= 0) {
65 		Dcount = 1;
66 		len = wslen (s);
67 		Strncpy ((char *)d[0].ddata, s, len);
68 		d[0].dlen = wcbyte(s);
69 		d[0].wlen = len;
70 		return(0);
71 	} else
72 		return(1);
73 }
74 
75 
76 
77 void
exec_douon()78 exec_douon()
79 {
80 	Conversion	*cv;
81 	int	val;
82 
83 	cv = GetConversion ();
84 	if (cv->CurBun == -1) {
85 		cv->CurBun = 0;
86 		Rdisp ();
87 	}
88 	cv->PreBun = cv->CurBun;
89 	if (cv->Bkettei[cv->CurBun] & Bmuhenkan)
90 		val = Sdouon (2);
91 	else
92 		val = Sdouon (1);
93 	if (!val)
94 		Rdisp ();
95 }
96 
97 void
wrap_douon(int back)98 wrap_douon(int back)
99 {
100 	Conversion	*cv;
101 	int	val;
102 
103 	cv = current_conversion;
104 	if (cv->CurBun == -1) {
105 		cv->CurBun = 0;
106 		Rdisp ();
107 	}
108 	cv->PreBun = cv->CurBun;
109 	if (cv->Dflag == cv->CurBun)
110 		val = Rdouon (back);
111 	else {
112 		val = Sdouon (2);
113 		cv->Dflag = cv->CurBun;
114 	}
115 	if (!val)
116 		Rdisp ();
117 }
118 
119 
120 
121 int
Cdouon(wchar16_t * yomi,int gnum)122 Cdouon(wchar16_t *yomi, int gnum)
123 {
124 
125 
126 	int	i, j;
127 	int	len;
128 	wchar16_t	*s;
129 	int	dispnum;
130 	int		num;
131 	int		displen;
132 	int		base;
133 	char		tmp[BUFFLENGTH], tmp2[BUFFLENGTH * 2];
134 	wchar16_t		wtmp[BUFFLENGTH], wtmp2[BUFFLENGTH * 2];
135 
136 	int		gakusyuu;
137 	u_short		row, col;
138 	Conversion	*cv;
139 
140 	cv = current_conversion;
141 
142 	gakusyuu = SJ_getdouon (yomi, HenkanDouon, gnum, 0, 0);
143 
144 	dispnum = DNUM;
145 	if (dispnum > Dcount)
146 		j = Dcount;
147 	else
148 		j = dispnum;
149 	len = 0;
150 	for (i = 0 ; i < j ; i ++)
151 		len += HenkanDouon[i].dlen;
152 	len /= j;
153 	if (len < 1)
154 		len = 1;
155 	len += 6;
156 	snprintf (tmp, sizeof(tmp), "%d/%d ", Dcount, Dcount);
157 	displen = cv->column - strlen (tmp) - 1;
158 	if (displen < 1)
159 		displen = 1;
160 	num = displen / len;
161 	if (num < 1)
162 		num = 1;
163 	if (num < dispnum && num > 0)
164 		dispnum = num;
165 
166 	for (i = 0 ; ; ) {
167 		if (i >= Dcount)
168 			i = 0;
169 		StartGuide (&row, &col);
170 		Clear_EOL ();
171 		base = i;
172 
173 		snprintf (tmp, sizeof(tmp), "%d/%d", i + 1, Dcount);
174 		(void) mbstowcs(wtmp, tmp, BUFFLENGTH);
175 		printR (wtmp);
176 		put_space (1);
177 
178 		for (j = 0 ; j < dispnum ; j ++, i ++) {
179 			if (i >= Dcount)
180 				break;
181 			len = HenkanDouon[i].dlen;
182 
183 			if (len > displen)
184 				len = displen;
185 
186 			s = (wchar16_t *)HenkanDouon[i].ddata;
187 			Strncpy (wtmp, s, HenkanDouon[i].wlen);
188 			wtmp[HenkanDouon[i].wlen] = '\0';
189                         (void) wcstombs(tmp, wtmp, BUFFLENGTH);
190 			snprintf (tmp2, sizeof(tmp2), "[%d] %s ", j+1, tmp);
191                         (void) mbstowcs(wtmp2, tmp2, BUFFLENGTH);
192 			SJ_print (wtmp2);
193 		}
194 
195 		EndGuide (row, col);
196 		Flush ();
197 		num = Dselect (j);
198 
199 
200 		if (num == 0)
201 			continue;
202 
203 
204 		else if (num == -1) {
205 			if ((i >= Dcount) && ((Dcount % dispnum) != 0))
206 				i = Dcount - (Dcount % dispnum);
207 			else
208 				i -= dispnum;
209 			i -= dispnum;
210 			if (i < 0) {
211 				if (Dcount > dispnum) {
212 					if ((Dcount % dispnum) == 0)
213 						i = Dcount - dispnum;
214 					else
215 						i = Dcount - (Dcount % dispnum);
216 				}
217 				else
218 					i = 0;
219 			}
220 			continue;
221 		}
222 
223 
224 		else if (num > j) {
225 			disp_mode ();
226 			return (FALSE);
227 		}
228 
229 
230 		else
231 			break;
232 	}
233 
234 	disp_mode ();
235 
236 	Dpoint = base + num - 1;
237 	len = HenkanDouon[Dpoint].dlen;
238 	s = (wchar16_t *)HenkanDouon[Dpoint].ddata;
239 	Strncpy (Dkanji, s, HenkanDouon[Dpoint].wlen);
240 	Dkanji[HenkanDouon[Dpoint].wlen] = '\0';
241  	if (HenkanDouon[Dpoint].valid)
242  		PushGD (gnum, &HenkanDouon[Dpoint].dcid);
243 
244 	if (gakusyuu)
245  		if (HenkanDouon[Dpoint].valid)
246  			SJ2_study (&HenkanDouon[Dpoint].dcid);
247  		else
248  			SJ2_toroku(yomi, HenkanDouon[Dpoint].ddata, SJ3_H_NRMNOUN);
249 
250 	return (TRUE);
251 }
252 
253 int
Dselect(int lim)254 Dselect(int lim)
255 {
256 	int	c, num;
257 	char		s[2];
258 
259 	SaveConversion ();
260 	while ((c = inkey ()) != EOF) {
261 		if (AnotherConversion ()) {
262 			unget_key (c);
263 			break;
264 		}
265 		if (keyvalue == KEY_KETTEI)
266 			break;
267 		else if (keyvalue == KEY_HENKAN || keyvalue == KEY_RIGHT)
268 			return (0);
269 		else if (c == ' ')
270 			return (0);
271 		else if (keyvalue == KEY_MUHENKAN || keyvalue == KEY_LEFT
272 			|| is_bsdel (c))
273 			return (-1);
274 		else if (WcIsASCII(c) && isdigit (WcLowByte(c))) {
275 			*s = c;
276 			s[1] = '\0';
277 			num = atoi (s);
278 			if (num > 0 && num <= lim)
279 				return (num);
280 		}
281 		else if (keyvalue != KEY_NORMAL)
282 			break;
283 		else if (keyvalue == KEY_NORMAL && IsESC (c))
284 			break;
285 	}
286 	return (lim + 1);
287 }
288 
289 
290 void
Gdouon(wchar16_t * yomi,int num,int choice,int reconv)291 Gdouon(wchar16_t *yomi, int num, int choice, int reconv)
292 {
293 
294 
295 	int	len;
296 	wchar16_t	*s;
297 
298 	SJ_getdouon (yomi, HenkanDouon, num, choice, reconv);
299 
300 	Dpoint = 0;
301 	len = HenkanDouon[Dpoint].wlen;
302 	s = (wchar16_t *)HenkanDouon[Dpoint].ddata;
303 	Strncpy (Dkanji, s, len);
304 	Dkanji[len] = '\0';
305 	if (HenkanDouon[Dpoint].valid)
306 		PushGD (num, &HenkanDouon[Dpoint].dcid);
307 }
308 
309 int
Sdouon(int Choice)310 Sdouon(int Choice)
311 {
312 	Conversion	*cv;
313 	int	i, j;
314 	int		len;
315 	wchar16_t		yomi[BUFFLENGTH * 2];
316 	int		count;
317 
318 	cv = current_conversion;
319 	count = 0;
320 	if (Choice == 0)
321 		i = cv->PreBun;
322 	else
323 		i = cv->CurBun;
324 top:
325 	if ((len = load_bun(i, yomi, MODE_ZHIRA)) <= 0) {
326 		cv->Bkettei[i] |= Bmuhenkan;
327 		cv->Bkettei[i] &= ~Bhenkan;
328 		cv->Pkettei[i] = MODE_ZHIRA;
329 		*Dkanji = '\0';
330 		goto null;
331 	}
332 	else if (len > DLEN) {
333 		cv->Bkettei[i] |= Bmuhenkan;
334 		cv->Bkettei[i] &= ~Bhenkan;
335 		*Dkanji = '\0';
336 		goto null;
337 	}
338 	else if (Choice == 0 && (cv->Bkettei[i] & Bmuhenkan)) {
339 		goto tail;
340 	}
341 	else {
342 		cv->Bkettei[i] |= Bhenkan;
343 		cv->Bkettei[i] &= ~Bmuhenkan;
344 	}
345 
346 	if (Choice == 1) {
347 		if (Cdouon (yomi, i) == FALSE)
348 			return (1);
349 		cv->Pkettei[i] = MODE_ZHIRA;
350 	}
351 	else if (Choice == 2) {
352 		Gdouon (yomi, i, 0, 0);
353 	}
354 	else if (Choice == 3)
355 		Gdouon (yomi, i, count, 1);
356 	else
357 		Gdouon (yomi, i, count, 0);
358 null:
359 	len = wslen (Dkanji);
360 
361 	if (!(cv->Bkettei[i] & Bedit)) {
362 		if (cv->Enum >= MAXENUM)
363 			return (1);
364 		j = cv->Enum ++;
365 		cv->Edit[i] = j;
366 		cv->Epoint[j] = &(cv->Ebuff[cv->e_point]);
367 		cv->e_point += DLEN;
368 	}
369 	else
370 		j = cv->Edit[i];
371 	if (0 < len && len <= DLEN) {
372 		cv->Bkettei[i] |= Bedit;
373 		cv->Pkettei[i] = MODE_ZHIRA;
374 	}
375 	cv->Elen[j] = len;
376 	wscpy (cv->Epoint[j], Dkanji);
377 
378 tail:
379 	if (Choice == 0 && i != cv->CurBun) {
380 		i = cv->CurBun;
381 		goto top;
382 	}
383 	if (cv->PreBun == cv->Bnum)
384 		cv->Bkettei[cv->Bnum] = Bend;
385 	return (0);
386 }
387 
388 
389 
390 int
Rdouon(int back)391 Rdouon(int back)
392 {
393 	Conversion	*cv;
394 	int	i, j;
395 	int	len;
396 	wchar16_t	*s;
397 
398 	cv = current_conversion;
399 	if (Dcount > 0) {
400 		if (back) {
401 			Dpoint --;
402 			if (Dpoint < 0)
403 				Dpoint = Dcount - 1;
404 		}
405 		else {
406 			Dpoint ++;
407 			if (Dpoint >= Dcount)
408 				Dpoint = 0;
409 		}
410 		len = HenkanDouon[Dpoint].wlen;
411 		s = (wchar16_t *)HenkanDouon[Dpoint].ddata;
412 		Strncpy (Dkanji, s, len);
413 		Dkanji[len] = '\0';
414 
415 		i = cv->CurBun;
416 		j = cv->Edit[i];
417 		cv->Elen[j] = len;
418 		wscpy (cv->Epoint[j], Dkanji);
419 		return (0);
420 	}
421 	return (1);
422 }
423 
424 int
Bkanji(wchar16_t * kanji)425 Bkanji(wchar16_t *kanji)
426 {
427 	Conversion	*cv;
428 	int	i;
429 	int		plen, len;
430 	wchar16_t		*s;
431 
432 	cv = current_conversion;
433 	s = kanji;
434 	*s = '\0';
435 	plen = 0;
436 	for (i = 0 ; i < cv->Bnum ; i ++) {
437 		if ((len = Bstr (i, s)) <= 0)
438 			continue;
439 		s += len;
440 		plen += len;
441 	}
442 	return(plen);
443 }
444 
445 struct studyrec	Gdata[BUFFLENGTH];
446 
447 void
PushGD(int num,struct studyrec * wordid)448 PushGD(int num, struct studyrec *wordid)
449 {
450 	Gdata[num] = *wordid;
451 }
452 
453 void
cl_gakusyuu()454 cl_gakusyuu()
455 {
456 	Conversion	*cv;
457 	int	i, j;
458 	int	o_point, n_point;
459 
460 	cv = current_conversion;
461 	for (i = 0 ; i < cv->Bnum ; i ++) {
462 		if (cv->OrgPlen[i] != cv->Plen[i]) {
463 			o_point = n_point = 0;
464 			j = i;
465 			while (j < cv->Bnum) {
466 				o_point += cv->OrgPlen[j];
467 				n_point += cv->Plen[j];
468 				j ++;
469 				if (o_point == n_point)
470 					break;
471 			}
472 			j--;
473 			check_and_gakusyuu (i, j);
474 			i = j;
475 		}
476 	}
477 }
478 
479 void
check_and_gakusyuu(int m,int n)480 check_and_gakusyuu(int m, int n)
481 {
482 	Conversion	*cv;
483 	int	i, j;
484 
485 	cv = current_conversion;
486 	i = m;
487 	j = i + 1;
488 	while (j <= n && j < cv->Bnum) {
489 		if (cv->Bkettei[i] & Bedit && !(cv->Bkettei[i] & Bmuhenkan))
490 			go_gakusyuu (i);
491 		i ++;
492 		j ++;
493 	}
494 }
495 
496 void
go_gakusyuu(int n)497 go_gakusyuu(int n)
498 {
499 	Conversion	*cv;
500 	int	i, j;
501 	wchar16_t		yomi1[BUFFLENGTH], yomi2[BUFFLENGTH];
502 	struct studyrec	*gdatap;
503 	int		len;
504 
505 	cv = current_conversion;
506 	i = n;
507 	j = i + 1;
508 
509 	if (cv->Pedited[i] == 1 || cv->Pedited[j] == 1)
510 		return;
511 
512 
513 	if ((len = load_bun(i, yomi1, MODE_ZHIRA)) <= 0 && len > DLEN)
514 		return;
515 	if ((len = load_bun(j, yomi2, MODE_ZHIRA)) > DLEN)
516 		return;
517 
518 
519 	if (len <= 0)
520 		gdatap = NULL;
521 	else
522 		gdatap = &Gdata[j];
523 	SJ2_clstudy (yomi1, yomi2, gdatap);
524 }
525