X-Git-Url: https://jasonwoof.com/gitweb/?a=blobdiff_plain;f=st.c;h=5715f0fc0d675c4a234f01792bc22476b5f1518d;hb=10e49a0505a250fc78c41842d93eb2a0abaf4c93;hp=deb161055009db9f6fd2dccb94b535fa648d9ecf;hpb=b3b7ffce5f1cb1d82aa26df976f0316d89d15d7f;p=st.git diff --git a/st.c b/st.c old mode 100755 new mode 100644 index deb1610..5715f0f --- a/st.c +++ b/st.c @@ -20,7 +20,7 @@ #include #include -#define TNAME "xterm" +#define TNAME "st-256color" /* Arbitrary sizes */ #define ESC_TITLE_SIZ 256 @@ -39,7 +39,8 @@ /* Attribute, Cursor, Character state, Terminal mode, Screen draw mode */ enum { ATTR_NULL=0 , ATTR_REVERSE=1 , ATTR_UNDERLINE=2, ATTR_BOLD=4, ATTR_GFX=8 }; -enum { CURSOR_UP, CURSOR_DOWN, CURSOR_LEFT, CURSOR_RIGHT, CURSOR_HIDE, CURSOR_DRAW, CURSOR_SAVE, CURSOR_LOAD }; +enum { CURSOR_UP, CURSOR_DOWN, CURSOR_LEFT, CURSOR_RIGHT, CURSOR_HIDE, CURSOR_DRAW, + CURSOR_SAVE, CURSOR_LOAD }; enum { GLYPH_SET=1, GLYPH_DIRTY=2 }; enum { MODE_WRAP=1, MODE_INSERT=2, MODE_APPKEYPAD=4 }; enum { ESC_START=1, ESC_CSI=2, ESC_OSC=4, ESC_TITLE=8, ESC_ALTCHARSET=16 }; @@ -56,7 +57,7 @@ typedef struct { typedef Glyph* Line; typedef struct { - Glyph attr; /* current char attributes */ + Glyph attr; /* current char attributes */ int x; int y; } TCursor; @@ -65,24 +66,24 @@ typedef struct { /* ESC '[' [[ [] [;]] ] */ typedef struct { char buf[ESC_BUF_SIZ]; /* raw string */ - int len; /* raw string length */ + int len; /* raw string length */ char priv; int arg[ESC_ARG_SIZ]; - int narg; /* nb of args */ + int narg; /* nb of args */ char mode; } CSIEscape; /* Internal representation of the screen */ typedef struct { - int row; /* nb row */ - int col; /* nb col */ + int row; /* nb row */ + int col; /* nb col */ Line* line; /* screen */ - TCursor c; /* cursor */ + TCursor c; /* cursor */ char hidec; - int top; /* top scroll limit */ - int bot; /* bottom scroll limit */ - int mode; /* terminal mode flags */ - int esc; /* escape state flags */ + int top; /* top scroll limit */ + int bot; /* bottom scroll limit */ + int mode; /* terminal mode flags */ + int esc; /* escape state flags */ char title[ESC_TITLE_SIZ]; int titlelen; } Term; @@ -93,8 +94,10 @@ typedef struct { Window win; Pixmap buf; int scr; - int w; /* window width */ - int h; /* window height */ + int w; /* window width */ + int h; /* window height */ + int bufw; /* pixmap width */ + int bufh; /* pixmap height */ int ch; /* char height */ int cw; /* char width */ } XWindow; @@ -108,7 +111,7 @@ typedef struct { /* Drawing Context */ typedef struct { - unsigned long col[LEN(colorname)]; + unsigned long col[256]; XFontStruct* font; XFontStruct* bfont; GC gc; @@ -151,7 +154,6 @@ 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 xinit(void); @@ -208,14 +210,15 @@ die(const char *errstr, ...) { void execsh(void) { - char *args[3] = {SHELL, "-i", NULL}; + char *args[3] = {getenv("SHELL"), "-i", NULL}; + DEFAULT(args[0], "/bin/sh"); /* default shell if getenv() failed */ putenv("TERM=" TNAME); - execvp(SHELL, args); + execvp(args[0], args); } void xbell(void) { /* visual bell */ - XRectangle r = { BORDER, BORDER, xw.w, xw.h }; + XRectangle r = { BORDER, BORDER, xw.bufw, xw.bufh }; XSetForeground(xw.dis, dc.gc, dc.col[BellCol]); XFillRectangles(xw.dis, xw.win, dc.gc, &r, 1); /* usleep(30000); */ @@ -366,7 +369,7 @@ tscrolldown (int n) { 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]; @@ -581,7 +584,7 @@ tsetattr(int *attr, int l) { term.c.attr.mode |= ATTR_REVERSE; break; case 22: - term.c.attr.mode &= ~ATTR_BOLD; + term.c.attr.mode &= ~ATTR_BOLD; break; case 24: term.c.attr.mode &= ~ATTR_UNDERLINE; @@ -589,19 +592,45 @@ tsetattr(int *attr, int l) { case 27: term.c.attr.mode &= ~ATTR_REVERSE; break; + case 38: + if (i + 2 < l && attr[i + 1] == 5) { + i += 2; + if (BETWEEN(attr[i], 0, 255)) + term.c.attr.fg = attr[i]; + else + fprintf(stderr, "erresc: bad fgcolor %d\n", attr[i]); + } + else + fprintf(stderr, "erresc: gfx attr %d unknown\n", attr[i]); + break; case 39: term.c.attr.fg = DefaultFG; break; + case 48: + if (i + 2 < l && attr[i + 1] == 5) { + i += 2; + if (BETWEEN(attr[i], 0, 255)) + term.c.attr.bg = attr[i]; + else + fprintf(stderr, "erresc: bad bgcolor %d\n", attr[i]); + } + else + fprintf(stderr, "erresc: gfx attr %d unknown\n", attr[i]); + break; case 49: - term.c.attr.fg = DefaultBG; + term.c.attr.bg = 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; + else if(BETWEEN(attr[i], 90, 97)) + term.c.attr.fg = attr[i] - 90 + 8; + else if(BETWEEN(attr[i], 100, 107)) + term.c.attr.fg = attr[i] - 100 + 8; else - fprintf(stderr, "erresc: gfx attr %d unkown\n", attr[i]); + fprintf(stderr, "erresc: gfx attr %d unknown\n", attr[i]); break; } } @@ -664,7 +693,7 @@ csihandle(void) { case 'G': /* CHA -- Move to */ case '`': /* XXX: HPA -- same? */ DEFAULT(escseq.arg[0], 1); - tmoveto(escseq.arg[0]-1, term.c.y); + tmoveto(escseq.arg[0]-1, term.c.y); break; case 'H': /* CUP -- Move to */ case 'f': /* XXX: HVP -- same? */ @@ -844,7 +873,6 @@ tputtab(void) { void tputc(char c) { - /* dump(c); */ if(term.esc & ESC_START) { if(term.esc & ESC_CSI) { escseq.buf[escseq.len++] = c; @@ -877,7 +905,7 @@ tputc(char c) { printf("esc unhandled charset: ESC ( %c\n", c); } term.esc = 0; - } else { + } else { switch(c) { case '[': term.esc |= ESC_CSI; @@ -970,7 +998,7 @@ tputc(char c) { } void -tputs(char *s, int len) { +tputs(char *s, int len) { for(; len > 0; len--) tputc(*s++); } @@ -1006,34 +1034,73 @@ tresize(int col, int row) { term.col = col, term.row = row; } -unsigned long -xgetcol(const char *s) { +void +tloadcols(void) { + int i, r, g, b; XColor color; Colormap cmap = DefaultColormap(xw.dis, xw.scr); + unsigned long white = WhitePixel(xw.dis, xw.scr); + + for(i = 0; i < 16; i++) { + if (!XAllocNamedColor(xw.dis, cmap, colorname[i], &color, &color)) { + dc.col[i] = white; + fprintf(stderr, "Could not allocate color '%s'\n", colorname[i]); + } else + dc.col[i] = color.pixel; + } - if(!XAllocNamedColor(xw.dis, cmap, s, &color, &color)) { - color.pixel = WhitePixel(xw.dis, xw.scr); - fprintf(stderr, "Could not allocate color '%s'\n", s); + /* same colors as xterm */ + for(r = 0; r < 6; r++) + for(g = 0; g < 6; g++) + for(b = 0; b < 6; b++) { + color.red = r == 0 ? 0 : 0x3737 + 0x2828 * r; + color.green = g == 0 ? 0 : 0x3737 + 0x2828 * g; + color.blue = b == 0 ? 0 : 0x3737 + 0x2828 * b; + if (!XAllocColor(xw.dis, cmap, &color)) { + dc.col[i] = white; + fprintf(stderr, "Could not allocate color %d\n", i); + } else + dc.col[i] = color.pixel; + i++; + } + + for(r = 0; r < 24; r++, i++) { + color.red = color.green = color.blue = 0x0808 + 0x0a0a * r; + if (!XAllocColor(xw.dis, cmap, &color)) { + dc.col[i] = white; + fprintf(stderr, "Could not allocate color %d\n", i); + } else + dc.col[i] = color.pixel; } - return color.pixel; } void xclear(int x1, int y1, int x2, int y2) { 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); + x1 * xw.cw, y1 * xw.ch, + (x2-x1+1) * xw.cw, (y2-y1+1) * xw.ch); } void -xinit(void) { - XClassHint chint; - XWMHints wmhint; - XSizeHints shint; - char *args[] = {NULL}; - int i; +xhints(void) +{ + XClassHint class = {TNAME, TNAME}; + XWMHints wm = {.flags = InputHint, .input = 1}; + XSizeHints size = { + .flags = PSize | PResizeInc | PBaseSize, + .height = xw.h, + .width = xw.w, + .height_inc = xw.ch, + .width_inc = xw.cw, + .base_height = 2*BORDER, + .base_width = 2*BORDER, + }; + XSetWMProperties(xw.dis, xw.win, NULL, NULL, NULL, 0, &size, &wm, &class); +} +void +xinit(void) { xw.dis = XOpenDisplay(NULL); xw.scr = XDefaultScreen(xw.dis); if(!xw.dis) @@ -1048,34 +1115,27 @@ xinit(void) { xw.ch = dc.font->ascent + dc.font->descent; /* colors */ - for(i = 0; i < LEN(colorname); i++) - dc.col[i] = xgetcol(colorname[i]); + tloadcols(); term.c.attr.fg = DefaultFG; term.c.attr.bg = DefaultBG; term.c.attr.mode = ATTR_NULL; /* windows */ - xw.h = term.row * xw.ch; - xw.w = term.col * xw.cw; + xw.h = term.row * xw.ch + 2*BORDER; + xw.w = term.col * xw.cw + 2*BORDER; xw.win = XCreateSimpleWindow(xw.dis, XRootWindow(xw.dis, xw.scr), 0, 0, - xw.w + 2*BORDER, xw.h + 2*BORDER, 0, + xw.w, xw.h, 0, dc.col[DefaultBG], dc.col[DefaultBG]); - xw.buf = XCreatePixmap(xw.dis, xw.win, xw.w, xw.h, XDefaultDepth(xw.dis, xw.scr)); + xw.bufw = xw.w - 2*BORDER; + xw.bufh = xw.h - 2*BORDER; + xw.buf = XCreatePixmap(xw.dis, xw.win, xw.bufw, xw.bufh, XDefaultDepth(xw.dis, xw.scr)); /* gc */ 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 + 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); + xhints(); + XStoreName(xw.dis, xw.win, "st"); XSync(xw.dis, 0); - } void @@ -1094,9 +1154,9 @@ 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]]; + s[i] = gfx[(int)s[i]]; - XSetFont(xw.dis, dc.gc, base.mode & ATTR_BOLD ? dc.bfont->fid : dc.font->fid); + 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) @@ -1128,7 +1188,6 @@ xcursor(int mode) { } } - #ifdef DEBUG /* basic drawing routines */ void @@ -1141,7 +1200,7 @@ xdrawc(int x, int y, Glyph g) { } void -draw_(int dummy) { +draw(int dummy) { int x, y; xclear(0, 0, term.col-1, term.row-1); @@ -1152,17 +1211,20 @@ draw_(int dummy) { if(!term.hidec) xcursor(CURSOR_DRAW); - XCopyArea(xw.dis, xw.buf, xw.win, dc.gc, 0, 0, xw.w, xw.h, BORDER, BORDER); + XCopyArea(xw.dis, xw.buf, xw.win, dc.gc, 0, 0, xw.bufw, xw.bufh, BORDER, BORDER); XFlush(xw.dis); } -#endif +#else +/* optimized drawing routine */ void draw(int redraw_all) { int i, x, y, ox; Glyph base, new; char buf[DRAW_BUF_SIZ]; + XSetForeground(xw.dis, dc.gc, dc.col[DefaultBG]); + XFillRectangle(xw.dis, xw.buf, dc.gc, 0, 0, xw.w, xw.h); for(y = 0; y < term.row; y++) { base = term.line[y][0]; i = ox = 0; @@ -1181,10 +1243,12 @@ draw(int redraw_all) { xdraws(buf, base, ox, y, i); } xcursor(term.hidec ? CURSOR_HIDE : CURSOR_DRAW); - XCopyArea(xw.dis, xw.buf, xw.win, dc.gc, 0, 0, xw.w, xw.h, BORDER, BORDER); + XCopyArea(xw.dis, xw.buf, xw.win, dc.gc, 0, 0, xw.bufw, xw.bufh, BORDER, BORDER); XFlush(xw.dis); } +#endif + void expose(XEvent *ev) { draw(SCREEN_REDRAW); @@ -1209,11 +1273,11 @@ kpress(XEvent *ev) { int meta; int shift; - meta = e->state & Mod1Mask; + meta = e->state & Mod1Mask; shift = e->state & ShiftMask; len = XLookupString(e, buf, sizeof(buf), &ksym, NULL); - if(customkey = kmap(ksym)) + if((customkey = kmap(ksym))) ttywrite(customkey, strlen(customkey)); else if(len > 0) { buf[sizeof(buf)-1] = '\0'; @@ -1242,18 +1306,21 @@ kpress(XEvent *ev) { void resize(XEvent *e) { int col, row; - col = e->xconfigure.width / xw.cw; - row = e->xconfigure.height / xw.ch; - if(term.col != col || term.row != row) { - tresize(col, row); - 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); - } + if(e->xconfigure.width == xw.w && e->xconfigure.height == xw.h) + return; + + xw.w = e->xconfigure.width; + xw.h = e->xconfigure.height; + xw.bufw = xw.w - 2*BORDER; + xw.bufh = xw.h - 2*BORDER; + col = xw.bufw / xw.cw; + row = xw.bufh / xw.ch; + tresize(col, row); + ttyresize(col, row); + XFreePixmap(xw.dis, xw.buf); + xw.buf = XCreatePixmap(xw.dis, xw.win, xw.bufw, xw.bufh, XDefaultDepth(xw.dis, xw.scr)); + draw(SCREEN_REDRAW); } void @@ -1264,7 +1331,7 @@ run(void) { running = 1; XSelectInput(xw.dis, xw.win, ExposureMask | KeyPressMask | StructureNotifyMask); - XResizeWindow(xw.dis, xw.win, xw.w+2*BORDER, xw.h+2*BORDER); /* fix resize bug in wmii (?) */ + XResizeWindow(xw.dis, xw.win, xw.w, xw.h); /* XXX: fix resize bug in wmii (?) */ while(running) { FD_ZERO(&rfd); @@ -1277,7 +1344,7 @@ run(void) { } if(FD_ISSET(cmdfd, &rfd)) { ttyread(); - draw(SCREEN_UPDATE); + draw(SCREEN_UPDATE); } while(XPending(xw.dis)) { XNextEvent(xw.dis, &ev);