X-Git-Url: https://jasonwoof.com/gitweb/?p=st.git;a=blobdiff_plain;f=st.c;h=a494c7d1dace0578a1a94ca7e8b0c88eef718839;hp=497885b0b48c03fc19be0de0e558049d05168e51;hb=adeb2e95d633cf4bbe1bbe5d2caba71776577c21;hpb=51466e019a67e9319e6c5a7fa4205842ca860b71 diff --git a/st.c b/st.c index 497885b..a494c7d 100644 --- a/st.c +++ b/st.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -62,8 +63,6 @@ char *argv0; #define XK_NO_MOD 0 #define XK_SWITCH_MOD (1<<13) -#define REDRAW_TIMEOUT (80*1000) /* 80 ms */ - /* macros */ #define MIN(a, b) ((a) < (b) ? (a) : (b)) #define MAX(a, b) ((a) < (b) ? (b) : (a)) @@ -317,6 +316,8 @@ static void clippaste(const Arg *); static void numlock(const Arg *); static void selpaste(const Arg *); static void xzoom(const Arg *); +static void xzoomabs(const Arg *); +static void xzoomreset(const Arg *); static void printsel(const Arg *); static void printscreen(const Arg *) ; static void toggleprinter(const Arg *); @@ -346,7 +347,7 @@ typedef struct { static void die(const char *, ...); static void draw(void); -static void redraw(int); +static void redraw(void); static void drawregion(int, int, int, int); static void execsh(void); static void sigchld(int); @@ -503,6 +504,7 @@ static int oldbutton = 3; /* button event on startup: 3 = release */ static char *usedfont = NULL; static double usedfontsize = 0; +static double defaultfontsize = 0; static uchar utfbyte[UTF_SIZ + 1] = {0x80, 0, 0xC0, 0xE0, 0xF0}; static uchar utfmask[UTF_SIZ + 1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8}; @@ -520,6 +522,7 @@ enum { typedef struct { XftFont *font; int flags; + long unicodep; } Fontcache; /* Fontcache is an array now. A new font will be appended to the array. */ @@ -662,7 +665,10 @@ y2row(int y) { static int tlinelen(int y) { int i = term.col; - while (i > 0 && term.line[y][i - 1].c[0] == ' ') + if(term.line[y][i - 1].mode & ATTR_WRAP) + return i; + + while(i > 0 && term.line[y][i - 1].c[0] == ' ') --i; return i; @@ -940,6 +946,8 @@ getsel(void) { lastx = (sel.ne.y == y) ? sel.ne.x : term.col-1; } last = &term.line[y][MIN(lastx, linelen-1)]; + while(last >= gp && last->c[0] == ' ') + --last; for( ; gp <= last; ++gp) { if(gp->mode & ATTR_WDUMMY) @@ -959,7 +967,7 @@ getsel(void) { * st. * FIXME: Fix the computer world. */ - if(sel.ne.y > y || lastx >= linelen) + if((y < sel.ne.y || lastx >= linelen) && !(last->mode & ATTR_WRAP)) *ptr++ = '\n'; } *ptr = 0; @@ -1139,7 +1147,7 @@ die(const char *errstr, ...) { void execsh(void) { - char **args, *sh; + char **args, *sh, *prog; const struct passwd *pw; char buf[sizeof(long) * 8 + 1]; @@ -1150,13 +1158,24 @@ execsh(void) { else die("who are you?\n"); } - unsetenv("COLUMNS"); - unsetenv("LINES"); - unsetenv("TERMCAP"); - sh = (pw->pw_shell[0]) ? pw->pw_shell : shell; + if (!(sh = getenv("SHELL"))) { + sh = (pw->pw_shell[0]) ? pw->pw_shell : shell; + } + + if(opt_cmd) + prog = opt_cmd[0]; + else if(utmp) + prog = utmp; + else + prog = sh; + args = (opt_cmd) ? opt_cmd : (char *[]) {prog, NULL}; + snprintf(buf, sizeof(buf), "%lu", xw.win); + unsetenv("COLUMNS"); + unsetenv("LINES"); + unsetenv("TERMCAP"); setenv("LOGNAME", pw->pw_name, 1); setenv("USER", pw->pw_name, 1); setenv("SHELL", sh, 1); @@ -1171,9 +1190,8 @@ execsh(void) { signal(SIGTERM, SIG_DFL); signal(SIGALRM, SIG_DFL); - args = opt_cmd ? opt_cmd : (char *[]){sh, "-i", NULL}; - execvp(args[0], args); - exit(EXIT_FAILURE); + execvp(prog, args); + _exit(EXIT_FAILURE); } void @@ -1807,7 +1825,7 @@ tsetmode(bool priv, bool set, int *args, int narg) { mode = term.mode; MODBIT(term.mode, set, MODE_REVERSE); if(mode != term.mode) - redraw(REDRAW_TIMEOUT); + redraw(); break; case 6: /* DECOM -- Origin */ MODBIT(term.c.state, set, CURSOR_ORIGIN); @@ -2181,7 +2199,7 @@ strhandle(void) { * TODO if defaultbg color is changed, borders * are dirty */ - redraw(0); + redraw(); } return; } @@ -2412,7 +2430,7 @@ tcontrolcode(uchar ascii) { if(!(xw.state & WIN_FOCUSED)) xseturgency(1); if (bellvolume) - XBell(xw.dpy, bellvolume); + XkbBell(xw.dpy, xw.win, bellvolume, (Atom)NULL); } break; case '\033': /* ESC */ @@ -2420,11 +2438,9 @@ tcontrolcode(uchar ascii) { term.esc &= ~(ESC_CSI|ESC_ALTCHARSET|ESC_TEST); term.esc |= ESC_START; return; - case '\016': /* SO */ - term.charset = 0; - return; - case '\017': /* SI */ - term.charset = 1; + case '\016': /* SO (LS1 -- Locking shift 1) */ + case '\017': /* SI (LS0 -- Locking shift 0) */ + term.charset = 1 - (ascii - '\016'); return; case '\032': /* SUB */ tsetchar(question, &term.c.attr, term.c.x, term.c.y); @@ -2488,10 +2504,14 @@ eschandle(uchar ascii) { case 'k': /* old title set compatibility */ tstrsequence(ascii); return 0; - case '(': /* set primary charset G0 */ - case ')': /* set secondary charset G1 */ - case '*': /* set tertiary charset G2 */ - case '+': /* set quaternary charset G3 */ + case 'n': /* LS2 -- Locking shift 2 */ + case 'o': /* LS3 -- Locking shift 3 */ + term.charset = 2 + (ascii - 'n'); + break; + case '(': /* GZD4 -- set primary charset G0 */ + case ')': /* G1D4 -- set secondary charset G1 */ + case '*': /* G2D4 -- set tertiary charset G2 */ + case '+': /* G3D4 -- set quaternary charset G3 */ term.icharset = ascii - '('; term.esc |= ESC_ALTCHARSET; return 0; @@ -2560,7 +2580,10 @@ tputc(char *c, int len) { unicodep = ascii = *c; } else { utf8decode(c, &unicodep, UTF_SIZ); - width = wcwidth(unicodep); + if ((width = wcwidth(unicodep)) == -1) { + c = "\357\277\275"; /* UTF_INVALID */ + width = 1; + } control = ISCONTROLC1(unicodep); ascii = unicodep; } @@ -2649,13 +2672,16 @@ tputc(char *c, int len) { if(IS_SET(MODE_WRAP) && (term.c.state & CURSOR_WRAPNEXT)) { gp->mode |= ATTR_WRAP; tnewline(1); + gp = &term.line[term.c.y][term.c.x]; } - if(IS_SET(MODE_INSERT) && term.c.x+1 < term.col) - memmove(gp+1, gp, (term.col - term.c.x - 1) * sizeof(Glyph)); + if(IS_SET(MODE_INSERT) && term.c.x+width < term.col) + memmove(gp+width, gp, (term.col - term.c.x - width) * sizeof(Glyph)); - if(term.c.x+width > term.col) + if(term.c.x+width > term.col) { tnewline(1); + gp = &term.line[term.c.y][term.c.x]; + } tsetchar(c, &term.c.attr, term.c.x, term.c.y); @@ -2965,7 +2991,7 @@ xloadfonts(char *fontstr, double fontsize) { if(!pattern) die("st: can't open font %s\n", fontstr); - if(fontsize > 0) { + if(fontsize > 1) { FcPatternDel(pattern, FC_PIXEL_SIZE); FcPatternDel(pattern, FC_SIZE); FcPatternAddDouble(pattern, FC_PIXEL_SIZE, (double)fontsize); @@ -2985,6 +3011,7 @@ xloadfonts(char *fontstr, double fontsize) { FcPatternAddDouble(pattern, FC_PIXEL_SIZE, 12); usedfontsize = 12; } + defaultfontsize = usedfontsize; } FcConfigSubstitute(0, pattern, FcMatchPattern); @@ -2997,6 +3024,8 @@ xloadfonts(char *fontstr, double fontsize) { FcPatternGetDouble(dc.font.match->pattern, FC_PIXEL_SIZE, 0, &fontval); usedfontsize = fontval; + if(fontsize == 0) + defaultfontsize = fontval; } /* Setting character width and height. */ @@ -3052,14 +3081,32 @@ xunloadfonts(void) { void xzoom(const Arg *arg) { + Arg larg; + + larg.i = usedfontsize + arg->i; + xzoomabs(&larg); +} + +void +xzoomabs(const Arg *arg) { xunloadfonts(); - xloadfonts(usedfont, usedfontsize + arg->i); + xloadfonts(usedfont, arg->i); cresize(0, 0); - redraw(0); + redraw(); xhints(); } void +xzoomreset(const Arg *arg) { + Arg larg; + + if(defaultfontsize > 0) { + larg.i = defaultfontsize; + xzoomabs(&larg); + } +} + +void xinit(void) { XGCValues gcvalues; Cursor cursor; @@ -3099,8 +3146,8 @@ xinit(void) { | ButtonMotionMask | ButtonPressMask | ButtonReleaseMask; xw.attrs.colormap = xw.cmap; - parent = opt_embed ? strtol(opt_embed, NULL, 0) : \ - XRootWindow(xw.dpy, xw.scr); + if (!(opt_embed && (parent = strtol(opt_embed, NULL, 0)))) + parent = XRootWindow(xw.dpy, xw.scr); xw.win = XCreateWindow(xw.dpy, parent, xw.l, xw.t, xw.w, xw.h, 0, XDefaultDepth(xw.dpy, xw.scr), InputOutput, xw.vis, CWBackPixel | CWBorderPixel | CWBitGravity @@ -3162,7 +3209,7 @@ 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, xp, i; - int frcflags; + int frcflags, charexists; int u8fl, u8fblen, u8cblen, doesexist; char *u8c, *u8fs; long unicodep; @@ -3345,8 +3392,13 @@ xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) { /* Search the font cache. */ for(i = 0; i < frclen; i++) { - if(XftCharExists(xw.dpy, frc[i].font, unicodep) - && frc[i].flags == frcflags) { + charexists = XftCharExists(xw.dpy, frc[i].font, unicodep); + /* Everything correct. */ + if(charexists && frc[i].flags == frcflags) + break; + /* We got a default font for a not found glyph. */ + if(!charexists && frc[i].flags == frcflags \ + && frc[i].unicodep == unicodep) { break; } } @@ -3377,8 +3429,8 @@ xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) { FcMatchPattern); FcDefaultSubstitute(fcpattern); - fontpattern = FcFontSetMatch(0, fcsets, - FcTrue, fcpattern, &fcres); + fontpattern = FcFontSetMatch(0, fcsets, 1, + fcpattern, &fcres); /* * Overwrite or create the new cache entry. @@ -3386,11 +3438,13 @@ xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) { if(frclen >= LEN(frc)) { frclen = LEN(frc) - 1; XftFontClose(xw.dpy, frc[frclen].font); + frc[frclen].unicodep = 0; } frc[frclen].font = XftFontOpenPattern(xw.dpy, fontpattern); frc[frclen].flags = frcflags; + frc[frclen].unicodep = unicodep; i = frclen; frclen++; @@ -3456,39 +3510,40 @@ xdrawcursor(void) { xdraws(term.line[oldy][oldx].c, term.line[oldy][oldx], oldx, oldy, width, sl); - /* draw the new one */ - if(!(IS_SET(MODE_HIDE))) { - if(xw.state & WIN_FOCUSED) { - if(IS_SET(MODE_REVERSE)) { - g.mode |= ATTR_REVERSE; - g.fg = defaultcs; - g.bg = defaultfg; - } + if(IS_SET(MODE_HIDE)) + return; - sl = utf8len(g.c); - width = (term.line[term.c.y][curx].mode & ATTR_WIDE)\ - ? 2 : 1; - xdraws(g.c, g, term.c.x, term.c.y, width, sl); - } else { - XftDrawRect(xw.draw, &dc.col[defaultcs], - borderpx + curx * xw.cw, - borderpx + term.c.y * xw.ch, - xw.cw - 1, 1); - XftDrawRect(xw.draw, &dc.col[defaultcs], - borderpx + curx * xw.cw, - borderpx + term.c.y * xw.ch, - 1, xw.ch - 1); - XftDrawRect(xw.draw, &dc.col[defaultcs], - borderpx + (curx + 1) * xw.cw - 1, - borderpx + term.c.y * xw.ch, - 1, xw.ch - 1); - XftDrawRect(xw.draw, &dc.col[defaultcs], - borderpx + curx * xw.cw, - borderpx + (term.c.y + 1) * xw.ch - 1, - xw.cw, 1); + /* draw the new one */ + if(xw.state & WIN_FOCUSED) { + if(IS_SET(MODE_REVERSE)) { + g.mode |= ATTR_REVERSE; + g.fg = defaultcs; + g.bg = defaultfg; } - oldx = curx, oldy = term.c.y; + + sl = utf8len(g.c); + width = (term.line[term.c.y][curx].mode & ATTR_WIDE)\ + ? 2 : 1; + xdraws(g.c, g, term.c.x, term.c.y, width, sl); + } else { + XftDrawRect(xw.draw, &dc.col[defaultcs], + borderpx + curx * xw.cw, + borderpx + term.c.y * xw.ch, + xw.cw - 1, 1); + XftDrawRect(xw.draw, &dc.col[defaultcs], + borderpx + curx * xw.cw, + borderpx + term.c.y * xw.ch, + 1, xw.ch - 1); + XftDrawRect(xw.draw, &dc.col[defaultcs], + borderpx + (curx + 1) * xw.cw - 1, + borderpx + term.c.y * xw.ch, + 1, xw.ch - 1); + XftDrawRect(xw.draw, &dc.col[defaultcs], + borderpx + curx * xw.cw, + borderpx + (term.c.y + 1) * xw.ch - 1, + xw.cw, 1); } + oldx = curx, oldy = term.c.y; } @@ -3509,16 +3564,9 @@ xresettitle(void) { } void -redraw(int timeout) { - struct timespec tv = {0, timeout * 1000}; - +redraw(void) { tfulldirt(); draw(); - - if(timeout > 0) { - nanosleep(&tv, NULL); - XSync(xw.dpy, False); /* necessary for a good tput flash */ - } } void @@ -3585,7 +3633,7 @@ expose(XEvent *ev) { if(!e->count) xw.state &= ~WIN_REDRAW; } - redraw(0); + redraw(); } void @@ -3876,6 +3924,9 @@ run(void) { TIMEDIFF(now, lastblink))); } + drawtimeout.tv_sec = \ + drawtimeout.tv_nsec / 1E9; + drawtimeout.tv_nsec %= (long)1E9; } else { tv = NULL; } @@ -3886,7 +3937,7 @@ run(void) { void usage(void) { - die("%s " VERSION " (c) 2010-2014 st engineers\n" \ + 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] [-w windowid] [-e command ...]\n", argv0); }