st

simple terminal
git clone https://git.parazyd.org/st
Log | Files | Refs | README | LICENSE

commit 0f4dd5035ed920c67133f1a4b8aef5cbd957c7be
parent 7cdaf130b17e4991da9bb3d8d1341e0092474a73
Author: Aurélien Aptel <aurelien.aptel@gmail.com>
Date:   Thu, 11 Mar 2010 23:50:50 +0100

bold attribute is back.

visibility of the cursor is not saved/loaded anymore.
scrolling up/down is fixed.
added RI and RIS sequences.
fixed cursor drawing bug.
Diffstat:
Mconfig.h | 3++-
Mst.c | 173++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------
2 files changed, 126 insertions(+), 50 deletions(-)

diff --git a/config.h b/config.h @@ -1,7 +1,8 @@ #define SHELL "/bin/bash" #define TAB 8 -#define FONT "fixed" +#define FONT "6x13" +#define BOLDFONT FONT"bold" #define BORDER 3 #define LINESPACE 0 /* additional pixel between each line */ diff --git 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 */ @@ -109,6 +109,7 @@ typedef struct { typedef struct { unsigned long col[LEN(colorname)]; XFontStruct* font; + XFontStruct* bfont; GC gc; } DC; @@ -135,8 +136,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 +153,11 @@ 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 *); @@ -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,17 +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; + /* No dirty flag to set because of xscroll */ /* X stuff _before_ the line swapping (results in wrong line index) */ xscroll(); for(i = term.top; i < term.bot; i++) @@ -343,6 +360,41 @@ tscroll(void) { } void +tscrolldown (int n) { + int i; + Line temp; + + /* TODO: set dirty flag or scroll with some X func */ + 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); + + /* TODO: set dirty flag or scroll with some X func */ + 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) @@ -420,17 +472,20 @@ tsetchar(char c) { 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)); + for(y = y1; y <= y2; y++) + memset(&term.line[y][x1], 0, sizeof(Glyph)*(x2-x1+1)); xclear(x1, y1, x2, y2); } @@ -542,9 +597,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 +617,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 +644,7 @@ csihandle(void) { switch(escseq.mode) { default: unknown: - printf("erresc: unknown sequence -- "); + printf("erresc: unknown csi "); csidump(); /* die(""); */ break; @@ -665,7 +719,14 @@ csihandle(void) { break; } break; - case 'S': /* XXX: SU -- Scroll <n> line up (faked) */ + case 'S': /* SU -- Scroll <n> line up */ + DEFAULT(escseq.arg[0], 1); + tscrollup(escseq.arg[0]); + break; + case 'T': /* SD -- Scroll <n> line down */ + DEFAULT(escseq.arg[0], 1); + tscrolldown(escseq.arg[0]); + break; case 'L': /* IL -- Insert <n> blank lines */ DEFAULT(escseq.arg[0], 1); tinsertblankline(escseq.arg[0]); @@ -682,7 +743,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 +792,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 */ @@ -866,11 +927,15 @@ tputc(char c) { break; case 'M': /* RI -- Reverse index */ if(term.c.y == term.top) - tinsertblankline(1); + 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; @@ -888,7 +953,7 @@ tputc(char c) { 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; } } @@ -991,8 +1056,6 @@ xscroll(void) { void xinit(void) { - XGCValues values; - unsigned long valuemask; XClassHint chint; XWMHints wmhint; XSizeHints shint; @@ -1005,9 +1068,10 @@ 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; @@ -1027,10 +1091,7 @@ xinit(void) { dc.col[DefaultBG], dc.col[DefaultBG]); /* 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; @@ -1060,7 +1121,8 @@ 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]]; - + + XSetFont(xw.dis, dc.gc, base.mode & ATTR_BOLD ? dc.bfont->fid : dc.font->fid); XDrawImageString(xw.dis, xw.win, dc.gc, winx, winy, s, len); if(base.mode & ATTR_UNDERLINE) @@ -1068,22 +1130,6 @@ xdraws(char *s, Glyph base, int x, int y, int len) { } 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); -} - -void xcursor(int mode) { static int oldx = 0; static int oldy = 0; @@ -1094,24 +1140,54 @@ 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.win, 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); +} +#endif + void draw(int redraw_all) { int i, x, y, ox; Glyph base, new; char buf[DRAW_BUF_SIZ]; + /* XXX: optimize with GLYPH_DIRTY hint */ for(y = 0; y < term.row; y++) { base = term.line[y][0]; i = ox = 0; @@ -1129,8 +1205,7 @@ draw(int redraw_all) { } xdraws(buf, base, ox, y, i); } - if(!term.c.hidden) - xcursor(CURSOR_DRAW); + xcursor(term.hidec ? CURSOR_HIDE : CURSOR_DRAW); } void @@ -1179,7 +1254,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);