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/main.c |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/vt/main.c')
-rwxr-xr-x | sys/src/cmd/vt/main.c | 875 |
1 files changed, 875 insertions, 0 deletions
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); +} |