aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--config.h2
-rw-r--r--config.mk3
-rw-r--r--st.c115
3 files changed, 61 insertions, 59 deletions
diff --git a/config.h b/config.h
index 53795c6..5494b3b 100644
--- a/config.h
+++ b/config.h
@@ -29,8 +29,6 @@ static const char *colorname[] = {
29#define DefaultFG 7 29#define DefaultFG 7
30#define DefaultBG 0 30#define DefaultBG 0
31#define DefaultCS 1 31#define DefaultCS 1
32#define BellCol DefaultFG
33#define BellTime 30000 /* microseconds */
34 32
35/* special keys */ 33/* special keys */
36static Key key[] = { 34static Key key[] = {
diff --git a/config.mk b/config.mk
index 216e7df..b41a949 100644
--- a/config.mk
+++ b/config.mk
@@ -14,7 +14,8 @@ X11LIB = /usr/X11R6/lib
14INCS = -I. -I/usr/include -I${X11INC} 14INCS = -I. -I/usr/include -I${X11INC}
15LIBS = -L/usr/lib -lc -L${X11LIB} -lX11 -lutil 15LIBS = -L/usr/lib -lc -L${X11LIB} -lX11 -lutil
16 16
17# uncomment your system # 17# uncomment manualy your system if compilation fail
18SYSTEM = -D`uname | tr a-z A-Z`
18#SYSTEM = -DLINUX 19#SYSTEM = -DLINUX
19#SYSTEM = -DOPENBSD 20#SYSTEM = -DOPENBSD
20#SYSTEM = -DFREEBSD 21#SYSTEM = -DFREEBSD
diff --git a/st.c b/st.c
index 1692f81..436533c 100644
--- a/st.c
+++ b/st.c
@@ -16,7 +16,6 @@
16#include <sys/types.h> 16#include <sys/types.h>
17#include <sys/wait.h> 17#include <sys/wait.h>
18#include <unistd.h> 18#include <unistd.h>
19#include <pty.h>
20#include <X11/Xlib.h> 19#include <X11/Xlib.h>
21#include <X11/keysym.h> 20#include <X11/keysym.h>
22#include <X11/Xutil.h> 21#include <X11/Xutil.h>
@@ -47,8 +46,9 @@
47 46
48/* Attribute, Cursor, Character state, Terminal mode, Screen draw mode */ 47/* Attribute, Cursor, Character state, Terminal mode, Screen draw mode */
49enum { ATTR_NULL=0 , ATTR_REVERSE=1 , ATTR_UNDERLINE=2, ATTR_BOLD=4, ATTR_GFX=8 }; 48enum { ATTR_NULL=0 , ATTR_REVERSE=1 , ATTR_UNDERLINE=2, ATTR_BOLD=4, ATTR_GFX=8 };
50enum { CURSOR_UP, CURSOR_DOWN, CURSOR_LEFT, CURSOR_RIGHT, CURSOR_HIDE = 1, 49enum { CURSOR_UP, CURSOR_DOWN, CURSOR_LEFT, CURSOR_RIGHT,
51 CURSOR_DRAW = 0, CURSOR_SAVE, CURSOR_LOAD }; 50 CURSOR_SAVE, CURSOR_LOAD };
51enum { CURSOR_DEFAULT = 0, CURSOR_HIDE = 1, CURSOR_WRAPNEXT = 2 };
52enum { GLYPH_SET=1, GLYPH_DIRTY=2 }; 52enum { GLYPH_SET=1, GLYPH_DIRTY=2 };
53enum { MODE_WRAP=1, MODE_INSERT=2, MODE_APPKEYPAD=4 }; 53enum { MODE_WRAP=1, MODE_INSERT=2, MODE_APPKEYPAD=4 };
54enum { ESC_START=1, ESC_CSI=2, ESC_OSC=4, ESC_TITLE=8, ESC_ALTCHARSET=16 }; 54enum { ESC_START=1, ESC_CSI=2, ESC_OSC=4, ESC_TITLE=8, ESC_ALTCHARSET=16 };
@@ -68,7 +68,7 @@ typedef struct {
68 Glyph attr; /* current char attributes */ 68 Glyph attr; /* current char attributes */
69 int x; 69 int x;
70 int y; 70 int y;
71 char hide; 71 char state;
72} TCursor; 72} TCursor;
73 73
74/* CSI Escape sequence structs */ 74/* CSI Escape sequence structs */
@@ -108,6 +108,7 @@ typedef struct {
108 int bufh; /* pixmap height */ 108 int bufh; /* pixmap height */
109 int ch; /* char height */ 109 int ch; /* char height */
110 int cw; /* char width */ 110 int cw; /* char width */
111 int hasfocus;
111} XWindow; 112} XWindow;
112 113
113typedef struct { 114typedef struct {
@@ -161,23 +162,27 @@ static void ttyread(void);
161static void ttyresize(int, int); 162static void ttyresize(int, int);
162static void ttywrite(const char *, size_t); 163static void ttywrite(const char *, size_t);
163 164
164static void xbell(void);
165static void xdraws(char *, Glyph, int, int, int); 165static void xdraws(char *, Glyph, int, int, int);
166static void xhints(void); 166static void xhints(void);
167static void xclear(int, int, int, int); 167static void xclear(int, int, int, int);
168static void xcursor(int); 168static void xdrawcursor(void);
169static void xinit(void); 169static void xinit(void);
170static void xloadcols(void); 170static void xloadcols(void);
171static void xseturgency(int);
171 172
172static void expose(XEvent *); 173static void expose(XEvent *);
173static char* kmap(KeySym); 174static char* kmap(KeySym);
174static void kpress(XEvent *); 175static void kpress(XEvent *);
175static void resize(XEvent *); 176static void resize(XEvent *);
177static void focus(XEvent *);
178
176 179
177static void (*handler[LASTEvent])(XEvent *) = { 180static void (*handler[LASTEvent])(XEvent *) = {
178 [KeyPress] = kpress, 181 [KeyPress] = kpress,
179 [Expose] = expose, 182 [Expose] = expose,
180 [ConfigureNotify] = resize 183 [ConfigureNotify] = resize,
184 [FocusIn] = focus,
185 [FocusOut] = focus,
181}; 186};
182 187
183/* Globals */ 188/* Globals */
@@ -187,7 +192,6 @@ static Term term;
187static CSIEscape escseq; 192static CSIEscape escseq;
188static int cmdfd; 193static int cmdfd;
189static pid_t pid; 194static pid_t pid;
190static int running;
191 195
192#ifdef DEBUG 196#ifdef DEBUG
193void 197void
@@ -227,15 +231,6 @@ execsh(void) {
227 execvp(args[0], args); 231 execvp(args[0], args);
228} 232}
229 233
230void
231xbell(void) {
232 XSetForeground(xw.dis, dc.gc, dc.col[BellCol]);
233 XFillRectangle(xw.dis, xw.win, dc.gc, BORDER, BORDER, xw.bufw, xw.bufh);
234 XFlush(xw.dis);
235 usleep(BellTime);
236 draw(SCREEN_REDRAW);
237}
238
239void 234void
240sigchld(int a) { 235sigchld(int a) {
241 int stat = 0; 236 int stat = 0;
@@ -330,7 +325,7 @@ treset(void) {
330 .mode = ATTR_NULL, 325 .mode = ATTR_NULL,
331 .fg = DefaultFG, 326 .fg = DefaultFG,
332 .bg = DefaultBG 327 .bg = DefaultBG
333 }, .x = 0, .y = 0, .hide = 0}; 328 }, .x = 0, .y = 0, .state = CURSOR_DEFAULT};
334 329
335 term.top = 0, term.bot = term.row - 1; 330 term.top = 0, term.bot = term.row - 1;
336 term.mode = MODE_WRAP; 331 term.mode = MODE_WRAP;
@@ -415,8 +410,11 @@ csiparse(void) {
415 410
416void 411void
417tmoveto(int x, int y) { 412tmoveto(int x, int y) {
418 term.c.x = x < 0 ? 0 : x >= term.col ? term.col-1 : x; 413 LIMIT(x, 0, term.col-1);
419 term.c.y = y < 0 ? 0 : y >= term.row ? term.row-1 : y; 414 LIMIT(y, 0, term.row-1);
415 term.c.state &= ~CURSOR_WRAPNEXT;
416 term.c.x = x;
417 term.c.y = y;
420} 418}
421 419
422void 420void
@@ -712,7 +710,7 @@ csihandle(void) {
712 case 12: /* att610 -- Stop blinking cursor (IGNORED) */ 710 case 12: /* att610 -- Stop blinking cursor (IGNORED) */
713 break; 711 break;
714 case 25: 712 case 25:
715 term.c.hide = CURSOR_HIDE; 713 term.c.state |= CURSOR_HIDE;
716 break; 714 break;
717 case 1048: /* XXX: no alt. screen to erase/save */ 715 case 1048: /* XXX: no alt. screen to erase/save */
718 case 1049: 716 case 1049:
@@ -761,7 +759,7 @@ csihandle(void) {
761 case 12: /* att610 -- Start blinking cursor (IGNORED) */ 759 case 12: /* att610 -- Start blinking cursor (IGNORED) */
762 break; 760 break;
763 case 25: 761 case 25:
764 term.c.hide = CURSOR_DRAW; 762 term.c.state &= ~CURSOR_HIDE;
765 break; 763 break;
766 case 1048: 764 case 1048:
767 case 1049: /* XXX: no alt. screen to erase/save */ 765 case 1049: /* XXX: no alt. screen to erase/save */
@@ -789,6 +787,7 @@ csihandle(void) {
789 DEFAULT(escseq.arg[0], 1); 787 DEFAULT(escseq.arg[0], 1);
790 DEFAULT(escseq.arg[1], term.row); 788 DEFAULT(escseq.arg[1], term.row);
791 tsetscroll(escseq.arg[0]-1, escseq.arg[1]-1); 789 tsetscroll(escseq.arg[0]-1, escseq.arg[1]-1);
790 tmoveto(0, 0);
792 } 791 }
793 break; 792 break;
794 case 's': /* DECSC -- Save cursor position (ANSI.SYS) */ 793 case 's': /* DECSC -- Save cursor position (ANSI.SYS) */
@@ -868,20 +867,11 @@ tputc(char c) {
868 case '(': 867 case '(':
869 term.esc |= ESC_ALTCHARSET; 868 term.esc |= ESC_ALTCHARSET;
870 break; 869 break;
871 case 'A': 870 case 'D': /* IND -- Linefeed */
872 tmoveto(term.c.x, term.c.y-1); 871 if(term.c.y == term.bot)
873 term.esc = 0; 872 tscrollup(1);
874 break; 873 else
875 case 'B': 874 tmoveto(term.c.x, term.c.y+1);
876 tmoveto(term.c.x, term.c.y+1);
877 term.esc = 0;
878 break;
879 case 'C':
880 tmoveto(term.c.x+1, term.c.y);
881 term.esc = 0;
882 break;
883 case 'D': /* XXX: CUP (VT100) or IND (VT52) ... */
884 tmoveto(term.c.x-1, term.c.y);
885 term.esc = 0; 875 term.esc = 0;
886 break; 876 break;
887 case 'E': /* NEL -- Next line */ 877 case 'E': /* NEL -- Next line */
@@ -935,18 +925,21 @@ tputc(char c) {
935 tnewline(); 925 tnewline();
936 break; 926 break;
937 case '\a': 927 case '\a':
938 xbell(); 928 if(!xw.hasfocus)
929 xseturgency(1);
939 break; 930 break;
940 case '\033': 931 case '\033':
941 csireset(); 932 csireset();
942 term.esc = ESC_START; 933 term.esc = ESC_START;
943 break; 934 break;
944 default: 935 default:
936 if(IS_SET(MODE_WRAP) && term.c.state & CURSOR_WRAPNEXT)
937 tnewline();
945 tsetchar(c); 938 tsetchar(c);
946 if(term.c.x+1 < term.col) { 939 if(term.c.x+1 < term.col)
947 tmoveto(term.c.x+1, term.c.y); 940 tmoveto(term.c.x+1, term.c.y);
948 } else if(IS_SET(MODE_WRAP)) 941 else
949 tnewline(); 942 term.c.state |= CURSOR_WRAPNEXT;
950 break; 943 break;
951 } 944 }
952 } 945 }
@@ -984,13 +977,12 @@ tresize(int col, int row) {
984 for(/* i == minrow */; i < row; i++) 977 for(/* i == minrow */; i < row; i++)
985 term.line[i] = calloc(col, sizeof(Glyph)); 978 term.line[i] = calloc(col, sizeof(Glyph));
986 979
987 LIMIT(term.c.x, 0, col-1); 980 /* update terminal size */
988 LIMIT(term.c.y, 0, row-1);
989 LIMIT(term.top, 0, row-1);
990 LIMIT(term.bot, 0, row-1);
991
992 term.bot = row-1;
993 term.col = col, term.row = row; 981 term.col = col, term.row = row;
982 /* make use of the LIMIT in tmoveto */
983 tmoveto(term.c.x, term.c.y);
984 /* reset scrolling region */
985 tsetscroll(0, row-1);
994} 986}
995 987
996void 988void
@@ -1075,9 +1067,6 @@ xinit(void) {
1075 /* colors */ 1067 /* colors */
1076 xloadcols(); 1068 xloadcols();
1077 1069
1078 term.c.attr.fg = DefaultFG;
1079 term.c.attr.bg = DefaultBG;
1080 term.c.attr.mode = ATTR_NULL;
1081 /* windows */ 1070 /* windows */
1082 xw.h = term.row * xw.ch + 2*BORDER; 1071 xw.h = term.row * xw.ch + 2*BORDER;
1083 xw.w = term.col * xw.cw + 2*BORDER; 1072 xw.w = term.col * xw.cw + 2*BORDER;
@@ -1122,7 +1111,7 @@ xdraws(char *s, Glyph base, int x, int y, int len) {
1122} 1111}
1123 1112
1124void 1113void
1125xcursor(int mode) { 1114xdrawcursor(void) {
1126 static int oldx = 0; 1115 static int oldx = 0;
1127 static int oldy = 0; 1116 static int oldy = 0;
1128 Glyph g = {' ', ATTR_NULL, DefaultBG, DefaultCS, 0}; 1117 Glyph g = {' ', ATTR_NULL, DefaultBG, DefaultCS, 0};
@@ -1140,7 +1129,7 @@ xcursor(int mode) {
1140 xclear(oldx, oldy, oldx, oldy); 1129 xclear(oldx, oldy, oldx, oldy);
1141 1130
1142 /* draw the new one */ 1131 /* draw the new one */
1143 if(mode == CURSOR_DRAW) { 1132 if(!(term.c.state & CURSOR_HIDE)) {
1144 xdraws(&g.c, g, term.c.x, term.c.y, 1); 1133 xdraws(&g.c, g, term.c.x, term.c.y, 1);
1145 oldx = term.c.x, oldy = term.c.y; 1134 oldx = term.c.x, oldy = term.c.y;
1146 } 1135 }
@@ -1167,7 +1156,7 @@ draw(int dummy) {
1167 if(term.line[y][x].state & GLYPH_SET) 1156 if(term.line[y][x].state & GLYPH_SET)
1168 xdrawc(x, y, term.line[y][x]); 1157 xdrawc(x, y, term.line[y][x]);
1169 1158
1170 xcursor(term.c.hide); 1159 xdrawcursor();
1171 XCopyArea(xw.dis, xw.buf, xw.win, dc.gc, 0, 0, xw.bufw, xw.bufh, BORDER, BORDER); 1160 XCopyArea(xw.dis, xw.buf, xw.win, dc.gc, 0, 0, xw.bufw, xw.bufh, BORDER, BORDER);
1172 XFlush(xw.dis); 1161 XFlush(xw.dis);
1173} 1162}
@@ -1203,7 +1192,7 @@ draw(int redraw_all) {
1203 if(i > 0) 1192 if(i > 0)
1204 xdraws(buf, base, ox, y, i); 1193 xdraws(buf, base, ox, y, i);
1205 } 1194 }
1206 xcursor(term.c.hide); 1195 xdrawcursor();
1207 XCopyArea(xw.dis, xw.buf, xw.win, dc.gc, 0, 0, xw.bufw, xw.bufh, BORDER, BORDER); 1196 XCopyArea(xw.dis, xw.buf, xw.win, dc.gc, 0, 0, xw.bufw, xw.bufh, BORDER, BORDER);
1208 XFlush(xw.dis); 1197 XFlush(xw.dis);
1209} 1198}
@@ -1215,6 +1204,20 @@ expose(XEvent *ev) {
1215 draw(SCREEN_REDRAW); 1204 draw(SCREEN_REDRAW);
1216} 1205}
1217 1206
1207void
1208xseturgency(int add) {
1209 XWMHints *h = XGetWMHints(xw.dis, xw.win);
1210 h->flags = add ? (h->flags | XUrgencyHint) : (h->flags & ~XUrgencyHint);
1211 XSetWMHints(xw.dis, xw.win, h);
1212 XFree(h);
1213}
1214
1215void
1216focus(XEvent *ev) {
1217 if((xw.hasfocus = ev->type == FocusIn))
1218 xseturgency(0);
1219}
1220
1218char* 1221char*
1219kmap(KeySym k) { 1222kmap(KeySym k) {
1220 int i; 1223 int i;
@@ -1289,12 +1292,12 @@ run(void) {
1289 XEvent ev; 1292 XEvent ev;
1290 fd_set rfd; 1293 fd_set rfd;
1291 int xfd = XConnectionNumber(xw.dis); 1294 int xfd = XConnectionNumber(xw.dis);
1295 long mask = ExposureMask | KeyPressMask | StructureNotifyMask | FocusChangeMask;
1292 1296
1293 running = 1; 1297 XSelectInput(xw.dis, xw.win, mask);
1294 XSelectInput(xw.dis, xw.win, ExposureMask | KeyPressMask | StructureNotifyMask);
1295 XResizeWindow(xw.dis, xw.win, xw.w, xw.h); /* XXX: fix resize bug in wmii (?) */ 1298 XResizeWindow(xw.dis, xw.win, xw.w, xw.h); /* XXX: fix resize bug in wmii (?) */
1296 1299
1297 while(running) { 1300 while(1) {
1298 FD_ZERO(&rfd); 1301 FD_ZERO(&rfd);
1299 FD_SET(cmdfd, &rfd); 1302 FD_SET(cmdfd, &rfd);
1300 FD_SET(xfd, &rfd); 1303 FD_SET(xfd, &rfd);