X-Git-Url: https://jasonwoof.com/gitweb/?a=blobdiff_plain;f=st.c;h=5703e964ab644596bd5ed6e44e04cf447a10a740;hb=71b09ec4f172da9a89be2add54b5b94da8af3bea;hp=f6c9f18d400085ddc2c1ab3c2d60a2e7ddb5cbe9;hpb=4eddf19fdc2f3845c927291b99d3faefe73f98f3;p=st.git diff --git a/st.c b/st.c index f6c9f18..5703e96 100644 --- a/st.c +++ b/st.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -59,6 +60,8 @@ #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)) @@ -72,6 +75,8 @@ #define X2COL(x) (((x) - BORDER)/xw.cw) #define Y2ROW(y) (((y) - BORDER)/xw.ch) +#define VT102ID "\033[?6c" + enum glyph_attribute { ATTR_NULL = 0, ATTR_REVERSE = 1, @@ -121,6 +126,7 @@ enum escape_state { ESC_STR = 4, /* DSC, OSC, PM, APC */ ESC_ALTCHARSET = 8, ESC_STR_END = 16, /* a final string was encountered */ + ESC_TEST = 32, /* Enter in test mode */ }; enum window_state { @@ -224,7 +230,9 @@ typedef struct { int mode; int bx, by; int ex, ey; - struct {int x, y;} b, e; + struct { + int x, y; + } b, e; char *clip; Atom xtarget; bool alt; @@ -232,6 +240,24 @@ typedef struct { struct timeval tclick2; } Selection; +typedef union { + int i; + unsigned int ui; + float f; + const void *v; +} Arg; + +typedef struct { + unsigned int mod; + KeySym keysym; + void (*func)(const Arg *); + const Arg arg; +} Shortcut; + +/* function definitions used in config.h */ +static void xzoom(const Arg *); + +/* Config.h for applying patches and the configuration. */ #include "config.h" /* Font structure */ @@ -285,7 +311,7 @@ static int tresize(int, int); static void tscrollup(int, int); static void tscrolldown(int, int); static void tsetattr(int*, int); -static void tsetchar(char*); +static void tsetchar(char *, Glyph *, int, int); static void tsetscroll(int, int); static void tswapscreen(void); static void tsetdirt(int, int); @@ -300,7 +326,6 @@ static void ttywrite(const char *, size_t); static void xdraws(char *, Glyph, int, int, int, int); static void xhints(void); static void xclear(int, int, int, int); -static void xclearborders(void); static void xdrawcursor(void); static void xinit(void); static void xloadcols(void); @@ -316,6 +341,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 resize(XEvent *); static void focus(XEvent *); static void brelease(XEvent *); @@ -336,10 +362,10 @@ static int utf8encode(long *, char *); static int utf8size(char *); 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 char *smstrcat(char *, ...); static void (*handler[LASTEvent])(XEvent *) = { [KeyPress] = kpress, @@ -375,6 +401,23 @@ static char *opt_embed = NULL; static char *opt_class = NULL; static char *opt_font = NULL; +static char *usedfont = NULL; +static int usedfontsize = 0; + +ssize_t +xwrite(int fd, char *s, size_t len) { + size_t aux = len; + + while(len > 0) { + ssize_t r = write(fd, s, len); + if(r < 0) + return r; + len -= r; + s += r; + } + return aux; +} + void * xmalloc(size_t len) { void *p = malloc(len); @@ -403,44 +446,6 @@ xcalloc(size_t nmemb, size_t size) { return p; } -char * -smstrcat(char *src, ...) -{ - va_list fmtargs; - char *ret, *p, *v; - int len, slen, flen; - - len = slen = strlen(src); - - va_start(fmtargs, src); - for(;;) { - v = va_arg(fmtargs, char *); - if(v == NULL) - break; - len += strlen(v); - } - va_end(fmtargs); - - p = ret = xmalloc(len+1); - memmove(p, src, slen); - p += slen; - - va_start(fmtargs, src); - for(;;) { - v = va_arg(fmtargs, char *); - if(v == NULL) - break; - flen = strlen(v); - memmove(p, v, flen); - p += flen; - } - va_end(fmtargs); - - ret[len] = '\0'; - - return ret; -} - int utf8decode(char *s, long *u) { uchar c; @@ -587,10 +592,10 @@ selected(int x, int y) { return BETWEEN(x, bx, ex); } - return ((sel.b.y < y&&y < sel.e.y) - || (y==sel.e.y && x<=sel.e.x)) - || (y==sel.b.y && x>=sel.b.x - && (x<=sel.e.x || sel.b.y!=sel.e.y)); + return ((sel.b.y < y && y < sel.e.y) + || (y == sel.e.y && x <= sel.e.x)) + || (y == sel.b.y && x >= sel.b.x + && (x <= sel.e.x || sel.b.y != sel.e.y)); } void @@ -658,7 +663,7 @@ bpress(XEvent *e) { void selcopy(void) { - char *str, *ptr, *p; + char *str, *ptr; int x, y, bufsize, is_selected = 0, size; Glyph *gp; @@ -673,11 +678,12 @@ selcopy(void) { for(x = 0; x < term.col; x++) { gp = &term.line[y][x]; - if(!(is_selected = selected(x, y))) + if(!(is_selected = selected(x, y)) + || !(gp->state & GLYPH_SET)) { continue; - p = (gp->state & GLYPH_SET) ? gp->c : " "; - size = utf8size(p); - memcpy(ptr, p, size); + } + size = utf8size(gp->c); + memcpy(ptr, gp->c, size); ptr += size; } /* \n at the end of every selected line except for the last one */ @@ -803,12 +809,12 @@ brelease(XEvent *e) { /* double click to select word */ sel.bx = sel.ex; while(sel.bx > 0 && term.line[sel.ey][sel.bx-1].state & GLYPH_SET && - term.line[sel.ey][sel.bx-1].c[0] != ' ') { + term.line[sel.ey][sel.bx-1].c[0] != ' ') { sel.bx--; } sel.b.x = sel.bx; while(sel.ex < term.col-1 && term.line[sel.ey][sel.ex+1].state & GLYPH_SET && - term.line[sel.ey][sel.ex+1].c[0] != ' ') { + term.line[sel.ey][sel.ex+1].c[0] != ' ') { sel.ex++; } sel.e.x = sel.ex; @@ -860,11 +866,23 @@ void execsh(void) { char **args; char *envshell = getenv("SHELL"); + const struct passwd *pass = getpwuid(getuid()); + char buf[sizeof(long) * 8 + 1]; unsetenv("COLUMNS"); unsetenv("LINES"); unsetenv("TERMCAP"); + if(pass) { + setenv("LOGNAME", pass->pw_name, 1); + setenv("USER", pass->pw_name, 1); + setenv("SHELL", pass->pw_shell, 0); + setenv("HOME", pass->pw_dir, 0); + } + + snprintf(buf, sizeof(buf), "%lu", xw.win); + setenv("WINDOWID", buf, 1); + signal(SIGCHLD, SIG_DFL); signal(SIGHUP, SIG_DFL); signal(SIGINT, SIG_DFL); @@ -874,7 +892,7 @@ execsh(void) { DEFAULT(envshell, SHELL); putenv("TERM="TNAME); - args = opt_cmd ? opt_cmd : (char*[]){envshell, "-i", NULL}; + args = opt_cmd ? opt_cmd : (char *[]){envshell, "-i", NULL}; execvp(args[0], args); exit(EXIT_FAILURE); } @@ -922,13 +940,12 @@ ttynew(void) { cmdfd = m; signal(SIGCHLD, sigchld); if(opt_io) { - if(!strcmp(opt_io, "-")) { - iofd = STDOUT_FILENO; - } else { - if((iofd = open(opt_io, O_WRONLY | O_CREAT, 0666)) < 0) { - fprintf(stderr, "Error opening %s:%s\n", - opt_io, strerror(errno)); - } + iofd = (!strcmp(opt_io, "-")) ? + STDOUT_FILENO : + open(opt_io, O_WRONLY | O_CREAT, 0666); + if(iofd < 0) { + fprintf(stderr, "Error opening %s:%s\n", + opt_io, strerror(errno)); } } } @@ -1031,7 +1048,8 @@ treset(void) { memset(term.tabs, 0, term.col * sizeof(*term.tabs)); for(i = TAB; i < term.col; i += TAB) term.tabs[i] = 1; - term.top = 0, term.bot = term.row - 1; + term.top = 0; + term.bot = term.row - 1; term.mode = MODE_WRAP; tclearregion(0, 0, term.col-1, term.row-1); @@ -1040,7 +1058,8 @@ treset(void) { void tnew(int col, int row) { /* set screen size */ - term.row = row, term.col = col; + term.row = row; + term.col = col; term.line = xmalloc(term.row * sizeof(Line)); term.alt = xmalloc(term.row * sizeof(Line)); term.dirty = xmalloc(term.row * sizeof(*term.dirty)); @@ -1177,8 +1196,8 @@ tmoveto(int x, int y) { } void -tsetchar(char *c) { - char *vt100_0[62] = { /* 0x41 - 0x7e */ +tsetchar(char *c, Glyph *attr, int x, int y) { + static char *vt100_0[62] = { /* 0x41 - 0x7e */ "↑", "↓", "→", "←", "█", "▚", "☃", /* A - G */ 0, 0, 0, 0, 0, 0, 0, 0, /* H - O */ 0, 0, 0, 0, 0, 0, 0, 0, /* P - W */ @@ -1192,17 +1211,17 @@ tsetchar(char *c) { /* * The table is proudly stolen from rxvt. */ - if(term.c.attr.mode & ATTR_GFX) { + if(attr->mode & ATTR_GFX) { if(c[0] >= 0x41 && c[0] <= 0x7e && vt100_0[c[0] - 0x41]) { c = vt100_0[c[0] - 0x41]; } } - term.dirty[term.c.y] = 1; - term.line[term.c.y][term.c.x] = term.c.attr; - memcpy(term.line[term.c.y][term.c.x].c, c, UTF_SIZ); - term.line[term.c.y][term.c.x].state |= GLYPH_SET; + term.dirty[y] = 1; + term.line[y][x] = *attr; + memcpy(term.line[y][x].c, c, UTF_SIZ); + term.line[y][x].state |= GLYPH_SET; } void @@ -1437,8 +1456,8 @@ tsetmode(bool priv, bool set, int *args, int narg) { if(IS_SET(MODE_ALTSCREEN)) tclearregion(0, 0, term.col-1, term.row-1); if((set && !IS_SET(MODE_ALTSCREEN)) || - (!set && IS_SET(MODE_ALTSCREEN))) { - tswapscreen(); + (!set && IS_SET(MODE_ALTSCREEN))) { + tswapscreen(); } if(*args != 1049) break; @@ -1507,6 +1526,10 @@ csihandle(void) { DEFAULT(csiescseq.arg[0], 1); tmoveto(term.c.x, term.c.y+csiescseq.arg[0]); break; + case 'c': /* DA -- Device Attributes */ + if(csiescseq.arg[0] == 0) + ttywrite(VT102ID, sizeof(VT102ID) - 1); + break; case 'C': /* CUF -- Cursor Forward */ case 'a': DEFAULT(csiescseq.arg[0], 1); @@ -1781,40 +1804,86 @@ tputtab(bool forward) { void tputc(char *c, int len) { uchar ascii = *c; - - if(iofd != -1) - write(iofd, c, len); - - switch(ascii) { - case '\t': - tputtab(1); - return; - case '\b': - tmoveto(term.c.x-1, term.c.y); - return; - case '\r': - tmoveto(0, term.c.y); - return; - case '\f': - case '\v': - case '\n': - /* go to first col if the mode is set */ - tnewline(IS_SET(MODE_CRLF)); - return; - case '\a': - if(term.esc & ESC_STR) + bool control = ascii < '\x20' || ascii == 0177; + + if(iofd != -1) { + if (xwrite(iofd, c, len) < 0) { + fprintf(stderr, "Error writting in %s:%s\n", + opt_io, strerror(errno)); + close(iofd); + iofd = -1; + } + } + /* + * STR sequences must be checked before of anything + * because it can use some control codes as part of the sequence + */ + if(term.esc & ESC_STR) { + switch(ascii) { + case '\033': + term.esc = ESC_START | ESC_STR_END; break; - - if(!(xw.state & WIN_FOCUSED)) - xseturgency(1); - return; - case '\033': - csireset(); - term.esc = ESC_START; + case '\a': /* backwards compatibility to xterm */ + term.esc = 0; + strhandle(); + break; + default: + strescseq.buf[strescseq.len++] = ascii; + if(strescseq.len+1 >= STR_BUF_SIZ) { + term.esc = 0; + strhandle(); + } + } return; } - - if(term.esc & ESC_START) { + /* + * Actions of control codes must be performed as soon they arrive + * because they can be embedded inside a control sequence, and + * they must not cause conflicts with sequences. + */ + if(control) { + switch(ascii) { + case '\t': /* HT */ + tputtab(1); + return; + case '\b': /* BS */ + tmoveto(term.c.x-1, term.c.y); + return; + case '\r': /* CR */ + tmoveto(0, term.c.y); + return; + case '\f': /* LF */ + case '\v': /* VT */ + case '\n': /* LF */ + /* go to first col if the mode is set */ + tnewline(IS_SET(MODE_CRLF)); + return; + case '\a': /* BEL */ + if(!(xw.state & WIN_FOCUSED)) + xseturgency(1); + return; + case '\033': /* ESC */ + csireset(); + term.esc = ESC_START; + return; + case '\016': /* SO */ + term.c.attr.mode |= ATTR_GFX; + return; + case '\017': /* SI */ + term.c.attr.mode &= ~ATTR_GFX; + return; + case '\032': /* SUB */ + case '\030': /* CAN */ + csireset(); + return; + case '\005': /* ENQ (IGNORED) */ + case '\000': /* NUL (IGNORED) */ + case '\021': /* XON (IGNORED) */ + case '\023': /* XOFF (IGNORED) */ + case 0177: /* DEL (IGNORED) */ + return; + } + } else if(term.esc & ESC_START) { if(term.esc & ESC_CSI) { csiescseq.buf[csiescseq.len++] = ascii; if(BETWEEN(ascii, 0x40, 0x7E) @@ -1822,22 +1891,6 @@ tputc(char *c, int len) { term.esc = 0; csiparse(), csihandle(); } - } else if(term.esc & ESC_STR) { - switch(ascii) { - case '\033': - term.esc = ESC_START | ESC_STR_END; - break; - case '\a': /* backwards compatibility to xterm */ - term.esc = 0; - strhandle(); - break; - default: - strescseq.buf[strescseq.len++] = ascii; - if(strescseq.len+1 >= STR_BUF_SIZ) { - term.esc = 0; - strhandle(); - } - } } else if(term.esc & ESC_STR_END) { term.esc = 0; if(ascii == '\\') @@ -1860,11 +1913,25 @@ tputc(char *c, int len) { fprintf(stderr, "esc unhandled charset: ESC ( %c\n", ascii); } term.esc = 0; + } else if(term.esc & ESC_TEST) { + if(ascii == '8') { /* DEC screen alignment test. */ + char E[UTF_SIZ] = "E"; + int x, y; + + for(x = 0; x < term.col; ++x) { + for(y = 0; y < term.row; ++y) + tsetchar(E, &term.c.attr, x, y); + } + } + term.esc = 0; } else { switch(ascii) { case '[': term.esc |= ESC_CSI; break; + case '#': + term.esc |= ESC_TEST; + break; case 'P': /* DCS -- Device Control String */ case '_': /* APC -- Application Program Command */ case '^': /* PM -- Privacy Message */ @@ -1906,10 +1973,13 @@ tputc(char *c, int len) { } term.esc = 0; break; + case 'Z': /* DECID -- Identify Terminal */ + ttywrite(VT102ID, sizeof(VT102ID) - 1); + term.esc = 0; + break; case 'c': /* RIS -- Reset to inital state */ treset(); term.esc = 0; - xclearborders(); xresettitle(); break; case '=': /* DECPAM -- Application keypad */ @@ -1937,20 +2007,26 @@ tputc(char *c, int len) { term.esc = 0; } } - } else { - if(sel.bx != -1 && BETWEEN(term.c.y, sel.by, sel.ey)) - sel.bx = -1; - if(ascii >= '\020' || term.c.attr.mode & ATTR_GFX) { - if(IS_SET(MODE_WRAP) && term.c.state & CURSOR_WRAPNEXT) - tnewline(1); /* always go to first col */ - tsetchar(c); - if(term.c.x+1 < term.col) { - tmoveto(term.c.x+1, term.c.y); - } else { - term.c.state |= CURSOR_WRAPNEXT; - } - } + /* + * All characters which forms part of a sequence are not + * printed + */ + return; } + /* + * Display control codes only if we are in graphic mode + */ + if(control && !(term.c.attr.mode & ATTR_GFX)) + return; + if(sel.bx != -1 && BETWEEN(term.c.y, sel.by, sel.ey)) + sel.bx = -1; + if(IS_SET(MODE_WRAP) && term.c.state & CURSOR_WRAPNEXT) + tnewline(1); /* always go to first col */ + tsetchar(c, &term.c.attr, term.c.x, term.c.y); + if(term.c.x+1 < term.col) + tmoveto(term.c.x+1, term.c.y); + else + term.c.state |= CURSOR_WRAPNEXT; } int @@ -2015,7 +2091,8 @@ tresize(int col, int row) { *bp = 1; } /* update terminal size */ - term.col = col, term.row = row; + term.col = col; + term.row = row; /* make use of the LIMIT in tmoveto */ tmoveto(term.c.x, term.c.y); /* reset scrolling region */ @@ -2091,18 +2168,6 @@ xclear(int x1, int y1, int x2, int y2) { } void -xclearborders(void) { - /* top and left border */ - xclear(0, 0, BORDER, xw.h); - xclear(0, 0, xw.w, BORDER); - - /* lower and right border */ - xclear(BORDER, xw.th - 1, xw.w, xw.h); - /* Will just draw what hasn't been drawn by the previous call. */ - xclear(xw.tw - 1, BORDER, xw.w, xw.h - xw.th - 2); -} - -void xhints(void) { XClassHint class = {opt_class ? opt_class : TNAME, TNAME}; XWMHints wm = {.flags = InputHint, .input = 1}; @@ -2127,22 +2192,17 @@ xhints(void) { XFree(sizeh); } -void -xinitfont(Font *f, char *fontstr) { - FcPattern *pattern, *match; +int +xloadfont(Font *f, FcPattern *pattern) { + FcPattern *match; FcResult result; - pattern = FcNameParse((FcChar8 *)fontstr); - if(!pattern) - die("st: can't open font %s\n", fontstr); - match = XftFontMatch(xw.dpy, xw.scr, pattern, &result); - FcPatternDestroy(pattern); if(!match) - die("st: can't open font %s\n", fontstr); + return 1; if(!(f->xft_set = XftFontOpenPattern(xw.dpy, match))) { FcPatternDestroy(match); - die("st: can't open font %s.\n", fontstr); + return 1; } f->ascent = f->xft_set->ascent; @@ -2152,27 +2212,68 @@ xinitfont(Font *f, char *fontstr) { f->height = f->xft_set->height; f->width = f->lbearing + f->rbearing; + + return 0; } void -initfonts(char *fontstr) { - char *fstr; +xloadfonts(char *fontstr, int fontsize) { + FcPattern *pattern; + FcResult result; + double fontval; + + pattern = FcNameParse((FcChar8 *)fontstr); + if(!pattern) + die("st: can't open font %s\n", fontstr); - xinitfont(&dc.font, fontstr); + if(fontsize > 0) { + FcPatternDel(pattern, FC_PIXEL_SIZE); + FcPatternAddDouble(pattern, FC_PIXEL_SIZE, (double)fontsize); + usedfontsize = fontsize; + } else { + result = FcPatternGetDouble(pattern, FC_PIXEL_SIZE, 0, &fontval); + if(result == FcResultMatch) { + usedfontsize = (int)fontval; + } else { + /* + * Default font size is 12, if none given. This is to + * have a known usedfontsize value. + */ + FcPatternAddDouble(pattern, FC_PIXEL_SIZE, 12); + usedfontsize = 12; + } + } + + if(xloadfont(&dc.font, pattern)) + die("st: can't open font %s\n", fontstr); + + /* Setting character width and height. */ xw.cw = dc.font.width; xw.ch = dc.font.height; - fstr = smstrcat(fontstr, ":weight=bold", NULL); - xinitfont(&dc.bfont, fstr); - free(fstr); + FcPatternDel(pattern, FC_WEIGHT); + FcPatternAddInteger(pattern, FC_WEIGHT, FC_WEIGHT_BOLD); + if(xloadfont(&dc.bfont, pattern)) + die("st: can't open font %s\n", fontstr); - fstr = smstrcat(fontstr, ":slant=italic,oblique", NULL); - xinitfont(&dc.ifont, fstr); - free(fstr); + FcPatternDel(pattern, FC_SLANT); + FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ITALIC); + if(xloadfont(&dc.ibfont, pattern)) + die("st: can't open font %s\n", fontstr); + + FcPatternDel(pattern, FC_WEIGHT); + if(xloadfont(&dc.ifont, pattern)) + die("st: can't open font %s\n", fontstr); - fstr = smstrcat(fontstr, ":weight=bold:slant=italic,oblique", NULL); - xinitfont(&dc.ibfont, fstr); - free(fstr); + FcPatternDestroy(pattern); +} + +void +xzoom(const Arg *arg) +{ + xloadfonts(usedfont, usedfontsize + arg->i); + cresize(0, 0); + draw(); } void @@ -2188,7 +2289,8 @@ xinit(void) { xw.vis = XDefaultVisual(xw.dpy, xw.scr); /* font */ - initfonts((opt_font != NULL)? opt_font : FONT); + usedfont = (opt_font == NULL)? FONT : opt_font; + xloadfonts(usedfont, 0); /* colors */ xw.cmap = XDefaultColormap(xw.dpy, xw.scr); @@ -2264,8 +2366,8 @@ xinit(void) { void xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) { - int winx = BORDER+x*xw.cw, winy = BORDER+y*xw.ch, - width = charlen*xw.cw; + int winx = BORDER + x * xw.cw, winy = BORDER + y * xw.ch, + width = charlen * xw.cw; Font *font = &dc.font; XGlyphInfo extents; XftColor *fg = &dc.xft_col[base.fg], *bg = &dc.xft_col[base.bg], @@ -2290,7 +2392,7 @@ xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) { * Those ranges will not be brightened: * 8 - 15 – bright system colors * 196 - 231 – highest 256 color cube - * 252 - 255 – brightest colors in grescale + * 252 - 255 – brightest colors in greyscale */ font = &dc.bfont; } @@ -2328,6 +2430,20 @@ xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) { &extents); width = extents.xOff; + /* Intelligent cleaning up of the borders. */ + if(x == 0) { + xclear(0, (y == 0)? 0 : winy, BORDER, + winy + xw.ch + (y == term.row-1)? xw.h : 0); + } + if(x + charlen >= term.col-1) { + xclear(winx + width, (y == 0)? 0 : winy, xw.w, + (y == term.row-1)? xw.h : (winy + xw.ch)); + } + if(y == 0) + xclear(winx, 0, winx + width, BORDER); + if(y == term.row-1) + xclear(winx, winy + xw.ch, winx + width, xw.h); + XftDrawRect(xw.xft_draw, bg, winx, winy, width, xw.ch); XftDrawStringUtf8(xw.xft_draw, fg, font->xft_set, winx, winy + font->ascent, (FcChar8 *)s, bytelen); @@ -2382,7 +2498,6 @@ void redraw(void) { struct timespec tv = {0, REDRAW_TIMEOUT * 1000}; - xclearborders(); tfulldirt(); draw(); XSync(xw.dpy, False); /* necessary for a good tput flash */ @@ -2511,11 +2626,8 @@ void kpress(XEvent *ev) { XKeyEvent *e = &ev->xkey; KeySym ksym; - char buf[32]; - char *customkey; - int len; - int meta; - int shift; + char buf[32], *customkey; + int len, meta, shift, i; Status status; if (IS_SET(MODE_KBDLOCK)) @@ -2525,7 +2637,17 @@ kpress(XEvent *ev) { shift = e->state & ShiftMask; len = XmbLookupString(xw.xic, e, buf, sizeof(buf), &ksym, &status); - /* 1. custom keys from config.h */ + /* 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)); + } + } + + /* 2. custom keys from config.h */ if((customkey = kmap(ksym, e->state))) { ttywrite(customkey, strlen(customkey)); /* 2. hardcoded (overrides X lookup) */ @@ -2583,14 +2705,15 @@ cmessage(XEvent *e) { } void -resize(XEvent *e) { +cresize(int width, int height) +{ int col, row; - if(e->xconfigure.width == xw.w && e->xconfigure.height == xw.h) - return; + if(width != 0) + xw.w = width; + if(height != 0) + xw.h = height; - xw.w = e->xconfigure.width; - xw.h = e->xconfigure.height; col = (xw.w - 2*BORDER) / xw.cw; row = (xw.h - 2*BORDER) / xw.ch; if(col == term.col && row == term.row) @@ -2598,11 +2721,18 @@ resize(XEvent *e) { tresize(col, row); xresize(col, row); - xclearborders(); ttyresize(); } void +resize(XEvent *e) { + if(e->xconfigure.width == xw.w && e->xconfigure.height == xw.h) + return; + + cresize(e->xconfigure.width, e->xconfigure.height); +} + +void run(void) { XEvent ev; fd_set rfd; @@ -2716,8 +2846,8 @@ main(int argc, char *argv[]) { run: setlocale(LC_CTYPE, ""); tnew(80, 24); - ttynew(); xinit(); + ttynew(); selinit(); run(); return 0;