Compare commits

...
Sign in to create a new pull request.

1 commit

Author SHA1 Message Date
uobikiemukot
cd3a9612e3 disable osc/dcs feature 2018-03-14 12:45:21 +09:00
8 changed files with 10 additions and 1029 deletions

View file

@ -1,586 +0,0 @@
/* See LICENSE for licence details. */
/* function for dcs sequence */
enum {
RGBMAX = 255,
HUEMAX = 360,
LSMAX = 100,
};
/*
static inline void split_rgb(uint32_t color, uint8_t *r, uint8_t *g, uint8_t *b)
{
*r = bit_mask[8] & (color >> 16);
*g = bit_mask[8] & (color >> 8);
*b = bit_mask[8] & (color >> 0);
}
*/
static inline int sixel_bitmap(struct terminal_t *term, struct sixel_canvas_t *sc, uint8_t bitmap)
{
int i, offset;
//uint8_t r, g, b;
logging(DEBUG, "sixel_bitmap()\nbitmap:%.2X point(%d, %d)\n",
bitmap, sc->point.x, sc->point.y);
if (sc->point.x >= term->width || sc->point.y >= term->height)
return 1;
offset = sc->point.x * BYTES_PER_PIXEL + sc->point.y * sc->line_length;
for (i = 0; i < BITS_PER_SIXEL; i++) {
if (offset >= BYTES_PER_PIXEL * term->width * term->height)
break;
if (bitmap & (0x01 << i)) {
memcpy(sc->pixmap + offset, &sc->color_table[sc->color_index], BYTES_PER_PIXEL);
/*
split_rgb(sc->color_table[sc->color_index], &r, &g, &b);
*(sc->pixmap + offset + 0) = b;
*(sc->pixmap + offset + 1) = g;
*(sc->pixmap + offset + 2) = r;
*/
}
offset += sc->line_length;
}
sc->point.x++;
if (sc->point.x > sc->width)
sc->width = sc->point.x;
return 1;
}
static inline int sixel_repeat(struct terminal_t *term, struct sixel_canvas_t *sc, char *buf)
{
int i, count;
size_t length;
char *cp, tmp[BUFSIZE];
uint8_t bitmap;
cp = buf + 1; /* skip '!' itself */
while (isdigit(*cp)) /* skip non sixel bitmap character */
cp++;
length = (cp - buf);
strncpy(tmp, buf + 1, length - 1);
*(tmp + length - 1) = '\0';
count = dec2num(tmp);
logging(DEBUG, "sixel_repeat()\nbuf:%s length:%u\ncount:%d repeat:0x%.2X\n",
tmp, (unsigned) length, count, *cp);
if ('?' <= *cp && *cp <= '~') {
bitmap = bit_mask[BITS_PER_SIXEL] & (*cp - '?');
for (i = 0; i < count; i++)
sixel_bitmap(term, sc, bitmap);
}
return length + 1;
}
static inline int sixel_attr(struct sixel_canvas_t *sc, char *buf)
{
char *cp, tmp[BUFSIZE];
size_t length;
struct parm_t parm;
cp = buf + 1;
while (isdigit(*cp) || *cp == ';') /* skip valid params */
cp++;
length = (cp - buf);
strncpy(tmp, buf + 1, length - 1);
*(tmp + length - 1) = '\0';
reset_parm(&parm);
parse_arg(tmp, &parm, ';', isdigit);
if (parm.argc >= 4) {
sc->width = dec2num(parm.argv[2]);
sc->height = dec2num(parm.argv[3]);
}
logging(DEBUG, "sixel_attr()\nbuf:%s\nwidth:%d height:%d\n",
tmp, sc->width, sc->height);
return length;
}
static inline uint32_t hue2rgb(int n1, int n2, int hue)
{
if (hue < 0)
hue += HUEMAX;
if (hue > HUEMAX)
hue -= HUEMAX;
if (hue < (HUEMAX / 6))
return (n1 + (((n2 - n1) * hue + (HUEMAX / 12)) / (HUEMAX / 6)));
if (hue < (HUEMAX / 2))
return n2;
if (hue < ((HUEMAX * 2) / 3))
return (n1 + (((n2 - n1) * (((HUEMAX * 2) / 3) - hue) + (HUEMAX / 12)) / (HUEMAX / 6)));
else
return n1;
}
static inline uint32_t hls2rgb(int hue, int lum, int sat)
{
uint32_t r, g, b;
int magic1, magic2;
if (sat == 0) {
r = g = b = (lum * RGBMAX) / LSMAX;
} else {
if (lum <= (LSMAX / 2) )
magic2 = (lum * (LSMAX + sat) + (LSMAX / 2)) / LSMAX;
else
magic2 = lum + sat - ((lum * sat) + (LSMAX / 2)) / LSMAX;
magic1 = 2 * lum - magic2;
r = (hue2rgb(magic1, magic2, hue + (HUEMAX / 3)) * RGBMAX + (LSMAX / 2)) / LSMAX;
g = (hue2rgb(magic1, magic2, hue) * RGBMAX + (LSMAX / 2)) / LSMAX;
b = (hue2rgb(magic1, magic2, hue - (HUEMAX / 3)) * RGBMAX + (LSMAX/2)) / LSMAX;
}
return (r << 16) + (g << 8) + b;
}
static inline int sixel_color(struct sixel_canvas_t *sc, char *buf)
{
char *cp, tmp[BUFSIZE];
int index, type;
size_t length;
uint16_t v1, v2, v3, r, g, b;
uint32_t color;
struct parm_t parm;
cp = buf + 1;
while (isdigit(*cp) || *cp == ';') /* skip valid params */
cp++;
length = (cp - buf);
strncpy(tmp, buf + 1, length - 1); /* skip '#' */
*(tmp + length - 1) = '\0';
reset_parm(&parm);
parse_arg(tmp, &parm, ';', isdigit);
if (parm.argc < 1)
return length;
index = dec2num(parm.argv[0]);
if (index < 0)
index = 0;
else if (index >= COLORS)
index = COLORS - 1;
logging(DEBUG, "sixel_color()\nbuf:%s length:%u\nindex:%d\n",
tmp, (unsigned) length, index);
if (parm.argc == 1) { /* select color */
sc->color_index = index;
return length;
}
if (parm.argc != 5)
return length;
type = dec2num(parm.argv[1]);
v1 = dec2num(parm.argv[2]);
v2 = dec2num(parm.argv[3]);
v3 = dec2num(parm.argv[4]);
if (type == 1) { /* HLS */
color = hls2rgb(v1, v2, v3);
} else {
r = bit_mask[8] & (0xFF * v1 / 100);
g = bit_mask[8] & (0xFF * v2 / 100);
b = bit_mask[8] & (0xFF * v3 / 100);
color = (r << 16) | (g << 8) | b;
}
logging(DEBUG, "type:%d v1:%u v2:%u v3:%u color:0x%.8X\n",
type, v1, v2, v3, color);
sc->color_table[index] = color;
return length;
}
static inline int sixel_cr(struct sixel_canvas_t *sc)
{
logging(DEBUG, "sixel_cr()\n");
sc->point.x = 0;
return 1;
}
static inline int sixel_nl(struct sixel_canvas_t *sc)
{
logging(DEBUG, "sixel_nl()\n");
/* DECGNL moves active position to left margin
and down one line of sixels:
http://odl.sysworks.biz/disk$vaxdocdec963/decw$book/d3qsaaa1.p67.decw$book */
sc->point.y += BITS_PER_SIXEL;
sc->point.x = 0;
if (sc->point.y > sc->height)
sc->height = sc->point.y;
return 1;
}
void sixel_parse_data(struct terminal_t *term, struct sixel_canvas_t *sc, char *start_buf)
{
/*
DECDLD sixel data
'$': carriage return
'-': new line
'#': color
# Pc: select color
# Pc; Pu; Px; Py; Pz
Pc : color index (0 to 255)
Pu : color coordinate system
1: HLS (0 to 360 for Hue, 0 to 100 for others)
2: RGB (0 to 100 percent) (default)
Px : Hue / Red
Py : Lightness / Green
Pz : Saturation / Blue
'"': attr
" Pan; Pad; Ph; Pv
Pan, Pad: defines aspect ratio (Pan / Pad) (ignored)
Ph, Pv : defines vertical/horizontal size of the image
'!': repeat
! Pn ch
Pn : repeat count ([0-9]+)
ch : character to repeat ('?' to '~')
sixel bitmap:
range of ? (hex 3F) to ~ (hex 7E)
? (hex 3F) represents the binary value 00 0000.
t (hex 74) represents the binary value 11 0101.
~ (hex 7E) represents the binary value 11 1111.
*/
int size = 0;
char *cp, *end_buf;
uint8_t bitmap;
cp = start_buf;
end_buf = cp + strlen(start_buf);
while (cp < end_buf) {
if (*cp == '!') {
size = sixel_repeat(term, sc, cp);
} else if (*cp == '"') {
size = sixel_attr(sc, cp);
} else if (*cp == '#') {
size = sixel_color(sc, cp);
} else if (*cp == '$') {
size = sixel_cr(sc);
} else if (*cp == '-') {
size = sixel_nl(sc);
} else if ('?' <= *cp && *cp <= '~') {
bitmap = bit_mask[BITS_PER_SIXEL] & (*cp - '?');
size = sixel_bitmap(term, sc, bitmap);
} else if (*cp == '\0') { /* end of sixel data */
break;
} else {
size = 1;
}
cp += size;
}
logging(DEBUG, "sixel_parse_data()\nwidth:%d height:%d\n", sc->width, sc->height);
}
void reset_sixel(struct sixel_canvas_t *sc, struct color_pair_t color_pair, int width, int height)
{
extern const uint32_t color_list[]; /* global */
int i;
memset(sc->pixmap, 0, BYTES_PER_PIXEL * width * height);
sc->width = 1;
sc->height = 6;
sc->point.x = 0;
sc->point.y = 0;
sc->line_length = BYTES_PER_PIXEL * width;
sc->color_index = 0;
/* 0 - 15: use vt340 or ansi color map */
/* VT340 VT340 Default Color Map
ref: http://www.vt100.net/docs/vt3xx-gp/chapter2.html#T2-3
*/
sc->color_table[0] = 0x000000; sc->color_table[8] = 0x424242;
sc->color_table[1] = 0x3333CC; sc->color_table[9] = 0x545499;
sc->color_table[2] = 0xCC2121; sc->color_table[10] = 0x994242;
sc->color_table[3] = 0x33CC33; sc->color_table[11] = 0x549954;
sc->color_table[4] = 0xCC33CC; sc->color_table[12] = 0x995499;
sc->color_table[5] = 0x33CCCC; sc->color_table[13] = 0x549999;
sc->color_table[6] = 0xCCCC33; sc->color_table[14] = 0x999954;
sc->color_table[7] = 0x878787; sc->color_table[15] = 0xCCCCCC;
/* ANSI 16color table (but unusual order corresponding vt340 color map)
sc->color_table[0] = color_list[0]; sc->color_table[8] = color_list[8];
sc->color_table[1] = color_list[4]; sc->color_table[9] = color_list[12];
sc->color_table[2] = color_list[1]; sc->color_table[10] = color_list[9];
sc->color_table[3] = color_list[2]; sc->color_table[11] = color_list[10];
sc->color_table[4] = color_list[5]; sc->color_table[12] = color_list[13];
sc->color_table[5] = color_list[6]; sc->color_table[13] = color_list[14];
sc->color_table[6] = color_list[3]; sc->color_table[14] = color_list[11];
sc->color_table[7] = color_list[7]; sc->color_table[15] = color_list[15];
*/
/* change palette 0, because its often the same color as terminal background */
sc->color_table[0] = color_list[color_pair.fg];
/* 16 - 255: use xterm 256 color palette */
/* copy 256 color map */
for (i = 16; i < COLORS; i++)
sc->color_table[i] = color_list[i];
}
void sixel_copy2cell(struct terminal_t *term, struct sixel_canvas_t *sc)
{
int y, x, h, cols, lines;
int src_offset, dst_offset;
struct cell_t *cellp;
if (sc->height > term->height)
sc->height = term->height;
cols = my_ceil(sc->width, CELL_WIDTH);
lines = my_ceil(sc->height, CELL_HEIGHT);
if (cols + term->cursor.x > term->cols)
cols -= (cols + term->cursor.x - term->cols);
for (y = 0; y < lines; y++) {
for (x = 0; x < cols; x++) {
erase_cell(term, term->cursor.y, term->cursor.x + x);
cellp = &term->cells[term->cursor.y][term->cursor.x + x];
cellp->has_pixmap = true;
for (h = 0; h < CELL_HEIGHT; h++) {
src_offset = (y * CELL_HEIGHT + h) * sc->line_length + (CELL_WIDTH * x) * BYTES_PER_PIXEL;
dst_offset = h * CELL_WIDTH * BYTES_PER_PIXEL;
if (src_offset >= BYTES_PER_PIXEL * term->width * term->height)
break;
memcpy(cellp->pixmap + dst_offset, sc->pixmap + src_offset, CELL_WIDTH * BYTES_PER_PIXEL);
}
}
move_cursor(term, 1, 0);
//set_cursor(term, term->cursor.y + 1, term->cursor.x);
}
cr(term);
}
void sixel_parse_header(struct terminal_t *term, char *start_buf)
{
/*
sixel format
DSC P1; P2; P3; q; s...s; ST
parameters
DCS: ESC(0x1B) P (0x50) (8bit C1 character not recognized)
P1 : pixel aspect ratio (force 0, 2:1) (ignored)
P2 : background mode (ignored)
0 or 2: 0 stdands for current background color (default)
1 : 0 stands for remaining current color
P3 : horizontal grid parameter (ignored)
q : final character of sixel sequence
s : see parse_sixel_data()
ST : ESC (0x1B) '\' (0x5C) or BEL (0x07)
*/
char *cp;
struct parm_t parm;
/* replace final char of sixel header by NUL '\0' */
cp = strchr(start_buf, 'q');
*cp = '\0';
logging(DEBUG, "sixel_parse_header()\nbuf:%s\n", start_buf);
/* split header by semicolon ';' */
reset_parm(&parm);
parse_arg(start_buf, &parm, ';', isdigit);
/* set canvas parameters */
reset_sixel(&term->sixel, term->color_pair, term->width, term->height);
sixel_parse_data(term, &term->sixel, cp + 1); /* skip 'q' */
sixel_copy2cell(term, &term->sixel);
}
static inline void decdld_bitmap(struct glyph_t *glyph, uint8_t bitmap, uint8_t row, uint8_t column)
{
/*
MSB LSB (glyph_t bitmap order, padding at LSB side)
-> column
sixel bit0 ->........
sixel bit1 ->........
sixel bit2 ->....@@..
sixel bit3 ->...@..@.
sixel bit4 ->...@....
sixel bit5 ->...@....
.@@@@@..
...@....
|...@....
row |...@....
v...@....
...@....
...@....
...@....
........
........
*/
int i, height_shift, width_shift;
logging(DEBUG, "bit pattern:0x%.2X\n", bitmap);
width_shift = CELL_WIDTH - 1 - column;
if (width_shift < 0)
return;
for (i = 0; i < BITS_PER_SIXEL; i++) {
if((bitmap >> i) & 0x01) {
height_shift = row * BITS_PER_SIXEL + i;
if (height_shift < CELL_HEIGHT) {
logging(DEBUG, "height_shift:%d width_shift:%d\n", height_shift, width_shift);
glyph->bitmap[height_shift] |= bit_mask[CELL_WIDTH] & (0x01 << width_shift);
}
}
}
}
static inline void init_glyph(struct glyph_t *glyph)
{
int i;
glyph->width = 1; /* drcs glyph must be HALF */
glyph->code = 0; /* this value not used: drcs call by DRCSMMv1 */
for (i = 0; i < CELL_HEIGHT; i++)
glyph->bitmap[i] = 0;
}
void decdld_parse_data(char *start_buf, int start_char, struct glyph_t *chars)
{
/*
DECDLD sixel data
';': glyph separator
'/': line feed
sixel bitmap:
range of ? (hex 3F) to ~ (hex 7E)
? (hex 3F) represents the binary value 00 0000.
t (hex 74) represents the binary value 11 0101.
~ (hex 7E) represents the binary value 11 1111.
*/
char *cp, *end_buf;
uint8_t char_num = start_char; /* start_char == 0 means SPACE(0x20) */
uint8_t bitmap, row = 0, column = 0;
init_glyph(&chars[char_num]);
cp = start_buf;
end_buf = cp + strlen(cp);
while (cp < end_buf) {
if ('?' <= *cp && *cp <= '~') { /* sixel bitmap */
logging(DEBUG, "char_num(ten):0x%.2X\n", char_num);
/* remove offset '?' and use only 6bit */
bitmap = bit_mask[BITS_PER_SIXEL] & (*cp - '?');
decdld_bitmap(&chars[char_num], bitmap, row, column);
column++;
} else if (*cp == ';') { /* next char */
row = column = 0;
char_num++;
init_glyph(&chars[char_num]);
} else if (*cp == '/') { /* sixel nl+cr */
row++;
column = 0;
} else if (*cp == '\0') { /* end of DECDLD sequence */
break;
}
cp++;
}
}
void decdld_parse_header(struct terminal_t *term, char *start_buf)
{
/*
DECDLD format
DCS Pfn; Pcn; Pe; Pcmw; Pss; Pt; Pcmh; Pcss; f Dscs Sxbp1 ; Sxbp2 ; .. .; Sxbpn ST
parameters
DCS : ESC (0x1B) 'P' (0x50) (DCS(8bit C1 code) is not supported)
Pfn : fontset (ignored)
Pcn : start char (0 means SPACE 0x20)
Pe : erase mode
0: clear selectet charset
1: clear only redefined glyph
2: clear all drcs charset
Pcmw: max cellwidth (force CELL_WEDTH defined in glyph.h)
Pss : screen size (ignored)
Pt : defines the glyph as text or full cell or sixel (force full cell mode)
(TODO: implement sixel/text mode)
Pcmh: max cellheight (force CELL_HEIGHT defined in glyph.h)
Pcss: character set size (force: 96)
0: 94 gylphs charset
1: 96 gylphs charset
f : '{' (0x7B)
Dscs: define character set
Intermediate char: SPACE (0x20) to '/' (0x2F)
final char : '0' (0x30) to '~' (0x7E)
but allow chars between '@' (0x40) and '~' (0x7E) for DRCSMMv1
(ref: https://github.com/saitoha/drcsterm/blob/master/README.rst)
Sxbp: see parse_decdld_sixel()
ST : ESC (0x1B) '\' (0x5C) or BEL (0x07)
*/
char *cp;
int start_char, erase_mode, charset;
struct parm_t parm;
/* replace final char of DECDLD header by NUL '\0' */
cp = strchr(start_buf, '{');
*cp = '\0';
logging(DEBUG, "decdld_parse_header()\nbuf:%s\n", start_buf);
/* split header by semicolon ';' */
reset_parm(&parm);
parse_arg(start_buf, &parm, ';', isdigit);
if (parm.argc != 8) /* DECDLD header must have 8 params */
return;
/* set params */
start_char = dec2num(parm.argv[1]);
erase_mode = dec2num(parm.argv[2]);
/* parse Dscs */
cp++; /* skip final char (NUL) of DECDLD header */
while (SPACE <= *cp && *cp <= '/') /* skip intermediate char */
cp++;
if (0x40 <= *cp && *cp <= 0x7E) /* final char of Dscs must be between 0x40 to 0x7E (DRCSMMv1) */
charset = *cp - 0x40;
else
charset = 0;
logging(DEBUG, "charset(ku):0x%.2X start_char:%d erase_mode:%d\n",
charset, start_char, erase_mode);
/* reset previous glyph data */
if (erase_mode < 0 || erase_mode > 2)
erase_mode = 0;
if (erase_mode == 2) /* reset all drcs charset */
memset(term->drcs, 0, sizeof(struct glyph_t) * DRCS_CHARS);
else if (erase_mode == 0) /* reset selected drcs charset */
memset(term->drcs + GLYPHS_PER_CHARSET * charset, 0, sizeof(struct glyph_t) * DRCS_CHARS);
//if (term->drcs[charset] == NULL) /* always allcate 96 chars buffer */
//term->drcs[charset] = ecalloc(GLYPH_PER_CHARSET, sizeof(struct glyph_t));
decdld_parse_data(cp + 1, start_char, term->drcs + GLYPHS_PER_CHARSET * charset); /* skip final char */
}

