version 1.23, 2013/03/21 16:12:10 |
version 1.24, 2013/03/22 15:51:54 |
|
|
void grid_reflow_split(struct grid *, u_int *, struct grid_line *, u_int, |
void grid_reflow_split(struct grid *, u_int *, struct grid_line *, u_int, |
u_int); |
u_int); |
void grid_reflow_move(struct grid *, u_int *, struct grid_line *); |
void grid_reflow_move(struct grid *, u_int *, struct grid_line *); |
|
size_t grid_string_cells_fg(const struct grid_cell *, int *); |
|
size_t grid_string_cells_bg(const struct grid_cell *, int *); |
|
void grid_string_cells_code(const struct grid_cell *, |
|
const struct grid_cell *, char *, size_t); |
|
|
/* Create a new grid. */ |
/* Create a new grid. */ |
struct grid * |
struct grid * |
|
|
} |
} |
} |
} |
|
|
|
/* Get ANSI foreground sequence. */ |
|
size_t |
|
grid_string_cells_fg(const struct grid_cell *gc, int *values) |
|
{ |
|
size_t n; |
|
|
|
n = 0; |
|
if (gc->flags & GRID_FLAG_FG256) { |
|
values[n++] = 38; |
|
values[n++] = 5; |
|
values[n++] = gc->fg; |
|
} else { |
|
switch (gc->fg) { |
|
case 0: |
|
case 1: |
|
case 2: |
|
case 3: |
|
case 4: |
|
case 5: |
|
case 6: |
|
case 7: |
|
values[n++] = gc->fg + 30; |
|
break; |
|
case 8: |
|
values[n++] = 39; |
|
break; |
|
case 90: |
|
case 91: |
|
case 92: |
|
case 93: |
|
case 94: |
|
case 95: |
|
case 96: |
|
case 97: |
|
values[n++] = gc->fg; |
|
break; |
|
} |
|
} |
|
return (n); |
|
} |
|
|
|
/* Get ANSI background sequence. */ |
|
size_t |
|
grid_string_cells_bg(const struct grid_cell *gc, int *values) |
|
{ |
|
size_t n; |
|
|
|
n = 0; |
|
if (gc->flags & GRID_FLAG_BG256) { |
|
values[n++] = 48; |
|
values[n++] = 5; |
|
values[n++] = gc->bg; |
|
} else { |
|
switch (gc->bg) { |
|
case 0: |
|
case 1: |
|
case 2: |
|
case 3: |
|
case 4: |
|
case 5: |
|
case 6: |
|
case 7: |
|
values[n++] = gc->bg + 40; |
|
break; |
|
case 8: |
|
values[n++] = 49; |
|
break; |
|
case 100: |
|
case 101: |
|
case 102: |
|
case 103: |
|
case 104: |
|
case 105: |
|
case 106: |
|
case 107: |
|
values[n++] = gc->bg - 10; |
|
break; |
|
} |
|
} |
|
return (n); |
|
} |
|
|
|
/* |
|
* Returns ANSI code to set particular attributes (colour, bold and so on) |
|
* given a current state. The output buffer must be able to hold at least 57 |
|
* bytes. |
|
*/ |
|
void |
|
grid_string_cells_code(const struct grid_cell *lastgc, |
|
const struct grid_cell *gc, char *buf, size_t len) |
|
{ |
|
int oldc[16], newc[16], s[32]; |
|
size_t noldc, nnewc, n, i; |
|
u_int attr = gc->attr; |
|
u_int lastattr = lastgc->attr; |
|
char tmp[64]; |
|
|
|
struct { |
|
u_int mask; |
|
u_int code; |
|
} attrs[] = { |
|
{ GRID_ATTR_BRIGHT, 1 }, |
|
{ GRID_ATTR_DIM, 2 }, |
|
{ GRID_ATTR_ITALICS, 3 }, |
|
{ GRID_ATTR_UNDERSCORE, 4 }, |
|
{ GRID_ATTR_BLINK, 5 }, |
|
{ GRID_ATTR_REVERSE, 7 }, |
|
{ GRID_ATTR_HIDDEN, 8 } |
|
}; |
|
n = 0; |
|
|
|
/* If any attribute is removed, begin with 0. */ |
|
for (i = 0; i < nitems(attrs); i++) { |
|
if (!(attr & attrs[i].mask) && (lastattr & attrs[i].mask)) { |
|
s[n++] = 0; |
|
break; |
|
} |
|
} |
|
/* For each attribute that is newly set, add its code. */ |
|
for (i = 0; i < nitems(attrs); i++) { |
|
if ((attr & attrs[i].mask) && !(lastattr & attrs[i].mask)) |
|
s[n++] = attrs[i].code; |
|
} |
|
|
|
/* If the foreground c changed, append its parameters. */ |
|
nnewc = grid_string_cells_fg(gc, newc); |
|
noldc = grid_string_cells_fg(lastgc, oldc); |
|
if (nnewc != noldc || memcmp(newc, oldc, nnewc * sizeof newc[0]) != 0) { |
|
for (i = 0; i < nnewc; i++) |
|
s[n++] = newc[i]; |
|
} |
|
|
|
/* If the background c changed, append its parameters. */ |
|
nnewc = grid_string_cells_bg(gc, newc); |
|
noldc = grid_string_cells_bg(lastgc, oldc); |
|
if (nnewc != noldc || memcmp(newc, oldc, nnewc * sizeof newc[0]) != 0) { |
|
for (i = 0; i < nnewc; i++) |
|
s[n++] = newc[i]; |
|
} |
|
|
|
/* If there are any parameters, append an SGR code. */ |
|
*buf = '\0'; |
|
if (n > 0) { |
|
strlcat(buf, "\033[", len); |
|
for (i = 0; i < n; i++) { |
|
if (i + 1 < n) |
|
xsnprintf(tmp, sizeof tmp, "%d;", s[i]); |
|
else |
|
xsnprintf(tmp, sizeof tmp, "%d", s[i]); |
|
strlcat(buf, tmp, len); |
|
} |
|
strlcat(buf, "m", len); |
|
} |
|
|
|
/* Append shift in/shift out if needed. */ |
|
if ((attr & GRID_ATTR_CHARSET) && !(lastattr & GRID_ATTR_CHARSET)) |
|
strlcat(buf, "\016", len); /* SO */ |
|
if (!(attr & GRID_ATTR_CHARSET) && (lastattr & GRID_ATTR_CHARSET)) |
|
strlcat(buf, "\017", len); /* SI */ |
|
} |
|
|
/* Convert cells into a string. */ |
/* Convert cells into a string. */ |
char * |
char * |
grid_string_cells(struct grid *gd, u_int px, u_int py, u_int nx) |
grid_string_cells(struct grid *gd, u_int px, u_int py, u_int nx, |
|
struct grid_cell **lastgc, int with_codes) |
{ |
{ |
const struct grid_cell *gc; |
const struct grid_cell *gc; |
|
static struct grid_cell lastgc1; |
struct utf8_data ud; |
struct utf8_data ud; |
char *buf; |
char *buf, code[128]; |
size_t len, off; |
size_t len, off, codelen; |
u_int xx; |
u_int xx; |
|
|
GRID_DEBUG(gd, "px=%u, py=%u, nx=%u", px, py, nx); |
GRID_DEBUG(gd, "px=%u, py=%u, nx=%u", px, py, nx); |
|
|
|
if (*lastgc == NULL) { |
|
memcpy(&lastgc1, &grid_default_cell, sizeof lastgc1); |
|
*lastgc = &lastgc1; |
|
} |
|
|
len = 128; |
len = 128; |
buf = xmalloc(len); |
buf = xmalloc(len); |
off = 0; |
off = 0; |
|
|
continue; |
continue; |
grid_cell_get(gc, &ud); |
grid_cell_get(gc, &ud); |
|
|
while (len < off + ud.size + 1) { |
if (with_codes) { |
|
grid_string_cells_code(*lastgc, gc, code, sizeof code); |
|
codelen = strlen(code); |
|
memcpy(*lastgc, gc, sizeof *gc); |
|
} else |
|
codelen = 0; |
|
|
|
while (len < off + ud.size + codelen + 1) { |
buf = xrealloc(buf, 2, len); |
buf = xrealloc(buf, 2, len); |
len *= 2; |
len *= 2; |
} |
} |
|
|
|
if (codelen != 0) { |
|
memcpy(buf + off, code, codelen); |
|
off += codelen; |
|
} |
memcpy(buf + off, ud.data, ud.size); |
memcpy(buf + off, ud.data, ud.size); |
off += ud.size; |
off += ud.size; |
} |
} |