summaryrefslogblamecommitdiff
path: root/cell.c
blob: 2b9e5f7f0d5fef1ada0933f93373dc2266c8da7b (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
















                                                                            
                              




                                                
                                                      

                                                
                                                                  


                                                
                              






                                                

                                                      








                                                
                                                            














                                                        
       




                                                        





                                                               




                                                        



                                                        

  

                                               




                                 


                                                  




                                                         







                                                 































































                                                                          
                                       





                                 
/* 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,
0x358,0x359,0x35A,0x35B,0x35C,
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,0x5A2,0x5A3,0x5A4,0x5A5,0x5A6,0x5A7,0x5A8,
0x5A9,0x5AA,0x5AB,0x5AC,0x5AD,0x5AE,0x5AF,0x5B0,
0x5B1,0x5B2,0x5B3,0x5B4,0x5B5,0x5B6,0x5B7,0x5B8,
0x5B9,0x5BA,0x5BB,0x5BC,0x5BD,0x5BF,0x5C1,0x5C2,0x5C4,0x5C5,0x5C7,
0x600,0x601,0x602,0x603,0x610,0x611,0x612,0x613,
0x614,0x615,0x64B,0x64C,0x64D,0x64E,0x64F,0x650,
0x651,0x652,0x653,0x654,0x655,0x656,0x657,0x658,
0x659,0x65A,0x65B,0x65C,0x65E,
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,0x7EB,0x7EC,
0x7ED,0x7EE,0x7EF,0x7F0,0x7F1,0x7F2,0x7F3,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,0xCE2,0xCE3,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,
0x135F,
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,0x1A17,0x1A18,0x1B00,
0x1B01,0x1B02,0x1B03,0x1B34,0x1B36,0x1B37,0x1B38,0x1B39,
0x1B3A,0x1B3C,0x1B42,0x1B6B,0x1B6C,0x1B6D,0x1B6E,0x1B6F,
0x1B70,0x1B71,0x1B72,0x1B73,0x1DC0,0x1DC1,0x1DC2,0x1DC3,
0x1DC4,0x1DC5,0x1DC6,0x1DC7,0x1DC8,0x1DC9,0x1DCA,0x1DFE,0x1DFF,
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,0x20EB,0x20EC,0x20ED,0x20EE,
0x20EF,0x302A,0x302B,0x302C,0x302D,0x302E,0x302F,0x3099,
0x309A,0xA805,0xA80B,0xA825,0xA826,0xFB1E,0xFE20,0xFE21,
0xFE22,0xFE23,0xFEFF,
};

#define COMB_CNT (sizeof(comb)/sizeof(comb[0]))

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

	if (c > 0xffff) return 0;
	if ((unsigned)c - 0x1160 < 0xa0)
		return COMB_CNT + 1 + c - 0x1160;
	for (a=0, n=(COMB_CNT+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;
}

static wchar_t comb_dec(int c)
{
	if ((unsigned)c > COMB_CNT)
		return c - COMB_CNT - 1 + 0x1160;
	else if (c) return comb[c-1];
	else return 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_dec(c);
		if (!(*ws++ = c))
			l = 1;
	}
	ws[-1] = 0;
	return i;
}