diff options
author | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
---|---|---|
committer | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
commit | e5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch) | |
tree | d8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/cmd/vt |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/vt')
-rwxr-xr-x | sys/src/cmd/vt/cons.h | 89 | ||||
-rwxr-xr-x | sys/src/cmd/vt/consctl.c | 71 | ||||
-rwxr-xr-x | sys/src/cmd/vt/event.c | 70 | ||||
-rwxr-xr-x | sys/src/cmd/vt/event.h | 13 | ||||
-rwxr-xr-x | sys/src/cmd/vt/hp.c | 212 | ||||
-rwxr-xr-x | sys/src/cmd/vt/main.c | 875 | ||||
-rwxr-xr-x | sys/src/cmd/vt/mkfile | 18 | ||||
-rwxr-xr-x | sys/src/cmd/vt/termcap | 5 | ||||
-rwxr-xr-x | sys/src/cmd/vt/vt.c | 943 |
9 files changed, 2296 insertions, 0 deletions
diff --git a/sys/src/cmd/vt/cons.h b/sys/src/cmd/vt/cons.h new file mode 100755 index 000000000..436ef6366 --- /dev/null +++ b/sys/src/cmd/vt/cons.h @@ -0,0 +1,89 @@ +/* console state (for consctl) */ +typedef struct Consstate Consstate; +struct Consstate{ + int raw; + int hold; +}; + +extern Consstate* consctl(void); +extern Consstate* cs; + +#define XMARGIN 5 /* inset from border of layer */ +#define YMARGIN 5 +#define INSET 3 +#define BUFS 32 +#define HISTSIZ 4096 /* number of history characters */ +#define BSIZE 1000 + +#define SCROLL 2 +#define NEWLINE 1 +#define OTHER 0 + +#define COOKED 0 +#define RAW 1 + +/* text attributes */ +enum { + THighIntensity = (1<<0), + TUnderline = (1<<1), + TBlink = (1<<2), + TReverse = (1<<3), + TInvisible = (1<<4), +}; + + +#define button2() ((mouse.buttons & 07)==2) +#define button3() ((mouse.buttons & 07)==4) + +struct ttystate { + int crnl; + int nlcr; +}; +extern struct ttystate ttystate[]; + +#define NKEYS 32 /* max key definitions */ +struct funckey { + char *name; + char *sequence; +}; +extern struct funckey *fk; +extern struct funckey vt100fk[], vt220fk[], ansifk[], xtermfk[]; + +extern int x, y, xmax, ymax, olines; +extern int peekc, attribute; +extern char* term; + +extern void emulate(void); +extern int host_avail(void); +extern void clear(Rectangle); +extern void newline(void); +extern int get_next_char(void); +extern void ringbell(void); +extern int number(char *, int *); +extern void scroll(int,int,int,int); +extern void backup(int); +extern void sendnchars(int, char *); +extern void sendnchars2(int, char *); +extern Point pt(int, int); +extern void funckey(int); +extern void drawstring(Point, char*, int); + +extern int debug; +extern int yscrmin, yscrmax; +extern int attr; +extern int defattr; + +extern Image *fgcolor; +extern Image *bgcolor; +extern Image *colors[]; +extern Image *hicolors[]; +extern Image *bgdefault; +extern Image *fgdefault; + +extern int cursoron; +extern int nocolor; + +extern void curson(int); +extern void cursoff(void); +extern void setdim(int, int); + diff --git a/sys/src/cmd/vt/consctl.c b/sys/src/cmd/vt/consctl.c new file mode 100755 index 000000000..525bbb664 --- /dev/null +++ b/sys/src/cmd/vt/consctl.c @@ -0,0 +1,71 @@ +#include <u.h> +#include <libc.h> +#include <draw.h> +#include "cons.h" + +/* + * bind a pipe onto consctl and keep reading it to + * get changes to console state. + */ +Consstate* +consctl(void) +{ + int i, n, fd, tries; + char buf[128]; + Consstate *x; + char *field[10]; + + x = segattach(0, "shared", 0, sizeof *x); + if(x == (void*)-1) + sysfatal("segattach: %r"); + + /* a pipe to simulate consctl */ + if(bind("#|", "/mnt/cons/consctl", MBEFORE) < 0 + || bind("/mnt/cons/consctl/data1", "/dev/consctl", MREPL) < 0) + sysfatal("bind consctl: %r"); + + /* a pipe to simulate the /dev/cons */ + if(bind("#|", "/mnt/cons/cons", MREPL) < 0 + || bind("/mnt/cons/cons/data1", "/dev/cons", MREPL) < 0) + sysfatal("bind cons: %r"); + + switch(fork()){ + case -1: + sysfatal("fork: %r"); + case 0: + break; + default: + return x; + } + + notify(0); + + for(tries = 0; tries < 100; tries++){ + x->raw = 0; + x->hold = 0; + fd = open("/mnt/cons/consctl/data", OREAD); + if(fd < 0) + break; + tries = 0; + for(;;){ + n = read(fd, buf, sizeof(buf)-1); + if(n <= 0) + break; + buf[n] = 0; + n = getfields(buf, field, 10, 1, " "); + for(i = 0; i < n; i++){ + if(strcmp(field[i], "rawon") == 0) + x->raw = 1; + else if(strcmp(field[i], "rawoff") == 0) + x->raw = 0; + else if(strcmp(field[i], "holdon") == 0) + x->hold = 1; + else if(strcmp(field[i], "holdoff") == 0) + x->hold = 0; + } + } + close(fd); + } + exits(0); + return 0; /* dummy to keep compiler quiet*/ +} diff --git a/sys/src/cmd/vt/event.c b/sys/src/cmd/vt/event.c new file mode 100755 index 000000000..12f1f0e43 --- /dev/null +++ b/sys/src/cmd/vt/event.c @@ -0,0 +1,70 @@ +#include <u.h> +#include <libc.h> +#include <draw.h> +#include <event.h> +#include "cons.h" + +#define BUFSIZ 4000 + +extern int outfd; + +int hostpid; + +void +edie(void) +{ + static int dead = 0; + + if(dead++ > 0) return; + close(outfd); + postnote(PNGROUP, getpid(), "exit"); +} + +static int +start_host(void) +{ + int fd; + + cs = consctl(); + + switch((hostpid = rfork(RFPROC|RFNAMEG|RFFDG|RFNOTEG))) { + case 0: + fd = open("/dev/cons", OREAD); + dup(fd,0); + if(fd != 0) + close(fd); + fd = open("/dev/cons", OWRITE); + dup(fd,1); + dup(fd,2); + if(fd != 1 && fd !=2) + close(fd); + execl("/bin/rc","rcX",nil); + fprint(2,"failed to start up rc\n"); + _exits("rc"); + case -1: + fprint(2,"rc startup: fork error\n"); + _exits("rc_fork"); + } + + return open("/mnt/cons/cons/data", ORDWR); +} + +void +ebegin(int Ehost) +{ + + atexit(edie); + + einit(Emouse|Ekeyboard); + + outfd = start_host(); + if( estart(Ehost, outfd, BUFSIZ) != Ehost) { + exits("event init error"); + } +} + +void +send_interrupt(void) +{ + postnote(PNGROUP, hostpid,"interrupt"); +} diff --git a/sys/src/cmd/vt/event.h b/sys/src/cmd/vt/event.h new file mode 100755 index 000000000..baa108623 --- /dev/null +++ b/sys/src/cmd/vt/event.h @@ -0,0 +1,13 @@ +#define BSIZE 4000 +#define MOUSE 0 +#define KBD 1 +#define HOST 2 +#define HOST_BLOCKED 1 +#define KBD_BLOCKED 2 + +typedef struct IOEvent { + short key; + short size; + uchar data[BSIZE]; +} IOEvent; + diff --git a/sys/src/cmd/vt/hp.c b/sys/src/cmd/vt/hp.c new file mode 100755 index 000000000..cfca3033e --- /dev/null +++ b/sys/src/cmd/vt/hp.c @@ -0,0 +1,212 @@ +#include <u.h> +#include <libc.h> +#include <ndraw.h> +#include <bio.h> +#include "cons.h" + +char *term = "2621"; + +struct funckey fk[32]; + +void +emulate(void) +{ + char buf[BUFS+1]; + int n; + int c; + int standout = 0; + int insmode = 0; + + for (;;) { + if (x > xmax || y > ymax) { + x = 0; + newline(); + } + buf[0] = get_next_char(); + buf[1] = '\0'; + switch(buf[0]) { + + case '\000': /* nulls, just ignore 'em */ + break; + + case '\007': /* bell */ + ringbell(); + break; + + case '\t': /* tab modulo 8 */ + x = (x|7)+1; + break; + + case '\033': + switch(get_next_char()) { + + case 'j': + get_next_char(); + break; + + case '&': /* position cursor &c */ + switch(get_next_char()) { + + case 'a': + for (;;) { + n = number(buf, nil); + switch(buf[0]) { + + case 'r': + case 'y': + y = n; + continue; + + case 'c': + x = n; + continue; + + case 'R': + case 'Y': + y = n; + break; + + case 'C': + x = n; + break; + } + break; + } + break; + + case 'd': /* underline stuff */ + if ((n=get_next_char())>='A' && n <= 'O') + standout++; + else if (n == '@') + standout = 0; + break; + + default: + get_next_char(); + break; + + } + break; + + case 'i': /* back tab */ + if (x>0) + x = (x-1) & ~07; + break; + + case 'H': /* home cursor */ + case 'h': + x = 0; + y = 0; + break; + + case 'L': /* insert blank line */ + scroll(y, ymax, y+1, y); + break; + + case 'M': /* delete line */ + scroll(y+1, ymax+1, y, ymax); + break; + + case 'J': /* clear to end of display */ + xtipple(Rpt(pt(0, y+1), + pt(xmax+1, ymax+1))); + /* flow */ + case 'K': /* clear to EOL */ + xtipple(Rpt(pt(x, y), + pt(xmax+1, y+1))); + break; + + case 'P': /* delete char */ + bitblt(&screen, pt(x, y), + &screen, Rpt(pt(x+1, y), + pt(xmax+1, y+1)), + S); + xtipple(Rpt(pt(xmax, y), + pt(xmax+1, y+1))); + break; + + case 'Q': /* enter insert mode */ + insmode++; + break; + + case 'R': /* leave insert mode */ + insmode = 0; + break; + + case 'S': /* roll up */ + scroll(1, ymax+1, 0, ymax); + break; + + case 'T': + scroll(0, ymax, 1, 0); + break; + + case 'A': /* upline */ + case 't': + if (y>0) + y--; + if (olines > 0) + olines--; + break; + + case 'B': + case 'w': + y++; /* downline */ + break; + + case 'C': /* right */ + case 'v': + x++; + break; + + case 'D': /* left */ + case 'u': + x--; + + } + break; + + case '\b': /* backspace */ + if(x > 0) + --x; + break; + + case '\n': /* linefeed */ + newline(); + standout = 0; + if( ttystate[cs->raw].nlcr ) + x = 0; + break; + + case '\r': /* carriage return */ + x = 0; + standout = 0; + if( ttystate[cs->raw].crnl ) + newline(); + break; + + default: /* ordinary char */ + n = 1; + c = 0; + while (!cs->raw && host_avail() && x+n<=xmax && n<BUFS + && (c = get_next_char())>=' ' && c<'\177') { + buf[n++] = c; + c = 0; + } + buf[n] = 0; + if (insmode) { + bitblt(&screen, pt(x+n, y), &screen, + Rpt(pt(x, y), pt(xmax-n+1, y+1)), S); + } + xtipple(Rpt(pt(x,y), pt(x+n, y+1))); + string(&screen, pt(x, y), font, buf, DxorS); + if (standout) + rectf(&screen, + Rpt(pt(x,y),pt(x+n,y+1)), + DxorS); + x += n; + peekc = c; + break; + } + } +} diff --git a/sys/src/cmd/vt/main.c b/sys/src/cmd/vt/main.c new file mode 100755 index 000000000..a342a8984 --- /dev/null +++ b/sys/src/cmd/vt/main.c @@ -0,0 +1,875 @@ +#include <u.h> +#include <libc.h> +#include <draw.h> +#include <event.h> +#include <bio.h> +#include <keyboard.h> +#include "cons.h" + +enum{ + Ehost = 4, +}; + +char *menutext2[] = { + "backup", + "forward", + "reset", + "clear", + "send", + "page", + 0 +}; + +char *menutext3[] = { + "24x80", + "crnl", + "nl", + "raw", + "exit", + 0 +}; + +/* variables associated with the screen */ + +int x, y; /* character positions */ +char *backp; +int backc; +int atend; +int nbacklines; +int xmax, ymax; +int blocked; +int resize_flag; +int pagemode; +int olines; +int peekc; +int cursoron = 1; +Menu menu2; +Menu menu3; +char *histp; +char hist[HISTSIZ]; +int yscrmin, yscrmax; +int attr, defattr; +int wctlout; + +Image *bordercol; +Image *cursback; +Image *colors[8]; +Image *hicolors[8]; +Image *red; +Image *fgcolor; +Image *bgcolor; +Image *fgdefault; +Image *bgdefault; + +uint rgbacolors[8] = { + 0x000000FF, /* black */ + 0xAA0000FF, /* red */ + 0x00AA00FF, /* green */ + 0xFF5500FF, /* brown */ + 0x0000FFFF, /* blue */ + 0xAA00AAFF, /* purple */ + 0x00AAAAFF, /* cyan */ + 0x7F7F7FFF, /* white */ +}; + +ulong rgbahicolors[8] = { + 0x555555FF, /* light black aka grey */ + 0xFF5555FF, /* light red */ + 0x55FF55FF, /* light green */ + 0xFFFF55FF, /* light brown aka yellow */ + 0x5555FFFF, /* light blue */ + 0xFF55FFFF, /* light purple */ + 0x55FFFFFF, /* light cyan */ + 0xFFFFFFFF, /* light grey aka white */ +}; + +/* terminal control */ +struct ttystate ttystate[2] = { {0, 1}, {0, 1} }; + +int NS; +int CW; +Consstate *cs; +Mouse mouse; + +int debug; +int nocolor; +int logfd = -1; +int outfd = -1; +Biobuf *snarffp = 0; + +char *host_buf; +char *hostp; /* input from host */ +int host_bsize = 2*BSIZE; +int hostlength; /* amount of input from host */ +char echo_input[BSIZE]; +char *echop = echo_input; /* characters to echo, after canon */ +char sendbuf[BSIZE]; /* hope you can't type ahead more than BSIZE chars */ +char *sendp = sendbuf; + +char *term; +struct funckey *fk; + +/* functions */ +void initialize(int, char **); +void ebegin(int); +int waitchar(void); +int rcvchar(void); +void set_input(char *); +void set_host(Event *); +void bigscroll(void); +void readmenu(void); +void eresized(int); +void resize(void); +void send_interrupt(void); +int alnum(int); +void escapedump(int,uchar *,int); + +void +main(int argc, char **argv) +{ + initialize(argc, argv); + emulate(); +} + +void +usage(void) +{ + fprint(2, "usage: %s [-2abcx] [-f font] [-l logfile]\n", argv0); + exits("usage"); +} + +void +initialize(int argc, char **argv) +{ + int i, blkbg; + char *fontname, *p; + + rfork(RFNAMEG|RFNOTEG); + + fontname = nil; + term = "vt100"; + fk = vt100fk; + blkbg = nocolor = 0; + ARGBEGIN{ + case '2': + term = "vt220"; + fk = vt220fk; + break; + case 'a': + term = "ansi"; + fk = ansifk; + break; + case 'b': + blkbg = 1; /* e.g., for linux colored output */ + break; + case 'c': + nocolor = 1; + break; + case 'f': + fontname = EARGF(usage()); + break; + case 'l': + p = EARGF(usage()); + logfd = create(p, OWRITE, 0666); + if(logfd < 0) + sysfatal("could not create log file: %s: %r", p); + break; + case 'x': + fk = xtermfk; + term = "xterm"; + break; + default: + usage(); + break; + }ARGEND; + + host_buf = malloc(host_bsize); + hostp = host_buf; + hostlength = 0; + + if(initdraw(0, fontname, term) < 0){ + fprint(2, "%s: initdraw failed: %r\n", term); + exits("initdraw"); + } + werrstr(""); /* clear spurious error messages */ + ebegin(Ehost); + + histp = hist; + menu2.item = menutext2; + menu3.item = menutext3; + pagemode = 0; + blocked = 0; + NS = font->height; + CW = stringwidth(font, "m"); + + red = allocimage(display, Rect(0,0,1,1), screen->chan, 1, DRed); + bordercol = allocimage(display, Rect(0,0,1,1), screen->chan, 1, 0xCCCCCCCC); + cursback = allocimage(display, Rect(0, 0, CW+1, NS+1), screen->chan, 0, DNofill); + + for(i=0; i<8; i++){ + colors[i] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, + rgbacolors[i]); + hicolors[i] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, + rgbahicolors[i]); + } + + bgdefault = (blkbg? display->black: display->white); + fgdefault = (blkbg? display->white: display->black); + bgcolor = bgdefault; + fgcolor = fgdefault; + + resize(); + + if(argc > 0) { + sendnchars(strlen(argv[0]),argv[0]); + sendnchars(1,"\n"); + } +} + +void +clear(Rectangle r) +{ + draw(screen, r, bgcolor, nil, ZP); +} + +void +newline(void) +{ + nbacklines--; + if(y >= yscrmax) { + y = yscrmax; + if(pagemode && olines >= yscrmax) { + blocked = 1; + return; + } + scroll(yscrmin+1, yscrmax+1, yscrmin, yscrmax); + } else + y++; + olines++; +} + +void +cursoff(void) +{ + draw(screen, Rpt(pt(x, y), addpt(pt(x, y), Pt(CW,NS))), + cursback, nil, cursback->r.min); +} + +void +curson(int bl) +{ + Image *col; + + if(!cursoron){ + cursoff(); + return; + } + + draw(cursback, cursback->r, screen, nil, pt(x, y)); + if(bl) + col = red; + else + col = bordercol; + border(screen, Rpt(pt(x, y), addpt(pt(x, y), Pt(CW,NS))), 2, col, ZP); +} + +int +get_next_char(void) +{ + int c = peekc; + uchar buf[1]; + peekc = 0; + if(c > 0) + return(c); + while(c <= 0) { + if(backp) { + c = *backp; + if(c && nbacklines >= 0) { + backp++; + if(backp >= &hist[HISTSIZ]) + backp = hist; + return(c); + } + backp = 0; + } + c = (uchar)waitchar(); + if(c > 0 && logfd >= 0) { + buf[0] = c; + write(logfd, buf, 1); + } + } + *histp++ = c; + if(histp >= &hist[HISTSIZ]) + histp = hist; + *histp = '\0'; + return(c); +} + +int +canon(char *ep, int c) +{ + if(c&0200) + return(SCROLL); + switch(c) { + case '\b': + if(sendp > sendbuf) + sendp--; + *ep++ = '\b'; + *ep++ = ' '; + *ep++ = '\b'; + break; + case 0x15: /* ^U line kill */ + sendp = sendbuf; + *ep++ = '^'; + *ep++ = 'U'; + *ep++ = '\n'; + break; + case 0x17: /* ^W word kill */ + while(sendp > sendbuf && !alnum(*sendp)) { + *ep++ = '\b'; + *ep++ = ' '; + *ep++ = '\b'; + sendp--; + } + while(sendp > sendbuf && alnum(*sendp)) { + *ep++ = '\b'; + *ep++ = ' '; + *ep++ = '\b'; + sendp--; + } + break; + case '\177': /* interrupt */ + sendp = sendbuf; + send_interrupt(); + return(NEWLINE); + case '\021': /* quit */ + case '\r': + case '\n': + if(sendp < &sendbuf[512]) + *sendp++ = '\n'; + sendnchars((int)(sendp-sendbuf), sendbuf); + sendp = sendbuf; + if(c == '\n' || c == '\r') { + *ep++ = '\n'; + } + *ep = 0; + return(NEWLINE); + case '\004': /* EOT */ + if(sendp == sendbuf) { + sendnchars(0,sendbuf); + *ep = 0; + return(NEWLINE); + } + /* fall through */ + default: + if(sendp < &sendbuf[512]) + *sendp++ = c; + *ep++ = c; + break; + + } + *ep = 0; + return(OTHER); +} + +void +sendfk(char *name) +{ + int i; + static int fd; + + for(i=0; fk[i].name; i++) + if(strcmp(name, fk[i].name)==0){ + sendnchars2(strlen(fk[i].sequence), fk[i].sequence); + return; + } +} + +int +waitchar(void) +{ + Event e; + int c; + char c2; + int newmouse; + int wasblocked; + int kbdchar = -1; + char echobuf[3*BSIZE]; + static int lastc = -1; + + + for(;;) { + if(resize_flag) + resize(); + wasblocked = blocked; + if(backp) + return(0); + if(ecanmouse() && (button2() || button3())) + readmenu(); + if(snarffp) { + if((c = Bgetc(snarffp)) < 0) { + if(lastc != '\n') + write(outfd,"\n",1); + Bterm(snarffp); + snarffp = 0; + if(lastc != '\n') { + lastc = -1; + return('\n'); + } + lastc = -1; + continue; + } + lastc = c; + c2 = c; + write(outfd, &c2, 1); + return(c); + } + if(!blocked && host_avail()) + return(rcvchar()); + if(kbdchar > 0) { + if(blocked) + resize(); + if(cs->raw) { + switch(kbdchar){ + case Kup: + sendfk("up key"); + break; + case Kdown: + sendfk("down key"); + break; + case Kleft: + sendfk("left key"); + break; + case Kright: + sendfk("right key"); + break; + case Kpgup: + sendfk("page up"); + break; + case Kpgdown: + sendfk("page down"); + break; + case KF|1: + sendfk("F1"); + break; + case KF|2: + sendfk("F2"); + break; + case KF|3: + sendfk("F3"); + break; + case KF|4: + sendfk("F4"); + break; + case KF|5: + sendfk("F5"); + break; + case KF|6: + sendfk("F6"); + break; + case KF|7: + sendfk("F7"); + break; + case KF|8: + sendfk("F8"); + break; + case KF|9: + sendfk("F9"); + break; + case KF|10: + sendfk("F10"); + break; + case KF|11: + sendfk("F11"); + break; + case KF|12: + sendfk("F12"); + break; + case '\n': + echobuf[0] = '\r'; + sendnchars(1, echobuf); + break; + case '\r': + echobuf[0] = '\n'; + sendnchars(1, echobuf); + break; + default: + echobuf[0] = kbdchar; + sendnchars(1, echobuf); + break; + } + } else if(canon(echobuf,kbdchar) == SCROLL) { + if(!blocked) + bigscroll(); + } else + strcat(echo_input,echobuf); + blocked = 0; + kbdchar = -1; + continue; + } + curson(wasblocked); /* turn on cursor while we're waiting */ + do { + newmouse = 0; + switch(eread(blocked ? Emouse|Ekeyboard : + Emouse|Ekeyboard|Ehost, &e)) { + case Emouse: + mouse = e.mouse; + if(button2() || button3()) + readmenu(); + else if(resize_flag == 0) { + /* eresized() is triggered by special mouse event */ + newmouse = 1; + } + break; + case Ekeyboard: + kbdchar = e.kbdc; + break; + case Ehost: + set_host(&e); + break; + default: + perror("protocol violation"); + exits("protocol violation"); + } + } while(newmouse == 1); + cursoff(); /* turn cursor back off */ + } +} + +void +eresized(int new) +{ + resize_flag = 1+new; +} + +void +putenvint(char *name, int x) +{ + char buf[20]; + + snprint(buf, sizeof buf, "%d", x); + putenv(name, buf); +} + +void +exportsize(void) +{ + putenvint("XPIXELS", Dx(screen->r)-2*XMARGIN); + putenvint("YPIXELS", Dy(screen->r)-2*XMARGIN); + putenvint("LINES", ymax+1); + putenvint("COLS", xmax+1); + putenv("TERM", term); +} + +void +resize(void) +{ + if(resize_flag > 1 && getwindow(display, Refnone) < 0){ + fprint(2, "can't reattach to window: %r\n"); + exits("can't reattach to window"); + } + xmax = (Dx(screen->r)-2*XMARGIN)/CW-1; + ymax = (Dy(screen->r)-2*YMARGIN)/NS-1; + if(xmax == 0 || ymax == 0) + exits("window gone"); + x = 0; + y = 0; + yscrmin = 0; + yscrmax = ymax; + olines = 0; + exportsize(); + clear(screen->r); + resize_flag = 0; + werrstr(""); /* clear spurious error messages */ +} + +void +setdim(int ht, int wid) +{ + int fd; + Rectangle r; + + if(ht != -1) + ymax = ht-1; + if(wid != -1) + xmax = wid-1; + + r.min = screen->r.min; + r.max = addpt(screen->r.min, + Pt((xmax+1)*CW+2*XMARGIN+2*INSET, + (ymax+1)*NS+2*YMARGIN+2*INSET)); + fd = open("/dev/wctl", OWRITE); + if(fd < 0 || fprint(fd, "resize -dx %d -dy %d\n", Dx(r)+2*Borderwidth, + Dy(r)+2*Borderwidth) < 0){ + border(screen, r, INSET, bordercol, ZP); + exportsize(); + } + if(fd >= 0) + close(fd); +} + +void +readmenu(void) +{ + if(button3()) { + menu3.item[1] = ttystate[cs->raw].crnl ? "cr" : "crnl"; + menu3.item[2] = ttystate[cs->raw].nlcr ? "nl" : "nlcr"; + menu3.item[3] = cs->raw ? "cooked" : "raw"; + + switch(emenuhit(3, &mouse, &menu3)) { + case 0: /* 24x80 */ + setdim(24, 80); + return; + case 1: /* newline after cr? */ + ttystate[cs->raw].crnl = !ttystate[cs->raw].crnl; + return; + case 2: /* cr after newline? */ + ttystate[cs->raw].nlcr = !ttystate[cs->raw].nlcr; + return; + case 3: /* switch raw mode */ + cs->raw = !cs->raw; + return; + case 4: + exits(0); + } + return; + } + + menu2.item[5] = pagemode? "scroll": "page"; + + switch(emenuhit(2, &mouse, &menu2)) { + + case 0: /* back up */ + if(atend == 0) { + backc++; + backup(backc); + } + return; + + case 1: /* move forward */ + backc--; + if(backc >= 0) + backup(backc); + else + backc = 0; + return; + + case 2: /* reset */ + backc = 0; + backup(0); + return; + + case 3: /* clear screen */ + eresized(0); + return; + + case 4: /* send the snarf buffer */ + snarffp = Bopen("/dev/snarf",OREAD); + return; + + case 5: /* pause and clear at end of screen */ + pagemode = 1-pagemode; + if(blocked && !pagemode) { + eresized(0); + blocked = 0; + } + return; + } +} + +void +backup(int count) +{ + register n; + register char *cp; + + eresized(0); + n = 3*(count+1)*ymax/4; + cp = histp; + atend = 0; + while (n >= 0) { + cp--; + if(cp < hist) + cp = &hist[HISTSIZ-1]; + if(*cp == '\0') { + atend = 1; + break; + } + if(*cp == '\n') + n--; + } + cp++; + if(cp >= &hist[HISTSIZ]) + cp = hist; + backp = cp; + nbacklines = ymax-2; +} + +Point +pt(int x, int y) +{ + return addpt(screen->r.min, Pt(x*CW+XMARGIN,y*NS+YMARGIN)); +} + +void +scroll(int sy, int ly, int dy, int cy) /* source, limit, dest, which line to clear */ +{ + draw(screen, Rpt(pt(0, dy), pt(xmax+1, dy+ly-sy)), screen, nil, pt(0, sy)); + clear(Rpt(pt(0, cy), pt(xmax+1, cy+1))); + flushimage(display, 1); +} + +void +bigscroll(void) /* scroll up half a page */ +{ + int half = ymax/3; + + if(x == 0 && y == 0) + return; + if(y < half) { + clear(Rpt(pt(0,0),pt(xmax+1,ymax+1))); + x = y = 0; + return; + } + draw(screen, Rpt(pt(0, 0), pt(xmax+1, ymax+1)), screen, nil, pt(0, half)); + clear(Rpt(pt(0,y-half+1),pt(xmax+1,ymax+1))); + y -= half; + if(olines) + olines -= half; + flushimage(display, 1); +} + +int +number(char *p, int *got) +{ + int c, n = 0; + + if(got) + *got = 0; + while ((c = get_next_char()) >= '0' && c <= '9'){ + if(got) + *got = 1; + n = n*10 + c - '0'; + } + *p = c; + return(n); +} + +/* stubs */ + +void +sendnchars(int n,char *p) +{ + sendnchars2(n, p); + p[n+1] = 0; +} + +void +sendnchars2(int n,char *p) +{ + if(write(outfd,p,n) < 0) { + close(outfd); + close(0); + close(1); + close(2); + exits("write"); + } +} + +int +host_avail(void) +{ + return(*echop || ((hostp - host_buf) < hostlength)); +} + +int +rcvchar(void) +{ + int c; + if(*echop) { + c = *echop++; + if(!*echop) { + echop = echo_input; + *echop = 0; + } + return c; + } + return *hostp++; +} + +void +set_host(Event *e) +{ + hostlength = e->n; + if(hostlength > host_bsize) { + host_bsize *= 2; + host_buf = realloc(host_buf,host_bsize); + } + hostp = host_buf; + memmove(host_buf,e->data,hostlength); + host_buf[hostlength]=0; +} + +void +ringbell(void){ +} + +int +alnum(int c) +{ + if(c >= 'a' && c <= 'z') + return 1; + if(c >= 'A' && c <= 'Z') + return 1; + if(c >= '0' && c <= '9') + return 1; + return 0; +} + +void +escapedump(int fd,uchar *str,int len) +{ + int i; + + for(i = 0; i < len; i++) { + if((str[i] < ' ' || str[i] > '\177') && + str[i] != '\n' && str[i] != '\t') fprint(fd,"^%c",str[i]+64); + else if(str[i] == '\177') fprint(fd,"^$"); + else if(str[i] == '\n') fprint(fd,"^J\n"); + else fprint(fd,"%c",str[i]); + } +} + +void +funckey(int key) +{ + if(key >= NKEYS) + return; + if(fk[key].name == 0) + return; + sendnchars2(strlen(fk[key].sequence), fk[key].sequence); +} + + +void +drawstring(Point p, char *str, int attr) +{ + int i; + Image *txt, *bg, *tmp; + + txt = fgcolor; + bg = bgcolor; + if(attr & TReverse){ + tmp = txt; + txt = bg; + bg = tmp; + } + if(attr & THighIntensity){ + for(i=0; i<8; i++) + if(txt == colors[i]) + txt = hicolors[i]; + } + + draw(screen, Rpt(p, addpt(p, stringsize(font, str))), bg, nil, p); + string(screen, p, txt, ZP, font, str); +} diff --git a/sys/src/cmd/vt/mkfile b/sys/src/cmd/vt/mkfile new file mode 100755 index 000000000..b4cad99d7 --- /dev/null +++ b/sys/src/cmd/vt/mkfile @@ -0,0 +1,18 @@ +</$objtype/mkfile + +#TARG=hp\ +# vt\ +# vt220\ + +TARG=vt + +OFILES=\ + consctl.$O\ + event.$O\ + main.$O\ + vt.$O\ + +HFILES=cons.h + +BIN=/$objtype/bin +</sys/src/cmd/mkone diff --git a/sys/src/cmd/vt/termcap b/sys/src/cmd/vt/termcap new file mode 100755 index 000000000..b1c6ef1aa --- /dev/null +++ b/sys/src/cmd/vt/termcap @@ -0,0 +1,5 @@ +h2|2621|hp2621|hp2621a|hp2621p|2621|2621a|2621p|hp 2621:\ + :is=\E&j@\r\E3\r:bt=\Ei:cm=\E&a%r%dc%dY:dc=2\EP:ip=2:\ + :kh=\Ep\r:ku=\Et\r:kl=\Eu\r:kr=\Ev\r:kd=\Ew\r:\ + :kn#8:k1=\Ep\r:k2=\Eq\r:k3=\Er\r:k4=\Es\r:k5=\Et\r:k6=\Eu\r:k7=\Ev\r:\ + :k8=\Ew\r:ks=\E&jB:ke=\E&j@:ta=2^I:tc=hp: diff --git a/sys/src/cmd/vt/vt.c b/sys/src/cmd/vt/vt.c new file mode 100755 index 000000000..999ead350 --- /dev/null +++ b/sys/src/cmd/vt/vt.c @@ -0,0 +1,943 @@ +/* + * Known bugs: + * + * 1. We don't handle cursor movement characters inside escape sequences. + * That is, ESC[2C moves two to the right, so ESC[2\bC is supposed to back + * up one and then move two to the right. + * + * 2. We don't handle tabstops past nelem(tabcol) columns. + * + * 3. We don't respect requests to do reverse video for the whole screen. + * + * 4. We ignore the ESC#n codes, so that we don't do double-width nor + * double-height lines, nor the ``fill the screen with E's'' confidence check. + * + * 5. Cursor key sequences aren't selected by keypad application mode. + * + * 6. "VT220" mode (-2) currently just switches the default cursor key + * functions (same as -a); it's still just a VT100 emulation. + * + * 7. VT52 mode and a few other rarely used features are not implemented. + */ + +#include <u.h> +#include <libc.h> +#include <draw.h> +#include <bio.h> +#include <ctype.h> +#include "cons.h" + +int wraparound = 1; +int originrelative = 0; + +int tabcol[200]; + +struct funckey vt100fk[NKEYS] = { + { "up key", "\033OA", }, + { "down key", "\033OB", }, + { "left key", "\033OD", }, + { "right key", "\033OC", }, +}; + +struct funckey ansifk[NKEYS] = { + { "up key", "\033[A", }, + { "down key", "\033[B", }, + { "left key", "\033[D", }, + { "right key", "\033[C", }, + { "F1", "\033OP", }, + { "F2", "\033OQ", }, + { "F3", "\033OR", }, + { "F4", "\033OS", }, + { "F5", "\033OT", }, + { "F6", "\033OU", }, + { "F7", "\033OV", }, + { "F8", "\033OW", }, + { "F9", "\033OX", }, + { "F10", "\033OY", }, + { "F11", "\033OZ", }, + { "F12", "\033O1", }, +}; + +struct funckey vt220fk[NKEYS] = { + { "up key", "\033[A", }, + { "down key", "\033[B", }, + { "left key", "\033[D", }, + { "right key", "\033[C", }, +}; + +struct funckey xtermfk[NKEYS] = { + { "page up", "\033[5~", }, + { "page down", "\033[6~", }, + { "up key", "\033[A", }, + { "down key", "\033[B", }, + { "left key", "\033[D", }, + { "right key", "\033[C", }, + { "F1", "\033[11~", }, + { "F2", "\033[12~", }, + { "F3", "\033[13~", }, + { "F4", "\033[14~", }, + { "F5", "\033[15~", }, + { "F6", "\033[17~", }, + { "F7", "\033[18~", }, + { "F8", "\033[19~", }, + { "F9", "\033[20~", }, + { "F10", "\033[21~", }, + { "F11", "\033[22~", }, + { "F12", "\033[23~", }, +}; + +char gmap[256] = { + ['_'] ' ', /* blank */ + ['\\'] '*', /* diamond */ + ['a'] 'X', /* checkerboard */ + ['b'] '\t', /* HT */ + ['c'] '\x0C', /* FF */ + ['d'] '\r', /* CR */ + ['e'] '\n', /* LF */ + ['f'] 'o', /* degree */ + ['g'] '+', /* plus/minus */ + ['h'] '\n', /* NL, but close enough */ + ['i'] '\v', /* VT */ + ['j'] '+', /* lower right corner */ + ['k'] '+', /* upper right corner */ + ['l'] '+', /* upper left corner */ + ['m'] '+', /* lower left corner */ + ['n'] '+', /* crossing lines */ + ['o'] '-', /* horiz line - scan 1 */ + ['p'] '-', /* horiz line - scan 3 */ + ['q'] '-', /* horiz line - scan 5 */ + ['r'] '-', /* horiz line - scan 7 */ + ['s'] '-', /* horiz line - scan 9 */ + ['t'] '+', /* |- */ + ['u'] '+', /* -| */ + ['v'] '+', /* upside down T */ + ['w'] '+', /* rightside up T */ + ['x'] '|', /* vertical bar */ + ['y'] '<', /* less/equal */ + ['z'] '>', /* gtr/equal */ + ['{'] 'p', /* pi */ + ['|'] '!', /* not equal */ + ['}'] 'L', /* pound symbol */ + ['~'] '.', /* centered dot: ยท */ +}; + +static void setattr(int argc, int *argv); + +void +fixops(int *operand) +{ + if(operand[0] < 1) + operand[0] = 1; +} + +void +emulate(void) +{ + char buf[BUFS+1]; + int i; + int n; + int c; + int operand[10]; + int noperand; + int savex, savey, saveattr, saveisgraphics; + int isgraphics; + int g0set, g1set; + int dch; + + isgraphics = 0; + g0set = 'B'; /* US ASCII */ + g1set = 'B'; /* US ASCII */ + savex = savey = 0; + yscrmin = 0; + yscrmax = ymax; + saveattr = 0; + saveisgraphics = 0; + /* set initial tab stops to DEC-standard 8-column spacing */ + for(c=0; (c+=8)<nelem(tabcol);) + tabcol[c] = 1; + + for (;;) { + if (y > ymax) { + x = 0; + newline(); + } + buf[0] = get_next_char(); + buf[1] = '\0'; + switch(buf[0]) { + + case '\000': + case '\001': + case '\002': + case '\003': + case '\004': + case '\005': + case '\006': + goto Default; + + case '\007': /* bell */ + ringbell(); + break; + + case '\010': /* backspace */ + if (x > 0) + --x; + break; + + case '\011': /* tab to next tab stop; if none, to right margin */ + for(c=x+1; c<nelem(tabcol) && !tabcol[c]; c++) + ; + if(c < nelem(tabcol)) + x = c; + else + x = xmax; + break; + + case '\012': /* linefeed */ + case '\013': + case '\014': + newline(); + if (ttystate[cs->raw].nlcr) + x = 0; + break; + + case '\015': /* carriage return */ + x = 0; + if (ttystate[cs->raw].crnl) + newline(); + break; + + case '\016': /* SO: invoke G1 char set */ + isgraphics = (isdigit(g1set)); + break; + case '\017': /* SI: invoke G0 char set */ + isgraphics = (isdigit(g0set)); + break; + + case '\020': /* DLE */ + case '\021': /* DC1 */ + case '\022': /* XON */ + case '\023': /* DC3 */ + case '\024': /* XOFF */ + case '\025': /* NAK */ + case '\026': /* SYN */ + case '\027': /* ETB */ + case '\030': /* CAN: cancel escape sequence, display checkerboard (not implemented) */ + case '\031': /* EM */ + case '\032': /* SUB: same as CAN */ + goto Default; +; + /* ESC, \033, is handled below */ + case '\034': /* FS */ + case '\035': /* GS */ + case '\036': /* RS */ + case '\037': /* US */ + break; + case '\177': /* delete: ignored */ + break; + + case '\033': + switch(dch = get_next_char()){ + /* + * 1 - graphic processor option on (no-op; not installed) + */ + case '1': + break; + + /* + * 2 - graphic processor option off (no-op; not installed) + */ + case '2': + break; + + /* + * 7 - save cursor position. + */ + case '7': +//print("save\n"); + savex = x; + savey = y; + saveattr = attr; + saveisgraphics = isgraphics; + break; + + /* + * 8 - restore cursor position. + */ + case '8': +//print("restore\n"); + x = savex; + y = savey; + attr = saveattr; + isgraphics = saveisgraphics; + break; + + /* + * c - Reset terminal. + */ + case 'c': +print("resetterminal\n"); + cursoron = 1; + ttystate[cs->raw].nlcr = 0; + break; + + /* + * D - active position down a line, scroll if at bottom margin. + * (Original VT100 had a bug: tracked new-line/line-feed mode.) + */ + case 'D': + if(++y > yscrmax) { + y = yscrmax; + scroll(yscrmin+1, yscrmax+1, yscrmin, yscrmax); + } + break; + + /* + * E - active position to start of next line, scroll if at bottom margin. + */ + case 'E': + x = 0; + if(++y > yscrmax) { + y = yscrmax; + scroll(yscrmin+1, yscrmax+1, yscrmin, yscrmax); + } + break; + + /* + * H - set tab stop at current column. + * (This is cursor home in VT52 mode (not implemented).) + */ + case 'H': + if(x < nelem(tabcol)) + tabcol[x] = 1; + break; + + /* + * M - active position up a line, scroll if at top margin.. + */ + case 'M': + if(--y < yscrmin) { + y = yscrmin; + scroll(yscrmin, yscrmax, yscrmin+1, yscrmin); + } + break; + + /* + * Z - identification. the terminal + * emulator will return the response + * code for a generic VT100. + */ + case 'Z': + Ident: + sendnchars2(7, "\033[?1;2c"); /* VT100 with AVO option */ +// sendnchars2(5, "\033[?6c"); /* VT102 (insert/delete-char, etc.) */ + break; + + /* + * < - enter ANSI mode + */ + case '<': + break; + + /* + * > - set numeric keypad mode on (not implemented) + */ + case '>': + break; + + /* + * = - set numeric keypad mode off (not implemented) + */ + case '=': + break; + + /* + * # - Takes a one-digit argument + */ + case '#': + switch(get_next_char()){ + case '3': /* Top half of double-height line */ + case '4': /* Bottom half of double-height line */ + case '5': /* Single-width single-height line */ + case '6': /* Double-width line */ + case '7': /* Screen print */ + case '8': /* Fill screen with E's */ + break; + } + break; + + /* + * ( - switch G0 character set + */ + case '(': + g0set = get_next_char(); + break; + + /* + * - switch G1 character set + */ + case ')': + g1set = get_next_char(); + break; + + /* + * Received left bracket. + */ + case '[': + /* + * A semi-colon or ? delimits arguments. + */ + memset(operand, 0, sizeof(operand)); + operand[0] = number(buf, &i); + noperand = 1; + while(buf[0] == ';' || buf[0] == '?'){ + if(noperand < nelem(operand)){ + noperand++; + operand[noperand-1] = number(buf, nil); + } else + number(buf, nil); + } + + /* + * do escape2 stuff + */ + switch(dch = buf[0]){ + /* + * c - same as ESC Z: what are you? + */ + case 'c': + goto Ident; + + /* + * g - various tabstop manipulation + */ + case 'g': + switch(operand[0]){ + case 0: /* clear tab at current column */ + if(x < nelem(tabcol)) + tabcol[x] = 0; + break; + case 3: /* clear all tabs */ + memset(tabcol, 0, sizeof tabcol); + break; + } + break; + + /* + * l - clear various options. + */ + case 'l': + if(noperand == 1){ + switch(operand[0]){ + case 20: /* set line feed mode */ + ttystate[cs->raw].nlcr = 1; + break; + case 30: /* screen invisible (? not supported through VT220) */ + break; + } + }else while(--noperand > 0){ + switch(operand[noperand]){ + case 1: /* set cursor keys to send ANSI functions: ESC [ A..D */ + break; + case 2: /* set VT52 mode (not implemented) */ + break; + case 3: /* set 80 columns */ + setdim(-1, 80); + break; + case 4: /* set jump scrolling */ + break; + case 5: /* set normal video on screen */ + break; + case 6: /* set origin to absolute */ + originrelative = 0; + x = y = 0; + break; + case 7: /* reset auto-wrap mode */ + wraparound = 0; + break; + case 8: /* reset auto-repeat mode */ + break; + case 9: /* reset interlacing mode */ + break; + case 25: /* text cursor off (VT220) */ + cursoron = 0; + break; + } + } + break; + + /* + * s - some dec private stuff. actually [ ? num s, but we can't detect it. + */ + case 's': + break; + + /* + * h - set various options. + */ + case 'h': + if(noperand == 1){ + switch(operand[0]){ + default: + break; + case 20: /* set newline mode */ + ttystate[cs->raw].nlcr = 0; + break; + case 30: /* screen visible (? not supported through VT220) */ + break; + } + }else while(--noperand > 0){ + switch(operand[noperand]){ + default: + break; + case 1: /* set cursor keys to send application function: ESC O A..D */ + break; + case 2: /* set ANSI */ + break; + case 3: /* set 132 columns */ + setdim(-1, 132); + break; + case 4: /* set smooth scrolling */ + break; + case 5: /* set screen to reverse video (not implemented) */ + break; + case 6: /* set origin to relative */ + originrelative = 1; + x = 0; + y = yscrmin; + break; + case 7: /* set auto-wrap mode */ + wraparound = 1; + break; + case 8: /* set auto-repeat mode */ + break; + case 9: /* set interlacing mode */ + break; + case 25: /* text cursor on (VT220) */ + cursoron = 1; + break; + } + } + break; + + /* + * m - change character attrs. + */ + case 'm': + setattr(noperand, operand); + break; + + /* + * n - request various reports + */ + case 'n': + switch(operand[0]){ + case 5: /* status */ + sendnchars2(4, "\033[0n"); /* terminal ok */ + break; + case 6: /* cursor position */ + sendnchars2(sprint(buf, "\033[%d;%dR", + originrelative ? y+1 - yscrmin : y+1, x+1), buf); + break; + } + break; + + /* + * q - turn on list of LEDs; turn off others. + */ + case 'q': + break; + + /* + * r - change scrolling region. operand[0] is + * min scrolling region and operand[1] is max + * scrolling region. + */ + case 'r': + yscrmin = 0; + yscrmax = ymax; + switch(noperand){ + case 2: + yscrmax = operand[1]-1; + if(yscrmax > ymax) + yscrmax = ymax; + case 1: + yscrmin = operand[0]-1; + if(yscrmin < 0) + yscrmin = 0; + } + x = 0; + y = yscrmin; + break; + + /* + * x - report terminal parameters + */ + case 'x': + sendnchars2(20, "\033[3;1;1;120;120;1;0x"); + break; + + /* + * y - invoke confidence test + */ + case 'y': + break; + + /* + * A - cursor up. + */ + case 'e': + case 'A': + fixops(operand); + y -= operand[0]; + if(y < yscrmin) + y = yscrmin; + olines -= operand[0]; + if(olines < 0) + olines = 0; + break; + + /* + * B - cursor down + */ + case 'B': + fixops(operand); + y += operand[0]; + if(y > yscrmax) + y=yscrmax; + break; + + /* + * C - cursor right + */ + case 'a': + case 'C': + fixops(operand); + x += operand[0]; + /* + * VT-100-UG says not to go past the + * right margin. + */ + if(x > xmax) + x = xmax; + break; + + /* + * D - cursor left + */ + case 'D': + fixops(operand); + x -= operand[0]; + if(x < 0) + x = 0; + break; + + /* + * G - cursor to column + */ + case '\'': + case 'G': + fixops(operand); + x = operand[0] - 1; + if(x > xmax) + x = xmax; + break; + + /* + * H and f - cursor motion. operand[0] is row and + * operand[1] is column, origin 1. + */ + case 'H': + case 'f': + fixops(operand+1); + x = operand[1] - 1; + if(x > xmax) + x = xmax; + + /* fallthrough */ + + /* + * d - cursor to line n (xterm) + */ + case 'd': + fixops(operand); + y = operand[0] - 1; + if(originrelative){ + y += yscrmin; + if(y > yscrmax) + y = yscrmax; + }else{ + if(y > ymax) + y = ymax; + } + break; + + /* + * J - clear some or all of the display. + */ + case 'J': + switch (operand[0]) { + /* + * operand 2: whole screen. + */ + case 2: + clear(Rpt(pt(0, 0), pt(xmax+1, ymax+1))); + break; + /* + * operand 1: start of screen to active position, inclusive. + */ + case 1: + clear(Rpt(pt(0, 0), pt(xmax+1, y))); + clear(Rpt(pt(0, y), pt(x+1, y+1))); + break; + /* + * Default: active position to end of screen, inclusive. + */ + default: + clear(Rpt(pt(x, y), pt(xmax+1, y+1))); + clear(Rpt(pt(0, y+1), pt(xmax+1, ymax+1))); + break; + } + break; + + /* + * K - clear some or all of the line. + */ + case 'K': + switch (operand[0]) { + /* + * operand 2: whole line. + */ + case 2: + clear(Rpt(pt(0, y), pt(xmax+1, y+1))); + break; + /* + * operand 1: start of line to active position, inclusive. + */ + case 1: + clear(Rpt(pt(0, y), pt(x+1, y+1))); + break; + /* + * Default: active position to end of line, inclusive. + */ + default: + clear(Rpt(pt(x, y), pt(xmax+1, y+1))); + break; + } + break; + + /* + * P - delete character(s) from right of cursor (xterm) + */ + case 'P': + fixops(operand); + i = x + operand[0]; + draw(screen, Rpt(pt(x, y), pt(xmax+1, y+1)), screen, nil, pt(i, y)); + clear(Rpt(pt(xmax-operand[0], y), pt(xmax+1, y+1))); + break; + + /* + * @ - insert blank(s) to right of cursor (xterm) + */ + case '@': + fixops(operand); + i = x + operand[0]; + draw(screen, Rpt(pt(i, y), pt(xmax+1, y+1)), screen, nil, pt(x, y)); + clear(Rpt(pt(x, y), pt(i, y+1))); + break; + + + /* + * X - erase character(s) at cursor and to the right (xterm) + */ + case 'X': + fixops(operand); + i = x + operand[0]; + clear(Rpt(pt(x, y), pt(i, y+1))); + break; + + /* + * L - insert a line at cursor position (VT102 and later) + */ + case 'L': + fixops(operand); + for(i = 0; i < operand[0]; ++i) + scroll(y, yscrmax, y+1, y); + break; + + /* + * M - delete a line at cursor position (VT102 and later) + */ + case 'M': + fixops(operand); + for(i = 0; i < operand[0]; ++i) + scroll(y+1, yscrmax+1, y, yscrmax); + break; + + /* + * S,T - scroll up/down (xterm) + */ + case 'T': + fixops(operand); + for(i = 0; i < operand[0]; ++i) + scroll(yscrmin, yscrmax, yscrmin+1, yscrmin); + break; + + case 'S': + fixops(operand); + for(i = 0; i < operand[0]; ++i) + scroll(yscrmin+1, yscrmax+1, yscrmin, yscrmin); + break; + + case '=': /* ? not supported through VT220 */ + number(buf, nil); + switch(buf[0]) { + case 'h': + case 'l': + break; + } + break; + + /* + * Anything else we ignore for now... + */ + default: +print("unknown escape2 '%c' (0x%x)\n", dch, dch); + break; + } + + break; + + /* + * Collapse multiple '\033' to one. + */ + case '\033': + peekc = '\033'; + break; + + /* set title */ + case ']': /* it's actually <esc> ] num ; title <bel> */ + { + int ch, fd; + number(buf, nil); + i = 0; + while((ch = get_next_char()) != '\a') + if(i < sizeof buf) + buf[i++] = ch; + fd = open("/dev/label", OWRITE); + write(fd, buf, i); + close(fd); + } + break; + + /* + * Ignore other commands. + */ + default: +print("unknown command '%c' (0x%x)\n", dch, dch); + break; + + } + break; + + default: /* ordinary char */ +Default: + if(isgraphics && gmap[(uchar) buf[0]]) + buf[0] = gmap[(uchar) buf[0]]; + + /* line wrap */ + if (x > xmax){ + if(wraparound){ + x = 0; + newline(); + }else{ + continue; + } + } + n = 1; + c = 0; + while (!cs->raw && host_avail() && x+n<=xmax && n<BUFS + && (c = get_next_char())>=' ' && c<'\177') { + buf[n++] = c; + c = 0; + } + buf[n] = 0; +// clear(Rpt(pt(x,y), pt(x+n, y+1))); + drawstring(pt(x, y), buf, attr); + x += n; + peekc = c; + break; + } + } +} + +static void +setattr(int argc, int *argv) +{ + int i; + + for(i=0; i<argc; i++) { + switch(argv[i]) { + case 0: + attr = defattr; + fgcolor = fgdefault; + bgcolor = bgdefault; + break; + case 1: + attr |= THighIntensity; + break; + case 4: + attr |= TUnderline; + break; + case 5: + attr |= TBlink; + break; + case 7: + attr |= TReverse; + break; + case 8: + attr |= TInvisible; + break; + case 22: + attr &= ~THighIntensity; + break; + case 24: + attr &= ~TUnderline; + break; + case 25: + attr &= ~TBlink; + break; + case 27: + attr &= ~TReverse; + break; + case 28: + attr &= ~TInvisible; + break; + case 30: /* black */ + case 31: /* red */ + case 32: /* green */ + case 33: /* brown */ + case 34: /* blue */ + case 35: /* purple */ + case 36: /* cyan */ + case 37: /* white */ + fgcolor = (nocolor? fgdefault: colors[argv[i]-30]); + break; + case 39: + fgcolor = fgdefault; + break; + case 40: /* black */ + case 41: /* red */ + case 42: /* green */ + case 43: /* brown */ + case 44: /* blue */ + case 45: /* purple */ + case 46: /* cyan */ + case 47: /* white */ + bgcolor = (nocolor? bgdefault: colors[argv[i]-40]); + break; + case 49: + bgcolor = bgdefault; + break; + } + } +} |