/*
* $Log$
+ * 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 ***
*
*/
#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);
}
}
else
{
+ ansi_write (a, "\033[21m", 5);
ansi_write (a, "\033[22m", 5);
}
}
{
CRT_Pos p;
int o;
-
- ansi_showhide_cursor (a, 1);
+ int hidden_cursor = 0;
for (p.y = 0; p.y < CRT_ROWS; ++p.y)
{
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);
}
}
+
+ 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_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);
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)
+{
+ANSI_Parser *p=&a->parser;
+int i;
+
+for (i=0;i<p->escape_ptr;++i) {
+vt102_send(v,p->escape_buf[i]);
+}
+
+p->escape_ptr=0;
+p->in_escape=0;
+}
+
+void ansi_parse_deckey(ANSI *a,VT102 *v)
+{
+ANSI_Parser *p=&a->parser;
+if ((p->escape_buf[1]!='[') && (p->escape_buf[1]!='O')) {
+ ansi_flush_escape(a,v);
+ return;
+}
+
+if ((p->escape_buf[2]>='A') || (p->escape_buf[2]<='Z')){
+ vt102_send(v,KEY_UP+(p->escape_buf[2]-'A'));
+}else if ((p->escape_buf[2]>='a') || (p->escape_buf[2]<='z')){
+ vt102_send(v,KEY_154+(p->escape_buf[2]-'a'));
+} else {
+ ansi_flush_escape(a,v);
+ return;
+}
+p->in_escape=0;
+p->escape_ptr=0;
+}
+
+void ansi_parse_ansikey(ANSI *a,VT102 *v)
+{
+ANSI_Parser *p=&a->parser;
+
+if ((p->escape_buf[1]!='[') ||(p->escape_buf[3]!='~')) {
+ ansi_flush_escape(a,v);
+ return;
+}
+if ((p->escape_buf[2]>='0') || (p->escape_buf[2]<='9')){
+ vt102_send(v,KEY_180+(p->escape_buf[2]-'0'));
+} else {
+ ansi_flush_escape(a,v);
+ return;
+}
+
+p->in_escape=0;
+p->escape_ptr=0;
+}
+
+
+
+void ansi_parse_escape(ANSI *a,VT102 *v)
+{
+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);
+ }
+ break;
+case 3:
+ switch(p->escape_buf[1]) {
+ case 'O':
+ ansi_parse_deckey(a,v);
+ break;
+ case '[':
+ if ((p->escape_buf[2]>='A') &&
+ (p->escape_buf[2]<='Z'))
+ ansi_parse_deckey(a,v);
+ break;
+ default:
+ ansi_flush_escape(a,v);
+ }
+ break;
+case 4:
+ switch(p->escape_buf[1]) {
+ case '[':
+ ansi_parse_ansikey(a,v);
+ break;
+ default:
+ ansi_flush_escape(a,v);
+ }
+ break;
+case 5:
+ ansi_flush_escape(a,v);
+}
+}
+
+
+void ansi_check_escape(ANSI *a,VT102 *v)
+{
+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);
+
+}
+
+
+void ansi_parse_char(ANSI *a,int c,VT102 *v)
+{
+ANSI_Parser *p=&a->parser;
+
+
+/*See if it's time to flush the escape*/
+ansi_check_escape(a,v);
+
+if (c==033) {
+ if (p->in_escape)
+ ansi_flush_escape(a,v);
+
+ 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);
+} else {
+ vt102_send(v,c);
+}
+
+}
+
+void ansi_parse(ANSI *a,char *buf,int len,VT102 *v)
+{
+while (len--)
+ansi_parse_char(a,*(buf++),v);
+}
+
+int ansi_dispatch(ANSI *a,VT102 *v)
+{
+char buf[1024];
+int red;
+
+ansi_check_escape(a,v);
+
+
+red=ansi_read(a,buf,sizeof(buf));
+if (red<=0) return red;
+
+if (*buf==3) return -1;
+
+ansi_parse(a,buf,red,v);
+
+return 0;
+}