X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fansi.c;h=f70a2d55e844c7a890579f7babad27e7f5a920fa;hb=3684640e6bdec97cb1b60a34d03e8cde63149215;hp=5e7063413488797dfda4f2ccd4352827f775188e;hpb=8ba373fecb91b8f276c754f63a5a7f1490f76dcc;p=sympathy.git diff --git a/src/ansi.c b/src/ansi.c index 5e70634..f70a2d5 100644 --- a/src/ansi.c +++ b/src/ansi.c @@ -10,6 +10,36 @@ static char rcsid[] = "$Id$"; /* * $Log$ + * Revision 1.14 2008/02/07 12:21:16 james + * *** empty log message *** + * + * Revision 1.13 2008/02/07 12:16:04 james + * *** empty log message *** + * + * Revision 1.12 2008/02/07 11:32:41 james + * *** empty log message *** + * + * Revision 1.11 2008/02/07 11:11:14 staffcvs + * *** empty log message *** + * + * Revision 1.10 2008/02/07 01:02:52 james + * *** empty log message *** + * + * Revision 1.9 2008/02/07 00:43:27 james + * *** empty log message *** + * + * Revision 1.8 2008/02/07 00:39:13 james + * *** empty log message *** + * + * Revision 1.7 2008/02/06 20:26:57 james + * *** empty log message *** + * + * Revision 1.6 2008/02/06 17:53:28 james + * *** empty log message *** + * + * Revision 1.5 2008/02/06 15:53:22 james + * *** empty log message *** + * * Revision 1.4 2008/02/04 20:23:55 james * *** empty log message *** * @@ -25,9 +55,48 @@ static char rcsid[] = "$Id$"; */ #include "project.h" +static void +set_nonblocking (int fd) +{ + long arg; + arg = fcntl (fd, F_GETFL, arg); + arg |= O_NONBLOCK; + fcntl (fd, F_SETFL, arg); +} + +static void +set_blocking (int fd) +{ + long arg; + arg = fcntl (fd, F_GETFL, arg); + arg &= ~O_NONBLOCK; + fcntl (fd, F_SETFL, arg); +} + + +int +ansi_read (ANSI * a, void *buf, int n) +{ + int red; + + set_nonblocking (a->fd); + red = read (a->fd, buf, n); + + if (!red) + return -1; + + if ((red == -1) && (errno == EAGAIN)) + { + return 0; + } + + return red; +} + void ansi_write (ANSI * a, char *buf, int n) { + set_blocking (a->fd); write (a->fd, buf, n); } @@ -163,6 +232,41 @@ ansi_force_attr_normal (ANSI * a) { ansi_write (a, "\033[0m", 4); a->attr = CRT_ATTR_NORMAL; + a->color = ANSI_INVAL; +} + +void +ansi_set_color (ANSI * a, int color) +{ + int dif; + char buf[16]; + int i; + int fg,bg; + + if ((a->color == ANSI_INVAL) || (color!=a->color)) { + fg=CRT_COLOR_FG(color); + bg=CRT_COLOR_BG(color); + + if (fg & CRT_COLOR_INTENSITY) { + fg+=90; + } else { + fg+=30; + } + + if (bg & CRT_COLOR_INTENSITY) { + bg+=100; + } else { + bg+=40; + } + + i=sprintf(buf,"\033[%d;%dm",fg,bg); +#if 0 + fprintf(stderr,"Color set to %d %d %x\n",fg,bg,color); +#endif + + ansi_write (a,buf,i); + a->color=color; + } } void @@ -177,11 +281,13 @@ ansi_set_attr (ANSI * a, int attr) a->attr = attr; +#if 0 if (attr == CRT_ATTR_NORMAL) { ansi_force_attr_normal (a); return; } +#endif if (dif & CRT_ATTR_UNDERLINE) { @@ -207,12 +313,13 @@ ansi_set_attr (ANSI * a, int attr) } if (dif & CRT_ATTR_BOLD) { - if (attr & CRT_ATTR_REVERSE) + if (attr & CRT_ATTR_BOLD) { ansi_write (a, "\033[1m", 4); } else { + ansi_write (a, "\033[21m", 5); ansi_write (a, "\033[22m", 5); } } @@ -231,6 +338,7 @@ ansi_render (ANSI * a, CRT_CA ca) ca.chr = ' '; ansi_set_attr (a, ca.attr); + ansi_set_color(a,ca.color); ansi_write (a, &ca.chr, 1); @@ -252,6 +360,7 @@ ansi_cls (ANSI * a) crt_cls (&a->crt); ansi_force_attr_normal (a); + ansi_set_color(a,CRT_COLOR_NORMAL); ansi_move (a, p); ansi_write (a, "\033[2J", 4); /*different emulators leave cursor in different places after cls differently*/ @@ -264,8 +373,7 @@ ansi_draw (ANSI * a, CRT * c) { CRT_Pos p; int o; - - ansi_showhide_cursor (a, 1); + int hidden_cursor = 0; for (p.y = 0; p.y < CRT_ROWS; ++p.y) { @@ -278,6 +386,7 @@ ansi_draw (ANSI * a, CRT * c) continue; if (crt_ca_cmp (a->crt.screen[o], c->screen[o])) { + ansi_showhide_cursor (a, 1); a->crt.screen[o] = c->screen[o]; ansi_move (a, p); @@ -286,6 +395,29 @@ ansi_draw (ANSI * a, CRT * c) } } + + if ((CRT_COLS > a->size.x) || (CRT_ROWS > a->size.y)) + { + char msg[] = "Window is too small"; + p.x = 0; + p.y = 0; + + ansi_showhide_cursor (a, 1); + ansi_set_attr (a, CRT_ATTR_REVERSE); + ansi_set_color(a,CRT_MAKE_COLOR(CRT_COLOR_WHITE,CRT_COLOR_RED)); + ansi_move (a, p); + + ansi_write (a, msg, sizeof (msg)); + a->pos.x = ANSI_INVAL; + } + + + if ((c->pos.x >= a->size.x) || (c->pos.y >= a->size.y)) + { + ansi_showhide_cursor (a, 1); + return; + } + a->crt.pos = c->pos; ansi_move (a, a->crt.pos); @@ -306,5 +438,214 @@ ansi_reset (ANSI * a) crt_reset (&a->crt); ansi_cls (a); + ansi_write (a, "\033=", 2); ansi_draw (a, &a->crt); } + +void +ansi_flush_escape (ANSI * a, VT102 * v,TTY *t) +{ + ANSI_Parser *p = &a->parser; + int i; + + for (i = 0; i < p->escape_ptr; ++i) + { + vt102_send (v, p->escape_buf[i],t); + } + + p->escape_ptr = 0; + p->in_escape = 0; +} + +void +ansi_parse_deckey (ANSI * a, VT102 * v,TTY *t) +{ + ANSI_Parser *p = &a->parser; + if ((p->escape_buf[1] != '[') && (p->escape_buf[1] != 'O')) + { + ansi_flush_escape (a, v,t); + return; + } + + if ((p->escape_buf[2] >= 'A') || (p->escape_buf[2] <= 'Z')) + { + vt102_send (v, KEY_UP + (p->escape_buf[2] - 'A'),t); + } + else if ((p->escape_buf[2] >= 'a') || (p->escape_buf[2] <= 'z')) + { + vt102_send (v, KEY_154 + (p->escape_buf[2] - 'a'),t); + } + else + { + ansi_flush_escape (a, v,t); + return; + } + p->in_escape = 0; + p->escape_ptr = 0; +} + +void +ansi_parse_ansikey (ANSI * a, VT102 * v,TTY *t) +{ + ANSI_Parser *p = &a->parser; + + if ((p->escape_buf[1] != '[') || (p->escape_buf[3] != '~')) + { + ansi_flush_escape (a, v,t); + return; + } + if ((p->escape_buf[2] >= '0') || (p->escape_buf[2] <= '9')) + { + vt102_send (v, KEY_180 + (p->escape_buf[2] - '0'),t); + } + else + { + ansi_flush_escape (a, v,t); + return; + } + + p->in_escape = 0; + p->escape_ptr = 0; +} + + + +void +ansi_parse_escape (ANSI * a, VT102 * v,TTY *t) +{ + ANSI_Parser *p = &a->parser; + switch (p->escape_ptr) + { + case 0: + case 1: + return; + case 2: + switch (p->escape_buf[1]) + { + case '[': + case 'O': + break; + default: + ansi_flush_escape (a, v,t); + } + break; + case 3: + switch (p->escape_buf[1]) + { + case 'O': + ansi_parse_deckey (a, v,t); + break; + case '[': + if ((p->escape_buf[2] >= 'A') && (p->escape_buf[2] <= 'Z')) + ansi_parse_deckey (a, v,t); + break; + default: + ansi_flush_escape (a, v,t); + } + break; + case 4: + switch (p->escape_buf[1]) + { + case '[': + ansi_parse_ansikey (a, v,t); + break; + default: + ansi_flush_escape (a, v,t); + } + break; + case 5: + ansi_flush_escape (a, v,t); + } +} + + +void +ansi_check_escape (ANSI * a, VT102 * v,TTY *t) +{ + ANSI_Parser *p = &a->parser; + struct timeval now, diff; + gettimeofday (&now, NULL); + timersub (&now, &p->last_escape, &diff); + +#if 0 + fprintf (stderr, "ie %d tl %d.%06d eb %d\n", + p->in_escape, diff.tv_sec, diff.tv_usec, p->escape_ptr); +#endif + + if (!p->in_escape) + return; + + + /*Time up? */ + if (diff.tv_sec || (diff.tv_usec > ANSI_ESCAPE_TIMEOUT)) + ansi_flush_escape (a, v,t); + +} + + +void +ansi_parse_char (ANSI * a, int c, VT102 * v,TTY *t) +{ + ANSI_Parser *p = &a->parser; + + +/*See if it's time to flush the escape*/ + ansi_check_escape (a, v,t); + + if (c == 033) + { + if (p->in_escape) + ansi_flush_escape (a, v,t); + + p->in_escape++; + p->escape_ptr = 0; + gettimeofday (&p->last_escape, NULL); + } + + if (p->in_escape) + { + p->escape_buf[p->escape_ptr++] = c; + ansi_parse_escape (a, v,t); + } + else + { + vt102_send (v, c,t); + } + +} + +void +ansi_parse (ANSI * a, char *buf, int len, VT102 * v,TTY *t) +{ + while (len--) + ansi_parse_char (a, *(buf++), v,t); +} + +int +ansi_dispatch (ANSI * a, VT102 * v,TTY *t) +{ + char buf[1024]; + int red; + + ansi_check_escape (a, v,t); + + + red = ansi_read (a, buf, sizeof (buf)); + if (red <= 0) + return red; + +#if 0 + if (*buf == 3) + return -1; +#endif + +#if 0 + if (*buf == 1) + return 1; +#endif + + + ansi_parse (a, buf, red, v,t); + + return 0; +}