summaryrefslogtreecommitdiff
path: root/cell.c
blob: 101dce830e52af46eac4534b3e1dbdd91375afde (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
/* uuterm, Copyright (C) 2006 Rich Felker; licensed under GNU GPL v2 only */

#include <wchar.h>
#include "uuterm.h"

static const unsigned short comb[] = {
0x300,0x301,0x302,0x303,0x304,0x305,0x306,0x307,
0x308,0x309,0x30A,0x30B,0x30C,0x30D,0x30E,0x30F,
0x310,0x311,0x312,0x313,0x314,0x315,0x316,0x317,
0x318,0x319,0x31A,0x31B,0x31C,0x31D,0x31E,0x31F,
0x320,0x321,0x322,0x323,0x324,0x325,0x326,0x327,
0x328,0x329,0x32A,0x32B,0x32C,0x32D,0x32E,0x32F,
0x330,0x331,0x332,0x333,0x334,0x335,0x336,0x337,
0x338,0x339,0x33A,0x33B,0x33C,0x33D,0x33E,0x33F,
0x340,0x341,0x342,0x343,0x344,0x345,0x346,0x347,
0x348,0x349,0x34A,0x34B,0x34C,0x34D,0x34E,0x34F,
0x350,0x351,0x352,0x353,0x354,0x355,0x356,0x357,
0x35D,0x35E,0x35F,0x360,0x361,0x362,0x363,0x364,
0x365,0x366,0x367,0x368,0x369,0x36A,0x36B,0x36C,
0x36D,0x36E,0x36F,0x483,0x484,0x485,0x486,0x488,
0x489,0x591,0x592,0x593,0x594,0x595,0x596,0x597,
0x598,0x599,0x59A,0x59B,0x59C,0x59D,0x59E,0x59F,
0x5A0,0x5A1,0x5A3,0x5A4,0x5A5,0x5A6,0x5A7,0x5A8,
0x5A9,0x5AA,0x5AB,0x5AC,0x5AD,0x5AE,0x5AF,0x5B0,
0x5B1,0x5B2,0x5B3,0x5B4,0x5B5,0x5B6,0x5B7,0x5B8,
0x5B9,0x5BB,0x5BC,0x5BD,0x5BF,0x5C1,0x5C2,0x5C4,
0x600,0x601,0x602,0x603,0x610,0x611,0x612,0x613,
0x614,0x615,0x64B,0x64C,0x64D,0x64E,0x64F,0x650,
0x651,0x652,0x653,0x654,0x655,0x656,0x657,0x658,
0x670,0x6D6,0x6D7,0x6D8,0x6D9,0x6DA,0x6DB,0x6DC,
0x6DD,0x6DE,0x6DF,0x6E0,0x6E1,0x6E2,0x6E3,0x6E4,
0x6E7,0x6E8,0x6EA,0x6EB,0x6EC,0x6ED,0x70F,0x711,
0x730,0x731,0x732,0x733,0x734,0x735,0x736,0x737,
0x738,0x739,0x73A,0x73B,0x73C,0x73D,0x73E,0x73F,
0x740,0x741,0x742,0x743,0x744,0x745,0x746,0x747,
0x748,0x749,0x74A,0x7A6,0x7A7,0x7A8,0x7A9,0x7AA,
0x7AB,0x7AC,0x7AD,0x7AE,0x7AF,0x7B0,0x901,0x902,
0x93C,0x941,0x942,0x943,0x944,0x945,0x946,0x947,
0x948,0x94D,0x951,0x952,0x953,0x954,0x962,0x963,
0x981,0x9BC,0x9C1,0x9C2,0x9C3,0x9C4,0x9CD,0x9E2,
0x9E3,0xA01,0xA02,0xA3C,0xA41,0xA42,0xA47,0xA48,
0xA4B,0xA4C,0xA4D,0xA70,0xA71,0xA81,0xA82,0xABC,
0xAC1,0xAC2,0xAC3,0xAC4,0xAC5,0xAC7,0xAC8,0xACD,
0xAE2,0xAE3,0xB01,0xB3C,0xB3F,0xB41,0xB42,0xB43,
0xB4D,0xB56,0xB82,0xBC0,0xBCD,0xBF8,0xC3E,0xC3F,
0xC40,0xC46,0xC47,0xC48,0xC4A,0xC4B,0xC4C,0xC4D,
0xC55,0xC56,0xCBC,0xCBF,0xCC6,0xCCC,0xCCD,0xD41,
0xD42,0xD43,0xD4D,0xDCA,0xDD2,0xDD3,0xDD4,0xDD6,
0xE31,0xE34,0xE35,0xE36,0xE37,0xE38,0xE39,0xE3A,
0xE47,0xE48,0xE49,0xE4A,0xE4B,0xE4C,0xE4D,0xE4E,
0xEB1,0xEB4,0xEB5,0xEB6,0xEB7,0xEB8,0xEB9,0xEBB,
0xEBC,0xEC8,0xEC9,0xECA,0xECB,0xECC,0xECD,0xF18,
0xF19,0xF35,0xF37,0xF39,0xF71,0xF72,0xF73,0xF74,
0xF75,0xF76,0xF77,0xF78,0xF79,0xF7A,0xF7B,0xF7C,
0xF7D,0xF7E,0xF80,0xF81,0xF82,0xF83,0xF84,0xF86,
0xF87,0xF90,0xF91,0xF92,0xF93,0xF94,0xF95,0xF96,
0xF97,0xF99,0xF9A,0xF9B,0xF9C,0xF9D,0xF9E,0xF9F,
0xFA0,0xFA1,0xFA2,0xFA3,0xFA4,0xFA5,0xFA6,0xFA7,
0xFA8,0xFA9,0xFAA,0xFAB,0xFAC,0xFAD,0xFAE,0xFAF,
0xFB0,0xFB1,0xFB2,0xFB3,0xFB4,0xFB5,0xFB6,0xFB7,
0xFB8,0xFB9,0xFBA,0xFBB,0xFBC,0xFC6,0x102D,0x102E,
0x102F,0x1030,0x1032,0x1036,0x1037,0x1039,0x1058,0x1059,
0x1712,0x1713,0x1714,0x1732,0x1733,0x1734,0x1752,0x1753,
0x1772,0x1773,0x17B4,0x17B5,0x17B7,0x17B8,0x17B9,0x17BA,
0x17BB,0x17BC,0x17BD,0x17C6,0x17C9,0x17CA,0x17CB,0x17CC,
0x17CD,0x17CE,0x17CF,0x17D0,0x17D1,0x17D2,0x17D3,0x17DD,
0x180B,0x180C,0x180D,0x18A9,0x1920,0x1921,0x1922,0x1927,
0x1928,0x1932,0x1939,0x193A,0x193B,0x200B,0x200C,0x200D,
0x200E,0x200F,0x202A,0x202B,0x202C,0x202D,0x202E,0x2060,
0x2061,0x2062,0x2063,0x206A,0x206B,0x206C,0x206D,0x206E,
0x206F,0x20D0,0x20D1,0x20D2,0x20D3,0x20D4,0x20D5,0x20D6,
0x20D7,0x20D8,0x20D9,0x20DA,0x20DB,0x20DC,0x20DD,0x20DE,
0x20DF,0x20E0,0x20E1,0x20E2,0x20E3,0x20E4,0x20E5,0x20E6,
0x20E7,0x20E8,0x20E9,0x20EA,0x302A,0x302B,0x302C,0x302D,
0x302E,0x302F,0x3099,0x309A,0xFB1E,0xFE20,0xFE21,0xFE22,
0xFE23,0xFEFF,
};

static int comb_enc(wchar_t c)
{
	int a, n;

	if (c > 0xffff) return 0;
	for (a=0, n=(sizeof(comb)/sizeof(comb[0])+1)/2; n>1; n=n+1>>1)
		a += n & ((signed)(comb[a+n]-c-1) >> 21);
	if (comb[a]<c) a++;
	return comb[a]==c ? a+1 : 0;
}

#define BASE_BIT 11
#define COLOR_BIT 16

#define COMB_MASK 0x3ff
#define MAX_COMB 5

static const int comb_idx[] = { 0, 1, 1, 1, 2 };
static const int comb_bit[] = { 1, 0, 10, 20, 0 };

/*
** Bit layout (B=base char, #=combining chars, C=color, A=attr
** 0: BBBBBBBBBBBBBBBBBBBBB0000000000A
** 1: AA333333333322222222221111111111
** 2: CCCCCCCCCCCCCCCCAAAAAA4444444444
** Attribute bits have been placed not to overlap. The attribute
** bits defined in uuterm.h must come from available positions.
*/

#define ATTR_MASK0 0x00000001
#define ATTR_MASK1 0 /* 0xC0000000 */
#define ATTR_MASK2 0 /* 0x0000FC00 */

void uucell_set(struct uucell *cell, wchar_t wc, int attr, int color)
{
	if (attr & UU_ATTR_REV) {
		int tmp = color & 255;
		color >>= 8;
		color |= tmp << 8;
	}
	cell->x[0] = (attr & ATTR_MASK0) | (wc << BASE_BIT);
	cell->x[1] = (attr & ATTR_MASK1);
	cell->x[2] = (attr & ATTR_MASK2) | (color << COLOR_BIT);
}

void uucell_append(struct uucell *cell, wchar_t wc)
{
	int i;
	for (i=0; i<MAX_COMB; i++) {
		if (!((cell->x[comb_idx[i]]>>comb_bit[i]) & COMB_MASK)) {
			cell->x[comb_idx[i]] |= comb_enc(wc)<<comb_bit[i];
			return;
		}
	}
}

int uucell_get_attr(struct uucell *cell)
{
	return (cell->x[0] & ATTR_MASK0)
		| (cell->x[1] & ATTR_MASK1)
		| (cell->x[2] & ATTR_MASK2);
}

int uucell_get_color(struct uucell *cell)
{
	return cell->x[2] >> COLOR_BIT;
}

int uucell_get_wcs(struct uucell *cell, wchar_t *ws, size_t l)
{
	int i, c;
	if (!l--) return 0;
	*ws++ = cell->x[0] >> BASE_BIT;
	for (i=0; l; i++,l--) {
		c = (cell->x[comb_idx[i]]>>comb_bit[i]) & COMB_MASK;
		if (c) c = comb[c-1];
		if (!(*ws++ = c))
			l = 1;
	}
	ws[-1] = 0;
	return i;
}