diff options
| -rw-r--r-- | config.h | 2 | ||||
| -rw-r--r-- | config.mk | 3 | ||||
| -rw-r--r-- | st.c | 115 |
3 files changed, 61 insertions, 59 deletions
| @@ -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 */ |
| 36 | static Key key[] = { | 34 | static Key key[] = { |
| @@ -14,7 +14,8 @@ X11LIB = /usr/X11R6/lib | |||
| 14 | INCS = -I. -I/usr/include -I${X11INC} | 14 | INCS = -I. -I/usr/include -I${X11INC} |
| 15 | LIBS = -L/usr/lib -lc -L${X11LIB} -lX11 -lutil | 15 | LIBS = -L/usr/lib -lc -L${X11LIB} -lX11 -lutil |
| 16 | 16 | ||
| 17 | # uncomment your system # | 17 | # uncomment manualy your system if compilation fail |
| 18 | SYSTEM = -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 |
| @@ -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 */ |
| 49 | enum { ATTR_NULL=0 , ATTR_REVERSE=1 , ATTR_UNDERLINE=2, ATTR_BOLD=4, ATTR_GFX=8 }; | 48 | enum { ATTR_NULL=0 , ATTR_REVERSE=1 , ATTR_UNDERLINE=2, ATTR_BOLD=4, ATTR_GFX=8 }; |
| 50 | enum { CURSOR_UP, CURSOR_DOWN, CURSOR_LEFT, CURSOR_RIGHT, CURSOR_HIDE = 1, | 49 | enum { CURSOR_UP, CURSOR_DOWN, CURSOR_LEFT, CURSOR_RIGHT, |
| 51 | CURSOR_DRAW = 0, CURSOR_SAVE, CURSOR_LOAD }; | 50 | CURSOR_SAVE, CURSOR_LOAD }; |
| 51 | enum { CURSOR_DEFAULT = 0, CURSOR_HIDE = 1, CURSOR_WRAPNEXT = 2 }; | ||
| 52 | enum { GLYPH_SET=1, GLYPH_DIRTY=2 }; | 52 | enum { GLYPH_SET=1, GLYPH_DIRTY=2 }; |
| 53 | enum { MODE_WRAP=1, MODE_INSERT=2, MODE_APPKEYPAD=4 }; | 53 | enum { MODE_WRAP=1, MODE_INSERT=2, MODE_APPKEYPAD=4 }; |
| 54 | enum { ESC_START=1, ESC_CSI=2, ESC_OSC=4, ESC_TITLE=8, ESC_ALTCHARSET=16 }; | 54 | enum { 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 | ||
| 113 | typedef struct { | 114 | typedef struct { |
| @@ -161,23 +162,27 @@ static void ttyread(void); | |||
| 161 | static void ttyresize(int, int); | 162 | static void ttyresize(int, int); |
| 162 | static void ttywrite(const char *, size_t); | 163 | static void ttywrite(const char *, size_t); |
| 163 | 164 | ||
| 164 | static void xbell(void); | ||
| 165 | static void xdraws(char *, Glyph, int, int, int); | 165 | static void xdraws(char *, Glyph, int, int, int); |
| 166 | static void xhints(void); | 166 | static void xhints(void); |
| 167 | static void xclear(int, int, int, int); | 167 | static void xclear(int, int, int, int); |
| 168 | static void xcursor(int); | 168 | static void xdrawcursor(void); |
| 169 | static void xinit(void); | 169 | static void xinit(void); |
| 170 | static void xloadcols(void); | 170 | static void xloadcols(void); |
| 171 | static void xseturgency(int); | ||
| 171 | 172 | ||
| 172 | static void expose(XEvent *); | 173 | static void expose(XEvent *); |
| 173 | static char* kmap(KeySym); | 174 | static char* kmap(KeySym); |
| 174 | static void kpress(XEvent *); | 175 | static void kpress(XEvent *); |
| 175 | static void resize(XEvent *); | 176 | static void resize(XEvent *); |
| 177 | static void focus(XEvent *); | ||
| 178 | |||
| 176 | 179 | ||
| 177 | static void (*handler[LASTEvent])(XEvent *) = { | 180 | static 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; | |||
| 187 | static CSIEscape escseq; | 192 | static CSIEscape escseq; |
| 188 | static int cmdfd; | 193 | static int cmdfd; |
| 189 | static pid_t pid; | 194 | static pid_t pid; |
| 190 | static int running; | ||
| 191 | 195 | ||
| 192 | #ifdef DEBUG | 196 | #ifdef DEBUG |
| 193 | void | 197 | void |
| @@ -227,15 +231,6 @@ execsh(void) { | |||
| 227 | execvp(args[0], args); | 231 | execvp(args[0], args); |
| 228 | } | 232 | } |
| 229 | 233 | ||
| 230 | void | ||
| 231 | xbell(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 | |||
| 239 | void | 234 | void |
| 240 | sigchld(int a) { | 235 | sigchld(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 | ||
| 416 | void | 411 | void |
| 417 | tmoveto(int x, int y) { | 412 | tmoveto(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 | ||
| 422 | void | 420 | void |
| @@ -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 | ||
| 996 | void | 988 | void |
| @@ -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 | ||
| 1124 | void | 1113 | void |
| 1125 | xcursor(int mode) { | 1114 | xdrawcursor(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 | ||
| 1207 | void | ||
| 1208 | xseturgency(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 | |||
| 1215 | void | ||
| 1216 | focus(XEvent *ev) { | ||
| 1217 | if((xw.hasfocus = ev->type == FocusIn)) | ||
| 1218 | xseturgency(0); | ||
| 1219 | } | ||
| 1220 | |||
| 1218 | char* | 1221 | char* |
| 1219 | kmap(KeySym k) { | 1222 | kmap(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); |
