4 * Copyright (c) 2008 James McKenzie <james@fishsoup.dhs.org>,
9 static char rcsid[] = "$Id$";
13 * Revision 1.9 2008/02/07 00:43:27 james
14 * *** empty log message ***
16 * Revision 1.8 2008/02/07 00:39:13 james
17 * *** empty log message ***
19 * Revision 1.7 2008/02/06 20:26:57 james
20 * *** empty log message ***
22 * Revision 1.6 2008/02/06 17:53:28 james
23 * *** empty log message ***
25 * Revision 1.5 2008/02/06 15:53:22 james
26 * *** empty log message ***
28 * Revision 1.4 2008/02/04 20:23:55 james
29 * *** empty log message ***
31 * Revision 1.3 2008/02/04 05:45:55 james
34 * Revision 1.2 2008/02/04 02:05:06 james
35 * *** empty log message ***
37 * Revision 1.1 2008/02/03 23:31:25 james
38 * *** empty log message ***
44 set_nonblocking (int fd)
47 arg = fcntl (fd, F_GETFL, arg);
49 fcntl (fd, F_SETFL, arg);
56 arg = fcntl (fd, F_GETFL, arg);
58 fcntl (fd, F_SETFL, arg);
63 ansi_read (ANSI * a, void *buf, int n)
67 set_nonblocking (a->fd);
68 red = read (a->fd, buf, n);
73 if ((red == -1) && (errno == EAGAIN))
82 ansi_write (ANSI * a, char *buf, int n)
85 write (a->fd, buf, n);
89 ansi_getsize (ANSI * a)
91 struct winsize sz = { 0 };
92 if (ioctl (a->fd, TIOCGWINSZ, &sz))
99 a->size.x = sz.ws_col;
100 a->size.y = sz.ws_row;
107 ansi_move (ANSI * a, CRT_Pos p)
111 int dx = p.x - a->pos.x;
112 int dy = p.y - a->pos.y;
114 // a->pos.x = ANSI_INVAL;
116 if (a->pos.x != ANSI_INVAL)
126 ansi_write (a, "\033[C", 3);
130 ansi_write (a, "\033[D", 3);
134 n = snprintf (buf, sizeof (buf), "\033[%dG", p.x + 1);
135 ansi_write (a, buf, n);
142 ansi_write (a, "\033[A", 3);
146 ansi_write (a, "\033[B", 3);
150 n = snprintf (buf, sizeof (buf), "\033[%dA", -dy);
151 ansi_write (a, buf, n);
155 n = snprintf (buf, sizeof (buf), "\033[%dB", dy);
156 ansi_write (a, buf, n);
163 ansi_write (a, "\033[E", 3);
167 ansi_write (a, "\033[F", 3);
171 n = snprintf (buf, sizeof (buf), "\033[%dE", dy);
172 ansi_write (a, buf, n);
176 n = snprintf (buf, sizeof (buf), "\033[%dF", -dy);
177 ansi_write (a, buf, n);
182 n = snprintf (buf, sizeof (buf), "\033[%d;%dH", p.y + 1, p.x + 1);
183 ansi_write (a, buf, n);
188 n = snprintf (buf, sizeof (buf), "\033[%d;%dH", p.y + 1, p.x + 1);
189 ansi_write (a, buf, n);
197 ansi_showhide_cursor (ANSI * a, int hide)
199 if (a->hide_cursor == hide)
204 ansi_write (a, "\033[?25l", 6);
208 ansi_write (a, "\033[?25h", 6);
211 a->hide_cursor = hide;
216 ansi_force_attr_normal (ANSI * a)
218 ansi_write (a, "\033[0m", 4);
219 a->attr = CRT_ATTR_NORMAL;
223 ansi_set_attr (ANSI * a, int attr)
227 dif = attr ^ a->attr;
234 if (attr == CRT_ATTR_NORMAL)
236 ansi_force_attr_normal (a);
240 if (dif & CRT_ATTR_UNDERLINE)
242 if (attr & CRT_ATTR_UNDERLINE)
244 ansi_write (a, "\033[4m", 4);
248 ansi_write (a, "\033[24m", 5);
251 if (dif & CRT_ATTR_REVERSE)
253 if (attr & CRT_ATTR_REVERSE)
255 ansi_write (a, "\033[7m", 4);
259 ansi_write (a, "\033[27m", 5);
262 if (dif & CRT_ATTR_BOLD)
264 if (attr & CRT_ATTR_BOLD)
266 ansi_write (a, "\033[1m", 4);
270 ansi_write (a, "\033[21m", 5);
271 ansi_write (a, "\033[22m", 5);
279 ansi_render (ANSI * a, CRT_CA ca)
288 ansi_set_attr (a, ca.attr);
290 ansi_write (a, &ca.chr, 1);
294 /*Can't easily wrap round here as don't know size of destination screen*/
295 /*so invalidate the cached cursor position*/
297 if (a->pos.x >= CRT_COLS)
298 a->pos.x = ANSI_INVAL;
309 ansi_force_attr_normal (a);
311 ansi_write (a, "\033[2J", 4);
312 /*different emulators leave cursor in different places after cls differently*/
313 a->pos.x = ANSI_INVAL;
318 ansi_draw (ANSI * a, CRT * c)
322 int hidden_cursor = 0;
324 for (p.y = 0; p.y < CRT_ROWS; ++p.y)
326 if (p.y >= a->size.y)
328 o = CRT_ADDR (p.y, 0);
329 for (p.x = 0; p.x < CRT_COLS; ++p.x, ++o)
331 if (p.x >= a->size.x)
333 if (crt_ca_cmp (a->crt.screen[o], c->screen[o]))
335 ansi_showhide_cursor (a, 1);
336 a->crt.screen[o] = c->screen[o];
339 ansi_render (a, a->crt.screen[o]);
345 if ((CRT_COLS > a->size.x) || (CRT_ROWS > a->size.y))
347 char msg[] = "Window is too small";
351 ansi_showhide_cursor (a, 1);
352 ansi_set_attr (a, CRT_ATTR_REVERSE);
355 ansi_write (a, msg, sizeof (msg));
356 a->pos.x = ANSI_INVAL;
360 if ((c->pos.x >= a->size.x) || (c->pos.y >= a->size.y))
362 ansi_showhide_cursor (a, 1);
367 ansi_move (a, a->crt.pos);
369 a->crt.hide_cursor = c->hide_cursor;
370 ansi_showhide_cursor (a, a->crt.hide_cursor);
374 ansi_reset (ANSI * a)
376 // FIXME: -- echos back crap?
377 // ansi_write (a, "\033[c", 3);
380 a->pos.x = ANSI_INVAL;
381 a->hide_cursor = ANSI_INVAL;
386 ansi_write (a, "\033=", 2);
387 ansi_draw (a, &a->crt);
391 ansi_flush_escape (ANSI * a, VT102 * v)
393 ANSI_Parser *p = &a->parser;
396 for (i = 0; i < p->escape_ptr; ++i)
398 vt102_send (v, p->escape_buf[i]);
406 ansi_parse_deckey (ANSI * a, VT102 * v)
408 ANSI_Parser *p = &a->parser;
409 if ((p->escape_buf[1] != '[') && (p->escape_buf[1] != 'O'))
411 ansi_flush_escape (a, v);
415 if ((p->escape_buf[2] >= 'A') || (p->escape_buf[2] <= 'Z'))
417 vt102_send (v, KEY_UP + (p->escape_buf[2] - 'A'));
419 else if ((p->escape_buf[2] >= 'a') || (p->escape_buf[2] <= 'z'))
421 vt102_send (v, KEY_154 + (p->escape_buf[2] - 'a'));
425 ansi_flush_escape (a, v);
433 ansi_parse_ansikey (ANSI * a, VT102 * v)
435 ANSI_Parser *p = &a->parser;
437 if ((p->escape_buf[1] != '[') || (p->escape_buf[3] != '~'))
439 ansi_flush_escape (a, v);
442 if ((p->escape_buf[2] >= '0') || (p->escape_buf[2] <= '9'))
444 vt102_send (v, KEY_180 + (p->escape_buf[2] - '0'));
448 ansi_flush_escape (a, v);
459 ansi_parse_escape (ANSI * a, VT102 * v)
461 ANSI_Parser *p = &a->parser;
462 switch (p->escape_ptr)
468 switch (p->escape_buf[1])
474 ansi_flush_escape (a, v);
478 switch (p->escape_buf[1])
481 ansi_parse_deckey (a, v);
484 if ((p->escape_buf[2] >= 'A') && (p->escape_buf[2] <= 'Z'))
485 ansi_parse_deckey (a, v);
488 ansi_flush_escape (a, v);
492 switch (p->escape_buf[1])
495 ansi_parse_ansikey (a, v);
498 ansi_flush_escape (a, v);
502 ansi_flush_escape (a, v);
508 ansi_check_escape (ANSI * a, VT102 * v)
510 ANSI_Parser *p = &a->parser;
511 struct timeval now, diff;
512 gettimeofday (&now, NULL);
513 timersub (&now, &p->last_escape, &diff);
516 fprintf (stderr, "ie %d tl %d.%06d eb %d\n",
517 p->in_escape, diff.tv_sec, diff.tv_usec, p->escape_ptr);
525 if (diff.tv_sec || (diff.tv_usec > ANSI_ESCAPE_TIMEOUT))
526 ansi_flush_escape (a, v);
532 ansi_parse_char (ANSI * a, int c, VT102 * v)
534 ANSI_Parser *p = &a->parser;
537 /*See if it's time to flush the escape*/
538 ansi_check_escape (a, v);
543 ansi_flush_escape (a, v);
547 gettimeofday (&p->last_escape, NULL);
552 p->escape_buf[p->escape_ptr++] = c;
553 ansi_parse_escape (a, v);
563 ansi_parse (ANSI * a, char *buf, int len, VT102 * v)
566 ansi_parse_char (a, *(buf++), v);
570 ansi_dispatch (ANSI * a, VT102 * v)
575 ansi_check_escape (a, v);
578 red = ansi_read (a, buf, sizeof (buf));
585 ansi_parse (a, buf, red, v);