View file

@ -1,287 +0,0 @@
/* See LICENSE for licence details. */
/* function for osc sequence */
int32_t parse_color1(char *seq)
{
/*
format
rgb:r/g/b
rgb:rr/gg/bb
rgb:rrr/ggg/bbb
rgb:rrrr/gggg/bbbb
*/
int i, length, value;
int32_t color;
uint32_t rgb[3];
struct parm_t parm;
reset_parm(&parm);
parse_arg(seq, &parm, '/', isalnum);
for (i = 0; i < parm.argc; i++)
logging(DEBUG, "parm.argv[%d]: %s\n", i, parm.argv[i]);
if (parm.argc != 3)
return -1;
length = strlen(parm.argv[0]);
for (i = 0; i < 3; i++) {
value = hex2num(parm.argv[i]);
logging(DEBUG, "value:%d\n", value);
if (length == 1) /* r/g/b/ */
rgb[i] = bit_mask[8] & (value * 0xFF / 0x0F);
else if (length == 2) /* rr/gg/bb */
rgb[i] = bit_mask[8] & value;
else if (length == 3) /* rrr/ggg/bbb */
rgb[i] = bit_mask[8] & (value * 0xFF / 0xFFF);
else if (length == 4) /* rrrr/gggg/bbbb */
rgb[i] = bit_mask[8] & (value * 0xFF / 0xFFFF);
else
return -1;
}
color = (rgb[0] << 16) + (rgb[1] << 8) + rgb[2];
logging(DEBUG, "color:0x%.6X\n", color);
return color;
}
int32_t parse_color2(char *seq)
{
/*
format
#rgb
#rrggbb
#rrrgggbbb
#rrrrggggbbbb
*/
int i, length;
uint32_t rgb[3];
int32_t color;
char buf[BUFSIZE];
length = strlen(seq);
memset(buf, '\0', BUFSIZE);
if (length == 3) { /* rgb */
for (i = 0; i < 3; i++) {
strncpy(buf, seq + i, 1);
rgb[i] = bit_mask[8] & hex2num(buf) * 0xFF / 0x0F;
}
} else if (length == 6) { /* rrggbb */
for (i = 0; i < 3; i++) { /* rrggbb */
strncpy(buf, seq + i * 2, 2);
rgb[i] = bit_mask[8] & hex2num(buf);
}
} else if (length == 9) { /* rrrgggbbb */
for (i = 0; i < 3; i++) {
strncpy(buf, seq + i * 3, 3);
rgb[i] = bit_mask[8] & hex2num(buf) * 0xFF / 0xFFF;
}
} else if (length == 12) { /* rrrrggggbbbb */
for (i = 0; i < 3; i++) {
strncpy(buf, seq + i * 4, 4);
rgb[i] = bit_mask[8] & hex2num(buf) * 0xFF / 0xFFFF;
}
} else {
return -1;
}
color = (rgb[0] << 16) + (rgb[1] << 8) + rgb[2];
logging(DEBUG, "color:0x%.6X\n", color);
return color;
}
void set_palette(struct terminal_t *term, void *arg)
{
/*
OSC Ps ; Pt ST
ref: http://invisible-island.net/xterm/ctlseqs/ctlseqs.html
ref: http://ttssh2.sourceforge.jp/manual/ja/about/ctrlseq.html#OSC
only recognize change color palette:
Ps: 4
Pt: c ; spec
c: color index (from 0 to 255)
spec:
rgb:r/g/b
rgb:rr/gg/bb
rgb:rrr/ggg/bbb
rgb:rrrr/gggg/bbbb
#rgb
#rrggbb
#rrrgggbbb
#rrrrggggbbbb
this rgb format is "RGB Device String Specification"
see http://xjman.dsl.gr.jp/X11R6/X11/CH06.html
Pt: c ; ?
response rgb color
OSC 4 ; c ; rgb:rr/gg/bb ST
TODO: this function only works in 32bpp mode
*/
struct parm_t *pt = (struct parm_t *) arg;
int i, argc = pt->argc, index;
int32_t color;
uint8_t rgb[3];
char **argv = pt->argv;
char buf[BUFSIZE];
if (argc != 3)
return;
index = dec2num(argv[1]);
if (index < 0 || index >= COLORS)
return;
if (strncmp(argv[2], "rgb:", 4) == 0) {
if ((color = parse_color1(argv[2] + 4)) != -1) { /* skip "rgb:" */
term->virtual_palette[index] = (uint32_t) color;
term->palette_modified = true;
}
} else if (strncmp(argv[2], "#", 1) == 0) {
if ((color = parse_color2(argv[2] + 1)) != -1) { /* skip "#" */
term->virtual_palette[index] = (uint32_t) color;
term->palette_modified = true;
}
} else if (strncmp(argv[2], "?", 1) == 0) {
for (i = 0; i < 3; i++)
rgb[i] = bit_mask[8] & (term->virtual_palette[index] >> (8 * (2 - i)));
snprintf(buf, BUFSIZE, "\033]4;%d;rgb:%.2X/%.2X/%.2X\033\\",
index, rgb[0], rgb[1], rgb[2]);
ewrite(term->fd, buf, strlen(buf));
}
}
void reset_palette(struct terminal_t *term, void *arg)
{
/*
reset color c
OSC 104 ; c ST
c: index of color
ST: BEL or ESC \
reset all color
OSC 104 ST
ST: BEL or ESC \
terminfo: oc=\E]104\E\\
*/
struct parm_t *pt = (struct parm_t *) arg;
int i, argc = pt->argc, c;
char **argv = pt->argv;
if (argc < 2) { /* reset all color palette */
for (i = 0; i < COLORS; i++)
term->virtual_palette[i] = color_list[i];
term->palette_modified = true;
} else if (argc == 2) { /* reset color_palette[c] */
c = dec2num(argv[1]);
if (0 <= c && c < COLORS) {
term->virtual_palette[c] = color_list[c];
term->palette_modified = true;
}
}
}
int isdigit_or_questionmark(int c)
{
if (isdigit(c) || c == '?')
return 1;
else
return 0;
}
void glyph_width_report(struct terminal_t *term, void *arg)
{
/*
glyph width report
* request *
OSC 8900 ; Ps ; Pw ; ? : Pf : Pt ST
Ps: reserved
Pw: width (0 or 1 or 2)
Pfrom: beginning of unicode code point
Pto: end of unicode code point
ST: BEL(0x07) or ESC(0x1B) BACKSLASH(0x5C)
* answer *
OSC 8900 ; Ps ; Pv ; Pw ; Pf : Pt ; Pf : Pt ; ... ST
Ps: responce code
0: ok (default)
1: recognized but not supported
2: not recognized
Pv: reserved (maybe East Asian Width Version)
Pw: width (0 or 1 or 2)
Pfrom: beginning of unicode code point
Pto: end of unicode code point
ST: BEL(0x07) or ESC(0x1B) BACKSLASH(0x5C)
ref
http://uobikiemukot.github.io/yaft/glyph_width_report.html
https://gist.github.com/saitoha/8767268
*/
struct parm_t *pt = (struct parm_t *) arg, sub_parm;
int i, argc = pt->argc, width, from, to, left, right, w, wcw; //reserved
char **argv = pt->argv, buf[BUFSIZE];
if (argc < 4)
return;
reset_parm(&sub_parm);
parse_arg(argv[3], &sub_parm, ':', isdigit_or_questionmark);
if (sub_parm.argc != 3 || *sub_parm.argv[0] != '?')
return;
//reserved = dec2num(argv[1]);
width = dec2num(argv[2]);
from = dec2num(sub_parm.argv[1]);
to = dec2num(sub_parm.argv[2]);
if ((width < 0) || (width > 2))
return;
/* unicode private area: plane 16 (DRCSMMv1) is always half */
if ((from < 0) || (to >= UCS2_CHARS))
return;
snprintf(buf, BUFSIZE, "\033]8900;0;0;%d;", width); /* OSC 8900 ; Ps; Pv ; Pw ; */
ewrite(term->fd, buf, strlen(buf));
left = right = -1;
for (i = from; i <= to; i++) {
wcw = wcwidth(i);
if (wcw <= 0) /* zero width */
w = 0;
else if (term->glyph[i] == NULL) /* missing glyph */
w = wcw;
else
w = term->glyph[i]->width;
if (w != width) {
if (right != -1) {
snprintf(buf, BUFSIZE, "%d:%d;", left, right);
ewrite(term->fd, buf, strlen(buf));
} else if (left != -1) {
snprintf(buf, BUFSIZE, "%d:%d;", left, left);
ewrite(term->fd, buf, strlen(buf));
}
left = right = -1;
} else {
if (left == -1)
left = i;
else
right = i;
}
}
if (right != -1) {
snprintf(buf, BUFSIZE, "%d:%d;", left, right);
ewrite(term->fd, buf, strlen(buf));
} else if (left != -1) {
snprintf(buf, BUFSIZE, "%d:%d;", left, left);
ewrite(term->fd, buf, strlen(buf));
}
ewrite(term->fd, "\033\\", 2); /* ST (ESC BACKSLASH) */
}

