X-Git-Url: https://jasonwoof.com/gitweb/?p=st.git;a=blobdiff_plain;f=st.c;h=068fbb3469bd6c11aea544c57516a5d00e7509fe;hp=61024c847ac6ccc4e8f56239a4b5b56fd4e3c52d;hb=bafbba56cd5735c680676db2adf6f614ba61356f;hpb=955923b38b1f08f6cb25a706cea2af5966339187 diff --git a/st.c b/st.c index 61024c8..068fbb3 100644 --- a/st.c +++ b/st.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -70,7 +71,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 ISCONTROLC0(c) (BETWEEN(c, 0, 0x1f)) +#define ISCONTROLC0(c) (BETWEEN(c, 0, 0x1f) || (c) == '\177') #define ISCONTROLC1(c) (BETWEEN(c, 0x80, 0x9f)) #define ISCONTROL(c) (ISCONTROLC0(c) || ISCONTROLC1(c)) #define LIMIT(x, a, b) (x) = (x) < (a) ? (a) : (x) > (b) ? (b) : (x) @@ -86,22 +87,19 @@ char *argv0; #define TRUEBLUE(x) (((x) & 0xff) << 8) -#define VT102ID "\033[?6c" - enum glyph_attribute { - ATTR_NULL = 0, - ATTR_BOLD = 1, - ATTR_FAINT = 2, - ATTR_ITALIC = 4, - ATTR_UNDERLINE = 8, - ATTR_BLINK = 16, - ATTR_FASTBLINK = 32, - ATTR_REVERSE = 64, - ATTR_INVISIBLE = 128, - ATTR_STRUCK = 256, - ATTR_WRAP = 512, - ATTR_WIDE = 1024, - ATTR_WDUMMY = 2048, + ATTR_NULL = 0, + ATTR_BOLD = 1 << 0, + ATTR_FAINT = 1 << 1, + ATTR_ITALIC = 1 << 2, + ATTR_UNDERLINE = 1 << 3, + ATTR_BLINK = 1 << 4, + ATTR_REVERSE = 1 << 5, + ATTR_INVISIBLE = 1 << 6, + ATTR_STRUCK = 1 << 7, + ATTR_WRAP = 1 << 8, + ATTR_WIDE = 1 << 9, + ATTR_WDUMMY = 1 << 10, }; enum cursor_movement { @@ -116,27 +114,27 @@ enum cursor_state { }; enum term_mode { - MODE_WRAP = 1, - MODE_INSERT = 2, - MODE_APPKEYPAD = 4, - MODE_ALTSCREEN = 8, - MODE_CRLF = 16, - MODE_MOUSEBTN = 32, - MODE_MOUSEMOTION = 64, - MODE_REVERSE = 128, - MODE_KBDLOCK = 256, - MODE_HIDE = 512, - MODE_ECHO = 1024, - MODE_APPCURSOR = 2048, - MODE_MOUSESGR = 4096, - MODE_8BIT = 8192, - MODE_BLINK = 16384, - MODE_FBLINK = 32768, - MODE_FOCUS = 65536, - MODE_MOUSEX10 = 131072, - MODE_MOUSEMANY = 262144, - MODE_BRCKTPASTE = 524288, - MODE_PRINT = 1048576, + MODE_WRAP = 1 << 0, + MODE_INSERT = 1 << 1, + MODE_APPKEYPAD = 1 << 2, + MODE_ALTSCREEN = 1 << 3, + MODE_CRLF = 1 << 4, + MODE_MOUSEBTN = 1 << 5, + MODE_MOUSEMOTION = 1 << 6, + MODE_REVERSE = 1 << 7, + MODE_KBDLOCK = 1 << 8, + MODE_HIDE = 1 << 9, + MODE_ECHO = 1 << 10, + MODE_APPCURSOR = 1 << 11, + MODE_MOUSESGR = 1 << 12, + MODE_8BIT = 1 << 13, + MODE_BLINK = 1 << 14, + MODE_FBLINK = 1 << 15, + MODE_FOCUS = 1 << 16, + MODE_MOUSEX10 = 1 << 17, + MODE_MOUSEMANY = 1 << 18, + MODE_BRCKTPASTE = 1 << 19, + MODE_PRINT = 1 << 20, MODE_MOUSE = MODE_MOUSEBTN|MODE_MOUSEMOTION|MODE_MOUSEX10\ |MODE_MOUSEMANY, }; @@ -320,6 +318,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 *); @@ -359,6 +359,7 @@ static void csidump(void); static void csihandle(void); static void csiparse(void); static void csireset(void); +static int eschandle(uchar ascii); static void strdump(void); static void strhandle(void); static void strparse(void); @@ -383,7 +384,7 @@ static void tnewline(int); static void tputtab(int); static void tputc(char *, int); static void treset(void); -static int tresize(int, int); +static void tresize(int, int); static void tscrollup(int, int); static void tscrolldown(int, int); static void tsetattr(int *, int); @@ -405,6 +406,7 @@ static void ttyread(void); static void ttyresize(void); static void ttysend(char *, size_t); static void ttywrite(const char *, size_t); +static void tstrsequence(uchar c); static void xdraws(char *, Glyph, int, int, int, int); static void xhints(void); @@ -504,6 +506,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}; @@ -663,7 +666,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; @@ -683,6 +689,9 @@ selnormalize(void) { sel.nb.y = MIN(sel.ob.y, sel.oe.y); sel.ne.y = MAX(sel.ob.y, sel.oe.y); + selsnap(sel.snap, &sel.nb.x, &sel.nb.y, -1); + selsnap(sel.snap, &sel.ne.x, &sel.ne.y, +1); + /* expand selection over line breaks */ if (sel.type == SEL_RECTANGULAR) return; @@ -707,7 +716,8 @@ selected(int x, int y) { void selsnap(int mode, int *x, int *y, int direction) { int newx, newy, xt, yt; - Glyph *gp; + bool delim, prevdelim; + Glyph *gp, *prevgp; switch(mode) { case SNAP_WORD: @@ -715,6 +725,8 @@ selsnap(int mode, int *x, int *y, int direction) { * Snap around if the word wraps around at the end or * beginning of a line. */ + prevgp = &term.line[*y][*x]; + prevdelim = strchr(worddelimiters, prevgp->c[0]) != NULL; for(;;) { newx = *x + direction; newy = *y; @@ -736,11 +748,15 @@ selsnap(int mode, int *x, int *y, int direction) { break; gp = &term.line[newy][newx]; - if (!(gp->mode & ATTR_WDUMMY) && strchr(worddelimiters, gp->c[0])) + delim = strchr(worddelimiters, gp->c[0]) != NULL; + if(!(gp->mode & ATTR_WDUMMY) && (delim != prevdelim + || (delim && gp->c[0] != prevgp->c[0]))) break; *x = newx; *y = newy; + prevgp = gp; + prevdelim = delim; } break; case SNAP_LINE: @@ -778,15 +794,6 @@ getbuttoninfo(XEvent *e) { sel.oe.x = x2col(e->xbutton.x); sel.oe.y = y2row(e->xbutton.y); - - if(sel.ob.y < sel.oe.y - || (sel.ob.y == sel.oe.y && sel.ob.x < sel.oe.x)) { - selsnap(sel.snap, &sel.ob.x, &sel.ob.y, -1); - selsnap(sel.snap, &sel.oe.x, &sel.oe.y, +1); - } else { - selsnap(sel.snap, &sel.oe.x, &sel.oe.y, -1); - selsnap(sel.snap, &sel.ob.x, &sel.ob.y, +1); - } selnormalize(); sel.type = SEL_REGULAR; @@ -901,8 +908,6 @@ bpress(XEvent *e) { } else { sel.snap = 0; } - selsnap(sel.snap, &sel.ob.x, &sel.ob.y, -1); - selsnap(sel.snap, &sel.oe.x, &sel.oe.y, +1); selnormalize(); /* @@ -961,7 +966,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; @@ -1141,23 +1146,40 @@ die(const char *errstr, ...) { void execsh(void) { - char **args; - char *envshell = getenv("SHELL"); - const struct passwd *pass = getpwuid(getuid()); + char **args, *sh, *prog; + const struct passwd *pw; char buf[sizeof(long) * 8 + 1]; - unsetenv("COLUMNS"); - unsetenv("LINES"); - unsetenv("TERMCAP"); + errno = 0; + if((pw = getpwuid(getuid())) == NULL) { + if(errno) + die("getpwuid:%s\n", strerror(errno)); + else + die("who are you?\n"); + } - 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); + 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); + setenv("HOME", pw->pw_dir, 1); + setenv("TERM", termname, 1); setenv("WINDOWID", buf, 1); signal(SIGCHLD, SIG_DFL); @@ -1167,25 +1189,21 @@ execsh(void) { signal(SIGTERM, SIG_DFL); signal(SIGALRM, SIG_DFL); - DEFAULT(envshell, shell); - setenv("TERM", termname, 1); - args = opt_cmd ? opt_cmd : (char *[]){envshell, "-i", NULL}; - execvp(args[0], args); + execvp(prog, args); exit(EXIT_FAILURE); } void sigchld(int a) { - int stat = 0; + int stat, ret; if(waitpid(pid, &stat, 0) < 0) die("Waiting for pid %hd failed: %s\n", pid, strerror(errno)); - if(WIFEXITED(stat)) { - exit(WEXITSTATUS(stat)); - } else { - exit(EXIT_FAILURE); - } + ret = WIFEXITED(stat) ? WEXITSTATUS(stat) : EXIT_FAILURE; + if (ret != EXIT_SUCCESS) + die("child finished with error '%d'\n", stat); + exit(EXIT_SUCCESS); } void @@ -1359,9 +1377,12 @@ treset(void) { memset(term.trantbl, sizeof(term.trantbl), CS_USA); term.charset = 0; - tclearregion(0, 0, term.col-1, term.row-1); - tmoveto(0, 0); - tcursor(CURSOR_SAVE); + for(i = 0; i < 2; i++) { + tmoveto(0, 0); + tcursor(CURSOR_SAVE); + tclearregion(0, 0, term.col-1, term.row-1); + tswapscreen(); + } } void @@ -1554,6 +1575,7 @@ tsetchar(char *c, Glyph *attr, int x, int y) { void tclearregion(int x1, int y1, int x2, int y2) { int x, y, temp; + Glyph *gp; if(x1 > x2) temp = x1, x1 = x2, x2 = temp; @@ -1568,10 +1590,13 @@ tclearregion(int x1, int y1, int x2, int y2) { for(y = y1; y <= y2; y++) { term.dirty[y] = 1; for(x = x1; x <= x2; x++) { + gp = &term.line[y][x]; if(selected(x, y)) selclear(NULL); - term.line[y][x] = term.c.attr; - memcpy(term.line[y][x].c, " ", 2); + gp->fg = term.c.attr.fg; + gp->bg = term.c.attr.bg; + gp->mode = 0; + memcpy(gp->c, " ", 2); } } } @@ -1683,7 +1708,6 @@ tsetattr(int *attr, int l) { ATTR_ITALIC | ATTR_UNDERLINE | ATTR_BLINK | - ATTR_FASTBLINK | ATTR_REVERSE | ATTR_INVISIBLE | ATTR_STRUCK ); @@ -1703,10 +1727,9 @@ tsetattr(int *attr, int l) { term.c.attr.mode |= ATTR_UNDERLINE; break; case 5: /* slow blink */ - term.c.attr.mode |= ATTR_BLINK; - break; + /* FALLTHROUGH */ case 6: /* rapid blink */ - term.c.attr.mode |= ATTR_FASTBLINK; + term.c.attr.mode |= ATTR_BLINK; break; case 7: term.c.attr.mode |= ATTR_REVERSE; @@ -1717,11 +1740,8 @@ tsetattr(int *attr, int l) { case 9: term.c.attr.mode |= ATTR_STRUCK; break; - case 21: - term.c.attr.mode &= ~ATTR_BOLD; - break; case 22: - term.c.attr.mode &= ~ATTR_FAINT; + term.c.attr.mode &= ~(ATTR_BOLD | ATTR_FAINT); break; case 23: term.c.attr.mode &= ~ATTR_ITALIC; @@ -1732,9 +1752,6 @@ tsetattr(int *attr, int l) { case 25: term.c.attr.mode &= ~ATTR_BLINK; break; - case 26: - term.c.attr.mode &= ~ATTR_FASTBLINK; - break; case 27: term.c.attr.mode &= ~ATTR_REVERSE; break; @@ -1970,7 +1987,7 @@ csihandle(void) { break; case 'c': /* DA -- Device Attributes */ if(csiescseq.arg[0] == 0) - ttywrite(VT102ID, sizeof(VT102ID) - 1); + ttywrite(vtiden, sizeof(vtiden) - 1); break; case 'C': /* CUF -- Cursor Forward */ case 'a': /* HPR -- Cursor Forward */ @@ -2316,13 +2333,13 @@ techo(char *buf, int len) { for(; len > 0; buf++, len--) { char c = *buf; - if(ISCONTROL(c)) { /* control code */ + if(ISCONTROL((uchar) c)) { /* control code */ if(c & 0x80) { c &= 0x7f; tputc("^", 1); tputc("[", 1); } else if(c != '\n' && c != '\r' && c != '\t') { - c ^= '\x40'; + c ^= 0x40; tputc("^", 1); } tputc(&c, 1); @@ -2348,6 +2365,43 @@ tdeftran(char ascii) { } void +tdectest(char c) { + static char E[UTF_SIZ] = "E"; + int x, y; + + if(c == '8') { /* DEC screen alignment test. */ + for(x = 0; x < term.col; ++x) { + for(y = 0; y < term.row; ++y) + tsetchar(E, &term.c.attr, x, y); + } + } +} + +void +tstrsequence(uchar c) { + if (c & 0x80) { + switch (c) { + case 0x90: /* DCS -- Device Control String */ + c = 'P'; + break; + case 0x9f: /* APC -- Application Program Command */ + c = '_'; + break; + case 0x9e: /* PM -- Privacy Message */ + c = '^'; + break; + case 0x9d: /* OSC -- Operating System Command */ + c = ']'; + break; + } + } + strreset(); + strescseq.type = c; + term.esc |= ESC_STR; + return; +} + +void tcontrolcode(uchar ascii) { static char question[UTF_SIZ] = "?"; @@ -2375,7 +2429,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 */ @@ -2383,11 +2437,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); @@ -2401,37 +2453,117 @@ tcontrolcode(uchar ascii) { case 0177: /* DEL (IGNORED) */ return; case 0x84: /* TODO: IND */ - case 0x85: /* TODO: NEL */ - case 0x88: /* TODO: HTS */ + break; + case 0x85: /* NEL -- Next line */ + tnewline(1); /* always go to first col */ + break; + case 0x88: /* HTS -- Horizontal tab stop */ + term.tabs[term.c.x] = 1; + break; case 0x8d: /* TODO: RI */ case 0x8e: /* TODO: SS2 */ case 0x8f: /* TODO: SS3 */ - case 0x90: /* TODO: DCS */ case 0x98: /* TODO: SOS */ - case 0x9a: /* TODO: DECID */ + break; + case 0x9a: /* DECID -- Identify Terminal */ + ttywrite(vtiden, sizeof(vtiden) - 1); + break; case 0x9b: /* TODO: CSI */ case 0x9c: /* TODO: ST */ - case 0x9d: /* TODO: OSC */ - case 0x9e: /* TODO: PM */ - case 0x9f: /* TODO: APC */ break; + case 0x90: /* DCS -- Device Control String */ + case 0x9f: /* APC -- Application Program Command */ + case 0x9e: /* PM -- Privacy Message */ + case 0x9d: /* OSC -- Operating System Command */ + tstrsequence(ascii); + return; } /* only CAN, SUB, \a and C1 chars interrupt a sequence */ term.esc &= ~(ESC_STR_END|ESC_STR); return; } -void -tdectest(char c) { - static char E[UTF_SIZ] = "E"; - int x, y; - - if(c == '8') { /* DEC screen alignment test. */ - for(x = 0; x < term.col; ++x) { - for(y = 0; y < term.row; ++y) - tsetchar(E, &term.c.attr, x, y); +/* + * returns 1 when the sequence is finished and it hasn't to read + * more characters for this sequence, otherwise 0 + */ +int +eschandle(uchar ascii) { + switch(ascii) { + case '[': + term.esc |= ESC_CSI; + return 0; + case '#': + term.esc |= ESC_TEST; + return 0; + case 'P': /* DCS -- Device Control String */ + case '_': /* APC -- Application Program Command */ + case '^': /* PM -- Privacy Message */ + case ']': /* OSC -- Operating System Command */ + case 'k': /* old title set compatibility */ + tstrsequence(ascii); + return 0; + 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; + case 'D': /* IND -- Linefeed */ + if(term.c.y == term.bot) { + tscrollup(term.top, 1); + } else { + tmoveto(term.c.x, term.c.y+1); + } + break; + case 'E': /* NEL -- Next line */ + tnewline(1); /* always go to first col */ + break; + case 'H': /* HTS -- Horizontal tab stop */ + term.tabs[term.c.x] = 1; + break; + case 'M': /* RI -- Reverse index */ + if(term.c.y == term.top) { + tscrolldown(term.top, 1); + } else { + tmoveto(term.c.x, term.c.y-1); } + break; + case 'Z': /* DECID -- Identify Terminal */ + ttywrite(vtiden, sizeof(vtiden) - 1); + break; + case 'c': /* RIS -- Reset to inital state */ + treset(); + xresettitle(); + xloadcols(); + break; + case '=': /* DECPAM -- Application keypad */ + term.mode |= MODE_APPKEYPAD; + break; + case '>': /* DECPNM -- Normal keypad */ + term.mode &= ~MODE_APPKEYPAD; + break; + case '7': /* DECSC -- Save Cursor */ + tcursor(CURSOR_SAVE); + break; + case '8': /* DECRC -- Restore Cursor */ + tcursor(CURSOR_LOAD); + break; + case '\\': /* ST -- String Terminator */ + if(term.esc & ESC_STR_END) + strhandle(); + break; + default: + fprintf(stderr, "erresc: unknown sequence ESC 0x%02X '%c'\n", + (uchar) ascii, isprint(ascii)? ascii:'.'); + break; } + return 1; } void @@ -2447,7 +2579,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; } @@ -2518,78 +2653,9 @@ tputc(char *c, int len) { } else if(term.esc & ESC_TEST) { tdectest(ascii); } else { - switch(ascii) { - case '[': - term.esc |= ESC_CSI; - return; - case '#': - term.esc |= ESC_TEST; - return; - case 'P': /* DCS -- Device Control String */ - case '_': /* APC -- Application Program Command */ - case '^': /* PM -- Privacy Message */ - case ']': /* OSC -- Operating System Command */ - case 'k': /* old title set compatibility */ - strreset(); - strescseq.type = ascii; - term.esc |= ESC_STR; + if (!eschandle(ascii)) return; - case '(': /* set primary charset G0 */ - case ')': /* set secondary charset G1 */ - case '*': /* set tertiary charset G2 */ - case '+': /* set quaternary charset G3 */ - term.icharset = ascii - '('; - term.esc |= ESC_ALTCHARSET; - return; - case 'D': /* IND -- Linefeed */ - if(term.c.y == term.bot) { - tscrollup(term.top, 1); - } else { - tmoveto(term.c.x, term.c.y+1); - } - break; - case 'E': /* NEL -- Next line */ - tnewline(1); /* always go to first col */ - break; - case 'H': /* HTS -- Horizontal tab stop */ - term.tabs[term.c.x] = 1; - break; - case 'M': /* RI -- Reverse index */ - if(term.c.y == term.top) { - tscrolldown(term.top, 1); - } else { - tmoveto(term.c.x, term.c.y-1); - } - break; - case 'Z': /* DECID -- Identify Terminal */ - ttywrite(VT102ID, sizeof(VT102ID) - 1); - break; - case 'c': /* RIS -- Reset to inital state */ - treset(); - xresettitle(); - xloadcols(); - break; - case '=': /* DECPAM -- Application keypad */ - term.mode |= MODE_APPKEYPAD; - break; - case '>': /* DECPNM -- Normal keypad */ - term.mode &= ~MODE_APPKEYPAD; - break; - case '7': /* DECSC -- Save Cursor */ - tcursor(CURSOR_SAVE); - break; - case '8': /* DECRC -- Restore Cursor */ - tcursor(CURSOR_LOAD); - break; - case '\\': /* ST -- String Terminator */ - if(term.esc & ESC_STR_END) - strhandle(); - break; - default: - fprintf(stderr, "erresc: unknown sequence ESC 0x%02X '%c'\n", - (uchar) ascii, isprint(ascii)? ascii:'.'); - break; - } + /* sequence already finished */ } term.esc = 0; /* @@ -2629,18 +2695,20 @@ tputc(char *c, int len) { } } -int +void tresize(int col, int row) { int i; int minrow = MIN(row, term.row); int mincol = MIN(col, term.col); int slide = term.c.y - row + 1; bool *bp; - Line *orig; TCursor c; - if(col < 1 || row < 1) - return 0; + if(col < 1 || row < 1) { + fprintf(stderr, + "tresize: error resizing to %dx%d\n", col, row); + return; + } /* free unneeded rows */ i = 0; @@ -2670,14 +2738,12 @@ tresize(int col, int row) { /* resize each row to new width, zero-pad if needed */ for(i = 0; i < minrow; i++) { - term.dirty[i] = 1; term.line[i] = xrealloc(term.line[i], col * sizeof(Glyph)); term.alt[i] = xrealloc(term.alt[i], col * sizeof(Glyph)); } /* allocate any new rows */ for(/* i == minrow */; i < row; i++) { - term.dirty[i] = 1; term.line[i] = xmalloc(col * sizeof(Glyph)); term.alt[i] = xmalloc(col * sizeof(Glyph)); } @@ -2697,10 +2763,9 @@ tresize(int col, int row) { tsetscroll(0, row-1); /* make use of the LIMIT in tmoveto */ tmoveto(term.c.x, term.c.y); - /* Clearing both screens */ - orig = term.line; + /* Clearing both screens (it makes dirty all lines) */ c = term.c; - do { + for(i = 0; i < 2; i++) { if(mincol < col && 0 < minrow) { tclearregion(mincol, 0, col - 1, minrow - 1); } @@ -2709,10 +2774,8 @@ tresize(int col, int row) { } tswapscreen(); tcursor(CURSOR_LOAD); - } while(orig != term.line); + } term.c = c; - - return (slide > 0); } void @@ -2944,6 +3007,7 @@ xloadfonts(char *fontstr, double fontsize) { FcPatternAddDouble(pattern, FC_PIXEL_SIZE, 12); usedfontsize = 12; } + defaultfontsize = usedfontsize; } FcConfigSubstitute(0, pattern, FcMatchPattern); @@ -2956,6 +3020,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. */ @@ -3011,14 +3077,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); xhints(); } void +xzoomreset(const Arg *arg) { + Arg larg; + + if(defaultfontsize > 0) { + larg.i = defaultfontsize; + xzoomabs(&larg); + } +} + +void xinit(void) { XGCValues gcvalues; Cursor cursor; @@ -3058,8 +3142,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 @@ -3179,7 +3263,7 @@ xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) { * change basic system colors [0-7] * to bright system colors [8-15] */ - if(BETWEEN(base.fg, 0, 7)) + if(BETWEEN(base.fg, 0, 7) && !(base.mode & ATTR_FAINT)) fg = &dc.col[base.fg + 8]; if(base.mode & ATTR_ITALIC) { @@ -3223,6 +3307,14 @@ xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) { bg = temp; } + if(base.mode & ATTR_FAINT && !(base.mode & ATTR_BOLD)) { + colfg.red = fg->color.red / 2; + colfg.green = fg->color.green / 2; + colfg.blue = fg->color.blue / 2; + XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colfg, &revfg); + fg = &revfg; + } + if(base.mode & ATTR_BLINK && term.mode & MODE_BLINK) fg = bg; @@ -3407,39 +3499,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; } @@ -3745,6 +3838,8 @@ run(void) { /* Waiting for window mapping */ while(1) { XNextEvent(xw.dpy, &ev); + if(XFilterEvent(&ev, None)) + continue; if(ev.type == ConfigureNotify) { w = ev.xconfigure.width; h = ev.xconfigure.height; @@ -3836,8 +3931,8 @@ run(void) { void usage(void) { die("%s " VERSION " (c) 2010-2014 st engineers\n" \ - "usage: st [-a] [-v] [-c class] [-f font] [-g geometry] [-o file]" \ - " [-t title] [-w windowid] [-e command ...]\n", argv0); + "usage: st [-a] [-v] [-c class] [-f font] [-g geometry] [-o file]\n" + " [-i] [-t title] [-w windowid] [-e command ...]\n", argv0); } int