aboutsummaryrefslogtreecommitdiffstats
path: root/st.c
diff options
context:
space:
mode:
Diffstat (limited to 'st.c')
-rw-r--r--st.c115
1 files changed, 59 insertions, 56 deletions
diff --git a/st.c b/st.c
index 1692f81..436533c 100644
--- a/st.c
+++ b/st.c
@@ -16,7 +16,6 @@
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
-#include <pty.h>
#include <X11/Xlib.h>
#include <X11/keysym.h>
#include <X11/Xutil.h>
@@ -47,8 +46,9 @@
/* 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 = 1,
- CURSOR_DRAW = 0, CURSOR_SAVE, CURSOR_LOAD };
+enum { CURSOR_UP, CURSOR_DOWN, CURSOR_LEFT, CURSOR_RIGHT,
+ CURSOR_SAVE, CURSOR_LOAD };
+enum { CURSOR_DEFAULT = 0, CURSOR_HIDE = 1, CURSOR_WRAPNEXT = 2 };
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 };
@@ -68,7 +68,7 @@ typedef struct {
Glyph attr; /* current char attributes */
int x;
int y;
- char hide;
+ char state;
} TCursor;
/* CSI Escape sequence structs */
@@ -108,6 +108,7 @@ typedef struct {
int bufh; /* pixmap height */
int ch; /* char height */
int cw; /* char width */
+ int hasfocus;
} XWindow;
typedef struct {
@@ -161,23 +162,27 @@ static void ttyread(void);
static void ttyresize(int, int);
static void ttywrite(const char *, size_t);
-static void xbell(void);
static void xdraws(char *, Glyph, int, int, int);
static void xhints(void);
static void xclear(int, int, int, int);
-static void xcursor(int);
+static void xdrawcursor(void);
static void xinit(void);
static void xloadcols(void);
+static void xseturgency(int);
static void expose(XEvent *);
static char* kmap(KeySym);
static void kpress(XEvent *);
static void resize(XEvent *);
+static void focus(XEvent *);
+
static void (*handler[LASTEvent])(XEvent *) = {
[KeyPress] = kpress,
[Expose] = expose,
- [ConfigureNotify] = resize
+ [ConfigureNotify] = resize,
+ [FocusIn] = focus,
+ [FocusOut] = focus,
};
/* Globals */
@@ -187,7 +192,6 @@ static Term term;
static CSIEscape escseq;
static int cmdfd;
static pid_t pid;
-static int running;
#ifdef DEBUG
void
@@ -227,15 +231,6 @@ execsh(void) {
execvp(args[0], args);
}
-void
-xbell(void) {
- XSetForeground(xw.dis, dc.gc, dc.col[BellCol]);
- XFillRectangle(xw.dis, xw.win, dc.gc, BORDER, BORDER, xw.bufw, xw.bufh);
- XFlush(xw.dis);
- usleep(BellTime);
- draw(SCREEN_REDRAW);
-}
-
void
sigchld(int a) {
int stat = 0;
@@ -330,7 +325,7 @@ treset(void) {
.mode = ATTR_NULL,
.fg = DefaultFG,
.bg = DefaultBG
- }, .x = 0, .y = 0, .hide = 0};
+ }, .x = 0, .y = 0, .state = CURSOR_DEFAULT};
term.top = 0, term.bot = term.row - 1;
term.mode = MODE_WRAP;
@@ -415,8 +410,11 @@ csiparse(void) {
void
tmoveto(int x, int y) {
- term.c.x = x < 0 ? 0 : x >= term.col ? term.col-1 : x;
- term.c.y = y < 0 ? 0 : y >= term.row ? term.row-1 : y;
+ LIMIT(x, 0, term.col-1);
+ LIMIT(y, 0, term.row-1);
+ term.c.state &= ~CURSOR_WRAPNEXT;
+ term.c.x = x;
+ term.c.y = y;
}
void
@@ -712,7 +710,7 @@ csihandle(void) {
case 12: /* att610 -- Stop blinking cursor (IGNORED) */
break;
case 25:
- term.c.hide = CURSOR_HIDE;
+ term.c.state |= CURSOR_HIDE;
break;
case 1048: /* XXX: no alt. screen to erase/save */
case 1049:
@@ -761,7 +759,7 @@ csihandle(void) {
case 12: /* att610 -- Start blinking cursor (IGNORED) */
break;
case 25:
- term.c.hide = CURSOR_DRAW;
+ term.c.state &= ~CURSOR_HIDE;
break;
case 1048:
case 1049: /* XXX: no alt. screen to erase/save */
@@ -789,6 +787,7 @@ csihandle(void) {
DEFAULT(escseq.arg[0], 1);
DEFAULT(escseq.arg[1], term.row);
tsetscroll(escseq.arg[0]-1, escseq.arg[1]-1);
+ tmoveto(0, 0);
}
break;
case 's': /* DECSC -- Save cursor position (ANSI.SYS) */
@@ -868,20 +867,11 @@ tputc(char c) {
case '(':
term.esc |= ESC_ALTCHARSET;
break;
- case 'A':
- tmoveto(term.c.x, term.c.y-1);
- term.esc = 0;
- break;
- case 'B':
- tmoveto(term.c.x, term.c.y+1);
- term.esc = 0;
- break;
- case 'C':
- tmoveto(term.c.x+1, term.c.y);
- term.esc = 0;
- break;
- case 'D': /* XXX: CUP (VT100) or IND (VT52) ... */
- tmoveto(term.c.x-1, term.c.y);
+ case 'D': /* IND -- Linefeed */
+ if(term.c.y == term.bot)
+ tscrollup(1);
+ else
+ tmoveto(term.c.x, term.c.y+1);
term.esc = 0;
break;
case 'E': /* NEL -- Next line */
@@ -935,18 +925,21 @@ tputc(char c) {
tnewline();
break;
case '\a':
- xbell();
+ if(!xw.hasfocus)
+ xseturgency(1);
break;
case '\033':
csireset();
term.esc = ESC_START;
break;
default:
+ if(IS_SET(MODE_WRAP) && term.c.state & CURSOR_WRAPNEXT)
+ tnewline();
tsetchar(c);
- if(term.c.x+1 < term.col) {
+ if(term.c.x+1 < term.col)
tmoveto(term.c.x+1, term.c.y);
- } else if(IS_SET(MODE_WRAP))
- tnewline();
+ else
+ term.c.state |= CURSOR_WRAPNEXT;
break;
}
}
@@ -984,13 +977,12 @@ tresize(int col, int row) {
for(/* i == minrow */; i < row; i++)
term.line[i] = calloc(col, sizeof(Glyph));
- LIMIT(term.c.x, 0, col-1);
- LIMIT(term.c.y, 0, row-1);
- LIMIT(term.top, 0, row-1);
- LIMIT(term.bot, 0, row-1);
-
- term.bot = row-1;
+ /* update terminal size */
term.col = col, term.row = row;
+ /* make use of the LIMIT in tmoveto */
+ tmoveto(term.c.x, term.c.y);
+ /* reset scrolling region */
+ tsetscroll(0, row-1);
}
void
@@ -1075,9 +1067,6 @@ xinit(void) {
/* colors */
xloadcols();
- term.c.attr.fg = DefaultFG;
- term.c.attr.bg = DefaultBG;
- term.c.attr.mode = ATTR_NULL;
/* windows */
xw.h = term.row * xw.ch + 2*BORDER;
xw.w = term.col * xw.cw + 2*BORDER;
@@ -1122,7 +1111,7 @@ xdraws(char *s, Glyph base, int x, int y, int len) {
}
void
-xcursor(int mode) {
+xdrawcursor(void) {
static int oldx = 0;
static int oldy = 0;
Glyph g = {' ', ATTR_NULL, DefaultBG, DefaultCS, 0};
@@ -1140,7 +1129,7 @@ xcursor(int mode) {
xclear(oldx, oldy, oldx, oldy);
/* draw the new one */
- if(mode == CURSOR_DRAW) {
+ if(!(term.c.state & CURSOR_HIDE)) {
xdraws(&g.c, g, term.c.x, term.c.y, 1);
oldx = term.c.x, oldy = term.c.y;
}
@@ -1167,7 +1156,7 @@ draw(int dummy) {
if(term.line[y][x].state & GLYPH_SET)
xdrawc(x, y, term.line[y][x]);
- xcursor(term.c.hide);
+ xdrawcursor();
XCopyArea(xw.dis, xw.buf, xw.win, dc.gc, 0, 0, xw.bufw, xw.bufh, BORDER, BORDER);
XFlush(xw.dis);
}
@@ -1203,7 +1192,7 @@ draw(int redraw_all) {
if(i > 0)
xdraws(buf, base, ox, y, i);
}
- xcursor(term.c.hide);
+ xdrawcursor();
XCopyArea(xw.dis, xw.buf, xw.win, dc.gc, 0, 0, xw.bufw, xw.bufh, BORDER, BORDER);
XFlush(xw.dis);
}
@@ -1215,6 +1204,20 @@ expose(XEvent *ev) {
draw(SCREEN_REDRAW);
}
+void
+xseturgency(int add) {
+ XWMHints *h = XGetWMHints(xw.dis, xw.win);
+ h->flags = add ? (h->flags | XUrgencyHint) : (h->flags & ~XUrgencyHint);
+ XSetWMHints(xw.dis, xw.win, h);
+ XFree(h);
+}
+
+void
+focus(XEvent *ev) {
+ if((xw.hasfocus = ev->type == FocusIn))
+ xseturgency(0);
+}
+
char*
kmap(KeySym k) {
int i;
@@ -1289,12 +1292,12 @@ run(void) {
XEvent ev;
fd_set rfd;
int xfd = XConnectionNumber(xw.dis);
+ long mask = ExposureMask | KeyPressMask | StructureNotifyMask | FocusChangeMask;
- running = 1;
- XSelectInput(xw.dis, xw.win, ExposureMask | KeyPressMask | StructureNotifyMask);
+ XSelectInput(xw.dis, xw.win, mask);
XResizeWindow(xw.dis, xw.win, xw.w, xw.h); /* XXX: fix resize bug in wmii (?) */
- while(running) {
+ while(1) {
FD_ZERO(&rfd);
FD_SET(cmdfd, &rfd);
FD_SET(xfd, &rfd);
remember that computers suck.