X-Git-Url: https://git.danieliu.xyz/?a=blobdiff_plain;f=st.c;h=108908721d2dab133753096e02c1b4b5ebec7b5a;hb=638a30359d26c1f84a87f0f8df17df1765068029;hp=5633e4060174663901845309d5622277c40aacd6;hpb=97695baf4f9bc3632792a3330fb46e188ef166a2;p=st.git diff --git a/st.c b/st.c index 5633e40..1089087 100644 --- a/st.c +++ b/st.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -28,6 +29,10 @@ #include #endif +#define USAGE \ + "st-" VERSION ", (c) 2010 st engineers\n" \ + "usage: st [-t title] [-e cmd] [-v]\n" + /* Arbitrary sizes */ #define ESC_TITLE_SIZ 256 #define ESC_BUF_SIZ 256 @@ -50,9 +55,11 @@ 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, MODE_ALTSCREEN=8 }; +enum { MODE_WRAP=1, MODE_INSERT=2, MODE_APPKEYPAD=4, MODE_ALTSCREEN=8, + MODE_CRLF=16 }; enum { ESC_START=1, ESC_CSI=2, ESC_OSC=4, ESC_TITLE=8, ESC_ALTCHARSET=16 }; enum { SCREEN_UPDATE, SCREEN_REDRAW }; +enum { WIN_VISIBLE=1, WIN_REDRAW=2, WIN_FOCUSED=4 }; typedef struct { char c; /* character code */ @@ -100,8 +107,11 @@ typedef struct { /* Purely graphic info */ typedef struct { Display* dis; + Colormap cmap; Window win; Pixmap buf; + XIM xim; + XIC xic; int scr; int w; /* window width */ int h; /* window height */ @@ -109,7 +119,7 @@ typedef struct { int bufh; /* pixmap height */ int ch; /* char height */ int cw; /* char width */ - int hasfocus; + char state; /* focus, redraw, visible */ } XWindow; typedef struct { @@ -155,7 +165,7 @@ static void tinsertblank(int); static void tinsertblankline(int); static void tmoveto(int, int); static void tnew(int, int); -static void tnewline(void); +static void tnewline(int); static void tputtab(void); static void tputc(char); static void tputs(char*, int); @@ -180,8 +190,11 @@ static void xdrawcursor(void); static void xinit(void); static void xloadcols(void); static void xseturgency(int); +static void xresize(int, int); static void expose(XEvent *); +static void visibility(XEvent *); +static void unmap(XEvent *); static char* kmap(KeySym); static void kpress(XEvent *); static void resize(XEvent *); @@ -189,17 +202,22 @@ static void focus(XEvent *); static void brelease(XEvent *); static void bpress(XEvent *); static void bmotion(XEvent *); - +static void selection_notify(XEvent *); +static void selection_request(XEvent *); static void (*handler[LASTEvent])(XEvent *) = { [KeyPress] = kpress, - [Expose] = expose, [ConfigureNotify] = resize, + [VisibilityNotify] = visibility, + [UnmapNotify] = unmap, + [Expose] = expose, [FocusIn] = focus, [FocusOut] = focus, [MotionNotify] = bmotion, [ButtonPress] = bpress, [ButtonRelease] = brelease, + [SelectionNotify] = selection_notify, + [SelectionRequest] = selection_request, }; /* Globals */ @@ -210,6 +228,8 @@ static CSIEscape escseq; static int cmdfd; static pid_t pid; static Selection sel; +static char *opt_cmd = NULL; +static char *opt_title = NULL; void selinit(void) { @@ -229,8 +249,9 @@ static inline int selected(int x, int y) { } static void getbuttoninfo(XEvent *e, int *b, int *x, int *y) { - if(b) *b = e->xbutton.state, - *b=*b==4096?5:*b==2048?4:*b==1024?3:*b==512?2:*b==256?1:-1; + if(b) + *b = e->xbutton.button; + *x = e->xbutton.x/xw.cw; *y = e->xbutton.y/xw.ch; sel.b.x = sel.by < sel.ey ? sel.bx : sel.ex; @@ -263,15 +284,129 @@ static char *getseltext() { return str; } -/* TODO: use X11 clipboard */ +static void selection_notify(XEvent *e) { + unsigned long nitems; + unsigned long length; + int format, res; + unsigned char *data; + Atom type; + + res = XGetWindowProperty(xw.dis, xw.win, XA_PRIMARY, 0, 0, False, + AnyPropertyType, &type, &format, &nitems, &length, &data); + switch(res) { + case BadAtom: + case BadValue: + case BadWindow: + fprintf(stderr, "Invalid paste, XGetWindowProperty0"); + return; + } + + res = XGetWindowProperty(xw.dis, xw.win, XA_PRIMARY, 0, length, False, + AnyPropertyType, &type, &format, &nitems, &length, &data); + switch(res) { + case BadAtom: + case BadValue: + case BadWindow: + fprintf(stderr, "Invalid paste, XGetWindowProperty0"); + return; + } + + if(data) { + ttywrite((const char *) data, nitems * format / 8); + XFree(data); + } +} + +static void selpaste() { + XConvertSelection(xw.dis, XA_PRIMARY, XA_STRING, XA_PRIMARY, xw.win, CurrentTime); +} + +static void selection_request(XEvent *e) +{ + XSelectionRequestEvent *xsre; + XSelectionEvent xev; + int res; + Atom xa_targets; + + xsre = (XSelectionRequestEvent *) e; + xev.type = SelectionNotify; + xev.requestor = xsre->requestor; + xev.selection = xsre->selection; + xev.target = xsre->target; + xev.time = xsre->time; + /* reject */ + xev.property = None; + + xa_targets = XInternAtom(xw.dis, "TARGETS", 0); + if(xsre->target == xa_targets) { + /* respond with the supported type */ + Atom string = XA_STRING; + res = XChangeProperty(xsre->display, xsre->requestor, xsre->property, XA_ATOM, 32, + PropModeReplace, (unsigned char *) &string, 1); + switch(res) { + case BadAlloc: + case BadAtom: + case BadMatch: + case BadValue: + case BadWindow: + fprintf(stderr, "Error in selection_request, TARGETS"); + break; + default: + xev.property = xsre->property; + } + } else if(xsre->target == XA_STRING) { + res = XChangeProperty(xsre->display, xsre->requestor, xsre->property, + xsre->target, 8, PropModeReplace, (unsigned char *) sel.clip, + strlen(sel.clip)); + switch(res) { + case BadAlloc: + case BadAtom: + case BadMatch: + case BadValue: + case BadWindow: + fprintf(stderr, "Error in selection_request, XA_STRING"); + break; + default: + xev.property = xsre->property; + } + } + + /* all done, send a notification to the listener */ + res = XSendEvent(xsre->display, xsre->requestor, True, 0, (XEvent *) &xev); + switch(res) { + case 0: + case BadValue: + case BadWindow: + fprintf(stderr, "Error in selection_requested, XSendEvent"); + } +} + static void selcopy(char *str) { + /* register the selection for both the clipboard and the primary */ + Atom clipboard; + int res; + free(sel.clip); sel.clip = str; -} -static void selpaste() { - if(sel.clip) - ttywrite(sel.clip, strlen(sel.clip)); + res = XSetSelectionOwner(xw.dis, XA_PRIMARY, xw.win, CurrentTime); + switch(res) { + case BadAtom: + case BadWindow: + fprintf(stderr, "Invalid copy, XSetSelectionOwner"); + return; + } + + clipboard = XInternAtom(xw.dis, "CLIPBOARD", 0); + res = XSetSelectionOwner(xw.dis, clipboard, xw.win, CurrentTime); + switch(res) { + case BadAtom: + case BadWindow: + fprintf(stderr, "Invalid copy, XSetSelectionOwner"); + return; + } + + XFlush(xw.dis); } /* TODO: doubleclick to select word */ @@ -329,9 +464,12 @@ die(const char *errstr, ...) { void execsh(void) { - char *args[3] = {getenv("SHELL"), "-i", NULL}; - DEFAULT(args[0], SHELL); /* if getenv() failed */ - putenv("TERM=" TNAME); + char *args[] = {getenv("SHELL"), "-i", NULL}; + if(opt_cmd) + args[0] = opt_cmd, args[1] = NULL; + else + DEFAULT(args[0], SHELL); + putenv("TERM="TNAME); execvp(args[0], args); } @@ -490,13 +628,13 @@ tscrollup(int orig, int n) { } void -tnewline(void) { +tnewline(int first_col) { int y = term.c.y; - if(term.c.y == term.bot) + if(y == term.bot) tscrollup(term.top, 1); else y++; - tmoveto(0, y); + tmoveto(first_col ? 0 : term.c.x, y); } void @@ -541,7 +679,7 @@ tsetchar(char c) { void tclearregion(int x1, int y1, int x2, int y2) { - int y, temp; + int x, y, temp; if(x1 > x2) temp = x1, x1 = x2, x2 = temp; @@ -554,7 +692,8 @@ tclearregion(int x1, int y1, int x2, int y2) { LIMIT(y2, 0, term.row-1); for(y = y1; y <= y2; y++) - memset(&term.line[y][x1], 0, sizeof(Glyph)*(x2-x1+1)); + for(x = x1; x <= x2; x++) + term.line[y][x].state = 0; } void @@ -668,7 +807,8 @@ tsetattr(int *attr, int l) { else if(BETWEEN(attr[i], 100, 107)) term.c.attr.fg = attr[i] - 100 + 8; else - fprintf(stderr, "erresc: gfx attr %d unknown\n", attr[i]); + fprintf(stderr, "erresc: gfx attr %d unknown\n", attr[i]), csidump(); + break; } } @@ -786,11 +926,16 @@ csihandle(void) { case 1: term.mode &= ~MODE_APPKEYPAD; break; + case 5: /* TODO: DECSCNM -- Remove reverse video */ + break; case 7: term.mode &= ~MODE_WRAP; break; case 12: /* att610 -- Stop blinking cursor (IGNORED) */ break; + case 20: + term.mode &= ~MODE_CRLF; + break; case 25: term.c.state |= CURSOR_HIDE; break; @@ -841,11 +986,19 @@ csihandle(void) { case 1: term.mode |= MODE_APPKEYPAD; break; + case 5: /* DECSCNM -- Reverve video */ + /* TODO: set REVERSE on the whole screen (f) */ + break; case 7: term.mode |= MODE_WRAP; break; - case 12: /* att610 -- Start blinking cursor (IGNORED) */ + case 20: + term.mode |= MODE_CRLF; break; + case 12: /* att610 -- Start blinking cursor (IGNORED) */ + /* fallthrough for xterm cvvis = CSI [ ? 12 ; 25 h */ + if(escseq.narg > 1 && escseq.arg[1] != 25) + break; case 25: term.c.state &= ~CURSOR_HIDE; break; @@ -970,7 +1123,7 @@ tputc(char c) { term.esc = 0; break; case 'E': /* NEL -- Next line */ - tnewline(); + tnewline(1); /* always go to first col */ term.esc = 0; break; case 'M': /* RI -- Reverse index */ @@ -1016,11 +1169,14 @@ tputc(char c) { case '\r': tmoveto(0, term.c.y); break; + case '\f': + case '\v': case '\n': - tnewline(); + /* go to first col if the mode is set */ + tnewline(IS_SET(MODE_CRLF)); break; case '\a': - if(!xw.hasfocus) + if(!(xw.state & WIN_FOCUSED)) xseturgency(1); break; case '\033': @@ -1029,7 +1185,7 @@ tputc(char c) { break; default: if(IS_SET(MODE_WRAP) && term.c.state & CURSOR_WRAPNEXT) - tnewline(); + tnewline(1); /* always go to first col */ tsetchar(c); if(term.c.x+1 < term.col) tmoveto(term.c.x+1, term.c.y); @@ -1048,15 +1204,28 @@ tputs(char *s, int len) { void tresize(int col, int row) { - int i; + int i, x; int minrow = MIN(row, term.row); int mincol = MIN(col, term.col); + int slide = term.c.y - row + 1; if(col < 1 || row < 1) return; - /* free uneeded rows */ - for(i = row; i < term.row; i++) { + /* free unneeded rows */ + i = 0; + if(slide > 0) { + /* slide screen to keep cursor where we expect it - + * tscrollup would work here, but we can optimize to + * memmove because we're freeing the earlier lines */ + for(/* i = 0 */; i < slide; i++) { + free(term.line[i]); + free(term.alt[i]); + } + memmove(term.line, term.line + slide, row * sizeof(Line)); + memmove(term.alt, term.alt + slide, row * sizeof(Line)); + } + for(i += row; i < term.row; i++) { free(term.line[i]); free(term.alt[i]); } @@ -1069,8 +1238,10 @@ tresize(int col, int row) { for(i = 0; i < minrow; i++) { term.line[i] = realloc(term.line[i], col * sizeof(Glyph)); term.alt[i] = realloc(term.alt[i], col * sizeof(Glyph)); - memset(term.line[i] + mincol, 0, (col - mincol) * sizeof(Glyph)); - memset(term.alt[i] + mincol, 0, (col - mincol) * sizeof(Glyph)); + for(x = mincol; x < col; x++) { + term.line[i][x].state = 0; + term.alt[i][x].state = 0; + } } /* allocate any new rows */ @@ -1087,15 +1258,44 @@ tresize(int col, int row) { tsetscroll(0, row-1); } +void +xresize(int col, int row) { + Pixmap newbuf; + int oldw, oldh; + + oldw = xw.bufw; + oldh = xw.bufh; + xw.bufw = MAX(1, col * xw.cw); + xw.bufh = MAX(1, row * xw.ch); + newbuf = XCreatePixmap(xw.dis, xw.win, xw.bufw, xw.bufh, XDefaultDepth(xw.dis, xw.scr)); + XCopyArea(xw.dis, xw.buf, newbuf, dc.gc, 0, 0, xw.bufw, xw.bufh, 0, 0); + XFreePixmap(xw.dis, xw.buf); + XSetForeground(xw.dis, dc.gc, dc.col[DefaultBG]); + if(xw.bufw > oldw) + XFillRectangle(xw.dis, newbuf, dc.gc, oldw, 0, + xw.bufw-oldw, MIN(xw.bufh, oldh)); + else if(xw.bufw < oldw && (BORDER > 0 || xw.w > xw.bufw)) + XClearArea(xw.dis, xw.win, BORDER+xw.bufw, BORDER, + xw.w-xw.bufh-BORDER, BORDER+MIN(xw.bufh, oldh), + False); + if(xw.bufh > oldh) + XFillRectangle(xw.dis, newbuf, dc.gc, 0, oldh, + xw.bufw, xw.bufh-oldh); + else if(xw.bufh < oldh && (BORDER > 0 || xw.h > xw.bufh)) + XClearArea(xw.dis, xw.win, BORDER, BORDER+xw.bufh, + xw.w-2*BORDER, xw.h-xw.bufh-BORDER, + False); + xw.buf = newbuf; +} + void xloadcols(void) { int i, r, g, b; XColor color; - Colormap cmap = DefaultColormap(xw.dis, xw.scr); unsigned long white = WhitePixel(xw.dis, xw.scr); for(i = 0; i < 16; i++) { - if (!XAllocNamedColor(xw.dis, cmap, colorname[i], &color, &color)) { + if (!XAllocNamedColor(xw.dis, xw.cmap, colorname[i], &color, &color)) { dc.col[i] = white; fprintf(stderr, "Could not allocate color '%s'\n", colorname[i]); } else @@ -1109,7 +1309,7 @@ xloadcols(void) { color.red = r == 0 ? 0 : 0x3737 + 0x2828 * r; color.green = g == 0 ? 0 : 0x3737 + 0x2828 * g; color.blue = b == 0 ? 0 : 0x3737 + 0x2828 * b; - if (!XAllocColor(xw.dis, cmap, &color)) { + if (!XAllocColor(xw.dis, xw.cmap, &color)) { dc.col[i] = white; fprintf(stderr, "Could not allocate color %d\n", i); } else @@ -1119,7 +1319,7 @@ xloadcols(void) { for(r = 0; r < 24; r++, i++) { color.red = color.green = color.blue = 0x0808 + 0x0a0a * r; - if (!XAllocColor(xw.dis, cmap, &color)) { + if (!XAllocColor(xw.dis, xw.cmap, &color)) { dc.col[i] = white; fprintf(stderr, "Could not allocate color %d\n", i); } else @@ -1154,6 +1354,8 @@ xhints(void) void xinit(void) { + XSetWindowAttributes attrs; + if(!(xw.dis = XOpenDisplay(NULL))) die("Can't open display\n"); xw.scr = XDefaultScreen(xw.dis); @@ -1167,29 +1369,43 @@ xinit(void) { xw.ch = dc.font->ascent + dc.font->descent; /* colors */ + xw.cmap = XDefaultColormap(xw.dis, xw.scr); xloadcols(); - /* windows */ - xw.bufh = term.row * xw.ch; - xw.bufw = term.col * xw.cw; + /* window - default size */ + xw.bufh = 24 * xw.ch; + xw.bufw = 80 * xw.cw; xw.h = xw.bufh + 2*BORDER; xw.w = xw.bufw + 2*BORDER; - xw.win = XCreateSimpleWindow(xw.dis, XRootWindow(xw.dis, xw.scr), 0, 0, - xw.w, xw.h, 0, - dc.col[DefaultBG], - dc.col[DefaultBG]); + + attrs.background_pixel = dc.col[DefaultBG]; + attrs.border_pixel = dc.col[DefaultBG]; + attrs.bit_gravity = NorthWestGravity; + attrs.event_mask = FocusChangeMask | KeyPressMask + | ExposureMask | VisibilityChangeMask | StructureNotifyMask + | PointerMotionMask | ButtonPressMask | ButtonReleaseMask; + attrs.colormap = xw.cmap; + + xw.win = XCreateWindow(xw.dis, XRootWindow(xw.dis, xw.scr), 0, 0, + xw.w, xw.h, 0, XDefaultDepth(xw.dis, xw.scr), InputOutput, + XDefaultVisual(xw.dis, xw.scr), + CWBackPixel | CWBorderPixel | CWBitGravity | CWEventMask + | CWColormap, + &attrs); xw.buf = XCreatePixmap(xw.dis, xw.win, xw.bufw, xw.bufh, XDefaultDepth(xw.dis, xw.scr)); + + + /* input methods */ + xw.xim = XOpenIM(xw.dis, NULL, NULL, NULL); + xw.xic = XCreateIC(xw.xim, XNInputStyle, XIMPreeditNothing + | XIMStatusNothing, XNClientWindow, xw.win, + XNFocusWindow, xw.win, NULL); /* gc */ dc.gc = XCreateGC(xw.dis, xw.win, 0, NULL); - - /* event mask */ - XSelectInput(xw.dis, xw.win, ExposureMask | KeyPressMask - | StructureNotifyMask | FocusChangeMask | PointerMotionMask - | ButtonPressMask | ButtonReleaseMask); XMapWindow(xw.dis, xw.win); xhints(); - XStoreName(xw.dis, xw.win, "st"); + XStoreName(xw.dis, xw.win, opt_title ? opt_title : "st"); XSync(xw.dis, 0); } @@ -1208,8 +1424,13 @@ xdraws(char *s, Glyph base, int x, int y, int len) { XSetForeground(xw.dis, dc.gc, xfg); if(base.mode & ATTR_GFX) - for(i = 0; i < len; i++) - s[i] = gfx[(int)s[i]]; + for(i = 0; i < len; i++) { + char c = gfx[(unsigned int)s[i] % 256]; + if(c) + s[i] = c; + else if(s[i] > 0x5f) + s[i] -= 0x5f; + } XSetFont(xw.dis, dc.gc, base.mode & ATTR_BOLD ? dc.bfont->fid : dc.font->fid); XDrawImageString(xw.dis, xw.buf, dc.gc, winx, winy, s, len); @@ -1237,7 +1458,7 @@ xdrawcursor(void) { xclear(oldx, oldy, oldx, oldy); /* draw the new one */ - if(!(term.c.state & CURSOR_HIDE) && xw.hasfocus) { + if(!(term.c.state & CURSOR_HIDE) && (xw.state & WIN_FOCUSED)) { xdraws(&g.c, g, term.c.x, term.c.y, 1); oldx = term.c.x, oldy = term.c.y; } @@ -1277,8 +1498,10 @@ draw(int redraw_all) { Glyph base, new; char buf[DRAW_BUF_SIZ]; - XSetForeground(xw.dis, dc.gc, dc.col[DefaultBG]); - XFillRectangle(xw.dis, xw.buf, dc.gc, 0, 0, xw.bufw, xw.bufh); + if(!(xw.state & WIN_VISIBLE)) + return; + + xclear(0, 0, term.col-1, term.row-1); for(y = 0; y < term.row; y++) { base = term.line[y][0]; i = ox = 0; @@ -1304,14 +1527,36 @@ draw(int redraw_all) { } xdrawcursor(); XCopyArea(xw.dis, xw.buf, xw.win, dc.gc, 0, 0, xw.bufw, xw.bufh, BORDER, BORDER); - XFlush(xw.dis); } #endif void expose(XEvent *ev) { - draw(SCREEN_REDRAW); + XExposeEvent *e = &ev->xexpose; + if(xw.state & WIN_REDRAW) { + if(!e->count) { + xw.state &= ~WIN_REDRAW; + draw(SCREEN_REDRAW); + } + } else + XCopyArea(xw.dis, xw.buf, xw.win, dc.gc, e->x-BORDER, e->y-BORDER, + e->width, e->height, e->x, e->y); +} + +void +visibility(XEvent *ev) { + XVisibilityEvent *e = &ev->xvisibility; + if(e->state == VisibilityFullyObscured) + xw.state &= ~WIN_VISIBLE; + else if(!(xw.state & WIN_VISIBLE)) + /* need a full redraw for next Expose, not just a buf copy */ + xw.state |= WIN_VISIBLE | WIN_REDRAW; +} + +void +unmap(XEvent *ev) { + xw.state &= ~WIN_VISIBLE; } void @@ -1324,8 +1569,11 @@ xseturgency(int add) { void focus(XEvent *ev) { - if((xw.hasfocus = ev->type == FocusIn)) + if(ev->type == FocusIn) { + xw.state |= WIN_FOCUSED; xseturgency(0); + } else + xw.state &= ~WIN_FOCUSED; draw(SCREEN_UPDATE); } @@ -1347,19 +1595,17 @@ kpress(XEvent *ev) { int len; int meta; int shift; + Status status; meta = e->state & Mod1Mask; shift = e->state & ShiftMask; - len = XLookupString(e, buf, sizeof(buf), &ksym, NULL); - + len = XmbLookupString(xw.xic, e, buf, sizeof(buf), &ksym, &status); + + /* 1. custom keys from config.h */ if((customkey = kmap(ksym))) ttywrite(customkey, strlen(customkey)); - else if(len > 0) { - buf[sizeof(buf)-1] = '\0'; - if(meta && len == 1) - ttywrite("\033", 1); - ttywrite(buf, len); - } else + /* 2. hardcoded (overrides X lookup) */ + else switch(ksym) { case XK_Up: case XK_Down: @@ -1370,10 +1616,23 @@ kpress(XEvent *ev) { break; case XK_Insert: if(shift) - selpaste(), draw(1); + selpaste(); + break; + case XK_Return: + if(IS_SET(MODE_CRLF)) + ttywrite("\r\n", 2); + else + ttywrite("\r", 1); break; + /* 3. X lookup */ default: - fprintf(stderr, "errkey: %d\n", (int)ksym); + if(len > 0) { + buf[sizeof(buf)-1] = '\0'; + if(meta && len == 1) + ttywrite("\033", 1); + ttywrite(buf, len); + } else /* 4. nothing to send */ + fprintf(stderr, "errkey: %d\n", (int)ksym); break; } } @@ -1387,17 +1646,13 @@ resize(XEvent *e) { xw.w = e->xconfigure.width; xw.h = e->xconfigure.height; - xw.bufw = xw.w - 2*BORDER; - xw.bufh = xw.h - 2*BORDER; - col = xw.bufw / xw.cw; - row = xw.bufh / xw.ch; + col = (xw.w - 2*BORDER) / xw.cw; + row = (xw.h - 2*BORDER) / xw.ch; + if(col == term.col && row == term.row) + return; tresize(col, row); ttyresize(col, row); - xw.bufh = MAX(1, xw.bufh); - xw.bufw = MAX(1, xw.bufw); - XFreePixmap(xw.dis, xw.buf); - xw.buf = XCreatePixmap(xw.dis, xw.win, xw.bufw, xw.bufh, XDefaultDepth(xw.dis, xw.scr)); - draw(SCREEN_REDRAW); + xresize(col, row); } void @@ -1421,6 +1676,8 @@ run(void) { } while(XPending(xw.dis)) { XNextEvent(xw.dis, &ev); + if (XFilterEvent(&ev, xw.win)) + continue; if(handler[ev.type]) (handler[ev.type])(&ev); } @@ -1429,10 +1686,21 @@ run(void) { int main(int argc, char *argv[]) { - if(argc == 2 && !strncmp("-v", argv[1], 3)) - die("st-" VERSION ", (c) 2010 st engineers\n"); - else if(argc != 1) - die("usage: st [-v]\n"); + int i; + + for(i = 1; i < argc; i++) { + switch(argv[i][0] != '-' || argv[i][2] ? -1 : argv[i][1]) { + case 't': + if(++i < argc) opt_title = argv[i]; + break; + case 'e': + if(++i < argc) opt_cmd = argv[i]; + break; + case 'v': + default: + die(USAGE); + } + } setlocale(LC_CTYPE, ""); tnew(80, 24); ttynew();