tbold attribute is back. - st - [fork] customized build of st, the simple termi… | |
git clone git://src.adamsgaard.dk/st | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
commit 0f4dd5035ed920c67133f1a4b8aef5cbd957c7be | |
parent 7cdaf130b17e4991da9bb3d8d1341e0092474a73 | |
Author: Aurélien Aptel <[email protected]> | |
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: | |
M config.h | 3 ++- | |
M st.c | 173 ++++++++++++++++++++++-------… | |
2 files changed, 126 insertions(+), 50 deletions(-) | |
--- | |
diff --git a/config.h b/config.h | |
t@@ -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 | |
t@@ -57,7 +57,6 @@ typedef Glyph* Line; | |
typedef struct { | |
Glyph attr; /* current char attributes */ | |
- char hidden; | |
int x; | |
int y; | |
} TCursor; | |
t@@ -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 */ | |
t@@ -109,6 +109,7 @@ typedef struct { | |
typedef struct { | |
unsigned long col[LEN(colorname)]; | |
XFontStruct* font; | |
+ XFontStruct* bfont; | |
GC gc; | |
} DC; | |
t@@ -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); | |
t@@ -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 *); | |
t@@ -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; | |
t@@ -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++) | |
t@@ -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) | |
t@@ -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); | |
} | |
t@@ -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; | |
t@@ -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"… | |
break; | |
} | |
} | |
t@@ -590,7 +644,7 @@ csihandle(void) { | |
switch(escseq.mode) { | |
default: | |
unknown: | |
- printf("erresc: unknown sequence -- "); | |
+ printf("erresc: unknown csi "); | |
csidump(); | |
/* die(""); */ | |
break; | |
t@@ -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]); | |
t@@ -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: | |
t@@ -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 */ | |
t@@ -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; | |
t@@ -888,7 +953,7 @@ tputc(char c) { | |
term.esc = 0; | |
break; | |
default: | |
- fprintf(stderr, "erresc: unknown sequence ESC … | |
+ fprintf(stderr, "erresc: unknown sequence ESC … | |
term.esc = 0; | |
} | |
} | |
t@@ -991,8 +1056,6 @@ xscroll(void) { | |
void | |
xinit(void) { | |
- XGCValues values; | |
- unsigned long valuemask; | |
XClassHint chint; | |
XWMHints wmhint; | |
XSizeHints shint; | |
t@@ -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 = XLoadQuer… | |
+ 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; | |
t@@ -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; | |
t@@ -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.fon… | |
XDrawImageString(xw.dis, xw.win, dc.gc, winx, winy, s, len); | |
if(base.mode & ATTR_UNDERLINE) | |
t@@ -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… | |
-} | |
- | |
-void | |
xcursor(int mode) { | |
static int oldx = 0; | |
static int oldy = 0; | |
t@@ -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, … | |
+ 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->… | |
+ XDrawImageString(xw.dis, xw.win, dc.gc, r.x, r.y+dc.font->ascent, &g.c… | |
+} | |
+ | |
+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; | |
t@@ -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 | |
t@@ -1179,7 +1254,7 @@ kpress(XEvent *ev) { | |
break; | |
case XK_Insert: | |
if(shift) | |
- /* XXX: paste X clipboard */; | |
+ draw(1), puts("draw!")/* XXX: paste X clipboar… | |
break; | |
default: | |
fprintf(stderr, "errkey: %d\n", (int)ksym); |