X-Git-Url: https://jasonwoof.com/gitweb/?a=blobdiff_plain;f=st.c;h=d7d70e7007342390bac193588e308560343bae17;hb=44db38a5f8560564851683f80e1a649836e5885c;hp=9f5793c5865056735821303634b4513c89fc48f2;hpb=7d32471efffa825f52d24930b5ee617105f9c83e;p=st.git diff --git a/st.c b/st.c index 9f5793c..d7d70e7 100644 --- a/st.c +++ b/st.c @@ -1,5 +1,4 @@ /* See LICENSE for licence details. */ -#define _XOPEN_SOURCE 600 #include #include #include @@ -28,6 +27,10 @@ #include #include +#include "arg.h" + +char *argv0; + #define Glyph Glyph_ #define Font Font_ #define Draw XftDraw * @@ -42,10 +45,6 @@ #include #endif -#define USAGE \ - "st " VERSION " (c) 2010-2013 st engineers\n" \ - "usage: st [-v] [-c class] [-f font] [-g geometry] [-o file]" \ - " [-t title] [-w windowid] [-e command ...]\n" /* XEMBED messages */ #define XEMBED_FOCUS_IN 4 @@ -650,23 +649,18 @@ selected(int x, int y) { if(sel.ey == y && sel.by == y) { bx = MIN(sel.bx, sel.ex); ex = MAX(sel.bx, sel.ex); + 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)); - switch(sel.type) { - case SEL_REGULAR: - 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)); - case SEL_RECTANGULAR: + if(sel.type == SEL_RECTANGULAR) { return ((sel.b.y <= y && y <= sel.e.y) && (sel.b.x <= x && x <= sel.e.x)); - }; + } + 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 @@ -764,7 +758,7 @@ bpress(XEvent *e) { void selcopy(void) { char *str, *ptr, *p; - int x, y, bufsize, is_selected = 0, size; + int x, y, bufsize, isselected = 0, size; Glyph *gp, *last; if(sel.bx == -1) { @@ -775,7 +769,7 @@ selcopy(void) { /* append every set & selected glyph to the selection */ for(y = sel.b.y; y < sel.e.y + 1; y++) { - is_selected = 0; + isselected = 0; gp = &term.line[y][0]; last = gp + term.col; @@ -786,7 +780,7 @@ selcopy(void) { if(!selected(x, y)) { continue; } else { - is_selected = 1; + isselected = 1; } p = (gp->state & GLYPH_SET) ? gp->c : " "; @@ -794,8 +788,17 @@ selcopy(void) { memcpy(ptr, p, size); ptr += size; } - /* \n at the end of every selected line except for the last one */ - if(is_selected && y < sel.e.y) + + /* + * Copy and pasting of line endings is inconsistent + * in the inconsistent terminal and GUI world. + * The best solution seems like to produce '\n' when + * something is copied from st and convert '\n' to + * '\r', when something to be pasted is received by + * st. + * FIXME: Fix the computer world. + */ + if(isselected && y < sel.e.y) *ptr++ = '\n'; } *ptr = 0; @@ -807,7 +810,7 @@ void selnotify(XEvent *e) { ulong nitems, ofs, rem; int format; - uchar *data; + uchar *data, *last, *repl; Atom type; ofs = 0; @@ -818,7 +821,21 @@ selnotify(XEvent *e) { fprintf(stderr, "Clipboard allocation failed\n"); return; } - ttywrite((const char *) data, nitems * format / 8); + + /* + * As seen in selcopy: + * Line endings are inconsistent in the terminal and GUI world + * copy and pasting. When receiving some selection data, + * replace all '\n' with '\r'. + * FIXME: Fix the computer world. + */ + repl = data; + last = data + nitems * format / 8; + while((repl = memchr(repl, '\n', last - repl))) { + *repl++ = '\r'; + } + + ttywrite((const char *)data, nitems * format / 8); XFree(data); /* number of 32-bit chunks returned */ ofs += nitems * format / 32; @@ -1258,8 +1275,12 @@ selscroll(int orig, int n) { sel.bx = -1; return; } - switch(sel.type) { - case SEL_REGULAR: + if(sel.type == SEL_RECTANGULAR) { + if(sel.by < term.top) + sel.by = term.top; + if(sel.ey > term.bot) + sel.ey = term.bot; + } else { if(sel.by < term.top) { sel.by = term.top; sel.bx = 0; @@ -1268,14 +1289,7 @@ selscroll(int orig, int n) { sel.ey = term.bot; sel.ex = term.col; } - break; - case SEL_RECTANGULAR: - if(sel.by < term.top) - sel.by = term.top; - if(sel.ey > term.bot) - sel.ey = term.bot; - break; - }; + } sel.b.y = sel.by, sel.b.x = sel.bx; sel.e.y = sel.ey, sel.e.x = sel.ex; } @@ -1295,7 +1309,6 @@ tnewline(int first_col) { void csiparse(void) { - /* int noarg = 1; */ char *p = csiescseq.buf, *np; long int v; @@ -1305,10 +1318,12 @@ csiparse(void) { p++; } + csiescseq.buf[csiescseq.len] = '\0'; while(p < csiescseq.buf+csiescseq.len) { + np = NULL; v = strtol(p, &np, 10); if(np == p) - break; + v = 0; if(v == LONG_MAX || v == LONG_MIN) v = -1; csiescseq.arg[csiescseq.narg++] = v; @@ -1623,7 +1638,10 @@ tsetmode(bool priv, bool set, int *args, int narg) { break; case 1049: /* = 1047 and 1048 */ case 47: - case 1047: { + case 1047: + if (!allowaltscreen) + break; + alt = IS_SET(MODE_ALTSCREEN); if(alt) { tclearregion(0, 0, term.col-1, @@ -1633,8 +1651,7 @@ tsetmode(bool priv, bool set, int *args, int narg) { tswapscreen(); if(*args != 1049) break; - } - /* pass through */ + /* FALLTRU */ case 1048: tcursor((set) ? CURSOR_SAVE : CURSOR_LOAD); break; @@ -1925,14 +1942,12 @@ strhandle(void) { void strparse(void) { - char *p = strescseq.buf, *sp; + char *p = strescseq.buf; + strescseq.narg = 0; strescseq.buf[strescseq.len] = '\0'; - for(p = strtok_r(p, ";", &sp); p; p = strtok_r(NULL, ";", &sp)) { - if(strescseq.narg == STR_ARG_SIZ) - return; - strescseq.args[strescseq.narg++] = p; - } + while(p && strescseq.narg < STR_ARG_SIZ) + strescseq.args[strescseq.narg++] = strsep(&p, ";"); } void @@ -2109,7 +2124,8 @@ tputc(char *c, int len) { if(term.esc & ESC_CSI) { csiescseq.buf[csiescseq.len++] = ascii; if(BETWEEN(ascii, 0x40, 0x7E) - || csiescseq.len >= ESC_BUF_SIZ) { + || csiescseq.len >= \ + sizeof(csiescseq.buf)-1) { term.esc = 0; csiparse(); csihandle(); @@ -2342,10 +2358,8 @@ xresize(int col, int row) { XFreePixmap(xw.dpy, xw.buf); xw.buf = XCreatePixmap(xw.dpy, xw.win, xw.w, xw.h, DefaultDepth(xw.dpy, xw.scr)); - XSetForeground(xw.dpy, dc.gc, dc.col[IS_SET(MODE_REVERSE) ? defaultfg : defaultbg].pixel); - XFillRectangle(xw.dpy, xw.buf, dc.gc, 0, 0, xw.w, xw.h); - XftDrawChange(xw.draw, xw.buf); + xclear(0, 0, xw.w, xw.h); } static inline ushort @@ -2494,7 +2508,7 @@ xloadfont(Font *f, FcPattern *pattern) { f->lbearing = 0; f->rbearing = f->match->max_advance_width; - f->height = f->match->height; + f->height = f->ascent + f->descent; f->width = f->lbearing + f->rbearing; return 0; @@ -2720,12 +2734,28 @@ xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) { FcPattern *fcpattern, *fontpattern; FcFontSet *fcsets[] = { NULL }; FcCharSet *fccharset; - Colour *fg = &dc.col[base.fg], *bg = &dc.col[base.bg], - *temp, revfg, revbg; + Colour *fg, *bg, *temp, revfg, revbg; XRenderColor colfg, colbg; frcflags = FRC_NORMAL; + if(base.mode & ATTR_ITALIC) { + if(base.fg == defaultfg) + base.fg = defaultitalic; + font = &dc.ifont; + frcflags = FRC_ITALIC; + } else if((base.mode & ATTR_ITALIC) && (base.mode & ATTR_BOLD)) { + if(base.fg == defaultfg) + base.fg = defaultitalic; + font = &dc.ibfont; + frcflags = FRC_ITALICBOLD; + } else if(base.mode & ATTR_UNDERLINE) { + if(base.fg == defaultfg) + base.fg = defaultunderline; + } + fg = &dc.col[base.fg]; + bg = &dc.col[base.bg]; + if(base.mode & ATTR_BOLD) { if(BETWEEN(base.fg, 0, 7)) { /* basic system colors */ @@ -2747,15 +2777,6 @@ xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) { frcflags = FRC_BOLD; } - if(base.mode & ATTR_ITALIC) { - font = &dc.ifont; - 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]) { fg = &dc.col[defaultbg]; @@ -2882,8 +2903,7 @@ xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) { FcTrue, fcpattern, &fcres); /* - * Overwrite or create the new cache entry - * entry. + * Overwrite or create the new cache entry. */ frccur++; frclen++; @@ -2946,14 +2966,33 @@ xdrawcursor(void) { /* draw the new one */ if(!(IS_SET(MODE_HIDE))) { - if(!(xw.state & WIN_FOCUSED)) - g.bg = defaultucs; - - if(IS_SET(MODE_REVERSE)) - g.mode |= ATTR_REVERSE, g.fg = defaultcs, g.bg = defaultfg; + if(xw.state & WIN_FOCUSED) { + if(IS_SET(MODE_REVERSE)) { + g.mode |= ATTR_REVERSE; + g.fg = defaultcs; + g.bg = defaultfg; + } - sl = utf8size(g.c); - xdraws(g.c, g, term.c.x, term.c.y, 1, sl); + sl = utf8size(g.c); + xdraws(g.c, g, term.c.x, term.c.y, 1, sl); + } else { + XftDrawRect(xw.draw, &dc.col[defaultcs], + borderpx + term.c.x * xw.cw, + borderpx + term.c.y * xw.ch, + xw.cw - 1, 1); + XftDrawRect(xw.draw, &dc.col[defaultcs], + borderpx + term.c.x * xw.cw, + borderpx + term.c.y * xw.ch, + 1, xw.ch - 1); + XftDrawRect(xw.draw, &dc.col[defaultcs], + borderpx + (term.c.x + 1) * xw.cw - 1, + borderpx + term.c.y * xw.ch, + 1, xw.ch - 1); + XftDrawRect(xw.draw, &dc.col[defaultcs], + borderpx + term.c.x * xw.cw, + borderpx + (term.c.y + 1) * xw.ch - 1, + xw.cw, 1); + } oldx = term.c.x, oldy = term.c.y; } } @@ -3309,67 +3348,67 @@ run(void) { } } +void +usage(void) { + die("%s " VERSION " (c) 2010-2013 st engineers\n" \ + "usage: st [-a] [-v] [-c class] [-f font] [-g geometry] [-o file]" \ + " [-t title] [-w windowid] [-e command ...]\n", argv0); +} + int main(int argc, char *argv[]) { - int i, bitm, xr, yr; + int bitm, xr, yr; uint wr, hr; xw.fw = xw.fh = xw.fx = xw.fy = 0; xw.isfixed = False; - for(i = 1; i < argc; i++) { - switch(argv[i][0] != '-' || argv[i][2] ? -1 : argv[i][1]) { - case 'c': - if(++i < argc) - opt_class = argv[i]; - break; - case 'e': - /* eat all remaining arguments */ - if(++i < argc) - opt_cmd = &argv[i]; - goto run; - case 'f': - if(++i < argc) - opt_font = argv[i]; - break; - case 'g': - if(++i >= argc) - break; - - bitm = XParseGeometry(argv[i], &xr, &yr, &wr, &hr); - if(bitm & XValue) - xw.fx = xr; - if(bitm & YValue) - xw.fy = yr; - if(bitm & WidthValue) - xw.fw = (int)wr; - if(bitm & HeightValue) - xw.fh = (int)hr; - if(bitm & XNegative && xw.fx == 0) - xw.fx = -1; - if(bitm & XNegative && xw.fy == 0) - xw.fy = -1; - - if(xw.fh != 0 && xw.fw != 0) - xw.isfixed = True; - break; - case 'o': - if(++i < argc) - opt_io = argv[i]; - break; - case 't': - if(++i < argc) - opt_title = argv[i]; - break; - case 'v': - default: - die(USAGE); - case 'w': - if(++i < argc) - opt_embed = argv[i]; - break; - } - } + ARGBEGIN { + case 'a': + allowaltscreen = false; + break; + case 'c': + opt_class = EARGF(usage()); + break; + case 'e': + /* eat all remaining arguments */ + if(argc > 1) + opt_cmd = &argv[1]; + goto run; + case 'f': + opt_font = EARGF(usage()); + break; + case 'g': + bitm = XParseGeometry(EARGF(usage()), &xr, &yr, &wr, &hr); + if(bitm & XValue) + xw.fx = xr; + if(bitm & YValue) + xw.fy = yr; + if(bitm & WidthValue) + xw.fw = (int)wr; + if(bitm & HeightValue) + xw.fh = (int)hr; + if(bitm & XNegative && xw.fx == 0) + xw.fx = -1; + if(bitm & XNegative && xw.fy == 0) + xw.fy = -1; + + if(xw.fh != 0 && xw.fw != 0) + xw.isfixed = True; + break; + case 'o': + opt_io = EARGF(usage()); + break; + case 't': + opt_title = EARGF(usage()); + break; + case 'w': + opt_embed = EARGF(usage()); + break; + case 'v': + default: + usage(); + } ARGEND; run: setlocale(LC_CTYPE, ""); @@ -3378,6 +3417,8 @@ run: xinit(); ttynew(); selinit(); + if(xw.isfixed) + cresize(xw.h, xw.w); run(); return 0;