xref: /plan9-contrib/sys/src/cmd/dict/world.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
1*219b2ee8SDavid du Colombier #include <u.h>
2*219b2ee8SDavid du Colombier #include <libc.h>
3*219b2ee8SDavid du Colombier #include <bio.h>
4*219b2ee8SDavid du Colombier #include "dict.h"
5*219b2ee8SDavid du Colombier #include "kuten.h"
6*219b2ee8SDavid du Colombier 
7*219b2ee8SDavid du Colombier /*
8*219b2ee8SDavid du Colombier  * Routines for handling dictionaries in the "Languages of the World"
9*219b2ee8SDavid du Colombier  * format.  worldnextoff *must* be called with <address of valid entry>+1.
10*219b2ee8SDavid du Colombier  */
11*219b2ee8SDavid du Colombier 
12*219b2ee8SDavid du Colombier #define	GSHORT(p)	(((p)[0]<<8)|(p)[1])
13*219b2ee8SDavid du Colombier 
14*219b2ee8SDavid du Colombier static void	putchar(int, int*);
15*219b2ee8SDavid du Colombier 
16*219b2ee8SDavid du Colombier #define	NONE	0xffff
17*219b2ee8SDavid du Colombier 
18*219b2ee8SDavid du Colombier /* adapted from jhelling@cs.ruu.nl (Jeroen Hellingman) */
19*219b2ee8SDavid du Colombier 
20*219b2ee8SDavid du Colombier static Rune chartab[] = {
21*219b2ee8SDavid du Colombier 
22*219b2ee8SDavid du Colombier /*00*/	NONE,	NONE,	NONE,	NONE,	NONE,	NONE,	NONE,	NONE,
23*219b2ee8SDavid du Colombier 	NONE,	NONE,	L'\n',	L'æ',	L'ø',	L'å',	L'ä',	L'ö',
24*219b2ee8SDavid du Colombier /*10*/	NONE,	NONE,	NONE,	NONE,	NONE,	NONE,	NONE,	NONE,
25*219b2ee8SDavid du Colombier 	NONE,	NONE,	NONE,	L'Æ',	L'Ø',	L'Å',	L'Ä',	L'Ö',
26*219b2ee8SDavid du Colombier 
27*219b2ee8SDavid du Colombier /*20*/	L' ',	L'!',	L'"',	L'#',	L'$',	L'%',	L'&',	L'\'',
28*219b2ee8SDavid du Colombier 	L'(',	L')',	L'*',	L'+',	L',',	L'-',	L'.',	L'/',
29*219b2ee8SDavid du Colombier /*30*/  L'0',	L'1',	L'2',	L'3',	L'4',	L'5',	L'6',	L'7',
30*219b2ee8SDavid du Colombier 	L'8',	L'9',	L':',	L';',	L'<',	L'=',	L'>',	L'?',
31*219b2ee8SDavid du Colombier /*40*/  L'@',	L'A',	L'B',	L'C',	L'D',	L'E',	L'F',	L'G',
32*219b2ee8SDavid du Colombier 	L'H',	L'I',	L'J',	L'K',	L'L',	L'M',	L'N',	L'O',
33*219b2ee8SDavid du Colombier /*50*/	L'P',	L'Q',	L'R',	L'S',	L'T',	L'U',	L'V',	L'W',
34*219b2ee8SDavid du Colombier 	L'X',	L'Y',	L'Z',	L'[',	L'\\',	L']',	L'^',	L'_',
35*219b2ee8SDavid du Colombier /*60*/	L'`',	L'a',	L'b',	L'c',	L'd',	L'e',	L'f',	L'g',
36*219b2ee8SDavid du Colombier 	L'h',	L'i',	L'j',	L'k',	L'l',	L'm',	L'n',	L'o',
37*219b2ee8SDavid du Colombier /*70*/	L'p',	L'q',	L'r',	L's',	L't',	L'u',	L'v',	L'w',
38*219b2ee8SDavid du Colombier 	L'x',	L'y',	L'z',	L'{',	L'|',	L'}',	L'~',	NONE,
39*219b2ee8SDavid du Colombier 
40*219b2ee8SDavid du Colombier /*80*/	L'Ç',	L'ü',	L'é',	L'â',	L'ä',	L'à',	L'å',	L'ç',
41*219b2ee8SDavid du Colombier 	L'ê',	L'ë',	L'è',	L'ï',	L'î',	L'ì',	L'Ä',	L'Å',
42*219b2ee8SDavid du Colombier /*90*/	L'É',	L'æ',	L'Æ',	L'ô',	L'ö',	L'ò',	L'û',	L'ù',
43*219b2ee8SDavid du Colombier 	L'ÿ',	L'Ö',	L'Ü',	L'¢',	L'£',	L'¥',	L'₧',	L'ʃ',
44*219b2ee8SDavid du Colombier /*a0*/	L'á',	L'í',	L'ó',	L'ú',	L'ñ',	L'Ñ',	L'ª',	L'º',
45*219b2ee8SDavid du Colombier 	L'¿',	L'⌐',	L'¬',	L'½',	L'¼',	L'¡',	L'«',	L'»',
46*219b2ee8SDavid du Colombier 
47*219b2ee8SDavid du Colombier /*b0*/	L'ɔ',	L'ə',	L'ð',	L'ʃ',	L'ʒ',	L'ŋ',	L'ɑ',	L'z',
48*219b2ee8SDavid du Colombier 	L'ɪ',	L'ð',	L'ʒ',	L'ã',	L'œ',	L'ũ',	L'ʌ',	L'ɥ',
49*219b2ee8SDavid du Colombier /*c0*/	L'ʀ',	L'ë',	L'l',	L'ʌ',	L'õ',	L'ñ',	L'Œ',	NONE,
50*219b2ee8SDavid du Colombier 	NONE,	L'S',	L's',	L'Z',	L'z',	NONE,	NONE,	NONE,
51*219b2ee8SDavid du Colombier /*d0*/	L'ß',	NONE,	NONE,	L'ā',	L'ī',	L'ū',	L'ē',	L'ō',
52*219b2ee8SDavid du Colombier 	NONE,	NONE,	NONE,	L' ',	NONE,	NONE,	NONE,	NONE,
53*219b2ee8SDavid du Colombier 
54*219b2ee8SDavid du Colombier /*e0*/	L'α',	L'β',	L'γ',	L'π',	L'Σ',	L'σ',	L'µ',	L'τ',
55*219b2ee8SDavid du Colombier 	L'Φ',	L'Θ',	L'Ω',	L'δ',	L'∞',	L'Ø',	L'ε',	L'∩',
56*219b2ee8SDavid du Colombier /*f0*/	L'≡',	L'±',	L'≥',	L'≤',	L'⌠',	L'⌡',	L'÷',	L'≈',
57*219b2ee8SDavid du Colombier 	L'°',	L'∙',	L'·',	NONE,	NONE,	NONE,	NONE,	NONE,
58*219b2ee8SDavid du Colombier };
59*219b2ee8SDavid du Colombier 
60*219b2ee8SDavid du Colombier enum{ Utf, Kanahi, Kanalo=Kanahi+1, GBhi, GBlo=GBhi+1, };
61*219b2ee8SDavid du Colombier 
62*219b2ee8SDavid du Colombier void
worldprintentry(Entry e,int cmd)63*219b2ee8SDavid du Colombier worldprintentry(Entry e, int cmd)
64*219b2ee8SDavid du Colombier {
65*219b2ee8SDavid du Colombier 	int nh, state[3];
66*219b2ee8SDavid du Colombier 	uchar *p, *pe;
67*219b2ee8SDavid du Colombier 
68*219b2ee8SDavid du Colombier 	p = (uchar *)e.start;
69*219b2ee8SDavid du Colombier 	pe = (uchar *)e.end;
70*219b2ee8SDavid du Colombier 	nh = GSHORT(p);
71*219b2ee8SDavid du Colombier 	p += 6;
72*219b2ee8SDavid du Colombier 	if(cmd == 'h')
73*219b2ee8SDavid du Colombier 		pe = p+nh;
74*219b2ee8SDavid du Colombier 	state[0] = Utf;
75*219b2ee8SDavid du Colombier 	state[1] = 0;
76*219b2ee8SDavid du Colombier 	state[2] = 0;
77*219b2ee8SDavid du Colombier 	while(p < pe){
78*219b2ee8SDavid du Colombier 		if(cmd == 'r')
79*219b2ee8SDavid du Colombier 			outchar(*p++);
80*219b2ee8SDavid du Colombier 		else
81*219b2ee8SDavid du Colombier 			putchar(*p++, state);
82*219b2ee8SDavid du Colombier 	}
83*219b2ee8SDavid du Colombier 	outnl(0);
84*219b2ee8SDavid du Colombier }
85*219b2ee8SDavid du Colombier 
86*219b2ee8SDavid du Colombier long
worldnextoff(long fromoff)87*219b2ee8SDavid du Colombier worldnextoff(long fromoff)
88*219b2ee8SDavid du Colombier {
89*219b2ee8SDavid du Colombier 	int nh, np, nd;
90*219b2ee8SDavid du Colombier 	uchar buf[6];
91*219b2ee8SDavid du Colombier 
92*219b2ee8SDavid du Colombier 	if(Bseek(bdict, fromoff-1, 0) < 0)
93*219b2ee8SDavid du Colombier 		return -1;
94*219b2ee8SDavid du Colombier 	if(Bread(bdict, buf, 6) != 6)
95*219b2ee8SDavid du Colombier 		return -1;
96*219b2ee8SDavid du Colombier 	nh = GSHORT(buf);
97*219b2ee8SDavid du Colombier 	np = GSHORT(buf+2);
98*219b2ee8SDavid du Colombier 	nd = GSHORT(buf+4);
99*219b2ee8SDavid du Colombier 	return fromoff-1 + 6 + nh + np + nd;
100*219b2ee8SDavid du Colombier }
101*219b2ee8SDavid du Colombier 
102*219b2ee8SDavid du Colombier static void
putchar(int c,int * state)103*219b2ee8SDavid du Colombier putchar(int c, int *state)
104*219b2ee8SDavid du Colombier {
105*219b2ee8SDavid du Colombier 	int xflag = 0;
106*219b2ee8SDavid du Colombier 	Rune r;
107*219b2ee8SDavid du Colombier 	int hi, lo;
108*219b2ee8SDavid du Colombier 
109*219b2ee8SDavid du Colombier 	switch(state[0]){
110*219b2ee8SDavid du Colombier 	case Kanahi:
111*219b2ee8SDavid du Colombier 	case GBhi:
112*219b2ee8SDavid du Colombier 		if(CANS2JH(c) || c == 0xff){
113*219b2ee8SDavid du Colombier 			state[0]++;
114*219b2ee8SDavid du Colombier 			state[1] = c;
115*219b2ee8SDavid du Colombier 			break;
116*219b2ee8SDavid du Colombier 		}
117*219b2ee8SDavid du Colombier 		/* fall through */
118*219b2ee8SDavid du Colombier 	case Utf:
119*219b2ee8SDavid du Colombier 		if(c == 0xfe){
120*219b2ee8SDavid du Colombier 			state[0] = Kanahi;
121*219b2ee8SDavid du Colombier 			break;
122*219b2ee8SDavid du Colombier 		}else if(c == 0xff){
123*219b2ee8SDavid du Colombier 			state[0] = GBhi;
124*219b2ee8SDavid du Colombier 			break;
125*219b2ee8SDavid du Colombier 		}
126*219b2ee8SDavid du Colombier 		r = chartab[c];
127*219b2ee8SDavid du Colombier 		if(r < 0x80 && state[2] == 0)
128*219b2ee8SDavid du Colombier 			outchar(r);
129*219b2ee8SDavid du Colombier 		else if(r == NONE){
130*219b2ee8SDavid du Colombier 			switch(c){
131*219b2ee8SDavid du Colombier 			case 0xfb:
132*219b2ee8SDavid du Colombier 				if(!xflag){
133*219b2ee8SDavid du Colombier 					state[2] = 1;
134*219b2ee8SDavid du Colombier 					break;
135*219b2ee8SDavid du Colombier 				}
136*219b2ee8SDavid du Colombier 			case 0xfc:
137*219b2ee8SDavid du Colombier 				if(!xflag){
138*219b2ee8SDavid du Colombier 					state[2] = 0;
139*219b2ee8SDavid du Colombier 					break;
140*219b2ee8SDavid du Colombier 				}
141*219b2ee8SDavid du Colombier 			case 0x10:
142*219b2ee8SDavid du Colombier 			case 0xc7: case 0xc8:
143*219b2ee8SDavid du Colombier 			case 0xd8: case 0xd9: case 0xda:
144*219b2ee8SDavid du Colombier 			case 0xdc: case 0xdd: case 0xde: case 0xdf:
145*219b2ee8SDavid du Colombier 			case 0xfd:
146*219b2ee8SDavid du Colombier 				if(!xflag)
147*219b2ee8SDavid du Colombier 					break;
148*219b2ee8SDavid du Colombier 				/* fall through */
149*219b2ee8SDavid du Colombier 			default:
150*219b2ee8SDavid du Colombier 				outprint("\\%.2ux", c);
151*219b2ee8SDavid du Colombier 			}
152*219b2ee8SDavid du Colombier 		}else if(state[2] == 0)
153*219b2ee8SDavid du Colombier 			outrune(r);
154*219b2ee8SDavid du Colombier 		break;
155*219b2ee8SDavid du Colombier 	case Kanalo:
156*219b2ee8SDavid du Colombier 	case GBlo:
157*219b2ee8SDavid du Colombier 		if(state[1] == 0xff && c == 0xff){
158*219b2ee8SDavid du Colombier 			state[0] = Utf;
159*219b2ee8SDavid du Colombier 			break;
160*219b2ee8SDavid du Colombier 		}
161*219b2ee8SDavid du Colombier 		state[0]--;
162*219b2ee8SDavid du Colombier 		hi = state[1];
163*219b2ee8SDavid du Colombier 		lo = c;
164*219b2ee8SDavid du Colombier 		S2J(hi, lo);		/* convert to JIS */
165*219b2ee8SDavid du Colombier 		r = hi*100 + lo - 3232;	/* convert to jis208 */
166*219b2ee8SDavid du Colombier 		if(state[0] == Kanahi && r < JIS208MAX)
167*219b2ee8SDavid du Colombier 			r = tabjis208[r];
168*219b2ee8SDavid du Colombier 		else if(state[0] == GBhi && r < GB2312MAX)
169*219b2ee8SDavid du Colombier 			r = tabgb2312[r];
170*219b2ee8SDavid du Colombier 		else
171*219b2ee8SDavid du Colombier 			r = NONE;
172*219b2ee8SDavid du Colombier 		if(r == NONE)
173*219b2ee8SDavid du Colombier 			outprint("\\%.2ux\\%.2ux", state[1], c);
174*219b2ee8SDavid du Colombier 		else
175*219b2ee8SDavid du Colombier 			outrune(r);
176*219b2ee8SDavid du Colombier 		break;
177*219b2ee8SDavid du Colombier 	}
178*219b2ee8SDavid du Colombier }
179*219b2ee8SDavid du Colombier 
180*219b2ee8SDavid du Colombier void
worldprintkey(void)181*219b2ee8SDavid du Colombier worldprintkey(void)
182*219b2ee8SDavid du Colombier {
183*219b2ee8SDavid du Colombier 	Bprint(bout, "No pronunciation key.\n");
184*219b2ee8SDavid du Colombier }
185