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__)
24static char rcsid[]="@(#) 102.1 $Id: RKkana.c 14875 2005-11-12 21:25:31Z bonefish $";
25#endif
26
27/* LINTLIBRARY */
28#include "canna.h"
29#include	"RKintern.h"
30
31
32/* RkCvtZen
33 *	hankaku moji wo zenkaku moji ni suru
34 */
35static
36unsigned short
37hiragana[] =
38{
39/* 0x00 */
40	0x0000,	0x0000, 0x0000, 0x0000,		0x0000, 0x0000, 0x0000, 0x0000,
41	0x0000, 0x0000, 0x0000, 0x0000,		0x0000, 0x0000, 0x0000, 0x0000,
42/* 0x10 */
43	0x0000, 0x0000, 0x0000, 0x0000,		0x0000, 0x0000, 0x0000, 0x0000,
44	0x0000, 0x0000, 0x0000, 0x0000,		0x0000, 0x0000, 0x0000, 0x0000,
45/* 0x20 */
46	0xa1a1, 0xa1aa, 0xa1ed, 0xa1f4,		0xa1f0, 0xa1f3, 0xa1f5, 0xa1c7,
47	0xa1ca, 0xa1cb, 0xa1f6, 0xa1dc,		0xa1a4, 0xa1dd, 0xa1a5, 0xa1bf,
48/* 0x30 */
49	0xa3b0, 0xa3b1, 0xa3b2, 0xa3b3,		0xa3b4, 0xa3b5, 0xa3b6, 0xa3b7,
50	0xa3b8, 0xa3b9, 0xa1a7, 0xa1a8,		0xa1e3, 0xa1e1, 0xa1e4, 0xa1a9,
51/* 0x40 */
52	0xa1f7, 0xa3c1, 0xa3c2, 0xa3c3,		0xa3c4, 0xa3c5, 0xa3c6, 0xa3c7,
53	0xa3c8, 0xa3c9, 0xa3ca, 0xa3cb,		0xa3cc, 0xa3cd, 0xa3ce, 0xa3cf,
54/* 0x50 */
55	0xa3d0, 0xa3d1, 0xa3d2, 0xa3d3,		0xa3d4, 0xa3d5, 0xa3d6, 0xa3d7,
56	0xa3d8, 0xa3d9, 0xa3da, 0xa1ce,		0xa1ef, 0xa1cf, 0xa1b0, 0xa1b2,
57/* 0x60 */
58	0xa1c6, 0xa3e1, 0xa3e2, 0xa3e3,		0xa3e4, 0xa3e5, 0xa3e6, 0xa3e7,
59	0xa3e8, 0xa3e9, 0xa3ea, 0xa3eb,		0xa3ec, 0xa3ed, 0xa3ee, 0xa3ef,
60/* 0x70 */
61	0xa3f0, 0xa3f1, 0xa3f2, 0xa3f3,		0xa3f4, 0xa3f5, 0xa3f6, 0xa3f7,
62	0xa3f8, 0xa3f9, 0xa3fa, 0xa1d0,		0xa1c3, 0xa1d1, 0xa1c1, 0xa2a2,
63/*0x80 */
64	0x0000, 0x0000, 0x0000, 0x0000,		0x0000, 0x0000, 0x0000, 0x0000,
65	0x0000, 0x0000, 0x0000, 0x0000,		0x0000, 0x0000, 0x0000, 0x0000,
66/*0x90 */
67	0x0000, 0x0000, 0x0000, 0x0000,		0x0000, 0x0000, 0x0000, 0x0000,
68	0x0000, 0x0000, 0x0000, 0x0000,		0x0000, 0x0000, 0x0000, 0x0000,
69/*0xa0 */
70	0xa1a1, 0xa1a3, 0xa1d6, 0xa1d7,		0xa1a2, 0xa1a6, 0xa4f2, 0xa4a1,
71	0xa4a3, 0xa4a5, 0xa4a7, 0xa4a9,		0xa4e3, 0xa4e5, 0xa4e7, 0xa4c3,
72/*0xb0 */
73	0xa1bc, 0xa4a2, 0xa4a4, 0xa4a6,		0xa4a8, 0xa4aa, 0xa4ab, 0xa4ad,
74	0xa4af, 0xa4b1, 0xa4b3, 0xa4b5,		0xa4b7, 0xa4b9, 0xa4bb, 0xa4bd,
75/*0xc0 */
76	0xa4bf, 0xa4c1, 0xa4c4, 0xa4c6,		0xa4c8, 0xa4ca, 0xa4cb, 0xa4cc,
77	0xa4cd, 0xa4ce, 0xa4cf, 0xa4d2,		0xa4d5, 0xa4d8, 0xa4db, 0xa4de,
78/*0xd0 */
79	0xa4df, 0xa4e0, 0xa4e1, 0xa4e2,		0xa4e4, 0xa4e6, 0xa4e8, 0xa4e9,
80	0xa4ea, 0xa4eb, 0xa4ec, 0xa4ed,		0xa4ef, 0xa4f3, 0xa1ab, 0xa1ac,
81/* 0xe0 */
82	0x0000, 0x0000, 0x0000, 0x0000,		0x0000, 0x0000, 0x0000, 0x0000,
83	0x0000, 0x0000, 0x0000, 0x0000,		0x0000, 0x0000, 0x0000, 0x0000,
84/* 0xf0 */
85	0x0000, 0x0000, 0x0000, 0x0000,		0x0000, 0x0000, 0x0000, 0x0000,
86	0x0000, 0x0000, 0x0000, 0x0000,		0x0000, 0x0000, 0x0000, 0x0000,
87};
88static
89unsigned short
90hankaku[] = {
91/*0x00*/
92	0x0000, 0x0000, 0x0000, 0x0000,		0x0000, 0x0000, 0x0000, 0x0000,
93	0x0000, 0x0000, 0x0000, 0x0000,		0x0000, 0x0000, 0x0000, 0x0000,
94/*0x10*/
95	0x0000, 0x0000, 0x0000, 0x0000,		0x0000, 0x0000, 0x0000, 0x0000,
96	0x0000, 0x0000, 0x0000, 0x0000,		0x0000, 0x0000, 0x0000, 0x0000,
97/*0x20*/
98	0x0000,    ' ', 0x8ea4, 0x8ea1,		   ',',    '.', 0x8ea5,    ':',
99	   ';',    '?',    '!', 0x8ede,		0x8edf, 0x0000, 0x0000, 0x0000,
100/*0x30*/
101	   '^', 0x0000,    '_', 0x0000,		0x0000, 0x0000, 0x0000, 0x0000,
102	0x0000, 0x0000, 0x0000, 0x0000,		0x8eb0, 0x0000, 0x0000,    '/',
103/*0x40*/
104	0x0000,    '~', 0x0000,    '|',		0x0000, 0x0000,   '\'',   '\'',
105	   '"',    '"',    '(',    ')',		   '[',    ']',    '[',    ']',
106/*0x50*/
107	'{',    '}', 0x0000, 0x0000,		0x0000, 0x0000, 0x8ea2, 0x8ea3,
108	0x0000, 0x0000, 0x0000, 0x0000,		   '+',    '-', 0x0000, 0x0000,
109/*0x60*/
110	0x0000,    '=', 0x0000,    '<',		   '>', 0x0000, 0x0000, 0x0000,
111	0x0000, 0x0000, 0x0000, 0x0000,		0x0000, 0x0000, 0x0000,   '\\',
112/*0x70*/
113	    '$',0x0000, 0x0000,    '%',		   '#',    '&',    '*',    '@',
114	0x0000, 0x0000, 0x0000, 0x0000,		0x0000, 0x0000, 0x0000, 0x0000,
115/*0x80*/
116	0x0000, 0x0000, 0x0000, 0x0000,		0x0000, 0x0000, 0x0000, 0x0000,
117	0x0000, 0x0000, 0x0000, 0x0000,		0x0000, 0x0000, 0x0000, 0x0000,
118/*0x90*/
119	0x0000, 0x0000, 0x0000, 0x0000,		0x0000, 0x0000, 0x0000, 0x0000,
120	0x0000, 0x0000, 0x0000, 0x0000,		0x0000, 0x0000, 0x0000, 0x0000,
121/*0xa0*/
122	0x0020, 0x00a7, 0x00b1, 0x00a8, 	0x00b2, 0x00a9, 0x00b3, 0x00aa,
123	0x00b4, 0x00ab, 0x00b5, 0x00b6, 	0xb6de, 0x00b7, 0xb7de, 0x00b8,
124/*0xb0*/
125	0xb8de, 0x00b9, 0xb9de, 0x00ba, 	0xbade, 0x00bb, 0xbbde, 0x00bc,
126	0xbcde, 0x00bd, 0xbdde, 0x00be, 	0xbede, 0x00bf, 0xbfde, 0x00c0,
127/*0xc0*/
128	0xc0de, 0x00c1, 0xc1de, 0x00af, 	0x00c2, 0xc2de, 0x00c3, 0xc3de,
129	0x00c4, 0xc4de, 0x00c5, 0x00c6, 	0x00c7, 0x00c8, 0x00c9, 0x00ca,
130/*0xd0*/
131	0xcade, 0xcadf, 0x00cb, 0xcbde, 	0xcbdf, 0x00cc, 0xccde, 0xccdf,
132	0x00cd, 0xcdde, 0xcddf, 0x00ce, 	0xcede, 0xcedf, 0x00cf, 0x00d0,
133/*0xe0*/
134	0x00d1, 0x00d2, 0x00d3, 0x00ac, 	0x00d4, 0x00ad, 0x00d5, 0x00ae,
135	0x00d6, 0x00d7, 0x00d8, 0x00d9, 	0x00da, 0x00db, 0x00dc, 0x00dc,
136/*0xf0*/
137	0x00b2, 0x00b4, 0x00a6, 0x00dd,		0xb3de, 0x00b6, 0x00b9, 0x0000,
138	0x0000, 0x0000, 0x0000, 0x0000,		0x0000, 0x0000, 0x0000, 0x0000,
139};
140
141#ifdef OBSOLETE_RKKANA
142
143#define	ADDCODE(dst, maxdst, count, code, length) {\
144    if ( (unsigned long)(length) <= (unsigned long)(maxdst) ) {\
145	(maxdst) -= (length); (count) += (length);\
146	if ( (dst) ) {\
147	    (dst) += (length);\
148	    switch((length)) {\
149	    case 4:	*--(dst) = (code)&255; (code) >>= 8;\
150	    case 3:	*--(dst) = (code)&255; (code) >>= 8;\
151	    case 2:	*--(dst) = (code)&255; (code) >>= 8;\
152	    case 1:	*--(dst) = (code)&255; (code) >>= 8;\
153	    };\
154	    (dst) += (length);\
155	};\
156    };\
157}
158
159#else /* !OBSOLETE_RKKANA */
160
161static int _ADDCODE(unsigned char *dst, int maxdst, int count, unsigned long code, int length);
162
163static int
164_ADDCODE(unsigned char *dst, int maxdst, int count, unsigned long code, int length)
165{
166  if ((unsigned long)length <= (unsigned long)maxdst) {
167    maxdst -= length;
168    count += length;
169    if (dst) {
170      dst += length;
171      switch (length) {
172      case 4:	*--dst = (unsigned char)code; code >>= 8;
173      case 3:	*--dst = (unsigned char)code; code >>= 8;
174      case 2:	*--dst = (unsigned char)code; code >>= 8;
175      case 1:	*--dst = (unsigned char)code; code >>= 8;
176      }
177    }
178    return length;
179  }
180  return 0;
181}
182
183#define ADDCODE(dst, maxdst, count, code, length) \
184{ int llen = _ADDCODE(dst, maxdst, count, (unsigned long)code, length); \
185  if (llen > 0 && (dst)) { (dst) += llen; (maxdst) -= llen; (count) += llen; }}
186
187#define	ADDWCODE(dst, maxdst, count, code) {\
188    if ( (maxdst) > 0 ) {\
189	(maxdst)-- ; (count)++ ;\
190	if ( (dst) ) {\
191	    *(dst)++ = (code);\
192	}\
193    }\
194}
195
196#endif /* !OBSOLETE_RKKANA */
197
198/* RkCvtZen
199 *	hankaku moji(ASCII+katakana) wo taiou suru zenkaku moji ni suru
200 *	dakuten,handakuten shori mo okonau.
201 */
202int
203RkCvtZen(unsigned char *zen, int maxzen, unsigned char *han, int maxhan)
204{
205    unsigned char	*z = zen;
206    unsigned char	*h = han;
207    unsigned char	*H = han + maxhan;
208    unsigned short	hi, lo;
209    unsigned 		byte;
210    int 		count = 0;
211    unsigned long	code;
212
213    if ( --maxzen <= 0 )
214	return count;
215    while ( h < H ) {
216	hi = *h++;
217	byte = 2;
218	if ( hi == 0x8e ) {	/* hankaku katakana */
219	    if ( !(code = hiragana[lo = *h++]) )
220	    	code = (hi<<8)|lo;
221	    byte = (code>>8) ? 2 : 1;
222	    if ( (code>>8) == 0xa4 ) {
223		code |= 0x100;
224	    /* dakuten/handakuten ga tuku baai */
225		if ( h + 1 < H && h[0] == 0x8e ) {
226		    lo = h[1];
227		    switch(code&255) {
228	    /* u */ case 0xa6:
229			if ( lo == 0xde ) code = 0xa5f4, h += 2;
230			break;
231	    /* ha */case 0xcf: case 0xd2: case 0xd5: case 0xd8: case 0xdb:
232			if ( lo == 0xdf ) {
233			    code += 2, h += 2;
234			    break;
235			};
236	    /* ka */case 0xab: case 0xad: case 0xaf: case 0xb1: case 0xb3:
237	    /* sa */case 0xb5: case 0xb7: case 0xb9: case 0xbb: case 0xbd:
238	    /* ta */case 0xbf: case 0xc1: case 0xc4: case 0xc6: case 0xc8:
239			if ( lo == 0xde ) {
240			    code += 1, h += 2;
241			    break;
242			};
243		    };
244		};
245	    };
246	}
247	else if (hi == 0x8f) {
248	  ADDCODE(z, maxzen, count, hi, 1);
249	  code = (((unsigned long)h[0]) << 8)
250                   | ((unsigned long)h[1]); h += 2;
251	  byte = 2;
252	}
253	else if ( hi & 0x80 )
254	  code = (hi<<8)|*h++;
255	else  {
256	  if ( !(code = hiragana[hi]) )
257	    code = hi;
258	  byte = (code>>8) ? 2 : 1;
259	}
260	ADDCODE(z, maxzen, count, code, byte);
261    };
262    if ( z )
263	*z = 0;
264    return count;
265}
266/* RkCvtHan
267 *	zenkaku kana moji wo hankaku moji ni suru
268 */
269int
270RkCvtHan(unsigned char *han, int maxhan, unsigned char *zen, int maxzen)
271{
272    unsigned char	*h = han;
273    unsigned char	*z = zen;
274    unsigned char	*Z = zen + maxzen;
275    unsigned short	hi, lo;
276    unsigned short	byte;
277    int 		count = 0;
278    unsigned long	code;
279
280    if ( --maxhan <= 0 )
281	return 0;
282    while ( z < Z ) {
283	hi = *z++;
284	byte = 1;
285	switch(hi) {
286	case	0xa1:	/* kigou */
287	    lo = *z++;
288	    if ( !(code = hankaku[lo&0x7f]) )
289		code = (hi<<8)|lo;
290	    byte = (code>>8) ? 2 : 1;
291	    break;
292	case	0xa3:	/* eisuuji */
293	    lo = *z++;
294	    if ( 0xb0 <= lo && lo <= 0xb9 ) code = (lo - 0xb0) + '0';
295	    else
296	    if ( 0xc1 <= lo && lo <= 0xda ) code = (lo - 0xc1) + 'A';
297	    else
298	    if ( 0xe1 <= lo && lo <= 0xfa ) code = (lo - 0xe1) + 'a';
299	    else
300					    code = (hi<<8)|lo, byte = 2;
301	    break;
302	case	0xa4:	/* hiragana */
303	case	0xa5:	/* katakana */
304	    lo = *z++;
305	    if ( (code = hankaku[lo]) &&
306		(lo <= (unsigned short)(hi==0xa4 ? 0xf3: 0xf6)) ) {
307		if ( code>>8 ) {
308		    code = 0x8e000000|((code>>8)<<16)|0x00008e00|(code&255);
309		    byte = 4;
310		}
311		else {
312		    code = 0x00008e00|(code&255);
313		    byte = 2;
314		};
315	    }
316	    else
317		code = (hi<<8)|lo, byte = 2;
318	    break;
319	default:
320	    if (hi == 0x8f) {
321	      ADDCODE(h, maxhan, count, hi, 1);
322	      code = (((unsigned long)z[0]) << 8)
323                       | ((unsigned long)z[1]); z += 2;
324	      byte = 2;
325	    }
326	    else if ( hi & 0x80 ) { 	/* kanji */
327		code = (hi<<8)|(*z++);
328		byte = 2;
329	    }
330	    else
331		switch(hi) {
332		/*
333		case	',':	code = 0x8ea4; byte = 2; break;
334		case	'-': 	code = 0x8eb0; byte = 2; break;
335		case	'.': 	code = 0x8ea1; byte = 2; break;
336		*/
337		default:	code = hi; break;
338		};
339	    break;
340	};
341	ADDCODE(h, maxhan, count, code, byte);
342    };
343    if ( h )
344	*h = 0;
345    return count;
346}
347/* RkCvtKana/RkCvtHira
348 *	zenkaku hiragana wo katakana ni suru
349 */
350int
351RkCvtKana(unsigned char *kana, int maxkana, unsigned char *hira, int maxhira)
352{
353    register unsigned char	*k = kana;
354    register unsigned char	*h = hira;
355    register unsigned char	*H = hira + maxhira;
356    unsigned short	hi;
357    unsigned short	byte;
358    int 		count = 0;
359    unsigned long	code;
360
361    if ( --maxkana <= 0 )
362	return 0;
363    while ( h < H ) {
364	hi = *h++;
365	if (hi == 0x8f) {
366	  ADDCODE(k, maxkana, count, hi, 1);
367	  code = (((unsigned long)h[0]) << 8)
368                   | ((unsigned long)h[1]); h += 2;
369	  byte = 2;
370	}
371	else if ( hi & 0x80 ) {
372	    int		dakuon;
373
374	    code = (hi == 0xa4) ? (0xa500|(*h++)) : ((hi<<8)|(*h++));
375	    byte = 2;
376	/* hiragana U + " */
377	    dakuon = ( h + 1 < H &&
378              ((((unsigned long)h[0])<<8)|((unsigned long)h[1])) == 0xa1ab );
379	    if ( hi == 0xa4 && code == 0xa5a6 && dakuon ) {
380		code = 0xa5f4;
381		h += 2;
382	    };
383	}
384	else
385	    code = hi, byte = 1;
386	ADDCODE(k, maxkana, count, code, byte);
387    };
388    if ( k )
389	*k = 0;
390    return count;
391}
392int
393RkCvtHira(unsigned char *hira, int maxhira, unsigned char *kana, int maxkana)
394{
395    register unsigned char	*h = hira;
396    register unsigned char	*k = kana;
397    register unsigned char	*K = kana + maxkana;
398    unsigned short		hi;
399    unsigned short		byte;
400    int 			count = 0;
401    unsigned long		code;
402
403    if ( --maxhira <= 0 )
404	return 0;
405    while ( k < K ) {
406	hi = *k++;
407	if (hi == 0x8f) {
408	  ADDCODE(h, maxhira, count, hi, 1);
409	  code = (((unsigned long)k[0]) << 8)
410                   | ((unsigned long)k[1]); k += 2;
411	  byte = 2;
412	}
413	else if ( hi & 0x80 ) {
414	    code = (hi == 0xa5) ? (0xa400|(*k++)) : ((hi<<8)|(*k++));
415	    byte = 2;
416	/* katakana U + " */
417	    if ( code == 0xa4f4 ) {	/* u no dakuon */
418		code = 0xa4a6a1ab;
419		byte = 4;
420	    }
421	    else
422	    if ( code == 0xa4f5 )
423		code = 0xa4ab;
424	    else
425	    if ( code == 0xa4f6 )
426		code = 0xa4b1;
427	}
428	else
429	    code = hi, byte = 1;
430	ADDCODE(h, maxhira, count, code, byte);
431    };
432    if ( h )
433	*h = 0;
434    return count;
435}
436int
437RkCvtNone(unsigned char *dst, int maxdst, unsigned char *src, int maxsrc)
438{
439    register unsigned char	*d = dst;
440    register unsigned char	*s = src;
441    register unsigned char	*S = src + maxsrc;
442    unsigned short		byte;
443    int 			count = 0;
444    unsigned long		code;
445
446    if ( --maxdst <= 0 )
447	return 0;
448    while ( s < S ) {
449	code = *s++;
450	byte = 1;
451	if (code == 0x8f) {
452	  ADDCODE(d, maxdst, count, code, 1);
453	  code = (((unsigned long)s[0]) << 8)
454                   | ((unsigned long)s[1]); s += 2;
455	  byte = 2;
456	}
457	else if ( code & 0x80 )
458	    code = (code<<8)|(*s++), byte = 2;
459	ADDCODE(d, maxdst, count, code, byte);
460    };
461    if ( d )
462	*d = 0;
463    return count;
464}
465
466/* RkEuc
467 * 	shift jis --> euc
468 */
469int
470RkCvtEuc(unsigned char *euc, int maxeuc, unsigned char *sj, int maxsj)
471{
472    unsigned char	*e = euc;
473    unsigned char	*s = sj;
474    unsigned char	*S = sj + maxsj;
475    unsigned short	hi, lo;
476    unsigned short	byte;
477    int 		count = 0;
478    unsigned long	code;
479
480    if ( --maxeuc <= 0 )
481	return 0;
482
483    while ( s < S ) {
484	hi = *s++;
485	if ( hi <= 0x7f )  			/* ascii */
486	    code = hi, byte = 1;
487	else
488	if ( 0xa0 <= hi && hi <= 0xdf ) 	/* hankaku katakana */
489	    code = 0x8e00|hi, byte = 2;
490        else
491        if (0xf0 <= hi && hi <= 0xfc) {		/* gaiji */
492            hi -= 0xf0;
493            hi = 2*hi + 0x21;
494            if ((lo = *s++) <= 0x9e) {
495                if (lo < 0x80)
496                    lo++;
497                lo -= 0x20;
498            }
499            else {
500                hi++;
501                lo -= 0x7e;
502            }
503            code = 0x8f8080 | (hi<<8) | lo, byte = 3;
504        }
505	else {
506	    hi -= (hi <= 0x9f) ?  0x80 : 0xc0;
507	    hi = 2*hi + 0x20;
508	    if ( (lo = *s++) <= 0x9e ) {	/* kisuu ku */
509		hi--;
510		if ( 0x80 <= lo ) lo--;
511		lo -= (0x40 - 0x21);
512	    }
513	    else 			/* guusuu ku */
514		lo -= (0x9f - 0x21);
515	    code = 0x8080|(hi<<8)|lo, byte = 2;
516	};
517	ADDCODE(e, maxeuc, count, code, byte);
518    };
519    if ( e )
520	*e = 0;
521    return count;
522}
523/* RkCvtSuuji
524 * 	arabia suuji wo kansuuji ni kaeru
525 */
526static unsigned suujinew[] = {
527	0xa1bb, 0xb0ec, 0xc6f3, 0xbbb0, 0xbbcd,
528	0xb8de, 0xcfbb, 0xbcb7, 0xc8ac, 0xb6e5,
529};
530static unsigned suujiold[] = {
531	0xa1bb, 0xb0ed, 0xc6f5, 0xbbb2, 0xbbcd,
532	0xb8e0, 0xcfbb, 0xbcb7, 0xc8ac, 0xb6e5,
533};
534static unsigned kurai4[] = {
535	0, 0xcbfc, 0xb2af, 0xc3fb, 0xb5fe, 0,
536};
537
538static unsigned kurai3new[] = { 0, 0xbdbd, 0xc9b4, 0xc0e9, };
539static unsigned kurai3old[] = { 0, 0xbdbd, 0xc9b4, 0xc0e9, };
540
541int
542RkCvtSuuji(unsigned char *dst, int maxdst, unsigned char *src, int maxsrc, int format)
543{
544    int			count;
545    int			i, j, k;
546    int			digit[4], pend;
547    unsigned		code, tmp;
548    unsigned char	*d = dst;
549    unsigned char	*s = src + maxsrc - 1;
550
551    if ( --maxdst <= 0 )
552	return 0;
553/* yuukou keta suu wo kazoeru */
554    pend = 0;
555    for ( count = k = 0; s >= src; k++ ) {
556	int	dec;
557
558	if ( *s & 0x80 ) {
559	    if ( !(0xb0 <= *s && *s <= 0xb9) )
560		break;
561	    dec = *s - 0xb0;
562	    if ( --s < src || *s != 0xa3 )
563		break;
564	    s--;
565	}
566	else {
567	    if ( !('0' <= *s && *s <= '9') )
568		break;
569	    dec = *s-- - '0';
570	};
571
572	switch(format) {
573    /* simple */
574	case 0:	/* sanyou suuji */
575	    code = hiragana[dec + '0'];
576	    ADDCODE(d, maxdst, count, code, 2);
577	    break;
578	case 1:	/* kanji suuji */
579	    code = suujinew[dec];
580	    ADDCODE(d, maxdst, count, code, 2);
581	    break;
582    /* kanji kurai dori */
583	case 2:
584	case 3:
585	case 4:	/* 12 O 3456 M 7890 */
586	    digit[pend++] = dec;
587	    if ( pend == 4 ) {
588		while ( pend > 0 && digit[pend - 1] == 0 )
589		    pend--;
590		if ( pend ) {
591		/* kurai wo shuturyoku */
592		    code = kurai4[k/4];
593		    if (code)
594			ADDCODE(d, maxdst, count, code, 2)
595		    else
596			if ( k >= 4 )
597			    return 0;
598
599		    for ( i = 0; i < pend; i++ )
600			switch(format) {
601			case 2:
602			    if ( digit[i] ) {
603			        code = kurai3new[i];
604				if (code)
605				    ADDCODE(d, maxdst, count, code, 2);
606				if ( i == 0 || (digit[i] > 1) ) {
607				    code = suujinew[digit[i]];
608				    ADDCODE(d, maxdst, count, code, 2);
609				};
610			    };
611			    break;
612			case 3:
613			    if ( digit[i] ) {
614			        code = kurai3old[i];
615				if (code)
616				    ADDCODE(d, maxdst, count, code, 2);
617				code = suujiold[digit[i]];
618				ADDCODE(d, maxdst, count, code, 2);
619			    };
620			    break;
621			case 4:
622			    code = hiragana[digit[i]+'0'];
623			    ADDCODE(d, maxdst, count, code, 2);
624			    break;
625			};
626		};
627		pend = 0;
628	    };
629	    break;
630       case 5: /* 1,234,567,890 */
631	    if ( k && k%3 == 0 ) {
632		code = hiragana[','];
633		ADDCODE(d, maxdst, count, code, 2);
634	    };
635	    code = hiragana[dec + '0'];
636	    ADDCODE(d, maxdst, count, code, 2);
637	    break;
638	default:
639	    return 0;
640	};
641    };
642
643    if ( format == 2 || format == 3 || format == 4 ) {
644	while ( pend > 0 && digit[pend - 1] == 0 )
645	    pend--;
646	if ( pend ) {
647	    code = kurai4[k/4];
648	    if (code)
649		ADDCODE(d, maxdst, count, code, 2)
650	    else
651		if ( k >= 4 )
652		    return 0;
653	    for ( i = 0; i < pend; i++ )
654		switch(format) {
655		case 2:
656		    if ( digit[i] ) {
657		        code = kurai3new[i];
658			if (code)
659			    ADDCODE(d, maxdst, count, code, 2);
660			if ( i == 0 || (digit[i] > 1) ) {
661			    code = suujinew[digit[i]];
662			    ADDCODE(d, maxdst, count, code, 2);
663			};
664		    };
665		    break;
666		case 3:
667		    if ( digit[i] ) {
668		        code = kurai3old[i];
669			if (code)
670			    ADDCODE(d, maxdst, count, code, 2);
671			code = suujiold[digit[i]];
672			ADDCODE(d, maxdst, count, code, 2);
673		    };
674		    break;
675		case 4:
676		    code = hiragana[digit[i]+'0'];
677		    ADDCODE(d, maxdst, count, code, 2);
678		    break;
679		};
680	};
681    };
682
683    if ( dst ) {
684	*d = 0;
685	for ( i = 0, j = count - 1; i < j; i++, j-- ) {
686	    tmp = dst[i]; dst[i] = dst[j]; dst[j] = tmp;
687	};
688	for ( i = count - 1; i > 0; i-- )
689	    if ( dst[i] & 0x80 ) {
690		tmp = dst[i+0]; dst[i+0] = dst[i-1]; dst[i-1] = tmp;
691		i--;
692	    };
693    };
694    return count;
695}
696
697/* ¥ï¥¤¥É¥­¥ã¥é¥¯¥¿ */
698
699#define CBUFSIZE     512
700
701int
702RkwCvtHan(WCHAR_T *dst, int maxdst, WCHAR_T *src, int srclen)
703{
704  int len = 0;
705#ifndef WIN
706  char cbuf[CBUFSIZE], cbuf2[CBUFSIZE];
707#else
708  char *cbuf, *cbuf2;
709
710  cbuf = malloc(CBUFSIZE);
711  cbuf2 = malloc(CBUFSIZE);
712  if (!cbuf || !cbuf2) {
713    if (cbuf) {
714      free(cbuf);
715    }
716    if (cbuf2) {
717      free(cbuf2);
718    }
719    return len;
720  }
721#endif
722
723  len = CNvW2E(src, srclen, cbuf, CBUFSIZE);
724  len = RkCvtHan((unsigned char *)cbuf2, CBUFSIZE, (unsigned char *)cbuf, len);
725  if (len > 0) {
726    cbuf2[len] = '\0';
727    len = MBstowcs(dst, cbuf2, maxdst);
728  }
729#ifdef WIN
730  free(cbuf2);
731  free(cbuf);
732#endif
733  return len;
734}
735
736int
737RkwCvtHira(WCHAR_T *dst, int maxdst, WCHAR_T *src, int srclen)
738{
739  int len = 0;
740#ifndef WIN
741  char cbuf[CBUFSIZE], cbuf2[CBUFSIZE];
742#else
743  char *cbuf, *cbuf2;
744
745  cbuf = malloc(CBUFSIZE);
746  cbuf2 = malloc(CBUFSIZE);
747  if (!cbuf || !cbuf2) {
748    if (cbuf) {
749      free(cbuf);
750    }
751    if (cbuf2) {
752      free(cbuf2);
753    }
754    return len;
755  }
756#endif
757
758  len = CNvW2E(src, srclen, cbuf, CBUFSIZE);
759  len = RkCvtHira((unsigned char *)cbuf2, CBUFSIZE,
760		  (unsigned char *)cbuf, len);
761  if (len > 0) {
762    cbuf2[len] = (unsigned char)0;
763    len = MBstowcs(dst, cbuf2, maxdst);
764  }
765#ifdef WIN
766  free(cbuf2);
767  free(cbuf);
768#endif
769  return len;
770}
771
772int
773RkwCvtKana(WCHAR_T *dst, int maxdst, WCHAR_T *src, int srclen)
774{
775  int len = 0;
776#ifndef WIN
777  char cbuf[CBUFSIZE], cbuf2[CBUFSIZE];
778#else
779  char *cbuf, *cbuf2;
780
781  cbuf = malloc(CBUFSIZE);
782  cbuf2 = malloc(CBUFSIZE);
783  if (!cbuf || !cbuf2) {
784    if (cbuf) {
785      free(cbuf);
786    }
787    if (cbuf2) {
788      free(cbuf2);
789    }
790    return len;
791  }
792#endif
793
794  len = CNvW2E(src, srclen, cbuf, CBUFSIZE);
795  len = RkCvtKana((unsigned char *)cbuf2, CBUFSIZE,
796		  (unsigned char *)cbuf, len);
797  if (len > 0) {
798    cbuf2[len] = '\0';
799    len = MBstowcs(dst, cbuf2, maxdst);
800  }
801#ifdef WIN
802  free(cbuf2);
803  free(cbuf);
804#endif
805  return len;
806}
807
808int
809RkwCvtZen(WCHAR_T *dst, int maxdst, WCHAR_T *src, int srclen)
810{
811  int len = 0;
812#ifndef WIN
813  char cbuf[CBUFSIZE], cbuf2[CBUFSIZE];
814#else
815  char *cbuf, *cbuf2;
816
817  cbuf = malloc(CBUFSIZE);
818  cbuf2 = malloc(CBUFSIZE);
819  if (!cbuf || !cbuf2) {
820    if (cbuf) {
821      free(cbuf);
822    }
823    if (cbuf2) {
824      free(cbuf2);
825    }
826    return len;
827  }
828#endif
829
830  len = CNvW2E(src, srclen, cbuf, CBUFSIZE);
831  len = RkCvtZen((unsigned char *)cbuf2, CBUFSIZE,
832		 (unsigned char *)cbuf, len);
833  if (len > 0) {
834    cbuf2[len] = '\0';
835    len = MBstowcs(dst, cbuf2, maxdst);
836  }
837#ifdef WIN
838  free(cbuf2);
839  free(cbuf);
840#endif
841  return len;
842}
843
844int
845RkwCvtNone(WCHAR_T *dst, int maxdst, WCHAR_T *src, int srclen)
846{
847  int i;
848
849  if(!dst || !src) return 0;
850
851  int len = (maxdst < srclen) ? maxdst : srclen;
852  for (int i = 0 ; i < len ; i++) {
853    *dst++ = *src++;
854  }
855/*  *dst = *src; ¤Ê¤ó¤Ç¤³¤ì¤¬É¬ÍפʤΡ© */
856  return len;
857}
858
859int
860RkwMapRoma(struct RkRxDic *romaji, WCHAR_T *dst, int maxdst, WCHAR_T *src, int srclen, int flags, int *status)
861{
862  int len = 0, ret;
863  char cbuf1[CBUFSIZE], cbuf2[CBUFSIZE];
864
865  len = CNvW2E(src, srclen, cbuf1, CBUFSIZE);
866  len = RkMapRoma(romaji, (unsigned char *)cbuf2, CBUFSIZE,
867		  (unsigned char *)cbuf1, len, flags, status);
868  cbuf2[(*status > 0) ? *status : -*status] = (unsigned char)0;
869  ret = MBstowcs(dst, cbuf2, maxdst);
870  if (*status > 0) {
871    *status = ret;
872  }
873  else {
874    *status = -ret;
875  }
876
877  return len;
878}
879
880int
881RkwMapPhonogram(struct RkRxDic *romaji, WCHAR_T *dst, int maxdst, WCHAR_T *src, int srclen, WCHAR_T key, int flags, int *ulen, int *dlen, int *tlen, int *rule)
882{
883  int status = 0;
884  char tmpch;
885  int len, ret, fdlen, fulen, ftlen;
886  char cbuf1[CBUFSIZE], cbuf2[CBUFSIZE];
887  WCHAR_T wbuf[CBUFSIZE];
888
889  len = CNvW2E(src, srclen, cbuf1, CBUFSIZE);
890  status = RkMapPhonogram(romaji, (unsigned char *)cbuf2, CBUFSIZE,
891			  (unsigned char *)cbuf1, len,
892			  (unsigned) key, flags,
893			  &fulen, &fdlen, &ftlen, rule);
894  tmpch = cbuf2[fdlen];
895  cbuf2[fdlen] = '\0';
896  ret = MBstowcs(dst, cbuf2, maxdst);
897  cbuf2[fdlen] = tmpch;
898  if (dlen) {
899    *dlen = ret;
900  }
901  cbuf2[fdlen + ftlen] = (unsigned char)0;
902  ret = MBstowcs(dst + ret, cbuf2 + fdlen, maxdst - ret);
903  if (tlen) {
904    *tlen = ret;
905  }
906  if (ulen) {
907    cbuf1[fulen] = '\0';
908    *ulen = MBstowcs(wbuf, cbuf1, CBUFSIZE);
909  }
910
911  return status;
912}
913
914int
915RkwCvtRoma(struct RkRxDic *romaji, WCHAR_T *dst, int maxdst, WCHAR_T *src, int srclen, int flags)
916{
917  int ret = 0, len;
918  char cbuf1[CBUFSIZE], cbuf2[CBUFSIZE];
919
920  if (srclen) {
921    len = CNvW2E(src, srclen, cbuf1, CBUFSIZE);
922    len = RkCvtRoma(romaji, (unsigned char *)cbuf2, CBUFSIZE,
923		    (unsigned char *)cbuf1, len, flags);
924    cbuf2[len] = (unsigned char)0;
925    ret = MBstowcs(dst, cbuf2, maxdst);
926    dst[ret] = (WCHAR_T)0;
927  } else {
928    ret = 0;
929    *dst = (WCHAR_T)0;
930  }
931
932  return ret;
933}
934
935#define SUUJI_THROUGH		0
936#define SUUJI_HANKAKU		1
937#define SUUJI_ZENKAKU		2
938#define SUUJI_SIMPLEKANJI	3
939#define SUUJI_FULLKANJI		4
940#define SUUJI_FULLKANJITRAD	5
941#define SUUJI_WITHKANJIUNIT	6
942#define SUUJI_WITHCOMMA		7
943
944/* RkCvtSuuji
945 * 	arabia suuji wo kansuuji ni kaeru
946 */
947int
948RkwCvtSuuji(WCHAR_T *dst, int maxdst, WCHAR_T *src, int maxsrc, int format)
949{
950  int	count;
951  int	i, j, k;
952  int	digit[4], pend;
953  WCHAR_T	code, tmp;
954  WCHAR_T	*d = dst;
955  WCHAR_T	*s = src + maxsrc - 1;
956
957  if ( --maxdst <= 0 )
958    return 0;
959  /* Í­¸ú¤Ê·å¿ô¤ò¿ô¤¨¤ë */
960  pend = 0;
961  for ( count = k = 0; s >= src; k++ ) {
962    int	dec, thru = *s;
963
964    if ( thru & 0x8080 ) {
965      if ( !((WCHAR_T)0xa3b0 <= *s && *s <= (WCHAR_T)0xa3b9) )
966	break;
967      dec = *s-- - 0xa3b0;
968    }
969    else {
970      if ( !((WCHAR_T)'0' <= *s && *s <= (WCHAR_T)'9') )
971	break;
972      dec = *s-- - '0';
973    }
974
975    switch(format) {
976      /* simple */
977    case SUUJI_THROUGH:	/* sanyou suuji */
978      code = thru;
979      ADDWCODE(d, maxdst, count, code);
980      break;
981    case SUUJI_HANKAKU:	/* sanyou suuji */
982      code = dec + '0';
983      if (code == thru) {
984	return 0;
985      }
986      ADDWCODE(d, maxdst, count, code);
987      break;
988    case SUUJI_ZENKAKU:	/* sanyou suuji */
989      code = hiragana[dec + '0'];
990      if (code == thru) {
991	return 0;
992      }
993      ADDWCODE(d, maxdst, count, code);
994      break;
995      /* kanji kurai dori */
996    case SUUJI_SIMPLEKANJI:	/* kanji suuji */
997      code = suujinew[dec];
998      ADDWCODE(d, maxdst, count, code);
999      break;
1000    case SUUJI_FULLKANJI:
1001    case SUUJI_FULLKANJITRAD:
1002    case SUUJI_WITHKANJIUNIT:	/* 12 O 3456 M 7890 */
1003      digit[pend++] = dec;
1004      if ( pend == 4 ) {
1005	while ( pend > 0 && digit[pend - 1] == 0 )
1006	  pend--;
1007	if ( pend ) {
1008	  /* kurai wo shuturyoku */
1009	  code = kurai4[k/4];
1010	  if (code)
1011	    ADDWCODE(d, maxdst, count, code)
1012	  else
1013	    if ( k >= 4 )
1014	      return 0;
1015
1016	  for ( i = 0; i < pend; i++ )
1017	    switch(format) {
1018	    case SUUJI_FULLKANJI:
1019	      if ( digit[i] ) {
1020		code = kurai3new[i];
1021		if (code)
1022		  ADDWCODE(d, maxdst, count, code);
1023		if ( i == 0 || (digit[i] > 1) ) {
1024		  code = suujinew[digit[i]];
1025		  ADDWCODE(d, maxdst, count, code);
1026		}
1027	      }
1028	      break;
1029	    case SUUJI_FULLKANJITRAD:
1030	      if ( digit[i] ) {
1031		code = kurai3old[i];
1032		if (code)
1033		  ADDWCODE(d, maxdst, count, code);
1034		code = suujiold[digit[i]];
1035		ADDWCODE(d, maxdst, count, code);
1036	      };
1037	      break;
1038	    case SUUJI_WITHKANJIUNIT:
1039	      code = hiragana[digit[i]+'0'];
1040	      ADDWCODE(d, maxdst, count, code);
1041	      break;
1042	    }
1043	}
1044	pend = 0;
1045      }
1046      break;
1047    case SUUJI_WITHCOMMA: /* 1,234,567,890 */
1048      if ( k && k%3 == 0 ) {
1049	code = hiragana[','];
1050	ADDWCODE(d, maxdst, count, code);
1051      }
1052      code = hiragana[dec + '0'];
1053      ADDWCODE(d, maxdst, count, code);
1054      break;
1055    default:
1056      return 0;
1057    };
1058  };
1059
1060  if (format == SUUJI_FULLKANJI || format == SUUJI_FULLKANJITRAD ||
1061      format == SUUJI_WITHKANJIUNIT) {
1062    while ( pend > 0 && digit[pend - 1] == 0 )
1063      pend--;
1064    if ( pend ) {
1065      code = kurai4[k/4];
1066      if (code)
1067	ADDWCODE(d, maxdst, count, code)
1068      else
1069	if ( k >= 4 )
1070	  return 0;
1071      for ( i = 0; i < pend; i++ )
1072	switch(format) {
1073	case SUUJI_FULLKANJI:
1074	  if ( digit[i] ) {
1075	    code = kurai3new[i];
1076	    if (code)
1077	      ADDWCODE(d, maxdst, count, code);
1078	    if ( i == 0 || (digit[i] > 1) ) {
1079	      code = suujinew[digit[i]];
1080	      ADDWCODE(d, maxdst, count, code);
1081	    };
1082	  };
1083	  break;
1084	case SUUJI_FULLKANJITRAD:
1085	  if ( digit[i] ) {
1086	    code = kurai3old[i];
1087	    if (code)
1088	      ADDWCODE(d, maxdst, count, code);
1089	    code = suujiold[digit[i]];
1090	    ADDWCODE(d, maxdst, count, code);
1091	  };
1092	  break;
1093	case SUUJI_WITHKANJIUNIT:
1094	  code = hiragana[digit[i]+'0'];
1095	  ADDWCODE(d, maxdst, count, code);
1096	  break;
1097	}
1098    }
1099  }
1100
1101  if ( dst ) {
1102    *d = 0;
1103    for ( i = 0, j = count - 1; i < j; i++, j-- ) {
1104      tmp = dst[i]; dst[i] = dst[j]; dst[j] = tmp;
1105    }
1106  }
1107  return count;
1108}
1109/* RkCvtNarrow
1110 *
1111 */
1112int
1113RkCvtNarrow(char *dst, int maxdst, WCHAR_T *src, int maxsrc)
1114{
1115#ifdef USE_SJIS_TEXT_DIC
1116  return Wcstosjis(dst, maxdst, src, maxsrc);
1117#else /* !USE_SJIS_TEXT_DIC */
1118  unsigned char	*d = (unsigned char *)dst;
1119  WCHAR_T		*s = src;
1120  WCHAR_T		*S = src + maxsrc;
1121  int 		count = 0;
1122  long		code;
1123  int		byte;
1124
1125    if ( --maxdst <= 0 )
1126	return count;
1127    while ( s < S )
1128    {
1129	code = *s++;
1130	switch(code&0x8080)
1131	{
1132	case 0x0000:
1133	    code &= 0xff;
1134	    byte = 1;
1135	    break;
1136	case 0x0080:
1137	    code &= 0xff;
1138	    code |= 0x8e00;
1139	    byte = 2;
1140	    break;
1141	case 0x8000:
1142	    code &= 0xffff;
1143	    code |= 0x8f8080;
1144	    byte = 3;
1145	    break;
1146	case 0x8080:
1147	    code &= 0xffff;
1148	    byte = 2;
1149	    break;
1150        };
1151	ADDCODE(d, maxdst, count, code, byte);
1152    };
1153    if ( d )
1154	*d = 0;
1155    return count;
1156#endif /* !USE_SJIS_TEXT_DIC */
1157}
1158
1159/* RkCvtWide
1160 *
1161 */
1162int
1163RkCvtWide(WCHAR_T *dst, int maxdst, char *src, int maxsrc)
1164{
1165#ifdef USE_SJIS_TEXT_DIC
1166  return SJistowcs(dst, maxdst, src, maxsrc);
1167#else /* !USE_SJIS_TEXT_DIC, that is, EUC */
1168  WCHAR_T		*d = dst;
1169  unsigned char	*s = (unsigned char *)src;
1170  unsigned char	*S = (unsigned char *)src + maxsrc;
1171  int 		count = 0;
1172  unsigned long	code;
1173
1174    if ( --maxdst <= 0 )
1175	return count;
1176    while ( s < S )
1177    {
1178	code = *s++;
1179	if ( code & 0x80 )
1180	{
1181	    switch(code)
1182	    {
1183	    case RK_SS2:	/* hankaku katakana */
1184		code = 0x0080|(s[0]&0x7f);
1185		s++;
1186		break;
1187	    case RK_SS3:	/* gaiji */
1188		code = 0x8000|(((s[0]<<8)|s[1])&0x7f7f);
1189		s += 2;
1190		break;
1191	    default:
1192		code = 0x8080|(((s[-1]<<8)|s[0])&0x7f7f);
1193                s += 1;
1194            };
1195        };
1196	ADDWCODE(d, maxdst, count, (WCHAR_T)code);
1197    };
1198    if ( d )
1199	*d = 0;
1200    return count;
1201#endif /* !USE_SJIS_TEXT_DIC */
1202}
1203
1204