X-Git-Url: https://git.danieliu.xyz/?a=blobdiff_plain;f=st.c;h=2594c6506c3d221626490e59605724a020d92c43;hb=6e79e8357ed1987a7f7a52cc06249aadef478041;hp=b2a4fff18d17c3a952adad0358cb5ee17e040ca5;hpb=f56c58a968c1b3ddae76864bc9e27e5b9cc055c4;p=st.git diff --git a/st.c b/st.c index b2a4fff..2594c65 100644 --- a/st.c +++ b/st.c @@ -68,6 +68,7 @@ char *argv0; #define LEN(a) (sizeof(a) / sizeof(a)[0]) #define DEFAULT(a, b) (a) = (a) ? (a) : (b) #define BETWEEN(x, a, b) ((a) <= (x) && (x) <= (b)) +#define DIVCEIL(n, d) (((n) + ((d) - 1)) / (d)) #define ISCONTROLC0(c) (BETWEEN(c, 0, 0x1f) || (c) == '\177') #define ISCONTROLC1(c) (BETWEEN(c, 0x80, 0x9f)) #define ISCONTROL(c) (ISCONTROLC0(c) || ISCONTROLC1(c)) @@ -275,7 +276,7 @@ typedef struct { uint b; uint mask; char *s; -} Mousekey; +} MouseShortcut; typedef struct { KeySym k; @@ -415,7 +416,7 @@ static int32_t tdefcolor(int *, int *, int); static void tdeftran(char); static inline int match(uint, uint); static void ttynew(void); -static void ttyread(void); +static size_t ttyread(void); static void ttyresize(void); static void ttysend(char *, size_t); static void ttywrite(const char *, size_t); @@ -439,7 +440,6 @@ static void xresettitle(void); static void xsetpointermotion(int); static void xseturgency(int); static void xsetsel(char *, Time); -static void xtermclear(int, int, int, int); static void xunloadfont(Font *); static void xunloadfonts(void); static void xresize(int, int); @@ -523,14 +523,15 @@ static int cmdfd; static pid_t pid; static Selection sel; static int iofd = 1; -static char **opt_cmd = NULL; -static char *opt_io = NULL; -static char *opt_title = NULL; -static char *opt_embed = NULL; +static char **opt_cmd = NULL; static char *opt_class = NULL; -static char *opt_font = NULL; -static char *opt_line = NULL; -static int oldbutton = 3; /* button event on startup: 3 = release */ +static char *opt_embed = NULL; +static char *opt_font = NULL; +static char *opt_io = NULL; +static char *opt_line = NULL; +static char *opt_name = NULL; +static char *opt_title = NULL; +static int oldbutton = 3; /* button event on startup: 3 = release */ static char *usedfont = NULL; static double usedfontsize = 0; @@ -944,17 +945,17 @@ void bpress(XEvent *e) { struct timespec now; - Mousekey *mk; + MouseShortcut *ms; if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forceselmod)) { mousereport(e); return; } - for (mk = mshortcuts; mk < mshortcuts + LEN(mshortcuts); mk++) { - if (e->xbutton.button == mk->b - && match(mk->mask, e->xbutton.state)) { - ttysend(mk->s, strlen(mk->s)); + for (ms = mshortcuts; ms < mshortcuts + LEN(mshortcuts); ms++) { + if (e->xbutton.button == ms->b + && match(ms->mask, e->xbutton.state)) { + ttysend(ms->s, strlen(ms->s)); return; } } @@ -1150,8 +1151,7 @@ selnotify(XEvent *e) * Deleting the property again tells the selection owner to send the * next data chunk in the property. */ - if (e->type == PropertyNotify) - XDeleteProperty(xw.dpy, xw.win, (int)property); + XDeleteProperty(xw.dpy, xw.win, (int)property); } void @@ -1403,9 +1403,9 @@ stty(void) if ((n = strlen(s)) > siz-1) die("stty parameter length too long\n"); *q++ = ' '; - q = memcpy(q, s, n); + memcpy(q, s, n); q += n; - siz-= n + 1; + siz -= n + 1; } *q = '\0'; if (system(cmd) != 0) @@ -1464,7 +1464,7 @@ ttynew(void) } } -void +size_t ttyread(void) { static char buf[BUFSIZ]; @@ -1489,14 +1489,16 @@ ttyread(void) /* keep any uncomplete utf8 char for the next call */ memmove(buf, ptr, buflen); + + return ret; } void ttywrite(const char *s, size_t n) { - fd_set wfd; - struct timespec tv; + fd_set wfd, rfd; ssize_t r; + size_t lim = 256; /* * Remember that we are using a pty, which might be a modem line. @@ -1506,38 +1508,32 @@ ttywrite(const char *s, size_t n) */ while (n > 0) { FD_ZERO(&wfd); + FD_ZERO(&rfd); FD_SET(cmdfd, &wfd); - tv.tv_sec = 0; - tv.tv_nsec = 0; + FD_SET(cmdfd, &rfd); /* Check if we can write. */ - if (pselect(cmdfd+1, NULL, &wfd, NULL, &tv, NULL) < 0) { + if (pselect(cmdfd+1, &rfd, &wfd, NULL, NULL, NULL) < 0) { if (errno == EINTR) continue; die("select failed: %s\n", strerror(errno)); } - if(!FD_ISSET(cmdfd, &wfd)) { - /* No, then free some buffer space. */ - ttyread(); - } else { + if (FD_ISSET(cmdfd, &wfd)) { /* - * Only write 256 bytes at maximum. This seems to be a - * reasonable value for a serial line. Bigger values - * might clog the I/O. + * Only write the bytes written by ttywrite() or the + * default of 256. This seems to be a reasonable value + * for a serial line. Bigger values might clog the I/O. */ - r = write(cmdfd, s, (n < 256)? n : 256); - if (r < 0) { - die("write error on tty: %s\n", - strerror(errno)); - } + if ((r = write(cmdfd, s, (n < lim)? n : lim)) < 0) + goto write_error; if (r < n) { /* * We weren't able to write out everything. * This means the buffer is getting full * again. Empty it. */ - if (n < 256) - ttyread(); + if (n < lim) + lim = ttyread(); n -= r; s += r; } else { @@ -1545,7 +1541,13 @@ ttywrite(const char *s, size_t n) break; } } + if (FD_ISSET(cmdfd, &rfd)) + lim = ttyread(); } + return; + +write_error: + die("write error on tty: %s\n", strerror(errno)); } void @@ -3210,17 +3212,6 @@ xsetcolorname(int x, const char *name) return 0; } -void -xtermclear(int col1, int row1, int col2, int row2) -{ - XftDrawRect(xw.draw, - &dc.col[IS_SET(MODE_REVERSE) ? defaultfg : defaultbg], - borderpx + col1 * xw.cw, - borderpx + row1 * xw.ch, - (col2-col1+1) * xw.cw, - (row2-row1+1) * xw.ch); -} - /* * Absolute coordinates. */ @@ -3235,7 +3226,8 @@ xclear(int x1, int y1, int x2, int y2) void xhints(void) { - XClassHint class = {opt_class ? opt_class : termname, termname}; + XClassHint class = {opt_name ? opt_name : termname, + opt_class ? opt_class : termname}; XWMHints wm = {.flags = InputHint, .input = 1}; XSizeHints *sizeh = NULL; @@ -3285,8 +3277,9 @@ xloadfont(Font *f, FcPattern *pattern) { FcPattern *match; FcResult result; + XGlyphInfo extents; - match = FcFontMatch(NULL, pattern, &result); + match = XftFontMatch(xw.dpy, xw.scr, pattern, &result); if (!match) return 1; @@ -3295,6 +3288,10 @@ xloadfont(Font *f, FcPattern *pattern) return 1; } + XftTextExtentsUtf8(xw.dpy, f->match, + (const FcChar8 *) ascii_printable, + strlen(ascii_printable), &extents); + f->set = NULL; f->pattern = FcPatternDuplicate(pattern); @@ -3304,7 +3301,7 @@ xloadfont(Font *f, FcPattern *pattern) f->rbearing = f->match->max_advance_width; f->height = f->ascent + f->descent; - f->width = f->lbearing + f->rbearing; + f->width = DIVCEIL(extents.xOff, strlen(ascii_printable)); return 0; } @@ -3348,9 +3345,6 @@ xloadfonts(char *fontstr, double fontsize) defaultfontsize = usedfontsize; } - FcConfigSubstitute(0, pattern, FcMatchPattern); - FcDefaultSubstitute(pattern); - if (xloadfont(&dc.font, pattern)) die("st: can't open font %s\n", fontstr); @@ -3421,6 +3415,7 @@ xzoomabs(const Arg *arg) xunloadfonts(); xloadfonts(usedfont, arg->f); cresize(0, 0); + ttyresize(); redraw(); xhints(); } @@ -3467,7 +3462,7 @@ xinit(void) if (xw.gm & XNegative) xw.l += DisplayWidth(xw.dpy, xw.scr) - xw.w - 2; if (xw.gm & YNegative) - xw.t += DisplayWidth(xw.dpy, xw.scr) - xw.h - 2; + xw.t += DisplayHeight(xw.dpy, xw.scr) - xw.h - 2; /* Events */ xw.attrs.background_pixel = dc.col[defaultbg].pixel; @@ -3672,7 +3667,7 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x specs[numspecs].font = frc[f].font; specs[numspecs].glyph = glyphidx; specs[numspecs].x = (short)xp; - specs[numspecs].y = (short)(winy + frc[f].font->ascent); + specs[numspecs].y = (short)yp; xp += runewidth; numspecs++; } @@ -3978,7 +3973,6 @@ drawregion(int x1, int y1, int x2, int y2) if (!term.dirty[y]) continue; - xtermclear(0, y, term.col, y); term.dirty[y] = 0; specs = term.specbuf; @@ -4204,7 +4198,6 @@ cresize(int width, int height) tresize(col, row); xresize(col, row); - ttyresize(); } void @@ -4214,6 +4207,7 @@ resize(XEvent *e) return; cresize(e->xconfigure.width, e->xconfigure.height); + ttyresize(); } void @@ -4242,8 +4236,9 @@ run(void) } } while (ev.type != MapNotify); - ttynew(); cresize(w, h); + ttynew(); + ttyresize(); clock_gettime(CLOCK_MONOTONIC, &last); lastblink = last; @@ -4327,14 +4322,14 @@ run(void) void usage(void) { - die("%s " VERSION " (c) 2010-2015 st engineers\n" - "usage: st [-a] [-v] [-c class] [-f font] [-g geometry] [-o file]\n" - " [-i] [-t title] [-T title] [-w windowid] [-e command ...]" - " [command ...]\n" - " st [-a] [-v] [-c class] [-f font] [-g geometry] [-o file]\n" - " [-i] [-t title] [-T title] [-w windowid] -l line" - " [stty_args ...]\n", - argv0); + die("usage: %s [-aiv] [-c class] [-f font] [-g geometry]" + " [-n name] [-o file]\n" + " [-T title] [-t title] [-w windowid]" + " [[-e] command [args ...]]\n" + " %s [-aiv] [-c class] [-f font] [-g geometry]" + " [-n name] [-o file]\n" + " [-T title] [-t title] [-w windowid] -l line" + " [stty_args ...]\n", argv0, argv0); } int @@ -4373,6 +4368,9 @@ main(int argc, char *argv[]) case 'l': opt_line = EARGF(usage()); break; + case 'n': + opt_name = EARGF(usage()); + break; case 't': case 'T': opt_title = EARGF(usage()); @@ -4381,6 +4379,8 @@ main(int argc, char *argv[]) opt_embed = EARGF(usage()); break; case 'v': + die("%s " VERSION " (c) 2010-2016 st engineers\n", argv0); + break; default: usage(); } ARGEND;