X-Git-Url: https://jasonwoof.com/gitweb/?a=blobdiff_plain;f=st.c;h=701019558d21104c1467610b85619fbc9450b413;hb=c772a6e5719aa24d10d664262383b76a36e3458b;hp=8bf9337b74cc5e18e4bf7dcb4d65dcd5e39c5ed3;hpb=73177ba366e5363b8a6695882b52617a8909a925;p=st.git diff --git a/st.c b/st.c index 8bf9337..7010195 100644 --- a/st.c +++ b/st.c @@ -59,13 +59,12 @@ #define STR_ARG_SIZ 16 #define DRAW_BUF_SIZ 20*1024 #define UTF_SIZ 4 -#define XK_NO_MOD UINT_MAX -#define XK_ANY_MOD 0 +#define XK_ANY_MOD UINT_MAX +#define XK_NO_MOD 0 #define REDRAW_TIMEOUT (80*1000) /* 80 ms */ /* macros */ -#define CLEANMASK(mask) (mask & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask)) #define SERRNO strerror(errno) #define MIN(a, b) ((a) < (b) ? (a) : (b)) #define MAX(a, b) ((a) < (b) ? (b) : (a)) @@ -74,7 +73,7 @@ #define BETWEEN(x, a, b) ((a) <= (x) && (x) <= (b)) #define LIMIT(x, a, b) (x) = (x) < (a) ? (a) : (x) > (b) ? (b) : (x) #define ATTRCMP(a, b) ((a).mode != (b).mode || (a).fg != (b).fg || (a).bg != (b).bg) -#define IS_SET(flag) (term.mode & (flag)) +#define IS_SET(flag) ((term.mode & (flag)) != 0) #define TIMEDIFF(t1, t2) ((t1.tv_sec-t2.tv_sec)*1000 + (t1.tv_usec-t2.tv_usec)/1000) #define VT102ID "\033[?6c" @@ -90,10 +89,6 @@ enum glyph_attribute { }; enum cursor_movement { - CURSOR_UP, - CURSOR_DOWN, - CURSOR_LEFT, - CURSOR_RIGHT, CURSOR_SAVE, CURSOR_LOAD }; @@ -121,7 +116,8 @@ enum term_mode { MODE_REVERSE = 128, MODE_KBDLOCK = 256, MODE_HIDE = 512, - MODE_ECHO = 1024 + MODE_ECHO = 1024, + MODE_APPCURSOR = 2048 }; enum escape_state { @@ -198,6 +194,7 @@ typedef struct { int bot; /* bottom scroll limit */ int mode; /* terminal mode flags */ int esc; /* escape state flags */ + bool numlock; /* lock numbers in keyboard */ bool *tabs; } Term; @@ -227,6 +224,10 @@ typedef struct { KeySym k; uint mask; char s[ESC_BUF_SIZ]; + /* three valued logic variables: 0 indifferent, 1 on, -1 off */ + signed char appkey; /* application keypad */ + signed char appcursor; /* application cursor */ + signed char crlf; /* crlf mode */ } Key; /* TODO: use better name for vars... */ @@ -260,6 +261,8 @@ typedef struct { /* function definitions used in config.h */ static void xzoom(const Arg *); +static void selpaste(const Arg *); +static void numlock(const Arg *); /* Config.h for applying patches and the configuration. */ #include "config.h" @@ -272,7 +275,9 @@ typedef struct { int descent; short lbearing; short rbearing; - XftFont *set; + XftFont *match; + FcFontSet *set; + FcPattern *pattern; } Font; /* Drawing Context */ @@ -323,6 +328,7 @@ static void tsetmode(bool, bool, int *, int); static void tfulldirt(void); static void techo(char *, int); +static inline bool match(uint, uint); static void ttynew(void); static void ttyread(void); static void ttyresize(void); @@ -334,10 +340,13 @@ static void xclear(int, int, int, int); static void xdrawcursor(void); static void xinit(void); static void xloadcols(void); +static int xloadfont(Font *, FcPattern *); +static void xloadfonts(char *, int); static void xresettitle(void); static void xseturgency(int); static void xsetsel(char*); static void xtermclear(int, int, int, int); +static void xunloadfonts(void); static void xresize(int, int); static void expose(XEvent *); @@ -346,7 +355,7 @@ static void unmap(XEvent *); static char *kmap(KeySym, uint); static void kpress(XEvent *); static void cmessage(XEvent *); -static void cresize(int width, int height); +static void cresize(int, int); static void resize(XEvent *); static void focus(XEvent *); static void brelease(XEvent *); @@ -359,7 +368,6 @@ static void selrequest(XEvent *); static void selinit(void); static inline bool selected(int, int); static void selcopy(void); -static void selpaste(void); static void selscroll(int, int); static int utf8decode(char *, long *); @@ -370,7 +378,7 @@ static int isfullutf8(char *, int); static ssize_t xwrite(int, char *, size_t); static void *xmalloc(size_t); static void *xrealloc(void *, size_t); -static void *xcalloc(size_t nmemb, size_t size); +static void *xcalloc(size_t, size_t); static void (*handler[LASTEvent])(XEvent *) = { [KeyPress] = kpress, @@ -409,6 +417,28 @@ static char *opt_font = NULL; static char *usedfont = NULL; static int usedfontsize = 0; +/* Font Ring Cache */ +enum { + FRC_NORMAL, + FRC_ITALIC, + FRC_BOLD, + FRC_ITALICBOLD +}; + +typedef struct { + XftFont *font; + long c; + int flags; +} Fontcache; + +/* + * Fontcache is a ring buffer, with frccur as current position and frclen as + * the current length of used elements. + */ + +static Fontcache frc[2]; +static int frccur = -1, frclen = 0; + ssize_t xwrite(int fd, char *s, size_t len) { size_t aux = len; @@ -620,12 +650,11 @@ selected(int x, int y) { } void -getbuttoninfo(XEvent *e, int *b, int *x, int *y) { - if(b) - *b = e->xbutton.button; +getbuttoninfo(XEvent *e) { + sel.alt = IS_SET(MODE_ALTSCREEN); - *x = x2col(e->xbutton.x); - *y = y2row(e->xbutton.y); + sel.ex = x2col(e->xbutton.x); + sel.ey = y2row(e->xbutton.y); sel.b.x = sel.by < sel.ey ? sel.bx : sel.ex; sel.b.y = MIN(sel.by, sel.ey); @@ -722,7 +751,6 @@ selcopy(void) { } *ptr = 0; } - sel.alt = IS_SET(MODE_ALTSCREEN); xsetsel(str); } @@ -749,7 +777,7 @@ selnotify(XEvent *e) { } void -selpaste(void) { +selpaste(const Arg *dummy) { XConvertSelection(xw.dpy, XA_PRIMARY, sel.xtarget, XA_PRIMARY, xw.win, CurrentTime); } @@ -820,10 +848,10 @@ brelease(XEvent *e) { } if(e->xbutton.button == Button2) { - selpaste(); + selpaste(NULL); } else if(e->xbutton.button == Button1) { sel.mode = 0; - getbuttoninfo(e, NULL, &sel.ex, &sel.ey); + getbuttoninfo(e); term.dirty[sel.ey] = 1; if(sel.bx == sel.ex && sel.by == sel.ey) { sel.bx = -1; @@ -869,16 +897,17 @@ bmotion(XEvent *e) { return; } - if(sel.mode) { - oldey = sel.ey; - oldex = sel.ex; - getbuttoninfo(e, NULL, &sel.ex, &sel.ey); + if(!sel.mode) + return; + + oldey = sel.ey; + oldex = sel.ex; + getbuttoninfo(e); - if(oldey != sel.ey || oldex != sel.ex) { - starty = MIN(oldey, sel.ey); - endy = MAX(oldey, sel.ey); - tsetdirt(starty, endy); - } + if(oldey != sel.ey || oldex != sel.ex) { + starty = MIN(oldey, sel.ey); + endy = MAX(oldey, sel.ey); + tsetdirt(starty, endy); } } @@ -1102,6 +1131,8 @@ tnew(int col, int row) { term.alt [row] = xmalloc(term.col * sizeof(Glyph)); term.dirty[row] = 0; } + + term.numlock = 1; memset(term.tabs, 0, term.col * sizeof(*term.tabs)); /* setup screen */ treset(); @@ -1471,7 +1502,7 @@ tsetmode(bool priv, bool set, int *args, int narg) { switch(*args) { break; case 1: /* DECCKM -- Cursor key */ - MODBIT(term.mode, set, MODE_APPKEYPAD); + MODBIT(term.mode, set, MODE_APPCURSOR); break; case 5: /* DECSCNM -- Reverse video */ mode = term.mode; @@ -1508,7 +1539,7 @@ tsetmode(bool priv, bool set, int *args, int narg) { case 1049: /* = 1047 and 1048 */ case 47: case 1047: { - alt = IS_SET(MODE_ALTSCREEN) != 0; + alt = IS_SET(MODE_ALTSCREEN); if(alt) tclearregion(0, 0, term.col-1, term.row-1); if(set ^ alt) /* set is always 1 or 0 */ @@ -2081,7 +2112,7 @@ tputc(char *c, int len) { } } /* - * All characters which forms part of a sequence are not + * All characters which form part of a sequence are not * printed */ return; @@ -2095,11 +2126,19 @@ tputc(char *c, int len) { sel.bx = -1; if(IS_SET(MODE_WRAP) && term.c.state & CURSOR_WRAPNEXT) tnewline(1); /* always go to first col */ + + if(IS_SET(MODE_INSERT) && term.c.x+1 < term.col) { + memmove(&term.line[term.c.y][term.c.x+1], + &term.line[term.c.y][term.c.x], + (term.col - term.c.x - 1) * sizeof(Glyph)); + } + tsetchar(c, &term.c.attr, term.c.x, term.c.y); - if(term.c.x+1 < term.col) + if(term.c.x+1 < term.col) { tmoveto(term.c.x+1, term.c.y); - else + } else { term.c.state |= CURSOR_WRAPNEXT; + } } int @@ -2176,8 +2215,8 @@ tresize(int col, int row) { void xresize(int col, int row) { - xw.tw = MAX(1, 2*borderpx + col * xw.cw); - xw.th = MAX(1, 2*borderpx + row * xw.ch); + xw.tw = MAX(1, col * xw.cw); + xw.th = MAX(1, row * xw.ch); XftDrawChange(xw.draw, xw.buf); } @@ -2236,7 +2275,7 @@ xtermclear(int col1, int row1, int col2, int row2) { void xclear(int x1, int y1, int x2, int y2) { XftDrawRect(xw.draw, - &dc.col[IS_SET(MODE_REVERSE) ? defaultfg : defaultbg], + &dc.col[IS_SET(MODE_REVERSE)? defaultfg : defaultbg], x1, y1, x2-x1, y2-y1); } @@ -2253,8 +2292,8 @@ xhints(void) { sizeh->width = xw.w; sizeh->height_inc = xw.ch; sizeh->width_inc = xw.cw; - sizeh->base_height = 2*borderpx; - sizeh->base_width = 2*borderpx; + sizeh->base_height = 2 * borderpx; + sizeh->base_width = 2 * borderpx; } else { sizeh->flags = PMaxSize | PMinSize; sizeh->min_width = sizeh->max_width = xw.fw; @@ -2270,20 +2309,28 @@ xloadfont(Font *f, FcPattern *pattern) { FcPattern *match; FcResult result; - match = XftFontMatch(xw.dpy, xw.scr, pattern, &result); + match = FcFontMatch(NULL, pattern, &result); if(!match) return 1; - if(!(f->set = XftFontOpenPattern(xw.dpy, match))) { + + if(!(f->set = FcFontSort(0, match, FcTrue, 0, &result))) { FcPatternDestroy(match); return 1; } - f->ascent = f->set->ascent; - f->descent = f->set->descent; + if(!(f->match = XftFontOpenPattern(xw.dpy, match))) { + FcPatternDestroy(match); + return 1; + } + + f->pattern = FcPatternDuplicate(pattern); + + f->ascent = f->match->ascent; + f->descent = f->match->descent; f->lbearing = 0; - f->rbearing = f->set->max_advance_width; + f->rbearing = f->match->max_advance_width; - f->height = f->set->height; + f->height = f->match->height; f->width = f->lbearing + f->rbearing; return 0; @@ -2322,6 +2369,9 @@ xloadfonts(char *fontstr, int fontsize) { } } + FcConfigSubstitute(0, pattern, FcMatchPattern); + FcDefaultSubstitute(pattern); + if(xloadfont(&dc.font, pattern)) die("st: can't open font %s\n", fontstr); @@ -2347,8 +2397,40 @@ xloadfonts(char *fontstr, int fontsize) { } void +xunloadfonts(void) +{ + int i, ip; + + /* + * Free the loaded fonts in the font cache. This is done backwards + * from the frccur. + */ + for (i = 0, ip = frccur; i < frclen; i++, ip--) { + if (ip < 0) + ip = LEN(frc) - 1; + XftFontClose(xw.dpy, frc[ip].font); + } + frccur = -1; + frclen = 0; + + XftFontClose(xw.dpy, dc.font.match); + FcPatternDestroy(dc.font.pattern); + FcFontSetDestroy(dc.font.set); + XftFontClose(xw.dpy, dc.bfont.match); + FcPatternDestroy(dc.bfont.pattern); + FcFontSetDestroy(dc.bfont.set); + XftFontClose(xw.dpy, dc.ifont.match); + FcPatternDestroy(dc.ifont.pattern); + FcFontSetDestroy(dc.ifont.set); + XftFontClose(xw.dpy, dc.ibfont.match); + FcPatternDestroy(dc.ibfont.pattern); + FcFontSetDestroy(dc.ibfont.set); +} + +void xzoom(const Arg *arg) { + xunloadfonts(); xloadfonts(usedfont, usedfontsize + arg->i); cresize(0, 0); draw(); @@ -2367,6 +2449,9 @@ xinit(void) { xw.vis = XDefaultVisual(xw.dpy, xw.scr); /* font */ + if (!FcInit()) + die("Could not init fontconfig.\n"); + usedfont = (opt_font == NULL)? font : opt_font; xloadfonts(usedfont, 0); @@ -2387,8 +2472,8 @@ xinit(void) { xw.w = xw.fw; } else { /* window - default size */ - xw.h = 2*borderpx + term.row * xw.ch; - xw.w = 2*borderpx + term.col * xw.cw; + xw.h = 2 * borderpx + term.row * xw.ch; + xw.w = 2 * borderpx + term.col * xw.cw; xw.fx = 0; xw.fy = 0; } @@ -2418,10 +2503,22 @@ xinit(void) { xw.draw = XftDrawCreate(xw.dpy, xw.buf, xw.vis, xw.cmap); /* input methods */ - xw.xim = XOpenIM(xw.dpy, NULL, NULL, NULL); + if((xw.xim = XOpenIM(xw.dpy, NULL, NULL, NULL)) == NULL) { + XSetLocaleModifiers("@im=local"); + if((xw.xim = XOpenIM(xw.dpy, NULL, NULL, NULL)) == NULL) { + XSetLocaleModifiers("@im="); + if((xw.xim = XOpenIM(xw.dpy, + NULL, NULL, NULL)) == NULL) { + die("XOpenIM failed. Could not open input" + " device.\n"); + } + } + } xw.xic = XCreateIC(xw.xim, XNInputStyle, XIMPreeditNothing | XIMStatusNothing, XNClientWindow, xw.win, XNFocusWindow, xw.win, NULL); + if(xw.xic == NULL) + die("XCreateIC failed. Could not obtain input method.\n"); /* white cursor, black outline */ cursor = XCreateFontCursor(xw.dpy, XC_xterm); @@ -2443,13 +2540,22 @@ xinit(void) { void xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) { int winx = borderpx + x * xw.cw, winy = borderpx + y * xw.ch, - width = charlen * xw.cw; + width = charlen * xw.cw, xp, i; + int frp, frcflags; + int u8fl, u8fblen, u8cblen, doesexist; + char *u8c, *u8fs; + long u8char; Font *font = &dc.font; - XGlyphInfo extents; + FcResult fcres; + FcPattern *fcpattern, *fontpattern; + FcFontSet *fcsets[] = { NULL }; + FcCharSet *fccharset; Colour *fg = &dc.col[base.fg], *bg = &dc.col[base.bg], *temp, revfg, revbg; XRenderColor colfg, colbg; + frcflags = FRC_NORMAL; + if(base.mode & ATTR_BOLD) { if(BETWEEN(base.fg, 0, 7)) { /* basic system colors */ @@ -2468,12 +2574,17 @@ xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) { * 252 - 255 – brightest colors in greyscale */ font = &dc.bfont; + frcflags = FRC_BOLD; } - if(base.mode & ATTR_ITALIC) + if(base.mode & ATTR_ITALIC) { font = &dc.ifont; - if((base.mode & ATTR_ITALIC) && (base.mode & ATTR_BOLD)) + frcflags = FRC_ITALIC; + } + if((base.mode & ATTR_ITALIC) && (base.mode & ATTR_BOLD)) { font = &dc.ibfont; + frcflags = FRC_ITALICBOLD; + } if(IS_SET(MODE_REVERSE)) { if(fg == &dc.col[defaultfg]) { @@ -2499,30 +2610,142 @@ xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) { } } - if(base.mode & ATTR_REVERSE) - temp = fg, fg = bg, bg = temp; - - XftTextExtentsUtf8(xw.dpy, font->set, (FcChar8 *)s, bytelen, - &extents); - width = extents.xOff; + if(base.mode & ATTR_REVERSE) { + temp = fg; + fg = bg; + bg = temp; + } /* Intelligent cleaning up of the borders. */ if(x == 0) { xclear(0, (y == 0)? 0 : winy, borderpx, - winy + xw.ch + (y == term.row-1)? xw.h : 0); + winy + xw.ch + ((y >= term.row-1)? xw.h : 0)); } - if(x + charlen >= term.col-1) { + if(x + charlen >= term.col) { xclear(winx + width, (y == 0)? 0 : winy, xw.w, - (y == term.row-1)? xw.h : (winy + xw.ch)); + ((y >= term.row-1)? xw.h : (winy + xw.ch))); } if(y == 0) xclear(winx, 0, winx + width, borderpx); if(y == term.row-1) xclear(winx, winy + xw.ch, winx + width, xw.h); + /* Clean up the region we want to draw to. */ XftDrawRect(xw.draw, bg, winx, winy, width, xw.ch); + + fcsets[0] = font->set; + for (xp = winx; bytelen > 0;) { + /* + * Search for the range in the to be printed string of glyphs + * that are in the main font. Then print that range. If + * some glyph is found that is not in the font, do the + * fallback dance. + */ + u8fs = s; + u8fblen = 0; + u8fl = 0; + for (;;) { + u8c = s; + u8cblen = utf8decode(s, &u8char); + s += u8cblen; + bytelen -= u8cblen; + + doesexist = XftCharIndex(xw.dpy, font->match, u8char); + if (!doesexist || bytelen <= 0) { + if (bytelen <= 0) { + if (doesexist) { + u8fl++; + u8fblen += u8cblen; + } + } + + if (u8fl > 0) { + XftDrawStringUtf8(xw.draw, fg, + font->match, xp, + winy + font->ascent, + (FcChar8 *)u8fs, + u8fblen); + xp += font->width * u8fl; + } + break; + } + + u8fl++; + u8fblen += u8cblen; + } + if (doesexist) + break; + + frp = frccur; + /* Search the font cache. */ + for (i = 0; i < frclen; i++, frp--) { + if (frp <= 0) + frp = LEN(frc) - 1; + + if (frc[frp].c == u8char + && frc[frp].flags == frcflags) { + break; + } + } + + /* Nothing was found. */ + if (i >= frclen) { + /* + * Nothing was found in the cache. Now use + * some dozen of Fontconfig calls to get the + * font for one single character. + */ + fcpattern = FcPatternDuplicate(font->pattern); + fccharset = FcCharSetCreate(); + + FcCharSetAddChar(fccharset, u8char); + FcPatternAddCharSet(fcpattern, FC_CHARSET, + fccharset); + FcPatternAddBool(fcpattern, FC_SCALABLE, + FcTrue); + + FcConfigSubstitute(0, fcpattern, + FcMatchPattern); + FcDefaultSubstitute(fcpattern); + + fontpattern = FcFontSetMatch(0, fcsets, + FcTrue, fcpattern, &fcres); + + /* + * Overwrite or create the new cache entry + * entry. + */ + frccur++; + frclen++; + if (frccur >= LEN(frc)) + frccur = 0; + if (frclen > LEN(frc)) { + frclen = LEN(frc); + XftFontClose(xw.dpy, frc[frccur].font); + } + + frc[frccur].font = XftFontOpenPattern(xw.dpy, + fontpattern); + frc[frccur].c = u8char; + frc[frccur].flags = frcflags; + + FcPatternDestroy(fcpattern); + FcCharSetDestroy(fccharset); + + frp = frccur; + } + + XftDrawStringUtf8(xw.draw, fg, frc[frp].font, + xp, winy + frc[frp].font->ascent, + (FcChar8 *)u8c, u8cblen); + + xp += font->width; + } + + /* XftDrawStringUtf8(xw.draw, fg, font->set, winx, winy + font->ascent, (FcChar8 *)s, bytelen); + */ if(base.mode & ATTR_UNDERLINE) { XftDrawRect(xw.draw, fg, winx, winy + font->ascent + 1, @@ -2593,10 +2816,11 @@ drawregion(int x1, int y1, int x2, int y2) { int ic, ib, x, y, ox, sl; Glyph base, new; char buf[DRAW_BUF_SIZ]; - bool ena_sel = sel.bx != -1, alt = IS_SET(MODE_ALTSCREEN) != 0; + bool ena_sel = sel.bx != -1; - if((sel.alt != 0) ^ alt) + if(sel.alt ^ IS_SET(MODE_ALTSCREEN)) ena_sel = 0; + if(!(xw.state & WIN_VISIBLE)) return; @@ -2683,20 +2907,70 @@ focus(XEvent *ev) { } } +inline bool +match(uint mask, uint state) { + if(mask == XK_NO_MOD && state) + return false; + if(mask != XK_ANY_MOD && mask != XK_NO_MOD && !state) + return false; + if((state & mask) != state) + return false; + return true; +} + +void +numlock(const Arg *dummy) { + term.numlock ^= 1; +} + char* kmap(KeySym k, uint state) { - int i; uint mask; + Key *kp; + int i; - state &= ~Mod2Mask; - for(i = 0; i < LEN(key); i++) { - mask = key[i].mask; + /* Check for mapped keys out of X11 function keys. */ + for(i = 0; i < LEN(mappedkeys); i++) { + if(mappedkeys[i] == k) + break; + } + if(i == LEN(mappedkeys)) { + if((k & 0xFFFF) < 0xFD00) + return NULL; + } - if(key[i].k == k && ((state & mask) == mask - || (mask == XK_NO_MOD && !state))) { - return (char*)key[i].s; + for(kp = key; kp < key + LEN(key); kp++) { + mask = kp->mask; + + if(kp->k != k) + continue; + + if(!match(mask, state)) + continue; + + if(kp->appkey > 0) { + if(!IS_SET(MODE_APPKEYPAD)) + continue; + if(term.numlock && kp->appkey == 2) + continue; + } else if(kp->appkey < 0 && IS_SET(MODE_APPKEYPAD)) { + continue; } + + if((kp->appcursor < 0 && IS_SET(MODE_APPCURSOR)) || + (kp->appcursor > 0 + && !IS_SET(MODE_APPCURSOR))) { + continue; + } + + if((kp->crlf < 0 && IS_SET(MODE_CRLF)) || + (kp->crlf > 0 && !IS_SET(MODE_CRLF))) { + continue; + } + + return kp->s; } + return NULL; } @@ -2705,23 +2979,20 @@ kpress(XEvent *ev) { XKeyEvent *e = &ev->xkey; KeySym ksym; char xstr[31], buf[32], *customkey, *cp = buf; - int len, meta, shift, i; + int len; Status status; + Shortcut *bp; if (IS_SET(MODE_KBDLOCK)) return; - meta = e->state & Mod1Mask; - shift = e->state & ShiftMask; len = XmbLookupString(xw.xic, e, xstr, sizeof(xstr), &ksym, &status); - + e->state &= ~Mod2Mask; /* 1. shortcuts */ - for(i = 0; i < LEN(shortcuts); i++) { - if((ksym == shortcuts[i].keysym) - && (CLEANMASK(shortcuts[i].mod) == \ - CLEANMASK(e->state)) - && shortcuts[i].func) { - shortcuts[i].func(&(shortcuts[i].arg)); + for(bp = shortcuts; bp < shortcuts + LEN(shortcuts); bp++) { + if(ksym == bp->keysym && match(bp->mod, e->state)) { + bp->func(&(bp->arg)); + return; } } @@ -2731,47 +3002,16 @@ kpress(XEvent *ev) { memcpy(buf, customkey, len); /* 2. hardcoded (overrides X lookup) */ } else { - switch(ksym) { - case XK_Up: - case XK_Down: - case XK_Left: - case XK_Right: - /* XXX: shift up/down doesn't work */ - sprintf(buf, "\033%c%c", - IS_SET(MODE_APPKEYPAD) ? 'O' : '[', - (shift ? "dacb":"DACB")[ksym - XK_Left]); - len = 3; - break; - case XK_Insert: - if(shift) { - selpaste(); - return; - } - memcpy(buf, xstr, len); - break; - case XK_Return: - len = 0; - if(meta) - *cp++ = '\033', len++; - - *cp++ = '\r', len++; - - if(IS_SET(MODE_CRLF)) - *cp = '\n', len++; - break; - /* 3. X lookup */ - default: - if(len == 0) - return; + if(len == 0) + return; - if (len == 1 && meta) - *cp++ = '\033'; + if (len == 1 && e->state & Mod1Mask) + *cp++ = '\033'; - memcpy(cp, xstr, len); - len = cp - buf + len; - break; - } + memcpy(cp, xstr, len); + len = cp - buf + len; } + ttywrite(buf, len); if(IS_SET(MODE_ECHO)) techo(buf, len); @@ -2806,8 +3046,8 @@ cresize(int width, int height) if(height != 0) xw.h = height; - col = (xw.w - 2*borderpx) / xw.cw; - row = (xw.h - 2*borderpx) / xw.ch; + col = (xw.w - 2 * borderpx) / xw.cw; + row = (xw.h - 2 * borderpx) / xw.ch; tresize(col, row); xresize(col, row); @@ -2886,7 +3126,7 @@ main(int argc, char *argv[]) { opt_class = argv[i]; break; case 'e': - /* eat every remaining arguments */ + /* eat all remaining arguments */ if(++i < argc) opt_cmd = &argv[i]; goto run; @@ -2941,6 +3181,7 @@ run: ttynew(); selinit(); run(); + return 0; }