View file

@ -170,7 +170,6 @@ static inline uint32_t color2pixel(struct fb_info_t *info, uint32_t color)
+ (b << info->blue.offset);
}
bool init_truecolor(struct fb_info_t *info, cmap_t **cmap, cmap_t **cmap_orig)
{
switch(info->bits_per_pixel) {
@ -364,24 +363,6 @@ void fb_die(struct framebuffer_t *fb)
//fb_release(fb->fd, &fb->info); /* os specific */
}
static inline void draw_sixel(struct framebuffer_t *fb, int line, int col, uint8_t *pixmap)
{
int h, w, src_offset, dst_offset;
uint32_t pixel, color = 0;
for (h = 0; h < CELL_HEIGHT; h++) {
for (w = 0; w < CELL_WIDTH; w++) {
src_offset = BYTES_PER_PIXEL * (h * CELL_WIDTH + w);
memcpy(&color, pixmap + src_offset, BYTES_PER_PIXEL);
dst_offset = (line * CELL_HEIGHT + h) * fb->info.line_length
+ (col * CELL_WIDTH + w) * fb->info.bytes_per_pixel;
pixel = color2pixel(&fb->info, color);
memcpy(fb->buf + dst_offset, &pixel, fb->info.bytes_per_pixel);
}
}
}
static inline void draw_line(struct framebuffer_t *fb, struct terminal_t *term, int line)
{
int pos, size, bdf_padding, glyph_width, margin_right;
@ -396,12 +377,6 @@ static inline void draw_line(struct framebuffer_t *fb, struct terminal_t *term,
/* target cell */
cellp = &term->cells[line][col];
/* draw sixel pixmap */
if (cellp->has_pixmap) {
draw_sixel(fb, line, col, cellp->pixmap);
continue;
}
/* copy current color_pair (maybe changed) */
color_pair = cellp->color_pair;
@ -460,12 +435,6 @@ static inline void draw_line(struct framebuffer_t *fb, struct terminal_t *term,
void refresh(struct framebuffer_t *fb, struct terminal_t *term)
{
if (term->palette_modified) {
term->palette_modified = false;
for (int i = 0; i < COLORS; i++)
fb->real_palette[i] = color2pixel(&fb->info, term->virtual_palette[i]);
}
if (term->mode & MODE_CURSOR)
term->line_dirty[term->cursor.y] = true;

View file

@ -8,7 +8,7 @@ XCFLAGS ?= -std=c99 -pedantic -Wall -Wextra -I/usr/include/X11/ -O3 -s -pipe
XLDFLAGS ?= -lX11
HDR = glyph.h yaft.h conf.h color.h parse.h terminal.h util.h \
ctrlseq/esc.h ctrlseq/csi.h ctrlseq/osc.h ctrlseq/dcs.h \
ctrlseq/esc.h ctrlseq/csi.h \
fb/common.h fb/linux.h fb/freebsd.h fb/netbsd.h fb/openbsd.h \
x/x.h

66
parse.h
View file

@ -108,79 +108,17 @@ void csi_sequence(struct terminal_t *term, uint8_t ch)
reset_esc(term);
}
int is_osc_parm(int c)
{
if (isdigit(c) || isalpha(c) ||
c == '?' || c == ':' || c == '/' || c == '#')
return true;
else
return false;
}
void omit_string_terminator(char *bp, uint8_t ch)
{
if (ch == BACKSLASH) /* ST: ESC BACKSLASH */
*(bp - 2) = '\0';
else /* ST: BEL */
*(bp - 1) = '\0';
}
void osc_sequence(struct terminal_t *term, uint8_t ch)
{
int osc_mode;
struct parm_t parm;
omit_string_terminator(term->esc.bp, ch);
(void) ch;
logging(DEBUG, "osc: OSC %s\n", term->esc.buf);
reset_parm(&parm);
parse_arg(term->esc.buf + 1, &parm, ';', is_osc_parm); /* skip ']' */
if (parm.argc > 0) {
osc_mode = dec2num(parm.argv[0]);
logging(DEBUG, "osc_mode:%d\n", osc_mode);
/* XXX: disable because this functions only work 24/32bpp
-> support other bpp (including pseudo color) */
if (osc_mode == 4)
set_palette(term, &parm);
else if (osc_mode == 104)
reset_palette(term, &parm);
if (osc_mode == 8900)
glyph_width_report(term, &parm);
}
reset_esc(term);
}
void dcs_sequence(struct terminal_t *term, uint8_t ch)
{
char *cp;
omit_string_terminator(term->esc.bp, ch);
(void) ch;
logging(DEBUG, "dcs: DCS %s\n", term->esc.buf);
/* check DCS header */
cp = term->esc.buf + 1; /* skip P */
while (cp < term->esc.bp) {
if (*cp == '{' || *cp == 'q') /* DECDLD or sixel */
break;
else if (*cp == ';' || ('0' <= *cp && *cp <= '9')) /* valid DCS header */
;
else /* invalid sequence */
cp = term->esc.bp;
cp++;
}
if (cp != term->esc.bp) { /* header only or couldn't find final char */
/* parse DCS header */
if (*cp == 'q')
sixel_parse_header(term, term->esc.buf + 1);
else if (*cp == '{')
decdld_parse_header(term, term->esc.buf + 1);
}
reset_esc(term);
}

View file

@ -8,7 +8,6 @@ void erase_cell(struct terminal_t *term, int y, int x)
cellp->color_pair = term->color_pair; /* bce */
cellp->attribute = ATTR_RESET;
cellp->width = HALF;
cellp->has_pixmap = false;
term->line_dirty[y] = true;
}
@ -54,7 +53,6 @@ int set_cell(struct terminal_t *term, int y, int x, const struct glyph_t *glyphp
cell.attribute = term->attribute;
cell.width = glyphp->width;
cell.has_pixmap = false;
cellp = &term->cells[y][x];
*cellp = cell;
@ -170,25 +168,6 @@ void set_cursor(struct terminal_t *term, int y, int x)
term->wrap_occured = false;
}
const struct glyph_t *drcs_glyph(struct terminal_t *term, uint32_t code)
{
/* DRCSMMv1
ESC ( SP <\xXX> <\xYY> ESC ( B
<===> U+10XXYY ( 0x40 <= 0xXX <=0x7E, 0x20 <= 0xYY <= 0x7F )
*/
int row, cell; /* = ku, ten */
row = (0xFF00 & code) >> 8;
cell = 0xFF & code;
logging(DEBUG, "drcs row:0x%.2X cell:0x%.2X\n", row, cell);
if ((0x40 <= row && row <= 0x7E) && (0x20 <= cell && cell <= 0x7F))
return &term->drcs[(row - 0x40) * GLYPHS_PER_CHARSET + (cell - 0x20)];
else
return term->glyph[SUBSTITUTE_HALF];
}
void addch(struct terminal_t *term, uint32_t code)
{
int width;
@ -198,11 +177,9 @@ void addch(struct terminal_t *term, uint32_t code)
width = wcwidth(code);
if (width <= 0) /* zero width: not support comibining character */
if (width <= 0) /* zero width: not support comibining character */
return;
else if (0x100000 <= code && code <= 0x10FFFD) /* unicode private area: plane 16 (DRCSMMv1) */
glyphp = drcs_glyph(term, code);
else if (code >= UCS2_CHARS /* yaft support only UCS2 */
else if (code >= UCS2_CHARS /* yaft support only UCS2 */
|| term->glyph[code] == NULL /* missing glyph */
|| term->glyph[code]->width != width) /* width unmatch */
glyphp = (width == 1) ? term->glyph[SUBSTITUTE_HALF]: term->glyph[SUBSTITUTE_WIDE];
@ -335,7 +312,6 @@ void term_die(struct terminal_t *term)
free(term->line_dirty);
free(term->tabstop);
free(term->esc.buf);
free(term->sixel.pixmap);
for (int i = 0; i < term->lines; i++)
free(term->cells[i]);
@ -360,23 +336,17 @@ bool term_init(struct terminal_t *term, int width, int height)
term->line_dirty = (bool *) ecalloc(term->lines, sizeof(bool));
term->tabstop = (bool *) ecalloc(term->cols, sizeof(bool));
term->esc.buf = (char *) ecalloc(1, term->esc.size);
term->sixel.pixmap = (uint8_t *) ecalloc(width * height, BYTES_PER_PIXEL);
term->cells = (struct cell_t **) ecalloc(term->lines, sizeof(struct cell_t *));
for (int i = 0; i < term->lines; i++)
term->cells[i] = (struct cell_t *) ecalloc(term->cols, sizeof(struct cell_t));
if (!term->line_dirty || !term->tabstop || !term->cells
|| !term->esc.buf || !term->sixel.pixmap) {
if (!term->line_dirty || !term->tabstop
|| !term->cells || !term->esc.buf) {
term_die(term);
return false;
}
/* initialize palette */
for (int i = 0; i < COLORS; i++)
term->virtual_palette[i] = color_list[i];
term->palette_modified = false;
/* initialize glyph map */
for (uint32_t code = 0; code < UCS2_CHARS; code++)
term->glyph[code] = NULL;

2
yaft.c
View file

@ -7,8 +7,6 @@
#include "terminal.h"
#include "ctrlseq/esc.h"
#include "ctrlseq/csi.h"
#include "ctrlseq/osc.h"
#include "ctrlseq/dcs.h"
#include "parse.h"
void sig_handler(int signo)

27
yaft.h
View file

@ -36,8 +36,6 @@ enum char_code {
enum misc {
BUFSIZE = 1024, /* read, esc, various buffer size */
BITS_PER_BYTE = 8, /* bits per byte */
BYTES_PER_PIXEL = sizeof(uint32_t), /* pixel size of sixel pixmap data */
BITS_PER_SIXEL = 6, /* number of bits of a sixel */
ESCSEQ_SIZE = 1024, /* limit size of terminal escape sequence */
SELECT_TIMEOUT = 15000, /* used by select() */
SLEEP_TIME = 30000, /* sleep time at EAGAIN, EWOULDBLOCK (usec) */
@ -45,9 +43,6 @@ enum misc {
UCS2_CHARS = 0x10000, /* number of UCS2 glyphs */
CTRL_CHARS = 0x20, /* number of ctrl_func */
ESC_CHARS = 0x80, /* number of esc_func */
DRCS_CHARSETS = 63, /* number of charset of DRCS (according to DRCSMMv1) */
GLYPHS_PER_CHARSET = 96, /* number of glyph of each DRCS charset */
DRCS_CHARS = DRCS_CHARSETS * GLYPHS_PER_CHARSET,
DEFAULT_CHAR = SPACE, /* used for erase char */
BRIGHT_INC = 8, /* value used for brightening color */
};
@ -112,10 +107,6 @@ struct cell_t {
struct color_pair_t color_pair; /* color (fg, bg) */
enum char_attr attribute; /* bold, underscore, etc... */
enum glyph_width width; /* wide char flag: WIDE, NEXT_TO_WIDE, HALF */
bool has_pixmap; /* has sixel pixmap data or not */
/* sixel pixmap data:
must be statically allocated for copy_cell() */
uint8_t pixmap[BYTES_PER_PIXEL * CELL_WIDTH * CELL_HEIGHT];
};
struct esc_t {
@ -126,8 +117,9 @@ struct esc_t {
};
struct charset_t {
uint32_t code; /* UCS4 code point: yaft only prints UCS2 and DRCSMMv1 */
int following_byte, count;
uint32_t code; /* UCS2 code point: yaft only supports BMP */
int following_byte;
int count;
bool is_valid;
};
@ -137,15 +129,6 @@ struct state_t { /* for save, restore state */
enum char_attr attribute;
};
struct sixel_canvas_t {
uint8_t *pixmap;
struct point_t point;
int width, height;
int line_length;
uint8_t color_index;
uint32_t color_table[COLORS];
};
struct terminal_t {
int fd; /* master of pseudo terminal */
int width, height; /* terminal size (pixel) */
@ -162,11 +145,7 @@ struct terminal_t {
enum char_attr attribute; /* bold, underscore, etc... */
struct charset_t charset; /* store UTF-8 byte stream */
struct esc_t esc; /* store escape sequence */
uint32_t virtual_palette[COLORS]; /* virtual color palette: always 32bpp */
bool palette_modified; /* true if palette changed by OSC 4/104 */
const struct glyph_t *glyph[UCS2_CHARS]; /* array of pointer to glyphs[] */
struct glyph_t drcs[DRCS_CHARS]; /* DRCS chars */
struct sixel_canvas_t sixel;
};
struct parm_t { /* for parse_arg() */