xref: /plan9-contrib/sys/src/cmd/unix/drawterm/libc/rune.c (revision 8ccd4a6360d974db7bd7bbd4f37e7018419ea908)
1*8ccd4a63SDavid du Colombier #include	<u.h>
2*8ccd4a63SDavid du Colombier #include	<libc.h>
3*8ccd4a63SDavid du Colombier 
4*8ccd4a63SDavid du Colombier enum
5*8ccd4a63SDavid du Colombier {
6*8ccd4a63SDavid du Colombier 	Bit1	= 7,
7*8ccd4a63SDavid du Colombier 	Bitx	= 6,
8*8ccd4a63SDavid du Colombier 	Bit2	= 5,
9*8ccd4a63SDavid du Colombier 	Bit3	= 4,
10*8ccd4a63SDavid du Colombier 	Bit4	= 3,
11*8ccd4a63SDavid du Colombier 
12*8ccd4a63SDavid du Colombier 	T1	= ((1<<(Bit1+1))-1) ^ 0xFF,	/* 0000 0000 */
13*8ccd4a63SDavid du Colombier 	Tx	= ((1<<(Bitx+1))-1) ^ 0xFF,	/* 1000 0000 */
14*8ccd4a63SDavid du Colombier 	T2	= ((1<<(Bit2+1))-1) ^ 0xFF,	/* 1100 0000 */
15*8ccd4a63SDavid du Colombier 	T3	= ((1<<(Bit3+1))-1) ^ 0xFF,	/* 1110 0000 */
16*8ccd4a63SDavid du Colombier 	T4	= ((1<<(Bit4+1))-1) ^ 0xFF,	/* 1111 0000 */
17*8ccd4a63SDavid du Colombier 
18*8ccd4a63SDavid du Colombier 	Rune1	= (1<<(Bit1+0*Bitx))-1,		/* 0000 0000 0111 1111 */
19*8ccd4a63SDavid du Colombier 	Rune2	= (1<<(Bit2+1*Bitx))-1,		/* 0000 0111 1111 1111 */
20*8ccd4a63SDavid du Colombier 	Rune3	= (1<<(Bit3+2*Bitx))-1,		/* 1111 1111 1111 1111 */
21*8ccd4a63SDavid du Colombier 
22*8ccd4a63SDavid du Colombier 	Maskx	= (1<<Bitx)-1,			/* 0011 1111 */
23*8ccd4a63SDavid du Colombier 	Testx	= Maskx ^ 0xFF,			/* 1100 0000 */
24*8ccd4a63SDavid du Colombier 
25*8ccd4a63SDavid du Colombier 	Bad	= Runeerror,
26*8ccd4a63SDavid du Colombier };
27*8ccd4a63SDavid du Colombier 
28*8ccd4a63SDavid du Colombier int
29*8ccd4a63SDavid du Colombier chartorune(Rune *rune, char *str)
30*8ccd4a63SDavid du Colombier {
31*8ccd4a63SDavid du Colombier 	int c, c1, c2;
32*8ccd4a63SDavid du Colombier 	long l;
33*8ccd4a63SDavid du Colombier 
34*8ccd4a63SDavid du Colombier 	/*
35*8ccd4a63SDavid du Colombier 	 * one character sequence
36*8ccd4a63SDavid du Colombier 	 *	00000-0007F => T1
37*8ccd4a63SDavid du Colombier 	 */
38*8ccd4a63SDavid du Colombier 	c = *(uchar*)str;
39*8ccd4a63SDavid du Colombier 	if(c < Tx) {
40*8ccd4a63SDavid du Colombier 		*rune = c;
41*8ccd4a63SDavid du Colombier 		return 1;
42*8ccd4a63SDavid du Colombier 	}
43*8ccd4a63SDavid du Colombier 
44*8ccd4a63SDavid du Colombier 	/*
45*8ccd4a63SDavid du Colombier 	 * two character sequence
46*8ccd4a63SDavid du Colombier 	 *	0080-07FF => T2 Tx
47*8ccd4a63SDavid du Colombier 	 */
48*8ccd4a63SDavid du Colombier 	c1 = *(uchar*)(str+1) ^ Tx;
49*8ccd4a63SDavid du Colombier 	if(c1 & Testx)
50*8ccd4a63SDavid du Colombier 		goto bad;
51*8ccd4a63SDavid du Colombier 	if(c < T3) {
52*8ccd4a63SDavid du Colombier 		if(c < T2)
53*8ccd4a63SDavid du Colombier 			goto bad;
54*8ccd4a63SDavid du Colombier 		l = ((c << Bitx) | c1) & Rune2;
55*8ccd4a63SDavid du Colombier 		if(l <= Rune1)
56*8ccd4a63SDavid du Colombier 			goto bad;
57*8ccd4a63SDavid du Colombier 		*rune = l;
58*8ccd4a63SDavid du Colombier 		return 2;
59*8ccd4a63SDavid du Colombier 	}
60*8ccd4a63SDavid du Colombier 
61*8ccd4a63SDavid du Colombier 	/*
62*8ccd4a63SDavid du Colombier 	 * three character sequence
63*8ccd4a63SDavid du Colombier 	 *	0800-FFFF => T3 Tx Tx
64*8ccd4a63SDavid du Colombier 	 */
65*8ccd4a63SDavid du Colombier 	c2 = *(uchar*)(str+2) ^ Tx;
66*8ccd4a63SDavid du Colombier 	if(c2 & Testx)
67*8ccd4a63SDavid du Colombier 		goto bad;
68*8ccd4a63SDavid du Colombier 	if(c < T4) {
69*8ccd4a63SDavid du Colombier 		l = ((((c << Bitx) | c1) << Bitx) | c2) & Rune3;
70*8ccd4a63SDavid du Colombier 		if(l <= Rune2)
71*8ccd4a63SDavid du Colombier 			goto bad;
72*8ccd4a63SDavid du Colombier 		*rune = l;
73*8ccd4a63SDavid du Colombier 		return 3;
74*8ccd4a63SDavid du Colombier 	}
75*8ccd4a63SDavid du Colombier 
76*8ccd4a63SDavid du Colombier 	/*
77*8ccd4a63SDavid du Colombier 	 * bad decoding
78*8ccd4a63SDavid du Colombier 	 */
79*8ccd4a63SDavid du Colombier bad:
80*8ccd4a63SDavid du Colombier 	*rune = Bad;
81*8ccd4a63SDavid du Colombier 	return 1;
82*8ccd4a63SDavid du Colombier }
83*8ccd4a63SDavid du Colombier 
84*8ccd4a63SDavid du Colombier int
85*8ccd4a63SDavid du Colombier runetochar(char *str, Rune *rune)
86*8ccd4a63SDavid du Colombier {
87*8ccd4a63SDavid du Colombier 	long c;
88*8ccd4a63SDavid du Colombier 
89*8ccd4a63SDavid du Colombier 	/*
90*8ccd4a63SDavid du Colombier 	 * one character sequence
91*8ccd4a63SDavid du Colombier 	 *	00000-0007F => 00-7F
92*8ccd4a63SDavid du Colombier 	 */
93*8ccd4a63SDavid du Colombier 	c = *rune;
94*8ccd4a63SDavid du Colombier 	if(c <= Rune1) {
95*8ccd4a63SDavid du Colombier 		str[0] = c;
96*8ccd4a63SDavid du Colombier 		return 1;
97*8ccd4a63SDavid du Colombier 	}
98*8ccd4a63SDavid du Colombier 
99*8ccd4a63SDavid du Colombier 	/*
100*8ccd4a63SDavid du Colombier 	 * two character sequence
101*8ccd4a63SDavid du Colombier 	 *	0080-07FF => T2 Tx
102*8ccd4a63SDavid du Colombier 	 */
103*8ccd4a63SDavid du Colombier 	if(c <= Rune2) {
104*8ccd4a63SDavid du Colombier 		str[0] = T2 | (c >> 1*Bitx);
105*8ccd4a63SDavid du Colombier 		str[1] = Tx | (c & Maskx);
106*8ccd4a63SDavid du Colombier 		return 2;
107*8ccd4a63SDavid du Colombier 	}
108*8ccd4a63SDavid du Colombier 
109*8ccd4a63SDavid du Colombier 	/*
110*8ccd4a63SDavid du Colombier 	 * three character sequence
111*8ccd4a63SDavid du Colombier 	 *	0800-FFFF => T3 Tx Tx
112*8ccd4a63SDavid du Colombier 	 */
113*8ccd4a63SDavid du Colombier 	str[0] = T3 |  (c >> 2*Bitx);
114*8ccd4a63SDavid du Colombier 	str[1] = Tx | ((c >> 1*Bitx) & Maskx);
115*8ccd4a63SDavid du Colombier 	str[2] = Tx |  (c & Maskx);
116*8ccd4a63SDavid du Colombier 	return 3;
117*8ccd4a63SDavid du Colombier }
118*8ccd4a63SDavid du Colombier 
119*8ccd4a63SDavid du Colombier int
120*8ccd4a63SDavid du Colombier runelen(long c)
121*8ccd4a63SDavid du Colombier {
122*8ccd4a63SDavid du Colombier 	Rune rune;
123*8ccd4a63SDavid du Colombier 	char str[10];
124*8ccd4a63SDavid du Colombier 
125*8ccd4a63SDavid du Colombier 	rune = c;
126*8ccd4a63SDavid du Colombier 	return runetochar(str, &rune);
127*8ccd4a63SDavid du Colombier }
128*8ccd4a63SDavid du Colombier 
129*8ccd4a63SDavid du Colombier int
130*8ccd4a63SDavid du Colombier runenlen(Rune *r, int nrune)
131*8ccd4a63SDavid du Colombier {
132*8ccd4a63SDavid du Colombier 	int nb, c;
133*8ccd4a63SDavid du Colombier 
134*8ccd4a63SDavid du Colombier 	nb = 0;
135*8ccd4a63SDavid du Colombier 	while(nrune--) {
136*8ccd4a63SDavid du Colombier 		c = *r++;
137*8ccd4a63SDavid du Colombier 		if(c <= Rune1)
138*8ccd4a63SDavid du Colombier 			nb++;
139*8ccd4a63SDavid du Colombier 		else
140*8ccd4a63SDavid du Colombier 		if(c <= Rune2)
141*8ccd4a63SDavid du Colombier 			nb += 2;
142*8ccd4a63SDavid du Colombier 		else
143*8ccd4a63SDavid du Colombier 			nb += 3;
144*8ccd4a63SDavid du Colombier 	}
145*8ccd4a63SDavid du Colombier 	return nb;
146*8ccd4a63SDavid du Colombier }
147*8ccd4a63SDavid du Colombier 
148*8ccd4a63SDavid du Colombier int
149*8ccd4a63SDavid du Colombier fullrune(char *str, int n)
150*8ccd4a63SDavid du Colombier {
151*8ccd4a63SDavid du Colombier 	int c;
152*8ccd4a63SDavid du Colombier 
153*8ccd4a63SDavid du Colombier 	if(n > 0) {
154*8ccd4a63SDavid du Colombier 		c = *(uchar*)str;
155*8ccd4a63SDavid du Colombier 		if(c < Tx)
156*8ccd4a63SDavid du Colombier 			return 1;
157*8ccd4a63SDavid du Colombier 		if(n > 1)
158*8ccd4a63SDavid du Colombier 			if(c < T3 || n > 2)
159*8ccd4a63SDavid du Colombier 				return 1;
160*8ccd4a63SDavid du Colombier 	}
161*8ccd4a63SDavid du Colombier 	return 0;
162*8ccd4a63SDavid du Colombier }
163