X-Git-Url: https://jasonwoof.com/gitweb/?a=blobdiff_plain;f=st.c;h=559dcda5789bc1c0c358640cbbf2a9b820b628a5;hb=cf65699a29683bff9d50187c18b160e21a538f48;hp=a203c72cfb9e1c0093b6acda7e6bfcc4359f22f6;hpb=8b4bfe31ec1075316dbb2e7d21753771ae3e5590;p=st.git diff --git a/st.c b/st.c index a203c72..559dcda 100644 --- a/st.c +++ b/st.c @@ -1,6 +1,5 @@ /* See LICENSE for licence details. */ -/* See LICENSE for licence details. */ -#define _XOPEN_SOURCE +#define _XOPEN_SOURCE 600 #include #include #include @@ -37,8 +36,8 @@ /* Attribute, Cursor, Character state, Terminal mode, Screen draw mode */ enum { ATnone=0 , ATreverse=1 , ATunderline=2, ATbold=4 }; enum { CSup, CSdown, CSright, CSleft, CShide, CSdraw, CSwrap, CSsave, CSload }; -enum { CRset=1 , CRupdate=2 }; -enum { TMwrap=1 , TMinsert=2, TMaltcharset }; +enum { CRset=1, CRupdate=2 }; +enum { TMwrap=1, TMinsert=2 }; enum { SCupdate, SCredraw }; typedef int Color; @@ -108,62 +107,68 @@ typedef struct { GC gc; } DC; -void die(const char *errstr, ...); -void draw(int); -void execsh(void); -void sigchld(int); -char* kmap(KeySym); -void kpress(XKeyEvent *); -void resize(XEvent *); -void run(void); - -int escaddc(char); -int escfinal(char); -void escdump(void); -void eschandle(void); -void escparse(void); -void escreset(void); - -void tclearregion(int, int, int, int); -void tcpos(int); -void tcursor(int); -void tdeletechar(int); -void tdeleteline(int); -void tdump(void); -void tinsertblank(int); -void tinsertblankline(int); -void tmoveto(int, int); -void tnew(int, int); -void tnewline(void); -void tputc(char); -void tputs(char*, int); -void tresize(int, int); -void tscroll(void); -void tsetattr(int*, int); -void tsetchar(char); -void tsetscroll(int, int); - -void ttynew(void); -void ttyread(void); -void ttyresize(int, int); -void ttywrite(char *, size_t); - -unsigned long xgetcol(const char *); -void xclear(int, int, int, int); -void xcursor(int); -void xdrawc(int, int, Glyph); -void xinit(void); -void xscroll(void); - +static void die(const char *errstr, ...); +static void draw(int); +static void execsh(void); +static void sigchld(int); +static void run(void); + +static int escaddc(char); +static int escfinal(char); +static void escdump(void); +static void eschandle(void); +static void escparse(void); +static void escreset(void); + +static void tclearregion(int, int, int, int); +static void tcpos(int); +static void tcursor(int); +static void tdeletechar(int); +static void tdeleteline(int); +static void tdump(void); +static void tinsertblank(int); +static void tinsertblankline(int); +static void tmoveto(int, int); +static void tnew(int, int); +static void tnewline(void); +static void tputc(char); +static void tputs(char*, int); +static void tresize(int, int); +static void tscroll(void); +static void tsetattr(int*, int); +static void tsetchar(char); +static void tsetscroll(int, int); + +static void ttynew(void); +static void ttyread(void); +static void ttyresize(int, int); +static void ttywrite(const char *, size_t); + +static unsigned long xgetcol(const char *); +static void xclear(int, int, int, int); +static void xcursor(int); +static void xdrawc(int, int, Glyph); +static void xinit(void); +static void xscroll(void); + +static void expose(XEvent *); +static void kpress(XEvent *); +static void resize(XEvent *); + +static void (*handler[LASTEvent])(XEvent *) = { + [KeyPress] = kpress, + [Expose] = expose, + [ConfigureNotify] = resize +}; /* Globals */ -DC dc; -XWindow xw; -Term term; -Escseq escseq; -int cmdfd; -pid_t pid; -int running; +static DC dc; +static XWindow xw; +static Term term; +static Escseq escseq; +static int cmdfd; +static pid_t pid; +static int running; void die(const char *errstr, ...) { @@ -202,7 +207,6 @@ sigchld(int a) { exit(EXIT_FAILURE); } - void ttynew(void) { int m, s; @@ -262,7 +266,7 @@ ttyread(void) { } void -ttywrite(char *s, size_t n) { +ttywrite(const char *s, size_t n) { if(write(cmdfd, s, n) == -1) die("write error on tty: %s\n", SERRNO); } @@ -329,21 +333,19 @@ void tscroll(void) { Line temp = term.line[term.top]; int i; - + /* X stuff _before_ the line swapping (results in wrong line index) */ + xscroll(); for(i = term.top; i < term.bot; i++) term.line[i] = term.line[i+1]; memset(temp, 0, sizeof(Glyph) * term.col); term.line[term.bot] = temp; - xscroll(); } void tnewline(void) { int y = term.c.y + 1; - - if(y > term.bot) { + if(y > term.bot) tscroll(), y = term.bot; - } tmoveto(0, y); } @@ -478,6 +480,13 @@ tinsertblank(int n) { } void +tsetlinestate(int n, int state) { + int i; + for(i = 0; i < term.col; i++) + term.line[n][i].state |= state; +} + +void tinsertblankline (int n) { int i; Line blank; @@ -498,10 +507,11 @@ tinsertblankline (int n) { term.line[i-n] = blank; /* blank it */ memset(blank, 0, term.col * sizeof(Glyph)); + tsetlinestate(i, CRupdate); + tsetlinestate(i-n, CRupdate); } } - void tdeleteline(int n) { int i; @@ -523,6 +533,8 @@ tdeleteline(int n) { term.line[i+n] = blank; /* blank it */ memset(blank, 0, term.col * sizeof(Glyph)); + tsetlinestate(i, CRupdate); + tsetlinestate(i-n, CRupdate); } } @@ -530,48 +542,48 @@ void tsetattr(int *attr, int l) { int i; - for(i = 0; i < l; i++) { - switch(attr[i]) { - case 0: - memset(&term.c.attr, 0, sizeof(term.c.attr)); - term.c.attr.fg = DefaultFG; - term.c.attr.bg = DefaultBG; - break; - case 1: - term.c.attr.mode |= ATbold; - break; - case 4: - term.c.attr.mode |= ATunderline; - break; - case 7: - term.c.attr.mode |= ATreverse; - break; - case 8: - term.c.hidden = CShide; - break; - case 22: - term.c.attr.mode &= ~ATbold; - break; - case 24: - term.c.attr.mode &= ~ATunderline; - break; - case 27: - term.c.attr.mode &= ~ATreverse; - break; - case 39: - term.c.attr.fg = DefaultFG; - break; - case 49: - term.c.attr.fg = DefaultBG; - break; - default: - if(BETWEEN(attr[i], 30, 37)) - term.c.attr.fg = attr[i] - 30; - else if(BETWEEN(attr[i], 40, 47)) - term.c.attr.bg = attr[i] - 40; - break; - } + for(i = 0; i < l; i++) { + switch(attr[i]) { + case 0: + memset(&term.c.attr, 0, sizeof(term.c.attr)); + term.c.attr.fg = DefaultFG; + term.c.attr.bg = DefaultBG; + break; + case 1: + term.c.attr.mode |= ATbold; + break; + case 4: + term.c.attr.mode |= ATunderline; + break; + case 7: + term.c.attr.mode |= ATreverse; + break; + case 8: + term.c.hidden = CShide; + break; + case 22: + term.c.attr.mode &= ~ATbold; + break; + case 24: + term.c.attr.mode &= ~ATunderline; + break; + case 27: + term.c.attr.mode &= ~ATreverse; + break; + case 39: + term.c.attr.fg = DefaultFG; + break; + case 49: + term.c.attr.fg = DefaultBG; + break; + default: + if(BETWEEN(attr[i], 30, 37)) + term.c.attr.fg = attr[i] - 30; + else if(BETWEEN(attr[i], 40, 47)) + term.c.attr.bg = attr[i] - 40; + break; } + } } void @@ -589,13 +601,18 @@ tsetscroll(int t, int b) { term.bot = b; } - void -eschandle(void) { - /* escdump(); */ +eschandle(void) { switch(escseq.pre) { + default: + goto unknown_seq; case '[': switch(escseq.mode) { + default: + unknown_seq: + fprintf(stderr, "erresc: unknown sequence\n"); + escdump(); + break; case '@': /* Insert blank char */ DEFAULT(escseq.arg[0], 1); tinsertblank(escseq.arg[0]); @@ -713,15 +730,13 @@ eschandle(void) { void escdump(void) { int i; - puts("------"); printf("rawbuf : %s\n", escseq.buf); printf("prechar : %c\n", escseq.pre); printf("private : %c\n", escseq.priv ? '?' : ' '); printf("narg : %d\n", escseq.narg); - if(escseq.narg) { + if(escseq.narg) for(i = 0; i < escseq.narg; i++) printf("\targ %d = %d\n", i, escseq.arg[i]); - } printf("mode : %c\n", escseq.mode); } @@ -843,7 +858,6 @@ xgetcol(const char *s) { return color.pixel; } - void xclear(int x1, int y1, int x2, int y2) { XClearArea(xw.dis, xw.win, @@ -852,7 +866,6 @@ xclear(int x1, int y1, int x2, int y2) { False); } - void xscroll(void) { int srcy = (term.top+1) * xw.ch; @@ -864,9 +877,6 @@ xscroll(void) { xclear(0, term.bot, term.col-1, term.bot); } - - - void xinit(void) { XGCValues values; @@ -960,14 +970,15 @@ xcursor(int mode) { /* remove the old cursor */ if(term.line[oldy][oldx].state & CRset) xdrawc(oldx, oldy, term.line[oldy][oldx]); - else xclear(oldx, oldy, oldx, oldy); /* XXX: maybe a bug */ - if(mode == CSdraw && !term.c.hidden) { + else + xclear(oldx, oldy, oldx, oldy); + /* draw the new one */ + if(mode == CSdraw) { xdrawc(term.c.x, term.c.y, g); oldx = term.c.x, oldy = term.c.y; } } - void draw(int redraw_all) { int x, y; @@ -975,43 +986,43 @@ draw(int redraw_all) { if(redraw_all) XClearWindow(xw.dis, xw.win); + /* XXX: drawing could be optimised */ for(y = 0; y < term.row; y++) { for(x = 0; x < term.col; x++) { changed = term.line[y][x].state & CRupdate; set = term.line[y][x].state & CRset; - if((changed && set) || (redraw_all && set)) { + if(redraw_all || changed) { term.line[y][x].state &= ~CRupdate; - xdrawc(x, y, term.line[y][x]); + if(set) + xdrawc(x, y, term.line[y][x]); + else + xclear(x, y, x, y); } } } xcursor(CSdraw); } -char* -kmap(KeySym k) { - int i; - for(i = 0; i < LEN(key); i++) - if(key[i].k == k) - return (char*)key[i].s; - return NULL; +void +expose(XEvent *ev) { + draw(SCredraw); } void -kpress(XKeyEvent *e) { +kpress(XEvent *ev) { + XKeyEvent *e = &ev->xkey; KeySym ksym; char buf[32]; int len; int meta; int shift; - char* skmap; meta = e->state & Mod1Mask; shift = e->state & ShiftMask; len = XLookupString(e, buf, sizeof(buf), &ksym, NULL); - if(skmap = kmap(ksym)) - ttywrite(skmap, strlen(skmap)); + if(key[ksym]) + ttywrite(key[ksym], strlen(key[ksym])); else if(len > 0) { buf[sizeof(buf)-1] = '\0'; if(meta && len == 1) @@ -1046,7 +1057,6 @@ resize(XEvent *e) { void run(void) { - int ret; XEvent ev; fd_set rfd; int xfd = XConnectionNumber(xw.dis); @@ -1054,39 +1064,25 @@ run(void) { running = 1; XSelectInput(xw.dis, xw.win, ExposureMask | KeyPressMask | StructureNotifyMask); XResizeWindow(xw.dis, xw.win, xw.w , xw.h); /* fix resize bug in wmii (?) */ - + while(running) { FD_ZERO(&rfd); FD_SET(cmdfd, &rfd); FD_SET(xfd, &rfd); - XFlush(xw.dis); - ret = select(MAX(xfd, cmdfd)+1, &rfd, NULL, NULL, NULL); - - if(ret < 0) + if(select(MAX(xfd, cmdfd)+1, &rfd, NULL, NULL, NULL) == -1) { + if(errno == EINTR) + continue; die("select failed: %s\n", SERRNO); - - if(FD_ISSET(xfd, &rfd)) { - while(XPending(xw.dis)) { - XNextEvent(xw.dis, &ev); - switch (ev.type) { - default: - break; - case KeyPress: - kpress(&ev.xkey); - break; - case Expose: - draw(SCredraw); - break; - case ConfigureNotify: - resize(&ev); - break; - } - } } if(FD_ISSET(cmdfd, &rfd)) { ttyread(); draw(SCupdate); } + while(XPending(xw.dis)) { + XNextEvent(xw.dis, &ev); + if(handler[ev.type]) + (handler[ev.type])(&ev); + } } }