diff options
author | james <> | 2008-02-07 00:39:13 +0000 |
---|---|---|
committer | james <> | 2008-02-07 00:39:13 +0000 |
commit | 10e44cc4a65158fb6aaab3428a747ad4e5ead2f9 (patch) | |
tree | 2aef7fd3972bd6a8b67ee264c2b8c4b73e03e615 /src/ansi.c | |
parent | b4c47719823e9907f6040e1e899b927cbeb8282e (diff) | |
download | sympathy-10e44cc4a65158fb6aaab3428a747ad4e5ead2f9.tar.gz sympathy-10e44cc4a65158fb6aaab3428a747ad4e5ead2f9.tar.bz2 sympathy-10e44cc4a65158fb6aaab3428a747ad4e5ead2f9.zip |
*** empty log message ***
Diffstat (limited to 'src/ansi.c')
-rw-r--r-- | src/ansi.c | 194 |
1 files changed, 189 insertions, 5 deletions
@@ -10,6 +10,9 @@ static char rcsid[] = "$Id$"; /* * $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 *** * @@ -34,9 +37,45 @@ 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); } @@ -338,12 +377,154 @@ 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) +{ +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) { -vt102_send(v,c); +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) @@ -357,12 +538,15 @@ int ansi_dispatch(ANSI *a,VT102 *v) char buf[1024]; int red; -red=read(a.fd,buf,sizeof(buf)); -if (red<0) return -1; -if (!red) return -1; +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; } -int |