X-Git-Url: https://jasonwoof.com/gitweb/?a=blobdiff_plain;f=st.c;h=deb161055009db9f6fd2dccb94b535fa648d9ecf;hb=b3b7ffce5f1cb1d82aa26df976f0316d89d15d7f;hp=84292f545395b129b5928152f1059e9a2f7ca94b;hpb=636c369d86b6452a89f54c497a9816ca1f866d4e;p=st.git diff --git a/st.c b/st.c old mode 100644 new mode 100755 index 84292f5..deb1610 --- a/st.c +++ b/st.c @@ -57,7 +57,6 @@ typedef Glyph* Line; typedef struct { Glyph attr; /* current char attributes */ - char hidden; int x; int y; } TCursor; @@ -79,6 +78,7 @@ typedef struct { int col; /* nb col */ Line* line; /* screen */ TCursor c; /* cursor */ + char hidec; int top; /* top scroll limit */ int bot; /* bottom scroll limit */ int mode; /* terminal mode flags */ @@ -91,6 +91,7 @@ typedef struct { typedef struct { Display* dis; Window win; + Pixmap buf; int scr; int w; /* window width */ int h; /* window height */ @@ -109,6 +110,7 @@ typedef struct { typedef struct { unsigned long col[LEN(colorname)]; XFontStruct* font; + XFontStruct* bfont; GC gc; } DC; @@ -135,8 +137,11 @@ static void tnew(int, int); static void tnewline(void); static void tputc(char); static void tputs(char*, int); +static void treset(void); static void tresize(int, int); static void tscroll(void); +static void tscrollup(int); +static void tscrolldown(int); static void tsetattr(int*, int); static void tsetchar(char); static void tsetscroll(int, int); @@ -149,12 +154,10 @@ 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 char * kmap(KeySym); +static char* kmap(KeySym); static void kpress(XEvent *); static void resize(XEvent *); @@ -212,7 +215,7 @@ execsh(void) { void xbell(void) { /* visual bell */ - XRectangle r = { 0, 0, xw.w, xw.h }; + XRectangle r = { BORDER, BORDER, xw.w, xw.h }; XSetForeground(xw.dis, dc.gc, dc.col[BellCol]); XFillRectangles(xw.dis, xw.win, dc.gc, &r, 1); /* usleep(30000); */ @@ -313,6 +316,18 @@ tcursor(int mode) { } void +treset(void) { + term.c.attr.mode = ATTR_NULL; + term.c.attr.fg = DefaultFG; + term.c.attr.bg = DefaultBG; + term.c.x = term.c.y = 0; + term.hidec = 0; + term.top = 0, term.bot = term.row - 1; + term.mode = MODE_WRAP; + tclearregion(0, 0, term.col-1, term.row-1); +} + +void tnew(int col, int row) { /* screen size */ term.row = row, term.col = col; term.top = 0, term.bot = term.row - 1; @@ -323,19 +338,19 @@ tnew(int col, int row) { /* screen size */ term.c.attr.fg = DefaultFG; term.c.attr.bg = DefaultBG; term.c.x = term.c.y = 0; - term.c.hidden = 0; + term.hidec = 0; /* allocate screen */ term.line = calloc(term.row, sizeof(Line)); for(row = 0 ; row < term.row; row++) term.line[row] = calloc(term.col, sizeof(Glyph)); } +/* TODO: Replace with scrollup/scolldown */ 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); @@ -343,6 +358,39 @@ tscroll(void) { } void +tscrolldown (int n) { + int i; + Line temp; + + LIMIT(n, 0, term.bot-term.top+1); + + for(i = 0; i < n; i++) + memset(term.line[term.bot-i], 0, term.col*sizeof(Glyph)); + + for(i = term.bot; i >= term.top+n; i--) { + temp = term.line[i]; + term.line[i] = term.line[i-n]; + term.line[i-n] = temp; + } +} + +void +tscrollup (int n) { + int i; + Line temp; + LIMIT(n, 0, term.bot-term.top+1); + + for(i = 0; i < n; i++) + memset(term.line[term.top+i], 0, term.col*sizeof(Glyph)); + + for(i = term.top; i <= term.bot-n; i++) { + temp = term.line[i]; + term.line[i] = term.line[i+n]; + term.line[i+n] = temp; + } +} + +void tnewline(void) { int y = term.c.y + 1; if(y > term.bot) @@ -415,24 +463,25 @@ void tsetchar(char c) { term.line[term.c.y][term.c.x] = term.c.attr; term.line[term.c.y][term.c.x].c = c; - term.line[term.c.y][term.c.x].state |= GLYPH_SET | GLYPH_DIRTY; + term.line[term.c.y][term.c.x].state |= GLYPH_SET; } void tclearregion(int x1, int y1, int x2, int y2) { - int x, y; + int y, temp; + + if(x1 > x2) + temp = x1, x1 = x2, x2 = temp; + if(y1 > y2) + temp = y1, y1 = y2, y2 = temp; LIMIT(x1, 0, term.col-1); LIMIT(x2, 0, term.col-1); LIMIT(y1, 0, term.row-1); LIMIT(y2, 0, term.row-1); - /* XXX: could be optimized */ - for(x = x1; x <= x2; x++) - for(y = y1; y <= y2; y++) - memset(&term.line[y][x], 0, sizeof(Glyph)); - - xclear(x1, y1, x2, y2); + for(y = y1; y <= y2; y++) + memset(&term.line[y][x1], 0, sizeof(Glyph)*(x2-x1+1)); } void @@ -464,13 +513,6 @@ 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; @@ -491,8 +533,6 @@ tinsertblankline(int n) { term.line[i-n] = blank; /* blank it */ memset(blank, 0, term.col * sizeof(Glyph)); - tsetlinestate(i, GLYPH_DIRTY); - tsetlinestate(i-n, GLYPH_DIRTY); } } @@ -517,8 +557,6 @@ tdeleteline(int n) { term.line[i+n] = blank; /* blank it */ memset(blank, 0, term.col * sizeof(Glyph)); - tsetlinestate(i, GLYPH_DIRTY); - tsetlinestate(i-n, GLYPH_DIRTY); } } @@ -542,9 +580,6 @@ tsetattr(int *attr, int l) { case 7: term.c.attr.mode |= ATTR_REVERSE; break; - case 8: - term.c.hidden = CURSOR_HIDE; - break; case 22: term.c.attr.mode &= ~ATTR_BOLD; break; @@ -565,6 +600,8 @@ tsetattr(int *attr, int l) { term.c.attr.fg = attr[i] - 30; else if(BETWEEN(attr[i], 40, 47)) term.c.attr.bg = attr[i] - 40; + else + fprintf(stderr, "erresc: gfx attr %d unkown\n", attr[i]); break; } } @@ -590,7 +627,7 @@ csihandle(void) { switch(escseq.mode) { default: unknown: - printf("erresc: unknown sequence -- "); + printf("erresc: unknown csi "); csidump(); /* die(""); */ break; @@ -665,7 +702,14 @@ csihandle(void) { break; } break; - case 'S': /* XXX: SU -- Scroll line up (faked) */ + case 'S': /* SU -- Scroll line up */ + DEFAULT(escseq.arg[0], 1); + tscrollup(escseq.arg[0]); + break; + case 'T': /* SD -- Scroll line down */ + DEFAULT(escseq.arg[0], 1); + tscrolldown(escseq.arg[0]); + break; case 'L': /* IL -- Insert blank lines */ DEFAULT(escseq.arg[0], 1); tinsertblankline(escseq.arg[0]); @@ -682,7 +726,7 @@ csihandle(void) { case 12: /* att610 -- Stop blinking cursor (IGNORED) */ break; case 25: - term.c.hidden = 1; + term.hidec = 1; break; case 1048: /* XXX: no alt. screen to erase/save */ case 1049: @@ -731,7 +775,7 @@ csihandle(void) { case 12: /* att610 -- Start blinking cursor (IGNORED) */ break; case 25: - term.c.hidden = 0; + term.hidec = 0; break; case 1048: case 1049: /* XXX: no alt. screen to erase/save */ @@ -856,10 +900,25 @@ tputc(char c) { tmoveto(term.c.x+1, term.c.y); term.esc = 0; break; - case 'D': + case 'D': /* XXX: CUP (VT100) or IND (VT52) ... */ tmoveto(term.c.x-1, term.c.y); term.esc = 0; break; + case 'E': /* NEL -- Next line */ + tnewline(); + term.esc = 0; + break; + case 'M': /* RI -- Reverse index */ + if(term.c.y == term.top) + tscrolldown(1); + else + tmoveto(term.c.x, term.c.y-1); + term.esc = 0; + break; + case 'c': /* RIS -- Reset to inital state */ + treset(); + term.esc = 0; + break; case '=': /* DECPAM */ term.mode |= MODE_APPKEYPAD; term.esc = 0; @@ -870,12 +929,14 @@ tputc(char c) { break; case '7': tcursor(CURSOR_SAVE); + term.esc = 0; break; case '8': tcursor(CURSOR_LOAD); + term.esc = 0; break; default: - fprintf(stderr, "erresc: unknown sequence ESC %02X '%c'\n", c, isprint(c)?c:'.'); + fprintf(stderr, "erresc: unknown sequence ESC 0x%02X '%c'\n", c, isprint(c)?c:'.'); term.esc = 0; } } @@ -959,27 +1020,14 @@ xgetcol(const char *s) { void xclear(int x1, int y1, int x2, int y2) { - XClearArea(xw.dis, xw.win, - x1 * xw.cw, y1 * xw.ch, - (x2-x1+1) * xw.cw, (y2-y1+1) * xw.ch, - False); -} - -void -xscroll(void) { - int srcy = (term.top+1) * xw.ch; - int dsty = term.top * xw.ch; - int height = (term.bot-term.top) * xw.ch; - - xcursor(CURSOR_HIDE); - XCopyArea(xw.dis, xw.win, xw.win, dc.gc, 0, srcy, xw.w, height, 0, dsty); - xclear(0, term.bot, term.col-1, term.bot); + XSetForeground(xw.dis, dc.gc, dc.col[DefaultBG]); + XFillRectangle(xw.dis, xw.buf, dc.gc, + x1 * xw.cw, y1 * xw.ch, + (x2-x1+1) * xw.cw, (y2-y1+1) * xw.ch); } void xinit(void) { - XGCValues values; - unsigned long valuemask; XClassHint chint; XWMHints wmhint; XSizeHints shint; @@ -992,11 +1040,12 @@ xinit(void) { die("Can't open display\n"); /* font */ - if(!(dc.font = XLoadQueryFont(xw.dis, FONT))) - die("Can't load font %s\n", FONT); + if(!(dc.font = XLoadQueryFont(xw.dis, FONT)) || !(dc.bfont = XLoadQueryFont(xw.dis, BOLDFONT))) + die("Can't load font %s\n", dc.font ? BOLDFONT : FONT); + /* XXX: Assuming same size for bold font */ xw.cw = dc.font->max_bounds.rbearing - dc.font->min_bounds.lbearing; - xw.ch = dc.font->ascent + dc.font->descent + LINESPACE; + xw.ch = dc.font->ascent + dc.font->descent; /* colors */ for(i = 0; i < LEN(colorname); i++) @@ -1008,26 +1057,25 @@ xinit(void) { /* windows */ xw.h = term.row * xw.ch; xw.w = term.col * xw.cw; - /* XXX: this BORDER is useless after the first resize, handle it in xdraws() */ xw.win = XCreateSimpleWindow(xw.dis, XRootWindow(xw.dis, xw.scr), 0, 0, - xw.w, xw.h, BORDER, + xw.w + 2*BORDER, xw.h + 2*BORDER, 0, dc.col[DefaultBG], dc.col[DefaultBG]); + xw.buf = XCreatePixmap(xw.dis, xw.win, xw.w, xw.h, XDefaultDepth(xw.dis, xw.scr)); /* gc */ - values.foreground = XWhitePixel(xw.dis, xw.scr); - values.font = dc.font->fid; - valuemask = GCForeground | GCFont; - dc.gc = XCreateGC(xw.dis, xw.win, valuemask, &values); + dc.gc = XCreateGC(xw.dis, xw.win, 0, NULL); XMapWindow(xw.dis, xw.win); /* wm stuff */ chint.res_name = TNAME, chint.res_class = TNAME; wmhint.input = 1, wmhint.flags = InputHint; shint.height_inc = xw.ch, shint.width_inc = xw.cw; - shint.height = xw.h, shint.width = xw.w; + shint.height = xw.h + 2*BORDER, shint.width = xw.w + 2*BORDER; shint.flags = PSize | PResizeInc; XSetWMProperties(xw.dis, xw.win, NULL, NULL, &args[0], 0, &shint, &wmhint, &chint); XStoreName(xw.dis, xw.win, TNAME); + XFillRectangle(xw.dis, xw.buf, dc.gc, 0, 0, xw.w, xw.h); XSync(xw.dis, 0); + } void @@ -1047,27 +1095,12 @@ xdraws(char *s, Glyph base, int x, int y, int len) { if(base.mode & ATTR_GFX) for(i = 0; i < len; i++) s[i] = gfx[s[i]]; - - XDrawImageString(xw.dis, xw.win, dc.gc, winx, winy, s, len); + + XSetFont(xw.dis, dc.gc, base.mode & ATTR_BOLD ? dc.bfont->fid : dc.font->fid); + XDrawImageString(xw.dis, xw.buf, dc.gc, winx, winy, s, len); if(base.mode & ATTR_UNDERLINE) - XDrawLine(xw.dis, xw.win, dc.gc, winx, winy+1, winx+width-1, winy+1); -} - -void -xdrawc(int x, int y, Glyph g) { - XRectangle r = { x * xw.cw, y * xw.ch, xw.cw, xw.ch }; - unsigned long xfg, xbg; - - /* reverse video */ - if(g.mode & ATTR_REVERSE) - xfg = dc.col[g.bg], xbg = dc.col[g.fg]; - else - xfg = dc.col[g.fg], xbg = dc.col[g.bg]; - /* background */ - XSetBackground(xw.dis, dc.gc, xbg); - XSetForeground(xw.dis, dc.gc, xfg); - XDrawImageString(xw.dis, xw.win, dc.gc, r.x, r.y+dc.font->ascent, &g.c, 1); + XDrawLine(xw.dis, xw.buf, dc.gc, winx, winy+1, winx+width-1, winy+1); } void @@ -1081,18 +1114,49 @@ xcursor(int mode) { if(term.line[term.c.y][term.c.x].state & GLYPH_SET) g.c = term.line[term.c.y][term.c.x].c; + /* remove the old cursor */ if(term.line[oldy][oldx].state & GLYPH_SET) - xdrawc(oldx, oldy, term.line[oldy][oldx]); - else + xdraws(&term.line[oldy][oldx].c, term.line[oldy][oldx], oldx, oldy, 1); + else xclear(oldx, oldy, oldx, oldy); + /* draw the new one */ if(mode == CURSOR_DRAW) { - xdrawc(term.c.x, term.c.y, g); + xdraws(&g.c, g, term.c.x, term.c.y, 1); oldx = term.c.x, oldy = term.c.y; } } + +#ifdef DEBUG +/* basic drawing routines */ +void +xdrawc(int x, int y, Glyph g) { + XRectangle r = { x * xw.cw, y * xw.ch, xw.cw, xw.ch }; + XSetBackground(xw.dis, dc.gc, dc.col[g.bg]); + XSetForeground(xw.dis, dc.gc, dc.col[g.fg]); + XSetFont(xw.dis, dc.gc, g.mode & ATTR_BOLD ? dc.bfont->fid : dc.font->fid); + XDrawImageString(xw.dis, xw.buf, dc.gc, r.x, r.y+dc.font->ascent, &g.c, 1); +} + +void +draw_(int dummy) { + int x, y; + + xclear(0, 0, term.col-1, term.row-1); + for(y = 0; y < term.row; y++) + for(x = 0; x < term.col; x++) + if(term.line[y][x].state & GLYPH_SET) + xdrawc(x, y, term.line[y][x]); + + if(!term.hidec) + xcursor(CURSOR_DRAW); + XCopyArea(xw.dis, xw.buf, xw.win, dc.gc, 0, 0, xw.w, xw.h, BORDER, BORDER); + XFlush(xw.dis); +} +#endif + void draw(int redraw_all) { int i, x, y, ox; @@ -1116,8 +1180,9 @@ draw(int redraw_all) { } xdraws(buf, base, ox, y, i); } - if(!term.c.hidden) - xcursor(CURSOR_DRAW); + xcursor(term.hidec ? CURSOR_HIDE : CURSOR_DRAW); + XCopyArea(xw.dis, xw.buf, xw.win, dc.gc, 0, 0, xw.w, xw.h, BORDER, BORDER); + XFlush(xw.dis); } void @@ -1166,7 +1231,7 @@ kpress(XEvent *ev) { break; case XK_Insert: if(shift) - /* XXX: paste X clipboard */; + draw(1), puts("draw!")/* XXX: paste X clipboard */; break; default: fprintf(stderr, "errkey: %d\n", (int)ksym); @@ -1185,6 +1250,8 @@ resize(XEvent *e) { ttyresize(col, row); xw.w = e->xconfigure.width; xw.h = e->xconfigure.height; + XFreePixmap(xw.dis, xw.buf); + xw.buf = XCreatePixmap(xw.dis, xw.win, xw.w, xw.h, XDefaultDepth(xw.dis, xw.scr)); draw(SCREEN_REDRAW); } } @@ -1197,7 +1264,7 @@ 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 (?) */ + XResizeWindow(xw.dis, xw.win, xw.w+2*BORDER, xw.h+2*BORDER); /* fix resize bug in wmii (?) */ while(running) { FD_ZERO(&rfd);