diff options
author | james <> | 2008-02-03 23:31:25 +0000 |
---|---|---|
committer | james <> | 2008-02-03 23:31:25 +0000 |
commit | 148184f54c08d931007fc31cfd26ac88cc86e493 (patch) | |
tree | 4fcbc6fc7b58aca6bad6365c8526337e327e5a20 /src/ansi.c | |
parent | 4163308ecae26c76d22e4cc80d8bae729b06b94f (diff) | |
download | sympathy-148184f54c08d931007fc31cfd26ac88cc86e493.tar.gz sympathy-148184f54c08d931007fc31cfd26ac88cc86e493.tar.bz2 sympathy-148184f54c08d931007fc31cfd26ac88cc86e493.zip |
*** empty log message ***
Diffstat (limited to 'src/ansi.c')
-rw-r--r-- | src/ansi.c | 275 |
1 files changed, 275 insertions, 0 deletions
diff --git a/src/ansi.c b/src/ansi.c new file mode 100644 index 0000000..5d6105e --- /dev/null +++ b/src/ansi.c @@ -0,0 +1,275 @@ +/* + * ansi.c: + * + * Copyright (c) 2008 James McKenzie <james@fishsoup.dhs.org>, + * All rights reserved. + * + */ + +static char rcsid[] = "$Id$"; + +/* + * $Log$ + * Revision 1.1 2008/02/03 23:31:25 james + * *** empty log message *** + * + */ + +void +ansi_write (ANSI * a, char *buf, int n) +{ + write (a->fd, buf, n); +} + + + +void +ansi_move (ANSI * a, CRT_Pos p) +{ + char buf[16]; + int n; + int dx = a->pos.x - p.x; + int dy = a->pos.y - p.y; + + + if (a->pos.x != ANSI_INVAL) + { + + if ((!dx) && (!dy)) + return; + + if (!dy) + { + if (dx == 1) + { + ansi_write (a, "\033[C", 3); + } + else if (dx == -1) + { + ansi_write (a, "\033[D", 3); + } + else + { + n = snprintf (buf, sizeof (buf), "\033[%dG", p.x + 1); + ansi_write (a, buf, n); + } + } + else if (!dx) + { + if (dy == -1) + { + ansi_write (a, "\033[A", 3); + } + else if (dy == 1) + { + ansi_write (a, "\033[B", 3); + } + else if (dy < 0) + { + n = snprintf (buf, sizeof (buf), "\033[%dA", -dy); + ansi_write (a, buf, n); + } + else + { + n = snprintf (buf, sizeof (buf), "\033[%dB", dy); + ansi_write (a, buf, n); + } + } + else if (!p.x) + { + if (dy == 1) + { + ansi_write (a, "\033[E", 3); + } + else if (dy == -1) + { + ansi_write (a, "\033[F", 3); + } + else if (dy > 0) + { + n = snprintf (buf, sizeof (buf), "\033[%dE", -dy); + ansi_write (a, buf, n); + } + else + { + n = snprintf (buf, sizeof (buf), "\033[%dF", dy); + ansi_write (a, buf, n); + } + } + else + { + n = snprintf (buf, sizeof (buf), "\033[%d;%dHF", p.y + 1, p.x + 1); + ansi_write (a, buf, n); + } + } + else + { + n = snprintf (buf, sizeof (buf), "\033[%d;%dHF", p.y + 1, p.x + 1); + ansi_write (a, buf, n); + } + + a->pos = p; +} + + +void +ansi_showhide_cursor (ANSI * a, int hide) +{ + if (a->hide_cursor == hide) + return; + + if (hide) + { + ansi_write (a, "\033[?25h", 6); + } + else + { + ansi_write (a, "\033[?25l", 6); + } + + a->hide_cursor = hide; +} + + +void ansi_force_attr_normal(ANSI *a) +{ + ansi_write (a, "\033[0m", 4); + a->attr=CRT_ATTR_NORMAL; +} + +void +ansi_set_attr (ANSI * a, int attr) +{ + + dif = attr ^ a->attr; + + if (!dif) + return; + + if (attr == ATTR_NORMAL) + { + ansi_force_attr_normal(a); + return; + } + + if (dif & CRT_ATTR_UNDERLINE) + { + if (attr & CRT_ATTR_UNDERLINE) + { + ansi_write (a, "\033[4m", 4); + } + else + { + ansi_write (a, "\033[24m", 5); + } + } + if (dif & CRT_ATTR_REVERSE) + { + if (attr & CRT_ATTR_REVERSE) + { + ansi_write (a, "\033[7m", 4); + } + else + { + ansi_write (a, "\033[27m", 5); + } + } + if (dif & CRT_ATTR_BOLD) + { + if (attr & CRT_ATTR_REVERSE) + { + ansi_write (a, "\033[1m", 4); + } + else + { + ansi_write (a, "\033[22m", 5); + } + } +} + + +void +ansi_render (ANSI * a, CRT_CA ca) +{ + int dif; + + if (ca.chr < 32) + ca.chr = ' '; + if (ca.chr > 126) + ca.chr = ' '; + + ansi_set_attr (a, ca.attr); + + ansi_write (a, &ca.chr, 1); + + a->pos.x++; + +/*Can't easily wrap round here as don't know size of destination screen*/ +/*so invalidate the cached cursor position*/ + + if (a->pos.x >= CRT_COLS) + a->pos.x = ANSI_INVAL; + +} + +void +ansi_cls (ANSI * a) +{ + CRT_Pos p = { 0 }; + + crt_cls (&a->crt); + ansi_force_attr_normal(a); + ansi_move (a, p); + ansi_write (a, "\033[2J", 4); +/*different emulators leave cursor in different places after cls differently*/ + a->pos.x = ANSI_INVAL; +} + + +void +ansi_draw (ANSI * a, CRT * c) +{ + CRT_Pos p; + int o; + + ansi_showhide_cursor (a, 1); + + for (p.y = 0; p.y < CRT_ROWS; ++p.y) + { + if (p.y >= a->size.y) + continue; + o = CRT_ADDR (r, 0); + for (p.x = 0; p.x < CRT_COLS; ++p.x, ++o) + { + if (p.x >= a->size.x) + continue; + if (crt_ca_cmp (a->crt.screen[p], c->screen[p])) + { + a->crt.screen[p] = c->screen[p]; + + ansi_move (a, p); + ansi_render (a, a->crt.screen[p]); + } + } + } + + a->crt.pos = c->pos; + ansi_move (a, a->crt.pos); + + a->crt.hide_cursor = c->hide_cursor; + ansi_showhide_cursor (a, ci->crt.hide_cursor); +} + +void +ansi_reset (ANSI * a) +{ + ansi_write (a, "\033[c", 3); + + a->pos.x = ANSI_INVAL; + a->hide_cursor = ANSI_INVAL; + + crt_reset (&a->crt); + + ansi_cls (a); + ansi_draw (a, &a->crt); +} |