[dev] [st] [patch] typedefs instead of #defines
Replaced #defines with typedefs where possible, patch attached. diff --git a/st.c b/st.c index a4f467d..89e93e0 100644 --- a/st.c +++ b/st.c @@ -36,10 +36,6 @@ char *argv0; #define Glyph Glyph_ #define Font Font_ -#define Draw XftDraw * -#define Colour XftColor -#define Colourmap Colormap -#define Rectangle XRectangle #if defined(__linux) #include @@ -180,6 +176,10 @@ typedef unsigned int uint; typedef unsigned long ulong; typedef unsigned short ushort; +typedef XftDraw *Draw; +typedef XftColor Colour; +typedef Colormap Colourmap; + typedef struct { char c[UTF_SIZ]; /* character code */ ushort mode; /* attribute flags */ @@ -3107,7 +3107,7 @@ xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) { FcCharSet *fccharset; Colour *fg, *bg, *temp, revfg, revbg, truefg, truebg; XRenderColor colfg, colbg; - Rectangle r; + XRectangle r; int oneatatime; frcflags = FRC_NORMAL;
Re: [dev] [st] [patch] typedefs instead of #defines
On Tue, Apr 08, 2014 at 02:11:24PM +0200, Roberto E. Vargas Caballero wrote: > > -#define Rectangle XRectangle > > > ... > > - Rectangle r; > > + XRectangle r; > > You remove the define at all in this point, and if I remember well, this > define was needed to avoid something. Maybe Christoph can talk a bit > more about this, because I think he was who write these defines. There are defines that are used to avoid conflicts with already defined types. But here I just removed #define and applied it everywhere (one place) manually. Also, I have another cleanup patch. It removes special case of ^[, because it is handled well by "control code" case. I have tested it using printf '\e[12l' and it works. diff --git a/st.c b/st.c index a104a50..ef732a5 100644 --- a/st.c +++ b/st.c @@ -2315,10 +2315,7 @@ techo(char *buf, int len) { for(; len > 0; buf++, len--) { char c = *buf; - if(c == '\033') { /* escape */ - tputc("^", 1); - tputc("[", 1); - } else if(c < '\x20') { /* control code */ + if(c < '\x20') { /* control code */ if(c != '\n' && c != '\r' && c != '\t') { c |= '\x40'; tputc("^", 1);
[dev] [st] [patch] move MODBIT to Macros section
Patch moves MODBIT to macros section and uses it in tselcs. diff --git a/st.c b/st.c index df660ff..8237d78 100644 --- a/st.c +++ b/st.c @@ -64,7 +64,7 @@ char *argv0; #define REDRAW_TIMEOUT (80*1000) /* 80 ms */ -/* macros */ +/* Macros */ #define SERRNO strerror(errno) #define MIN(a, b) ((a) < (b) ? (a) : (b)) #define MAX(a, b) ((a) < (b) ? (b) : (a)) @@ -76,6 +76,7 @@ char *argv0; #define IS_SET(flag) ((term.mode & (flag)) != 0) #define TIMEDIFF(t1, t2) ((t1.tv_sec-t2.tv_sec)*1000 + (t1.tv_usec-t2.tv_usec)/1000) #define CEIL(x) (((x) != (int) (x)) ? (x) + 1 : (x)) +#define MODBIT(x, set, bit) ((set) ? ((x) |= (bit)) : ((x) &= ~(bit))) #define TRUECOLOR(r,g,b) (1 << 24 | (r) << 16 | (g) << 8 | (b)) #define IS_TRUECOL(x)(1 << 24 & (x)) @@ -1785,8 +1786,6 @@ tsetscroll(int t, int b) { term.bot = b; } -#define MODBIT(x, set, bit) ((set) ? ((x) |= (bit)) : ((x) &= ~(bit))) - void tsetmode(bool priv, bool set, int *args, int narg) { int *lim, mode; @@ -2356,10 +2355,7 @@ tdeftran(char ascii) { void tselcs(void) { - if (term.trantbl[term.charset] == CS_GRAPHIC0) - term.c.attr.mode |= ATTR_GFX; - else - term.c.attr.mode &= ~ATTR_GFX; + MODBIT(term.c.attr.mode, term.trantbl[term.charset] == CS_GRAPHIC0, ATTR_GFX); } void
Re: [dev] [st] [patch] use SERRNO instead of strerror(errno)
Replaced strerror(errno) with SERRNO where possible. diff --git a/st.c b/st.c index 8237d78..f9ac1f7 100644 --- a/st.c +++ b/st.c @@ -1226,7 +1226,7 @@ ttynew(void) { open(opt_io, O_WRONLY | O_CREAT, 0666); if(iofd < 0) { fprintf(stderr, "Error opening %s:%s\n", - opt_io, strerror(errno)); + opt_io, SERRNO); } } } @@ -2239,7 +2239,7 @@ void tprinter(char *s, size_t len) { if(iofd != -1 && xwrite(iofd, s, len) < 0) { fprintf(stderr, "Error writing in %s:%s\n", - opt_io, strerror(errno)); + opt_io, SERRNO); close(iofd); iofd = -1; }
Re: [dev] [st] [patch] remove unnecessary line continuations
Patch attached. diff --git a/st.c b/st.c index df660ff..5cc5da7 100644 --- a/st.c +++ b/st.c @@ -132,7 +132,7 @@ enum term_mode { MODE_MOUSEMANY = 262144, MODE_BRCKTPASTE = 524288, MODE_PRINT = 1048576, - MODE_MOUSE = MODE_MOUSEBTN|MODE_MOUSEMOTION|MODE_MOUSEX10\ + MODE_MOUSE = MODE_MOUSEBTN|MODE_MOUSEMOTION|MODE_MOUSEX10 |MODE_MOUSEMANY, }; @@ -1698,8 +1698,8 @@ tsetattr(int *attr, int l) { for(i = 0; i < l; i++) { switch(attr[i]) { case 0: - term.c.attr.mode &= ~(ATTR_REVERSE | ATTR_UNDERLINE \ - | ATTR_BOLD | ATTR_ITALIC \ + term.c.attr.mode &= ~(ATTR_REVERSE | ATTR_UNDERLINE + | ATTR_BOLD | ATTR_ITALIC | ATTR_BLINK); term.c.attr.fg = defaultfg; term.c.attr.bg = defaultbg; @@ -2470,7 +2470,7 @@ tputc(char *c, int len) { if(term.esc & ESC_CSI) { csiescseq.buf[csiescseq.len++] = ascii; if(BETWEEN(ascii, 0x40, 0x7E) - || csiescseq.len >= \ + || csiescseq.len >= sizeof(csiescseq.buf)-1) { term.esc = 0; csiparse(); @@ -3036,7 +3036,7 @@ xinit(void) { | ButtonMotionMask | ButtonPressMask | ButtonReleaseMask; xw.attrs.colormap = xw.cmap; - parent = opt_embed ? strtol(opt_embed, NULL, 0) : \ + parent = opt_embed ? strtol(opt_embed, NULL, 0) : XRootWindow(xw.dpy, xw.scr); xw.win = XCreateWindow(xw.dpy, parent, xw.fx, xw.fy, xw.w, xw.h, 0, XDefaultDepth(xw.dpy, xw.scr), InputOutput, @@ -3397,7 +3397,7 @@ xdrawcursor(void) { } sl = utf8len(g.c); - width = (term.line[term.c.y][curx].mode & ATTR_WIDE)\ + 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 { @@ -3802,12 +3802,12 @@ run(void) { xev--; if(!FD_ISSET(cmdfd, &rfd) && !FD_ISSET(xfd, &rfd)) { if(blinkset) { - if(TIMEDIFF(now, lastblink) \ + if(TIMEDIFF(now, lastblink) > blinktimeout) { drawtimeout.tv_usec = 1; } else { - drawtimeout.tv_usec = (1000 * \ - (blinktimeout - \ + drawtimeout.tv_usec = (1000 * + (blinktimeout - TIMEDIFF(now, lastblink))); } @@ -3821,8 +3821,8 @@ 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]" \ + 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); }
Re: [dev] [st] [patch] misplaced parenthesis in LEN macro
diff --git a/st.c b/st.c index df660ff..fbbdc34 100644 --- a/st.c +++ b/st.c @@ -68,7 +68,7 @@ char *argv0; #define SERRNO strerror(errno) #define MIN(a, b) ((a) < (b) ? (a) : (b)) #define MAX(a, b) ((a) < (b) ? (b) : (a)) -#define LEN(a) (sizeof(a) / sizeof(a[0])) +#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 LIMIT(x, a, b)(x) = (x) < (a) ? (a) : (x) > (b) ? (b) : (x)
Re: [dev] [st] [patch] misplaced parenthesis in LEN macro
On Sun, Apr 20, 2014 at 01:53:33PM +0200, Alexander Huemer wrote: > Hi, > > On Sun, Apr 20, 2014 at 03:41:40PM +0400, non...@inventati.org wrote: > > […] > > -#define LEN(a) (sizeof(a) / sizeof(a[0])) > > +#define LEN(a) (sizeof(a) / sizeof(a)[0]) > > […] > > Why parenthesis anyway? a[0] is an expression, not a type, and there is > nothing to group here. sizeof is not a function! Because it is a macro and there can be another expression (such as m+1 where m is an array). Macro would expand to (sizeof(m+1) / sizeof(m+1[0])) instead of (sizeof(m+1) / sizeof(m+1)[0])
[dev] [PATCH] [st 1/3] Use tsetdirt in tscrollup and tscrolldown.
--- st.c | 10 -- 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/st.c b/st.c index df660ff..e625237 100644 --- a/st.c +++ b/st.c @@ -1401,14 +1401,13 @@ tscrolldown(int orig, int n) { LIMIT(n, 0, term.bot-orig+1); tclearregion(0, term.bot-n+1, term.col-1, term.bot); + tsetdirt(orig, term.bot-n); + tsetdirt(orig+n, term.bot); for(i = term.bot; i >= orig+n; i--) { temp = term.line[i]; term.line[i] = term.line[i-n]; term.line[i-n] = temp; - - term.dirty[i] = 1; - term.dirty[i-n] = 1; } selscroll(orig, n); @@ -1421,14 +1420,13 @@ tscrollup(int orig, int n) { LIMIT(n, 0, term.bot-orig+1); tclearregion(0, orig, term.col-1, orig+n-1); + tsetdirt(orig, term.bot-n); + tsetdirt(orig+n, term.bot); for(i = orig; i <= term.bot-n; i++) { temp = term.line[i]; term.line[i] = term.line[i+n]; term.line[i+n] = temp; - -term.dirty[i] = 1; -term.dirty[i+n] = 1; } selscroll(orig, -n); -- 1.8.4
[dev] [PATCH] [st 3/3] Style fixes in tscrollup.
--- st.c | 7 --- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/st.c b/st.c index fecf1c2..185c615 100644 --- a/st.c +++ b/st.c @@ -1416,15 +1416,16 @@ void tscrollup(int orig, int n) { int i; Line temp; + LIMIT(n, 0, term.bot-orig+1); tclearregion(0, orig, term.col-1, orig+n-1); tsetdirt(orig+n, term.bot); for(i = orig; i <= term.bot-n; i++) { -temp = term.line[i]; -term.line[i] = term.line[i+n]; -term.line[i+n] = temp; + temp = term.line[i]; + term.line[i] = term.line[i+n]; + term.line[i+n] = temp; } selscroll(orig, -n); -- 1.8.4
[dev] [PATCH] [st 2/3] Do not set dirty flag twice in tscrollup and tscrolldown.
--- st.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/st.c b/st.c index e625237..fecf1c2 100644 --- a/st.c +++ b/st.c @@ -1400,9 +1400,8 @@ tscrolldown(int orig, int n) { LIMIT(n, 0, term.bot-orig+1); - tclearregion(0, term.bot-n+1, term.col-1, term.bot); tsetdirt(orig, term.bot-n); - tsetdirt(orig+n, term.bot); + tclearregion(0, term.bot-n+1, term.col-1, term.bot); for(i = term.bot; i >= orig+n; i--) { temp = term.line[i]; @@ -1420,7 +1419,6 @@ tscrollup(int orig, int n) { LIMIT(n, 0, term.bot-orig+1); tclearregion(0, orig, term.col-1, orig+n-1); - tsetdirt(orig, term.bot-n); tsetdirt(orig+n, term.bot); for(i = orig; i <= term.bot-n; i++) { -- 1.8.4
Re: [dev] [PATCH] [st 1/3] Use tsetdirt in tscrollup and tscrolldown.
tscrollup and tscrolldown do not use tsetdirt, but their code is equivalent to tsetdirt(orig, term.bot-n); tsetdirt(orig+n, term.bot); tclearregion also marks cleared lines as dirty. In tscrolldown it sets lines from term.bot-n+1 to term.bot dirty, and in tscrollup it sets lines from orig to orig+n-1 dirty. In both functions all lines from orig to term.bot are effectively set dirty, but in tscrolldown lines from orig+n to term.bot are set dirty twice, and in tscrollup lines from orig to term.bot-n are set dirty twice. These patches make it clear which lines are set dirty and sets them dirty once in each funciton.
[dev] [st] [PATCH 3/6] Remove argument names from function prototypes.
--- st.c | 12 ++-- 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/st.c b/st.c index 6da4827..64384cd 100644 --- a/st.c +++ b/st.c @@ -360,7 +360,7 @@ static void strparse(void); static void strreset(void); static int tattrset(int); -static void tprinter(char *s, size_t len); +static void tprinter(char *, size_t); static void tdumpsel(void); static void tdumpline(int); static void tdump(void); @@ -371,7 +371,7 @@ static void tdeleteline(int); static void tinsertblank(int); static void tinsertblankline(int); static void tmoveto(int, int); -static void tmoveato(int x, int y); +static void tmoveato(int, int); static void tnew(int, int); static void tnewline(int); static void tputtab(bool); @@ -380,7 +380,7 @@ static void treset(void); static int tresize(int, int); static void tscrollup(int, int); static void tscrolldown(int, int); -static void tsetattr(int*, int); +static void tsetattr(int *, int); static void tsetchar(char *, Glyph *, int, int); static void tsetscroll(int, int); static void tswapscreen(void); @@ -413,9 +413,9 @@ static void xsettitle(char *); static void xresettitle(void); static void xsetpointermotion(int); static void xseturgency(int); -static void xsetsel(char*); +static void xsetsel(char *); static void xtermclear(int, int, int, int); -static void xunloadfont(Font *f); +static void xunloadfont(Font *); static void xunloadfonts(void); static void xresize(int, int); @@ -453,7 +453,7 @@ static size_t utf8validate(long *, size_t); static ssize_t xwrite(int, char *, size_t); static void *xmalloc(size_t); static void *xrealloc(void *, size_t); -static char *xstrdup(char *s); +static char *xstrdup(char *); static void (*handler[LASTEvent])(XEvent *) = { [KeyPress] = kpress, -- 1.8.4
[dev] [st] [PATCH 2/6] Style fix in tdumpsel.
--- st.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/st.c b/st.c index 92fd7da..6da4827 100644 --- a/st.c +++ b/st.c @@ -2256,8 +2256,7 @@ printsel(const Arg *arg) { } void -tdumpsel(void) -{ +tdumpsel(void) { char *ptr; if((ptr = getsel())) { -- 1.8.4
[dev] [st] [PATCH 6/6] Make xrealloc and xstrdup style consistent.
--- st.c | 6 ++ 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/st.c b/st.c index bb3e687..aba034f 100644 --- a/st.c +++ b/st.c @@ -549,12 +549,10 @@ xrealloc(void *p, size_t len) { char * xstrdup(char *s) { - char *p = strdup(s); - - if (!p) + if((s = strdup(s)) == NULL) die("Out of memory\n"); - return p; + return s; } size_t -- 1.8.4
[dev] [st] [PATCH 4/6] Use uint and uchar instead of unsigned int and unsigned char.
--- st.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/st.c b/st.c index 64384cd..b8bf84b 100644 --- a/st.c +++ b/st.c @@ -298,13 +298,13 @@ typedef struct { typedef union { int i; - unsigned int ui; + uint ui; float f; const void *v; } Arg; typedef struct { - unsigned int mod; + uint mod; KeySym keysym; void (*func)(const Arg *); const Arg arg; @@ -3076,7 +3076,7 @@ xinit(void) { xw.netwmpid = XInternAtom(xw.dpy, "_NET_WM_PID", False); XChangeProperty(xw.dpy, xw.win, xw.netwmpid, XA_CARDINAL, 32, - PropModeReplace, (unsigned char *)&thispid, 1); + PropModeReplace, (uchar *)&thispid, 1); xresettitle(); XMapWindow(xw.dpy, xw.win); -- 1.8.4
[dev] [st] [PATCH 5/6] Use BETWEEN in tsetchar.
--- st.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/st.c b/st.c index b8bf84b..bb3e687 100644 --- a/st.c +++ b/st.c @@ -1544,8 +1544,7 @@ tsetchar(char *c, Glyph *attr, int x, int y) { * The table is proudly stolen from rxvt. */ if(attr->mode & ATTR_GFX) { - if(c[0] >= 0x41 && c[0] <= 0x7e - && vt100_0[c[0] - 0x41]) { + if(BETWEEN(c[0], 0x41, 0x7e) && vt100_0[c[0] - 0x41]) { c = vt100_0[c[0] - 0x41]; } } -- 1.8.4
[dev] [st] [PATCH 1/6] Use BETWEEN in tinsertblankline and tdeleteline.
--- st.c | 12 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/st.c b/st.c index 019f53c..92fd7da 100644 --- a/st.c +++ b/st.c @@ -1628,18 +1628,14 @@ tinsertblank(int n) { void tinsertblankline(int n) { - if(term.c.y < term.top || term.c.y > term.bot) - return; - - tscrolldown(term.c.y, n); + if(BETWEEN(term.c.y, term.top, term.bot)) + tscrolldown(term.c.y, n); } void tdeleteline(int n) { - if(term.c.y < term.top || term.c.y > term.bot) - return; - - tscrollup(term.c.y, n); + if(BETWEEN(term.c.y, term.top, term.bot)) + tscrollup(term.c.y, n); } int32_t -- 1.8.4
[dev] [st] [PATCH] Fix techo handling of control characters.
Internally st represents characters using "char" type. It is used in CSIEscape.buf, Glyph.c etc. However, char can be either signed or unsigned depends on the architecture. On x86 '\x80' < 0x20 is true, but (uchar)'\x80' < 0x20 is false. tputc explicitly converts character to ascii code: uchar ascii = *c; In tsetchar there is this code: c[0] >= 0x41 && c[0] <= 0x7e This condition is false for negative chars, so, accidentally, it works the same way for signed and unsigned chars. However, techo compares signed char to '\x20' and has a bug. How to reproduce: 1. Add the following keybinding: { XK_F1,XK_NO_MOD, "\x80" , 0,0,0}, 2. Run st and enable echo mode: printf '\e[12l' 3. Press F1. Character '\x80' is recognized as control and ^ is displayed, followed by unprintable character. This patch fixes the bug the same way it is fixed in tputc. Also techo did not recognize DEL as control character and did not display ^? for it, this patch fixes this bug too. --- st.c | 6 -- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/st.c b/st.c index 019f53c..3bf8eee 100644 --- a/st.c +++ b/st.c @@ -2315,10 +2315,12 @@ void techo(char *buf, int len) { for(; len > 0; buf++, len--) { char c = *buf; + uchar ascii = c; + bool control = ascii < '\x20' || ascii == 0177; - if(c < '\x20') { /* control code */ + if(control) { /* control code */ if(c != '\n' && c != '\r' && c != '\t') { - c |= '\x40'; + c ^= '\x40'; tputc("^", 1); } tputc(&c, 1); -- 1.8.4
Re: [dev] [st] [PATCH] Fix techo handling of control characters.
BTW what do you think about converting st code to store characters in uchar instead of char to avoid these problems in the future and avoid manual conversions? tsetchar should probably be fixed too. c[0] >= 0x41 && c[0] <= 0x7e works, but it is better to change type of `c' to uchar *.
Re: [dev] [PATCH] [st 1/3] Use tsetdirt in tscrollup and tscrolldown.
On Tue, Apr 22, 2014 at 09:34:58PM +0200, Roberto E. Vargas Caballero wrote: > Hi, > > I like these patches, and I want to apply them, but there is a > small thing that I think should be modified. After the patches tscolldown > has: > > tsetdirt(orig, term.bot-n); > tclearregion(0, term.bot-n+1, term.col-1, term.bot); > > but tscrollup has: > > tclearregion(0, orig, term.col-1, orig+n-1); > tsetdirt(orig+n, term.bot); > > Is there any reason to do it in different order?. I think is more > understable if the order is the same in both cases. They are sorted by row number. In tscrolldown we set dirty orig..term.bot-n and then term.bot-n+1..term.bot In tscrollup we set dirty orig..orig+n-1 and then orig+n..term.bot If you concatenate these ranges, you get orig..term.bot.
[dev] [st] [PATCH] Fix techo handling of control and multibyte characters.
techo compares signed char to '\x20'. Any character with code less then '\x20' is treated as control character. This way characters with MSB set to 1 are considered control characters too. Also this patch makes techo display DEL character as ^?. To reprocuce the bug, enable echo mode using printf '\e[12l', then type DEL character or any non-ASCII character. --- st.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/st.c b/st.c index 019f53c..b6cb01c 100644 --- a/st.c +++ b/st.c @@ -2316,9 +2316,9 @@ techo(char *buf, int len) { for(; len > 0; buf++, len--) { char c = *buf; - if(c < '\x20') { /* control code */ + if(c < 0x20u || c == 0177) { /* control code */ if(c != '\n' && c != '\r' && c != '\t') { - c |= '\x40'; + c ^= '\x40'; tputc("^", 1); } tputc(&c, 1); -- 1.8.4
[dev] [PATCH] Simplify tdeletechar and tinsertblank and fix memory corruption.
Current CSI parsing code uses strtol to parse arguments and allows them to be negative. Negative argument is not properly handled in tdeletechar and tinsertblank and results in memory corruption in memmove. Reproduce with printf '\e[-500@' Patch also removes special handling for corner case and simplifies the code. Removed term.dirty[term.c.y] = 1 because tclearregion sets dirty flag. --- st.c | 26 ++ 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/st.c b/st.c index 019f53c..ae76731 100644 --- a/st.c +++ b/st.c @@ -1592,16 +1592,13 @@ tclearregion(int x1, int y1, int x2, int y2) { void tdeletechar(int n) { - int src = term.c.x + n; - int dst = term.c.x; - int size = term.col - src; + int dst, src, size; - term.dirty[term.c.y] = 1; + LIMIT(n, 0, term.col - term.c.x); - if(src >= term.col) { - tclearregion(term.c.x, term.c.y, term.col-1, term.c.y); - return; - } + dst = term.c.x; + src = term.c.x + n; + size = term.col - src; memmove(&term.line[term.c.y][dst], &term.line[term.c.y][src], size * sizeof(Glyph)); @@ -1610,16 +1607,13 @@ tdeletechar(int n) { void tinsertblank(int n) { - int src = term.c.x; - int dst = src + n; - int size = term.col - dst; + int dst, src, size; - term.dirty[term.c.y] = 1; + LIMIT(n, 0, term.col - term.c.x); - if(dst >= term.col) { - tclearregion(term.c.x, term.c.y, term.col-1, term.c.y); - return; - } + dst = term.c.x + n; + src = term.c.x; + size = term.col - dst; memmove(&term.line[term.c.y][dst], &term.line[term.c.y][src], size * sizeof(Glyph)); -- 1.8.4
[dev] [st PATCH 1/4] Simplify tsetscroll.
--- st.c | 12 +++- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/st.c b/st.c index aba034f..ede90d5 100644 --- a/st.c +++ b/st.c @@ -1765,17 +1765,11 @@ tsetattr(int *attr, int l) { void tsetscroll(int t, int b) { - int temp; - LIMIT(t, 0, term.row-1); LIMIT(b, 0, term.row-1); - if(t > b) { - temp = t; - t = b; - b = temp; - } - term.top = t; - term.bot = b; + + term.top = MIN(t, b); + term.bot = MAX(t, b); } void -- 1.8.4
[dev] [st PATCH 2/4] Use BETWEEN macro in xsetcolorname and fix style.
--- st.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/st.c b/st.c index ede90d5..07f408c 100644 --- a/st.c +++ b/st.c @@ -2750,10 +2750,10 @@ int xsetcolorname(int x, const char *name) { XRenderColor color = { .alpha = 0x }; Colour colour; - if (x < 0 || x > LEN(colorname)) + if(!BETWEEN(x, 0, LEN(colorname))) return -1; if(!name) { - if(16 <= x && x < 16 + 216) { + if(BETWEEN(x, 16, 16 + 215)) { int r = (x - 16) / 36, g = ((x - 16) % 36) / 6, b = (x - 16) % 6; color.red = sixd_to_16bit(r); color.green = sixd_to_16bit(g); @@ -2762,7 +2762,7 @@ xsetcolorname(int x, const char *name) { return 0; /* something went wrong */ dc.col[x] = colour; return 1; - } else if (16 + 216 <= x && x < 256) { + } else if(BETWEEN(x, 16 + 216, 255)) { color.red = color.green = color.blue = 0x0808 + 0x0a0a * (x - (16 + 216)); if(!XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &color, &colour)) return 0; /* something went wrong */ -- 1.8.4
[dev] [st PATCH 3/4] Use != instead of ^ for logical values.
sel.alt is only changed by sel.alt = IS_SET(MODE_ALTSCREEN); --- st.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/st.c b/st.c index 07f408c..e61ee68 100644 --- a/st.c +++ b/st.c @@ -3449,7 +3449,7 @@ drawregion(int x1, int y1, int x2, int y2) { bool ena_sel = sel.ob.x != -1; long unicodep; - if(sel.alt ^ IS_SET(MODE_ALTSCREEN)) + if(sel.alt != IS_SET(MODE_ALTSCREEN)) ena_sel = 0; if(!(xw.state & WIN_VISIBLE)) -- 1.8.4
[dev] [st PATCH 4/4] Optimize tputtab.
Before this patch executing printf '\e[100I' or printf '\e[100Z' resulted in long delay. --- st.c | 28 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/st.c b/st.c index e61ee68..964a0ae 100644 --- a/st.c +++ b/st.c @@ -374,7 +374,7 @@ static void tmoveto(int, int); static void tmoveato(int, int); static void tnew(int, int); static void tnewline(int); -static void tputtab(bool); +static void tputtab(int); static void tputc(char *, int); static void treset(void); static int tresize(int, int); @@ -1995,8 +1995,7 @@ csihandle(void) { break; case 'I': /* CHT -- Cursor Forward Tabulation tab stops */ DEFAULT(csiescseq.arg[0], 1); - while(csiescseq.arg[0]--) - tputtab(1); + tputtab(csiescseq.arg[0]); break; case 'J': /* ED -- Clear screen */ selclear(NULL); @@ -2064,8 +2063,7 @@ csihandle(void) { break; case 'Z': /* CBT -- Cursor Backward Tabulation tab stops */ DEFAULT(csiescseq.arg[0], 1); - while(csiescseq.arg[0]--) - tputtab(0); + tputtab(-csiescseq.arg[0]); break; case 'd': /* VPA -- Move to */ DEFAULT(csiescseq.arg[0], 1); @@ -2280,19 +2278,17 @@ tdump(void) { } void -tputtab(bool forward) { +tputtab(int n) { uint x = term.c.x; - if(forward) { - if(x == term.col) - return; - for(++x; x < term.col && !term.tabs[x]; ++x) - /* nothing */ ; - } else { - if(x == 0) - return; - for(--x; x > 0 && !term.tabs[x]; --x) - /* nothing */ ; + if(n > 0) { + while(x < term.col && n--) + for(++x; x < term.col && !term.tabs[x]; ++x) + /* nothing */ ; + } else if(n < 0) { + while(x > 0 && n++) + for(--x; x > 0 && !term.tabs[x]; --x) + /* nothing */ ; } tmoveto(x, term.c.y); } -- 1.8.4
Re: [dev] [st] [PATCH] Fix techo handling of control and multibyte characters.
On Wed, Apr 23, 2014 at 08:26:32PM +0200, Roberto E. Vargas Caballero wrote: > Applied with a small modification. Thanks u suffix was here for a purpose. The patch has comment about multibyte characters. As 0x20u is unsigned, c was converted to unsigned char before comparison so multibyte characters were not considered control characters. Try enabling echo mode and typing non-ASCII characters (add some non-latin layout or use compose key or copy and paste '®').
Re: [dev] [st] [PATCH] Fix techo handling of control and multibyte characters.
On Thu, Apr 24, 2014 at 07:29:35AM +0200, Roberto E. Vargas Caballero wrote: > Hello, > > > u suffix was here for a purpose. The patch has comment about multibyte > > characters. As 0x20u is unsigned, c was converted to unsigned char > > before comparison so multibyte characters were not considered control > > characters. > > I realized it after send the patch. I prefer use uchar instead of > suffix u. I known that gcc will complaint with a warning about pointer > to data with different signess, but I think we are the programmers > and not gcc, so using uchar is the way. We can modify it as follows: if(BETWEEN(c, 0x00, 0x1f) || c == 0x7f) { /* control code */ I also thought about using incntrl(). It should work the same way everywhere but it is still possible to break it with locales.
[dev] [st patch queue 01/12] Simplify tsetscroll.
--- st.c | 11 ++- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/st.c b/st.c index 60243a7..816caf7 100644 --- a/st.c +++ b/st.c @@ -1762,17 +1762,10 @@ tsetattr(int *attr, int l) { void tsetscroll(int t, int b) { - int temp; - LIMIT(t, 0, term.row-1); LIMIT(b, 0, term.row-1); - if(t > b) { - temp = t; - t = b; - b = temp; - } - term.top = t; - term.bot = b; + term.top = MIN(t, b); + term.bot = MAX(t, b); } void -- 1.8.4
[dev] [st patch queue 02/12] Use BETWEEN macro in xsetcolorname and fix style.
--- st.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/st.c b/st.c index 816caf7..35bbe9c 100644 --- a/st.c +++ b/st.c @@ -2746,10 +2746,10 @@ int xsetcolorname(int x, const char *name) { XRenderColor color = { .alpha = 0x }; Colour colour; - if (x < 0 || x > LEN(colorname)) + if(!BETWEEN(x, 0, LEN(colorname))) return -1; if(!name) { - if(16 <= x && x < 16 + 216) { + if(BETWEEN(x, 16, 16 + 215)) { int r = (x - 16) / 36, g = ((x - 16) % 36) / 6, b = (x - 16) % 6; color.red = sixd_to_16bit(r); color.green = sixd_to_16bit(g); @@ -2758,7 +2758,7 @@ xsetcolorname(int x, const char *name) { return 0; /* something went wrong */ dc.col[x] = colour; return 1; - } else if (16 + 216 <= x && x < 256) { + } else if(BETWEEN(x, 16 + 216, 255)) { color.red = color.green = color.blue = 0x0808 + 0x0a0a * (x - (16 + 216)); if(!XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &color, &colour)) return 0; /* something went wrong */ -- 1.8.4
[dev] [st patch queue 03/12] Use != instead of ^ for logical values.
sel.alt is only changed by sel.alt = IS_SET(MODE_ALTSCREEN); --- st.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/st.c b/st.c index 35bbe9c..083d1c1 100644 --- a/st.c +++ b/st.c @@ -3445,7 +3445,7 @@ drawregion(int x1, int y1, int x2, int y2) { bool ena_sel = sel.ob.x != -1; long unicodep; - if(sel.alt ^ IS_SET(MODE_ALTSCREEN)) + if(sel.alt != IS_SET(MODE_ALTSCREEN)) ena_sel = 0; if(!(xw.state & WIN_VISIBLE)) -- 1.8.4
[dev] [st patch queue 04/12] Comment fix.
--- st.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/st.c b/st.c index 083d1c1..fd342aa 100644 --- a/st.c +++ b/st.c @@ -990,7 +990,7 @@ selnotify(XEvent *e) { } /* -* As seen in selcopy: +* As seen in getsel: * Line endings are inconsistent in the terminal and GUI world * copy and pasting. When receiving some selection data, * replace all '\n' with '\r'. -- 1.8.4
[dev] [st patch queue 07/12] Remove unnecessary break;s
--- st.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/st.c b/st.c index 9de7f81..061dafd 100644 --- a/st.c +++ b/st.c @@ -1778,7 +1778,6 @@ tsetmode(bool priv, bool set, int *args, int narg) { for(lim = args + narg; args < lim; ++args) { if(priv) { switch(*args) { - break; case 1: /* DECCKM -- Cursor key */ MODBIT(term.mode, set, MODE_APPCURSOR); break; @@ -1897,7 +1896,6 @@ tsetmode(bool priv, bool set, int *args, int narg) { fprintf(stderr, "erresc: unknown set/reset mode %d\n", *args); - break; } } } -- 1.8.4
[dev] [st patch queue 05/12] Consistent FALLTHROUGH comments.
--- st.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/st.c b/st.c index fd342aa..dae23c5 100644 --- a/st.c +++ b/st.c @@ -1839,7 +1839,7 @@ tsetmode(bool priv, bool set, int *args, int narg) { if (!allowaltscreen) break; tcursor((set) ? CURSOR_SAVE : CURSOR_LOAD); - /* FALLTHRU */ + /* FALLTHROUGH */ case 47: /* swap screen */ case 1047: if (!allowaltscreen) @@ -1853,7 +1853,7 @@ tsetmode(bool priv, bool set, int *args, int narg) { tswapscreen(); if(*args != 1049) break; - /* FALLTRU */ + /* FALLTHROUGH */ case 1048: tcursor((set) ? CURSOR_SAVE : CURSOR_LOAD); break; @@ -2149,7 +2149,7 @@ strhandle(void) { if(narg < 3) break; p = strescseq.args[2]; - /* fall through */ + /* FALLTHROUGH */ case 104: /* color reset, here p = NULL */ j = (narg > 1) ? atoi(strescseq.args[1]) : -1; if (!xsetcolorname(j, p)) { -- 1.8.4
[dev] [st patch queue 06/12] Avoid integer overflow in dump().
--- st.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/st.c b/st.c index dae23c5..9de7f81 100644 --- a/st.c +++ b/st.c @@ -1234,8 +1234,10 @@ dump(char c) { static int col; fprintf(stderr, " %02x '%c' ", c, isprint(c)?c:'.'); - if(++col % 10 == 0) + if(++col == 10) { fprintf(stderr, "\n"); + col = 0; + } } void -- 1.8.4
[dev] [st patch queue 11/12] Fix for multibyte characters in techo.
Works for both signed and unsigned char. --- st.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/st.c b/st.c index 22ce4fb..cb95b8c 100644 --- a/st.c +++ b/st.c @@ -2292,7 +2292,7 @@ techo(char *buf, int len) { for(; len > 0; buf++, len--) { char c = *buf; - if(c < 0x20 || c == 0177) { /* control code */ + if(BETWEEN(c, 0x00, 0x1f) || c == 0x7f) { /* control code */ if(c != '\n' && c != '\r' && c != '\t') { c ^= '\x40'; tputc("^", 1); -- 1.8.4
[dev] [st patch queue 12/12] Do not eat ESC character if control string is not properly terminated.
Currently tputc handles the case of too long control string waiting for the end of control string. Another case is when there is ESC character is encountered but is not followed by '\\'. In this case st stops processing control string, but ESC character is ignored. After this patch st processes ESC characters in control strings properly. Test case: printf '\e]0;abc\e[1mBOLD\e[0m' Also ^[\ is actually processed in the code that handles ST. According to ECMA-048 ST stands for STRING TERMINATOR and is used to close control strings. --- st.c | 8 +++- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/st.c b/st.c index cb95b8c..5399809 100644 --- a/st.c +++ b/st.c @@ -2446,10 +2446,6 @@ tputc(char *c, int len) { csiparse(); csihandle(); } - } else if(term.esc & ESC_STR_END) { - term.esc = 0; - if(ascii == '\\') - strhandle(); } else if(term.esc & ESC_ALTCHARSET) { tdeftran(ascii); tselcs(); @@ -2539,7 +2535,9 @@ tputc(char *c, int len) { tcursor(CURSOR_LOAD); term.esc = 0; break; - case '\\': /* ST -- Stop */ + case '\\': /* ST -- String Terminator */ + if(term.esc & ESC_STR_END) + strhandle(); term.esc = 0; break; default: -- 1.8.4
[dev] [st patch queue 10/12] s/DSC/DCS/ DCS stands for DEVICE CONTROL STRING
--- st.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/st.c b/st.c index 5477c81..22ce4fb 100644 --- a/st.c +++ b/st.c @@ -149,7 +149,7 @@ enum charset { enum escape_state { ESC_START = 1, ESC_CSI= 2, - ESC_STR= 4, /* DSC, OSC, PM, APC */ + ESC_STR= 4, /* DCS, OSC, PM, APC */ ESC_ALTCHARSET = 8, ESC_STR_END= 16, /* a final string was encountered */ ESC_TEST = 32, /* Enter in test mode */ @@ -2161,7 +2161,7 @@ strhandle(void) { case 'k': /* old title set compatibility */ xsettitle(strescseq.args[0]); return; - case 'P': /* DSC -- Device Control String */ + case 'P': /* DCS -- Device Control String */ case '_': /* APC -- Application Program Command */ case '^': /* PM -- Privacy Message */ return; -- 1.8.4
[dev] [st patch queue 08/12] Use xwrite instead of write.
--- st.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/st.c b/st.c index 061dafd..e4df18f 100644 --- a/st.c +++ b/st.c @@ -450,7 +450,7 @@ static char utf8encodebyte(long, size_t); static size_t utf8len(char *); static size_t utf8validate(long *, size_t); -static ssize_t xwrite(int, char *, size_t); +static ssize_t xwrite(int, const char *, size_t); static void *xmalloc(size_t); static void *xrealloc(void *, size_t); static char *xstrdup(char *); @@ -516,7 +516,7 @@ static Fontcache frc[16]; static int frclen = 0; ssize_t -xwrite(int fd, char *s, size_t len) { +xwrite(int fd, const char *s, size_t len) { size_t aux = len; while(len > 0) { @@ -1270,7 +1270,7 @@ ttyread(void) { void ttywrite(const char *s, size_t n) { - if(write(cmdfd, s, n) == -1) + if(xwrite(cmdfd, s, n) == -1) die("write error on tty: %s\n", strerror(errno)); } -- 1.8.4
[dev] [st patch queue 09/12] Simplify tdeletechar and tinsertblank and fix memory corruption.
Removed special handling of corner case. Current CSI parsing code uses strtol to parse arguments and allows them to be negative. Negative argument is not properly handled in tdeletechar and tinsertblank and results in memory corruption in memmove. Reproduce with printf '\e[-500@' --- st.c | 26 ++ 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/st.c b/st.c index e4df18f..5477c81 100644 --- a/st.c +++ b/st.c @@ -1588,16 +1588,13 @@ tclearregion(int x1, int y1, int x2, int y2) { void tdeletechar(int n) { - int src = term.c.x + n; - int dst = term.c.x; - int size = term.col - src; + int dst, src, size; - term.dirty[term.c.y] = 1; + LIMIT(n, 0, term.col - term.c.x); - if(src >= term.col) { - tclearregion(term.c.x, term.c.y, term.col-1, term.c.y); - return; - } + dst = term.c.x; + src = term.c.x + n; + size = term.col - src; memmove(&term.line[term.c.y][dst], &term.line[term.c.y][src], size * sizeof(Glyph)); @@ -1606,16 +1603,13 @@ tdeletechar(int n) { void tinsertblank(int n) { - int src = term.c.x; - int dst = src + n; - int size = term.col - dst; + int dst, src, size; - term.dirty[term.c.y] = 1; + LIMIT(n, 0, term.col - term.c.x); - if(dst >= term.col) { - tclearregion(term.c.x, term.c.y, term.col-1, term.c.y); - return; - } + dst = term.c.x + n; + src = term.c.x; + size = term.col - dst; memmove(&term.line[term.c.y][dst], &term.line[term.c.y][src], size * sizeof(Glyph)); -- 1.8.4
[dev] [st] [PATCH] Simplify selected().
--- st.c | 17 ++--- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/st.c b/st.c index 237ce8e..bd0d3ca 100644 --- a/st.c +++ b/st.c @@ -665,18 +665,13 @@ selsort(void) { static inline bool selected(int x, int y) { - if(sel.ne.y == y && sel.nb.y == y) - return BETWEEN(x, sel.nb.x, sel.ne.x); + if(sel.type == SEL_RECTANGULAR) + return BETWEEN(y, sel.nb.y, sel.ne.y) + && BETWEEN(x, sel.nb.x, sel.ne.x); - if(sel.type == SEL_RECTANGULAR) { - return ((sel.nb.y <= y && y <= sel.ne.y) - && (sel.nb.x <= x && x <= sel.ne.x)); - } - - return ((sel.nb.y < y && y < sel.ne.y) - || (y == sel.ne.y && x <= sel.ne.x)) - || (y == sel.nb.y && x >= sel.nb.x - && (x <= sel.ne.x || sel.nb.y != sel.ne.y)); + return BETWEEN(y, sel.nb.y, sel.ne.y) + && (y != sel.nb.y || x >= sel.nb.x) + && (y != sel.ne.y || x <= sel.ne.x); } void -- 1.8.4
[dev] [st PATCH 1/6] Compute ena_sel as one expression.
--- st.c | 5 + 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/st.c b/st.c index bd0d3ca..41a3e3c 100644 --- a/st.c +++ b/st.c @@ -3441,12 +3441,9 @@ drawregion(int x1, int y1, int x2, int y2) { int ic, ib, x, y, ox, sl; Glyph base, new; char buf[DRAW_BUF_SIZ]; - bool ena_sel = sel.ob.x != -1; + bool ena_sel = sel.ob.x != -1 && sel.alt == IS_SET(MODE_ALTSCREEN); long unicodep; - if(sel.alt != IS_SET(MODE_ALTSCREEN)) - ena_sel = 0; - if(!(xw.state & WIN_VISIBLE)) return; -- 1.8.4
[dev] [st PATCH 2/6] Use MODBIT in xseturgency.
--- st.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/st.c b/st.c index 41a3e3c..afede52 100644 --- a/st.c +++ b/st.c @@ -3520,7 +3520,7 @@ void xseturgency(int add) { XWMHints *h = XGetWMHints(xw.dpy, xw.win); - h->flags = add ? (h->flags | XUrgencyHint) : (h->flags & ~XUrgencyHint); + MODBIT(h->flags, add, XUrgencyHint); XSetWMHints(xw.dpy, xw.win, h); XFree(h); } -- 1.8.4
[dev] [st PATCH 5/6] Remove unused dump() function.
--- st.c | 10 -- 1 file changed, 10 deletions(-) diff --git a/st.c b/st.c index 6abda84..aa804eb 100644 --- a/st.c +++ b/st.c @@ -394,7 +394,6 @@ static int32_t tdefcolor(int *, int *, int); static void tselcs(void); static void tdeftran(char); static inline bool match(uint, uint); -static void dump(char c); static void ttynew(void); static void ttyread(void); static void ttyresize(void); @@ -1233,15 +1232,6 @@ ttynew(void) { } void -dump(char c) { - static int col; - - fprintf(stderr, " %02x '%c' ", c, isprint(c)?c:'.'); - if(++col % 10 == 0) - fprintf(stderr, "\n"); -} - -void ttyread(void) { static char buf[BUFSIZ]; static int buflen = 0; -- 1.8.4
[dev] [st PATCH 3/6] Add missing function prototypes.
--- st.c | 5 + 1 file changed, 5 insertions(+) diff --git a/st.c b/st.c index afede52..6abda84 100644 --- a/st.c +++ b/st.c @@ -394,6 +394,7 @@ static int32_t tdefcolor(int *, int *, int); static void tselcs(void); static void tdeftran(char); static inline bool match(uint, uint); +static void dump(char c); static void ttynew(void); static void ttyread(void); static void ttyresize(void); @@ -444,6 +445,8 @@ static char *getsel(void); static void selcopy(void); static void selscroll(int, int); static void selsnap(int, int *, int *, int); +static void getbuttoninfo(XEvent *); +static void mousereport(XEvent *); static size_t utf8decode(char *, long *, size_t); static long utf8decodebyte(char, size_t *); @@ -457,6 +460,8 @@ static void *xmalloc(size_t); static void *xrealloc(void *, size_t); static char *xstrdup(char *); +static void usage(void); + static void (*handler[LASTEvent])(XEvent *) = { [KeyPress] = kpress, [ClientMessage] = cmessage, -- 1.8.4
[dev] [st PATCH 4/6] Do not export chscale and cwscale.
--- config.def.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config.def.h b/config.def.h index d69c9ba..646a88a 100644 --- a/config.def.h +++ b/config.def.h @@ -10,8 +10,8 @@ static int borderpx = 2; static char shell[] = "/bin/sh"; /* Kerning / character bounding-box mutlipliers */ -float cwscale = 1.0; -float chscale = 1.0; +static float cwscale = 1.0; +static float chscale = 1.0; /* * word delimiter string -- 1.8.4
[dev] [st PATCH 6/6] Remove one indentation level in getsel().
--- st.c | 91 ++-- 1 file changed, 45 insertions(+), 46 deletions(-) diff --git a/st.c b/st.c index aa804eb..2750bfa 100644 --- a/st.c +++ b/st.c @@ -912,60 +912,59 @@ getsel(void) { int x, y, bufsize, size, i, ex; Glyph *gp, *last; - if(sel.ob.x == -1) { - str = NULL; - } else { - bufsize = (term.col+1) * (sel.ne.y-sel.nb.y+1) * UTF_SIZ; - ptr = str = xmalloc(bufsize); + if(sel.ob.x == -1) + return NULL; - /* append every set & selected glyph to the selection */ - for(y = sel.nb.y; y < sel.ne.y + 1; y++) { - gp = &term.line[y][0]; - last = &gp[term.col-1]; + bufsize = (term.col+1) * (sel.ne.y-sel.nb.y+1) * UTF_SIZ; + ptr = str = xmalloc(bufsize); - while(last >= gp && !(selected(last - gp, y) && - strcmp(last->c, " ") != 0)) { - --last; - } + /* append every set & selected glyph to the selection */ + for(y = sel.nb.y; y < sel.ne.y + 1; y++) { + gp = &term.line[y][0]; + last = &gp[term.col-1]; - for(x = 0; gp <= last; x++, ++gp) { - if(!selected(x, y) || (gp->mode & ATTR_WDUMMY)) - continue; + while(last >= gp && !(selected(last - gp, y) && + strcmp(last->c, " ") != 0)) { + --last; + } - size = utf8len(gp->c); - memcpy(ptr, gp->c, size); - ptr += size; - } + for(x = 0; gp <= last; x++, ++gp) { + if(!selected(x, y) || (gp->mode & ATTR_WDUMMY)) + continue; - /* -* 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(y < sel.ne.y && x > 0 && !((gp-1)->mode & ATTR_WRAP)) - *ptr++ = '\n'; + size = utf8len(gp->c); + memcpy(ptr, gp->c, size); + ptr += size; + } - /* -* If the last selected line expands in the selection -* after the visible text '\n' is appended. -*/ - if(y == sel.ne.y) { - i = term.col; - while(--i > 0 && term.line[y][i].c[0] == ' ') - /* nothing */; - ex = sel.ne.x; - if(sel.nb.y == sel.ne.y && sel.ne.x < sel.nb.x) - ex = sel.nb.x; - if(i < ex) - *ptr++ = '\n'; - } + /* +* 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(y < sel.ne.y && x > 0 && !((gp-1)->mode & ATTR_WRAP)) + *ptr++ = '\n'; + + /* +* If the last selected line expands in the selection +* after the visible text '\n' is appended. +*/ + if(y == sel.ne.y) { + i = term.col; + while(--i > 0 && term.line[y][i].c[0] == ' ') + /* nothing */; + ex = sel.ne.x; + if(sel.nb.y == sel.ne.y && sel.ne.x < sel.nb.x) + ex = sel.nb.x; + if(i < ex) + *ptr++ = '\n'; } - *ptr = 0; } + *ptr = 0; return str; } -- 1.8.4
[dev] [dwm PATCH] Add missing getatomprop prototype.
--- dwm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/dwm.c b/dwm.c index 1bbb4b3..2cadebc 100644 --- a/dwm.c +++ b/dwm.c @@ -169,6 +169,7 @@ static void focus(Client *c); static void focusin(XEvent *e); static void focusmon(const Arg *arg); static void focusstack(const Arg *arg); +static Atom getatomprop(Client *c, Atom prop); static Bool getrootptr(int *x, int *y); static long getstate(Window w); static Bool gettextprop(Window w, Atom atom, char *text, unsigned int size); -- 1.8.4
[dev] [st PATCH] Simplify tputtab.
--- st.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/st.c b/st.c index 2750bfa..689dce0 100644 --- a/st.c +++ b/st.c @@ -2267,11 +2267,11 @@ tputtab(int n) { if(n > 0) { while(x < term.col && n--) - for(++x; x < term.col && !term.tabs[x]; ++x) + while(++x < term.col && !term.tabs[x]) /* nothing */ ; } else if(n < 0) { while(x > 0 && n++) - for(--x; x > 0 && !term.tabs[x]; --x) + while(--x > 0 && !term.tabs[x]) /* nothing */ ; } tmoveto(x, term.c.y); -- 1.8.4
Re: [dev] [st PATCH 3/6] Add missing function prototypes.
On Sun, Apr 27, 2014 at 06:32:36PM +0200, Markus Teich wrote: > noname wrote: > > +static void dump(char c); > > Heyho, > > Wasn't this the function, which is never used? > > --Markus > It is. After I made it static, gcc gives a warning about it, so I removed it later in the same patchset.
[dev] [st PATCH] tresize return value is not used
--- st.c | 8 +++- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/st.c b/st.c index b8fec4c..25da193 100644 --- a/st.c +++ b/st.c @@ -378,7 +378,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); @@ -2581,7 +2581,7 @@ tputc(char *c, int len) { } } -int +void tresize(int col, int row) { int i; int minrow = MIN(row, term.row); @@ -2591,7 +2591,7 @@ tresize(int col, int row) { Line *orig; if(col < 1 || row < 1) - return 0; + return; /* free unneeded rows */ i = 0; @@ -2661,8 +2661,6 @@ tresize(int col, int row) { tswapscreen(); tcursor(CURSOR_LOAD); } while(orig != term.line); - - return (slide > 0); } void -- 1.8.4
[dev] [st PATCH] Use tfulldirt instead of setting all lines dirty in tresize.
--- st.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/st.c b/st.c index 25da193..57cc4c4 100644 --- a/st.c +++ b/st.c @@ -2621,14 +2621,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)); } @@ -2644,6 +2642,7 @@ tresize(int col, int row) { /* update terminal size */ term.col = col; term.row = row; + tfulldirt(); /* reset scrolling region */ tsetscroll(0, row-1); /* make use of the LIMIT in tmoveto */ -- 1.8.4
Re: [dev] [st PATCH] Use tfulldirt instead of setting all lines dirty in tresize.
In fact tfulldirt should be removed completely, as tswapscreen calls tfulldirt later (twice).
[dev] [st PATCH] Simplify xunloadfonts.
--- st.c | 8 ++-- 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/st.c b/st.c index 57cc4c4..087d2c9 100644 --- a/st.c +++ b/st.c @@ -2940,13 +2940,9 @@ xunloadfont(Font *f) { void xunloadfonts(void) { - int i; - /* Free the loaded fonts in the font cache. */ - for(i = 0; i < frclen; i++) { - XftFontClose(xw.dpy, frc[i].font); - } - frclen = 0; + while(frclen > 0) + XftFontClose(xw.dpy, frc[--frclen].font); xunloadfont(&dc.font); xunloadfont(&dc.bfont); -- 1.8.4
Re: [dev] [st] [PATCH] Simplify selected().
On Mon, Apr 28, 2014 at 06:58:29PM +0200, Roberto E. Vargas Caballero wrote: > Uhmmm, I am not sure about this patch, because it is related to some > parts of st that are not handled by me, and I am not sure if these > modifications are correct. Could someone else take care of this patch? > > Regards, > > -- > Roberto E. Vargas Caballero > If you select rectangle, then y should be between first and last line and x should between first and last column. If selection is normal, then y should be between first and last line of selection. Also (y != sel.nb.y || x >= sel.nb.x) should be read as y == sel.nb.y implies x >= sel.nb.x and (y != sel.ne.y || x <= sel.ne.x) should be read as y == sel.nb.y implies x <= sel.ne.x It is also easy to visually check that selection works properly.
Re: [dev] [st PATCH] Simplify tputtab.
On Mon, Apr 28, 2014 at 10:54:21AM +0200, Roberto E. Vargas Caballero wrote: > > - for(++x; x < term.col && !term.tabs[x]; ++x) > > + while(++x < term.col && !term.tabs[x]) > ... > > - for(--x; x > 0 && !term.tabs[x]; --x) > > + while(--x > 0 && !term.tabs[x]) > > I'm sorry, but this patch is incorrect, because it is implementation defined > when side effects of expressions are applied, so x of !term.tabs[x] can > be x before decrement, or x after decrement. && is a sequence point According to ISO IEC 9899:1999: """ The following are the sequence points described in 5.1.2.3: ... - The end of the first operand of the following operators: logical AND && (6.5.13); logical OR || (6.5.14); conditional ? (6.5.15); comma , (6.5.17). ... """
Re: [dev] [st] Feature to replace st window by spawned x window
On Mon, Apr 28, 2014 at 05:17:56PM -0400, Nick wrote: > Does someone with more knowledge of X11 know whether this is likely > to be readily do-able? Can you launch an arbitrary X program and say > "use this window"? I'm guessing not, but don't really know. It is impossible as each application can have more than one window.
[dev] [st PATCH] Do not save cursor in tresize.
This patch fixes the bug introduced in 8f11e1cd034ff28ca47bb4955505db7fa8016ba8 To reproduce the bug: 1. Save cursor: printf '\e[s' 2. Load cursor: printf '\e[u' 3. Resize st window. 4. Load cursor again: printf '\e[u' --- st.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/st.c b/st.c index 9079834..1c70761 100644 --- a/st.c +++ b/st.c @@ -2639,6 +2639,7 @@ tresize(int col, int row) { int slide = term.c.y - row + 1; bool *bp; Line *orig; + TCursor c; if(col < 1 || row < 1) return 0; @@ -2700,6 +2701,7 @@ tresize(int col, int row) { tmoveto(term.c.x, term.c.y); /* Clearing both screens */ orig = term.line; + c = term.c; do { if(mincol < col && 0 < minrow) { tclearregion(mincol, 0, col - 1, minrow - 1); @@ -2707,10 +2709,10 @@ tresize(int col, int row) { if(0 < col && minrow < row) { tclearregion(0, minrow, col - 1, row - 1); } - tcursor(CURSOR_SAVE); tswapscreen(); tcursor(CURSOR_LOAD); } while(orig != term.line); + term.c = c; return (slide > 0); } -- 1.8.4
Re: [dev] [st patch queue 05/12] Consistent FALLTHROUGH comments.
On Fri, Apr 25, 2014 at 06:21:10PM +0200, Roberto E. Vargas Caballero wrote: > It is true that it is ugly to have different styles in fall through, > but it is also true that we have a lot of fall through where we don't > put any comment. Put a comment in all these places is a very bad idea, > but I think maybe there are more places where we should put a comment. > I agree with you that the best comment is FALLTHROUGH (I used FALLTHRU > in the past because it was used in a project where I worked), that is > the comment that lint understand. I don't see any non-empty cases where we don't have FALLTHROUGH comment. And if the case is empty, it is obvious without any comment.
[dev] [st PATCH] Simplify tdeftran.
--- st.c | 22 ++ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/st.c b/st.c index d0c4595..3f248f3 100644 --- a/st.c +++ b/st.c @@ -2305,19 +2305,17 @@ techo(char *buf, int len) { void tdeftran(char ascii) { - char c, (*bp)[2]; - static char tbl[][2] = { - {'0', CS_GRAPHIC0}, {'B', CS_USA}, - {0, 0} - }; - - for (bp = &tbl[0]; (c = (*bp)[0]) && c != ascii; ++bp) - /* nothing */; - - if (c == 0) + switch(ascii) { + case '0': + term.trantbl[term.icharset] = CS_GRAPHIC0; + break; + case 'B': + term.trantbl[term.icharset] = CS_USA; + break; + default: fprintf(stderr, "esc unhandled charset: ESC ( %c\n", ascii); - else - term.trantbl[term.icharset] = (*bp)[1]; + break; + } } void -- 1.8.4
[dev] [tabbed PATCH] Replace emallocz with ecalloc.
--- tabbed.c | 12 ++-- 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tabbed.c b/tabbed.c index 2341998..ba22f9a 100644 --- a/tabbed.c +++ b/tabbed.c @@ -97,7 +97,7 @@ static void destroynotify(const XEvent *e); static void die(const char *errstr, ...); static void drawbar(void); static void drawtext(const char *text, unsigned long col[ColLast]); -static void *emallocz(size_t size); +static void *ecalloc(size_t n, size_t size); static void *erealloc(void *o, size_t size); static void expose(const XEvent *e); static void focus(int c); @@ -399,11 +399,11 @@ drawtext(const char *text, unsigned long col[ColLast]) { } void * -emallocz(size_t size) { +ecalloc(size_t n, size_t size) { void *p; - if(!(p = calloc(1, size))) - die("tabbed: cannot malloc\n"); + if(!(p = calloc(n, size))) + die("tabbed: cannot calloc\n"); return p; } @@ -713,7 +713,7 @@ manage(Window w) { } } - c = emallocz(sizeof(*c)); + c = ecalloc(1, sizeof *c); c->win = w; nclients++; @@ -921,7 +921,7 @@ void setcmd(int argc, char *argv[], int replace) { int i; - cmd = emallocz((argc+3) * sizeof(*cmd)); + cmd = ecalloc(argc + 3, sizeof *cmd); if (argc == 0) return; for(i = 0; i < argc; i++) -- 1.8.4
[dev] [sbase] [PATCH] Replace strlen with unary_n to test zero length.
--- test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test.c b/test.c index 660048a..957b205 100644 --- a/test.c +++ b/test.c @@ -100,7 +100,7 @@ noarg(char **argv) static int onearg(char **argv) { - return strlen(argv[0]); + return unary_n(argv[0]); } static int -- 1.8.4
[dev] [vis] buffer_alloc issues
I'm not sure if vis is supported in suckless mailing list, but as it was discussed here previously, i'm writing here. There are two issues with buffer_alloc function(s). First function is located in buffer.c: http://repo.or.cz/w/vis.git/blob/HEAD:/buffer.c The problem is on line 15: http://repo.or.cz/w/vis.git/blob/HEAD:/buffer.c#l15 If realloc fails, buf->data is set to NULL, but original buf->data is not freed, see realloc(3). The result of realloc should be stored in separate variable and buffer_free should be called to free buf->data and set size and len to 0 if realloc fails. Another issue is that there is another buffer_alloc in text.c: http://repo.or.cz/w/vis.git/blob/HEAD:/text.c Maybe these functions and data structures should be renamed to avoid name conflict.
Re: [dev] [vis] buffer_alloc issues
On Sun, Mar 29, 2015 at 03:45:50PM +0200, Silvan Jegen wrote: > Heyho! > > On Wed, Mar 25, 2015 at 07:15:08PM +, non...@inventati.org wrote: > > There are two issues with buffer_alloc function(s). > > > > First function is located in buffer.c: > > http://repo.or.cz/w/vis.git/blob/HEAD:/buffer.c > > > > The problem is on line 15: > > http://repo.or.cz/w/vis.git/blob/HEAD:/buffer.c#l15 > > > > If realloc fails, buf->data is set to NULL, but original buf->data is > > not freed, see realloc(3). The result of realloc should be stored in > > separate variable and buffer_free should be called to free buf->data and > > set size and len to 0 if realloc fails. > > This is true. In a memory-overcommitting system like Linux, however, > this should not be a problem in practice since realloc should never fail. Then NULL check is a dead code and should be removed.
Re: [dev] [surf] [patch] 13 patches from my Universal Same-Origin Policy branch
How about sending no UA at all? If all privacy-aware browsers drop UA, that would be optimal. Drop UA in Dillo, TorBrowser, drop UA in other browsers with add-ons etc. Otherwise all privacy-aware browsers try to adjust their UA to maximize "anonymity set", they all look different and this story never ends.
Re: [dev] [surf] [patch] 13 patches from my Universal Same-Origin Policy branch
On Sun, Mar 29, 2015 at 09:03:49PM +0200, Antenore Gatta wrote: > On 29/03/15 17:03:25, non...@inventati.org wrote: > > How about sending no UA at all? > > > > Not sending a UA at all, makes your browser fingerprint uniq and not the other > way around. > > Probably a safer solution is to have an array of (user's tailored) UAs and > loop > through them, but expect strange behaviours as highlighted by Dmitrij. It is a short-term solution. This way all privacy-aware browsers are spread across several largest anonymity sets instead of creating their own. They do not even make available anonymity sets significantly larger. The long-term solution is to stop sending UA and convince others (Dillo developers and TorBrowser first, addon developers and users second, major browsers last) to do the same.
Re: [dev] [surf] [patch] 13 patches from my Universal Same-Origin Policy branch
On Sun, Mar 29, 2015 at 09:58:42PM +0200, Markus Teich wrote: > even then you are still in the anonymity set of „Hey look, that guy want's to > be > anonymous, let's focus our effort on him!“. Think again. Advertisers focus on people who would click on advertisements, not the guys pretending to be paranoid, using Tor etc. And NSA tracking you using UA is ridiculous. > The really long term solution would > imho be to establish web standards which forbid such identifying information > leakage by default. There should be no need for a UA and OS/language > information > should only be submitted to servers on an opt-in basis. Unfortunately regular > users cannot be fixed and therefore this has to be enforced by a more > powerfull > gremium imho. So far these efforts resulted in a funny DNT: 1 header. > In the meantime the best compromise is to follow the largest group > of regular users and pretend to be one of them. You have just repeated what was said before. There are 4 options now: 1. Set UA to the most popular value. 2. Do not send UA 3. Start a holywar 4. Do more research
[dev] [vis] [PATCH] Fixed multiline comment regexp.
Comments like "/***/" with odd number of asterisks are handled like normal comments now. Previously they were handled like unfinished comments. Support for comments without opening "/*" at the beginning of the file is removed because people do not normally write comments backwards. --- config.def.h | 8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/config.def.h b/config.def.h index ee6d4ae..823aa71 100644 --- a/config.def.h +++ b/config.def.h @@ -869,10 +869,10 @@ static Color colors[] = { /* common rules, used by multiple languages */ -#define SYNTAX_MULTILINE_COMMENT { \ - "(/\\*([^*]|\\*+[^*/])*\\*+/|/\\*([^*]|\\*[^/])*$|^([^/]|/[^*])*\\*/)", \ - &colors[COLOR_COMMENT], \ - true, /* multiline */\ +#define SYNTAX_MULTILINE_COMMENT {\ + "(/\\*([^*]|\\*+[^*/])*\\*+/|/\\*([^*]|\\*+[^*/])*$)", \ + &colors[COLOR_COMMENT], \ + true, /* multiline */ \ } #define SYNTAX_SINGLE_LINE_COMMENT { \ -- 1.8.4
Re: [dev] [vis] [PATCH] Fixed multiline comment regexp.
On Thu, Apr 02, 2015 at 01:42:35AM +0200, koneu wrote: > noname wrote: > > Support for comments without opening "/*" at the beginning of the file > > is removed because people do not normally write comments backwards. > Oh look, I never knew it was possible to write comments like that. > It is not. Files with such "comments" do not compile. "Comments" without */ appear when you open /* and start writing a comment.
Re: [dev] [vis] [PATCH] Fixed multiline comment regexp.
On Fri, Apr 03, 2015 at 07:21:49PM +0200, Marc André Tanner wrote: > On Thu, Apr 02, 2015 at 02:27:31AM +0300, noname wrote: > > Comments like "/***/" with odd number of asterisks are handled like > > normal comments now. Previously they were handled like unfinished > > comments. > > Could you please provide a more complete test case? I can't seem to > reproduce it here. Attached C file. /***/ NOT COMMENTED BUT BLUE
[dev] [vis] [PATCH] Fixed multiline comment regexp.
Comments like "/***/" with odd number of asterisks are handled like normal comments now. Previously they were handled like unfinished comments. --- config.def.h | 8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/config.def.h b/config.def.h index ee6d4ae..2a9e258 100644 --- a/config.def.h +++ b/config.def.h @@ -869,10 +869,10 @@ static Color colors[] = { /* common rules, used by multiple languages */ -#define SYNTAX_MULTILINE_COMMENT { \ - "(/\\*([^*]|\\*+[^*/])*\\*+/|/\\*([^*]|\\*[^/])*$|^([^/]|/[^*])*\\*/)", \ - &colors[COLOR_COMMENT], \ - true, /* multiline */\ +#define SYNTAX_MULTILINE_COMMENT {\ + "(/\\*([^*]|\\*+[^*/])*\\*+/|/\\*([^*]|\\*+[^*/])*$|^([^/]|/+[^/*])*\\*/)", \ + &colors[COLOR_COMMENT], \ + true, /* multiline */ \ } #define SYNTAX_SINGLE_LINE_COMMENT { \ -- 1.8.4
Re: [dev] [vis] [PATCH] Fixed multiline comment regexp.
On Fri, Apr 03, 2015 at 07:21:49PM +0200, Marc André Tanner wrote: > On Thu, Apr 02, 2015 at 02:27:31AM +0300, noname wrote: > > Support for comments without opening "/*" at the beginning of the file > > is removed because people do not normally write comments backwards. > > At the moment vis only considers the currently visible text for syntax > highlighting. The rule you removed is a hack to catch multiline comments > even when their start marker "/*" has been scrolled off the screen. Sent a patch that keeps the hack.
Re: [dev] [vis] ui separation and mainloop considerations
On Sat, Apr 04, 2015 at 12:48:14AM +0200, Marc André Tanner wrote: > What is your opinion on libuv? Is there a better alternative I > should look into? What would you use for communication purposes? > Sending raw structs around or using something like msgpack? http://suckless.org/rocks links libev
[dev] [st] [PATCH] Fixed STR sequence termination condition
ascii code may only be checked for characters that have length equal to 1, not width equal to 1 --- st.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/st.c b/st.c index 39d3fee..827ed08 100644 --- a/st.c +++ b/st.c @@ -2663,7 +2663,7 @@ tputc(char *c, int len) { * character. */ if(term.esc & ESC_STR) { - if(width == 1 && + if(len == 1 && (ascii == '\a' || ascii == 030 || ascii == 032 || ascii == 033 || ISCONTROLC1(unicodep))) { -- 1.8.4
Re: [dev] [st] [PATCH] Fixed STR sequence termination condition
On Mon, Apr 06, 2015 at 10:50:07AM +0200, Roberto E. Vargas Caballero wrote: > > ascii code may only be checked for characters that have length equal to > > 1, not width equal to 1 > > I think they are equivalent, but I like more the 'len' versin, so > I will apply it. They are not equivalent at all. 'len' is the length of the character in bytes, it is 1 for ASCII, so you can check 'ascii' variable. 'width' is how much columns the character takes. It is one for 'ß' as it takes only one column to display, but the length of 'ß' is 2 bytes. Using 'ascii' variable in this case is wrong as it contains the first byte of UTF-8 encoding. It happens to be 030, 032, 033 by accident for non-latin characters and part of the string that should be, for example, a part of the terminal title, is displayed in the terminal, breaking layout.
Re: [dev] [st] [PATCH 2/2] Simplify window mapping loop.
On Fri, Apr 10, 2015 at 05:41:16PM +0200, Roberto E. Vargas Caballero wrote: > > - if(XFilterEvent(&ev, None)) > > - continue; > > Why are you removing the call to XFilterEvent here? XFilterEvent usually filters KeyPress events that are hooked by input method, but at this point the window is not mapped so it is impossible to press keys in the terminal. Calling XFilterEvent would only be useful if input methods filtered ConfigureNotify or MapNotify events. I don't think we want to ignore our ConfigureNotify or MapNotify only because some broken input method steals it.
[dev] [st] [PATCH 2/2] Remove keywords from function definitions.
--- st.c | 19 +++ 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/st.c b/st.c index 6522c9d..7dbd87a 100644 --- a/st.c +++ b/st.c @@ -408,6 +408,7 @@ static void ttysend(char *, size_t); static void ttywrite(const char *, size_t); static void tstrsequence(uchar); +static inline ushort sixd_to_16bit(int); static void xdraws(char *, Glyph, int, int, int, int); static void xhints(void); static void xclear(int, int, int, int); @@ -452,6 +453,8 @@ static char *getsel(void); static void selcopy(void); static void selscroll(int, int); static void selsnap(int, int *, int *, int); +static int x2col(int); +static int y2row(int); static void getbuttoninfo(XEvent *); static void mousereport(XEvent *); @@ -640,7 +643,7 @@ utf8validate(long *u, size_t i) { return i; } -static void +void selinit(void) { memset(&sel.tclick1, 0, sizeof(sel.tclick1)); memset(&sel.tclick2, 0, sizeof(sel.tclick2)); @@ -653,7 +656,7 @@ selinit(void) { sel.xtarget = XA_STRING; } -static int +int x2col(int x) { x -= borderpx; x /= xw.cw; @@ -661,7 +664,7 @@ x2col(int x) { return LIMIT(x, 0, term.col-1); } -static int +int y2row(int y) { y -= borderpx; y /= xw.ch; @@ -669,7 +672,7 @@ y2row(int y) { return LIMIT(y, 0, term.row-1); } -static int tlinelen(int y) { +int tlinelen(int y) { int i = term.col; if(term.line[y][i - 1].mode & ATTR_WRAP) @@ -681,7 +684,7 @@ static int tlinelen(int y) { return i; } -static void +void selnormalize(void) { int i; @@ -708,7 +711,7 @@ selnormalize(void) { sel.ne.x = term.col - 1; } -static inline bool +bool selected(int x, int y) { if(sel.type == SEL_RECTANGULAR) return BETWEEN(y, sel.nb.y, sel.ne.y) @@ -2857,7 +2860,7 @@ xresize(int col, int row) { xclear(0, 0, xw.w, xw.h); } -static inline ushort +ushort sixd_to_16bit(int x) { return x == 0 ? 0 : 0x3737 + 0x2828 * x; } @@ -3772,7 +3775,7 @@ focus(XEvent *ev) { } } -static inline bool +bool match(uint mask, uint state) { return mask == XK_ANY_MOD || mask == (state & ~ignoremod); } -- 1.8.4
[dev] [st] [PATCH 3/3] Remove 'xloadfontset' function.
It was used only once and its return value was ignored. --- st.c | 13 ++--- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/st.c b/st.c index 7dbd87a..0065240 100644 --- a/st.c +++ b/st.c @@ -419,7 +419,6 @@ static int xsetcolorname(int, const char *); static int xgeommasktogravity(int); static int xloadfont(Font *, FcPattern *); static void xloadfonts(char *, double); -static int xloadfontset(Font *); static void xsettitle(char *); static void xresettitle(void); static void xsetpointermotion(int); @@ -3116,15 +3115,6 @@ xloadfonts(char *fontstr, double fontsize) { FcPatternDestroy(pattern); } -int -xloadfontset(Font *f) { - FcResult result; - - if(!(f->set = FcFontSort(0, f->pattern, FcTrue, 0, &result))) - return 1; - return 0; -} - void xunloadfont(Font *f) { XftFontClose(xw.dpy, f->match); @@ -3472,7 +3462,8 @@ xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) { /* Nothing was found. */ if(i >= frclen) { if(!font->set) - xloadfontset(font); + font->set = FcFontSort(0, font->pattern, + FcTrue, 0, &fcres); fcsets[0] = font->set; /* -- 1.8.4
[dev] [PATCH 1/2] Remove variable names from function declarations.
--- st.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/st.c b/st.c index 6d20977..6522c9d 100644 --- a/st.c +++ b/st.c @@ -359,7 +359,7 @@ static void csidump(void); static void csihandle(void); static void csiparse(void); static void csireset(void); -static int eschandle(uchar ascii); +static int eschandle(uchar); static void strdump(void); static void strhandle(void); static void strparse(void); @@ -406,7 +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 tstrsequence(uchar); static void xdraws(char *, Glyph, int, int, int, int); static void xhints(void); -- 1.8.4
[dev] [st] [PATCH 1/2] Use MAX macro where possible.
--- st.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/st.c b/st.c index 0065240..a7064b1 100644 --- a/st.c +++ b/st.c @@ -4072,7 +4072,7 @@ main(int argc, char *argv[]) { run: setlocale(LC_CTYPE, ""); XSetLocaleModifiers(""); - tnew(cols? cols : 1, rows? rows : 1); + tnew(MAX(cols, 1), MAX(rows, 1)); xinit(); selinit(); run(); -- 1.8.4
[dev] [st] [PATCH 2/2] Simplify window mapping loop.
--- st.c | 8 ++-- 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/st.c b/st.c index a7064b1..c311164 100644 --- a/st.c +++ b/st.c @@ -3917,17 +3917,13 @@ run(void) { long deltatime; /* Waiting for window mapping */ - while(1) { + do { XNextEvent(xw.dpy, &ev); - if(XFilterEvent(&ev, None)) - continue; if(ev.type == ConfigureNotify) { w = ev.xconfigure.width; h = ev.xconfigure.height; - } else if(ev.type == MapNotify) { - break; } - } + } while(ev.type != MapNotify); ttynew(); cresize(w, h); -- 1.8.4
[dev] [st] [PATCH 1/2] Use do..while in window mapping loop.
--- st.c | 6 ++ 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/st.c b/st.c index b2bcfe9..83acd56 100644 --- a/st.c +++ b/st.c @@ -3917,17 +3917,15 @@ run(void) { long deltatime; /* Waiting for window mapping */ - while(1) { + do { XNextEvent(xw.dpy, &ev); if(XFilterEvent(&ev, None)) continue; if(ev.type == ConfigureNotify) { w = ev.xconfigure.width; h = ev.xconfigure.height; - } else if(ev.type == MapNotify) { - break; } - } + } while(ev.type != MapNotify); ttynew(); cresize(w, h); -- 2.3.5
[dev] [st] [PATCH 2/2] Remove unnecessary XFilterEvent call.
XFilterEvent usually filters KeyPress events according to input method. At this point the window is not mapped. The only events that we process are ConfigureNotify and MapNotify. They should not be filtered by input method. --- st.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/st.c b/st.c index 83acd56..c48132a 100644 --- a/st.c +++ b/st.c @@ -3919,8 +3919,6 @@ run(void) { /* Waiting for window mapping */ do { XNextEvent(xw.dpy, &ev); - if(XFilterEvent(&ev, None)) - continue; if(ev.type == ConfigureNotify) { w = ev.xconfigure.width; h = ev.xconfigure.height; -- 2.3.5
[dev] [st] [PATCH 1/2] Use do..while in window mapping loop.
--- st.c | 6 ++ 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/st.c b/st.c index b2bcfe9..83acd56 100644 --- a/st.c +++ b/st.c @@ -3917,17 +3917,15 @@ run(void) { long deltatime; /* Waiting for window mapping */ - while(1) { + do { XNextEvent(xw.dpy, &ev); if(XFilterEvent(&ev, None)) continue; if(ev.type == ConfigureNotify) { w = ev.xconfigure.width; h = ev.xconfigure.height; - } else if(ev.type == MapNotify) { - break; } - } + } while(ev.type != MapNotify); ttynew(); cresize(w, h); -- 2.3.5
[dev] [st] [PATCH 2/2] Simplify loop condition.
--- st.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/st.c b/st.c index df79e93..28beca2 100644 --- a/st.c +++ b/st.c @@ -944,7 +944,7 @@ getsel(void) { ptr = str = xmalloc(bufsize); /* append every set & selected glyph to the selection */ - for(y = sel.nb.y; y < sel.ne.y + 1; y++) { + for(y = sel.nb.y; y <= sel.ne.y; y++) { linelen = tlinelen(y); if(sel.type == SEL_RECTANGULAR) { -- 2.3.5
[dev] [st] [PATCH 1/2] Do not use switch for fork() call.
--- st.c | 11 --- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/st.c b/st.c index c48132a..df79e93 100644 --- a/st.c +++ b/st.c @@ -1257,11 +1257,10 @@ ttynew(void) { if(openpty(&m, &s, NULL, NULL, &w) < 0) die("openpty failed: %s\n", strerror(errno)); - switch(pid = fork()) { - case -1: + if((pid = fork()) == -1) die("fork failed\n"); - break; - case 0: + + if(pid == 0) { setsid(); /* create a new process group */ dup2(s, STDIN_FILENO); dup2(s, STDOUT_FILENO); @@ -1271,8 +1270,7 @@ ttynew(void) { close(s); close(m); execsh(); - break; - default: + } else { close(s); cmdfd = m; signal(SIGCHLD, sigchld); @@ -1286,7 +1284,6 @@ ttynew(void) { opt_io, strerror(errno)); } } - break; } } -- 2.3.5
[dev] [st] [PATCH 1/3] tresize: move for loop outside if
There is no need to check that slide > 0 before executing loop. If slide <= 0, loop stops immediately. --- st.c | 9 - 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/st.c b/st.c index b4e17e4..3b45c42 100644 --- a/st.c +++ b/st.c @@ -2781,17 +2781,16 @@ tresize(int col, int row) { } /* free unneeded rows */ - i = 0; + for(i = 0; i < slide; i++) { + free(term.line[i]); + free(term.alt[i]); + } if(slide > 0) { /* * slide screen to keep cursor where we expect it - * tscrollup would work here, but we can optimize to * memmove because we're freeing the earlier lines */ - for(/* i = 0 */; i < slide; i++) { - free(term.line[i]); - free(term.alt[i]); - } memmove(term.line, term.line + slide, row * sizeof(Line)); memmove(term.alt, term.alt + slide, row * sizeof(Line)); } -- 1.8.4
[dev] [st] [PATCH 2/3] Move tresize comments around.
--- st.c | 11 +-- 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/st.c b/st.c index 3b45c42..51bd40c 100644 --- a/st.c +++ b/st.c @@ -2780,17 +2780,16 @@ tresize(int col, int row) { return; } - /* free unneeded rows */ + /* +* slide screen to keep cursor where we expect it - +* tscrollup would work here, but we can optimize to +* memmove because we're freeing the earlier lines +*/ for(i = 0; i < slide; i++) { free(term.line[i]); free(term.alt[i]); } if(slide > 0) { - /* -* slide screen to keep cursor where we expect it - -* tscrollup would work here, but we can optimize to -* memmove because we're freeing the earlier lines -*/ memmove(term.line, term.line + slide, row * sizeof(Line)); memmove(term.alt, term.alt + slide, row * sizeof(Line)); } -- 1.8.4
[dev] [st] [PATCH 3/3] Remove 'slide' variable in tresize.
--- st.c | 9 - 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/st.c b/st.c index 51bd40c..ce2646e 100644 --- a/st.c +++ b/st.c @@ -2770,7 +2770,6 @@ 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; TCursor c; @@ -2785,13 +2784,13 @@ tresize(int col, int row) { * tscrollup would work here, but we can optimize to * memmove because we're freeing the earlier lines */ - for(i = 0; i < slide; i++) { + for(i = 0; i <= term.c.y - row; i++) { free(term.line[i]); free(term.alt[i]); } - if(slide > 0) { - memmove(term.line, term.line + slide, row * sizeof(Line)); - memmove(term.alt, term.alt + slide, row * sizeof(Line)); + if(i > 0) { + memmove(term.line, term.line + i, row * sizeof(Line)); + memmove(term.alt, term.alt + i, row * sizeof(Line)); } for(i += row; i < term.row; i++) { free(term.line[i]); -- 1.8.4
Re: [dev] [st] [PATCH 3/3] Remove 'slide' variable in tresize.
The commiter can squash 3 commits into 1 using rebase -i if he wants. I tried to separate moving loop outside if and removing local variable. I think these changes are independent.
[dev] [st] [PATCH 4/3] tresize: remove unnecessary if
--- st.c | 6 ++ 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/st.c b/st.c index 109122e..f183803 100644 --- a/st.c +++ b/st.c @@ -2788,10 +2788,8 @@ tresize(int col, int row) { free(term.line[i]); free(term.alt[i]); } - if(i > 0) { - memmove(term.line, term.line + i, row * sizeof(Line)); - memmove(term.alt, term.alt + i, row * sizeof(Line)); - } + memmove(term.line, term.line + i, row * sizeof(Line)); + memmove(term.alt, term.alt + i, row * sizeof(Line)); for(i += row; i < term.row; i++) { free(term.line[i]); free(term.alt[i]); -- 1.8.4
Re: [dev] [st] [PATCH 4/3] tresize: remove unnecessary if
On Sun, Apr 12, 2015 at 10:41:36AM +0200, Silvan Jegen wrote: > I was thinking about this option too but in that case you would be > calling memmove with an identical src and dst when i == 0. The man page > for glibc memmove(3) does not mention anything about this being a noop > so I am not sure that is a good thing to do. "The memory areas may overlap: copying takes place as though the bytes in src are first copied into a temporary array that does not overlap src or dest, and the bytes are then copied from the temporary array to dest." src == dest is just a case of overlapping areas, it must work.
Re: [dev] [st] [PATCH 4/3] tresize: remove unnecessary if
On Sun, Apr 12, 2015 at 11:35:42AM +0200, Silvan Jegen wrote: > I just wonder if it really will be copying the data around into a > temporary array for no reason when i == 0 (either in glibc or in another > libc). Well, it does not really move data to temporary array, memmove just chooses the right direction so it does not destroy data. glibc indeed wastes CPU cycles if dst == src, However, musl does not: http://git.musl-libc.org/cgit/musl/tree/src/string/memmove.c
Re: [dev] [dmenu] Potential bug in dmenu Ctrl+Enter handling
On Sun, Apr 12, 2015 at 11:18:02AM -0700, Eric Pruitt wrote: > While looking at the dmenu source code to make a patch for it, I noticed > this conditional on line 371: "if(!(ev->state & ControlMask))". It looks > as though pressing Ctrl+(Shift)+Enter is supposed to print the current > selection to stdout without terminating dmenu, but pressing > Ctrl+(Shift)+Enter doesn't do anything; is this a bug or am I misreading > the code? I am using a standard US keyboard layout with > LANG=en_US.UTF-8. The code that actually prints something is puts((sel && !(ev->state & ShiftMask)) ? sel->text : text); If you hold Shift, it prints the text you have typed ('text'), not the selection. If you hold Ctrl, it does not terminate. If you hold both Shift and Ctrl, it should at least print a newline.
Re: [dev] Re: [dmenu] [PATCH] Make Ctrl+Enter print current selection
Try to clone a clean git repo from git.suckless.org. For me everything works as expected without any patches.
Re: [dev] [st] [PATCH 1/2] Do not use switch for fork() call.
On Mon, Apr 13, 2015 at 09:20:34AM +0200, Roberto E. Vargas Caballero wrote: > I don't understand this patch. The switch-fork is a common idiom > and I don't know why you think it should be changed. It separates the case when fork fails and when fork succeeds. You can even move error-processing code to something like xfork(). First, we die if fork failed. If fork succeeds, we continue and have branches for child (pid == 0) and parent (pid == child). With switch, we have branches for failed parent, child and suceeded parent, in this order. Also, the code is obviously shorter.
[dev] [st] [PATCH 1/3] Fix typo.
It seems that LICENSE files are more common than LICENCE files. At least this patch makes spelling consistent. --- st.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/st.c b/st.c index f183803..db35e71 100644 --- a/st.c +++ b/st.c @@ -1,4 +1,4 @@ -/* See LICENSE for licence details. */ +/* See LICENSE for license details. */ #include #include #include -- 1.8.4
[dev] [st] [PATCH 3/3] Simplify tmoveto.
LIMIT returns value. This fact is already used in x2col and y2row. --- st.c | 6 ++ 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/st.c b/st.c index e01df66..33fd4de 100644 --- a/st.c +++ b/st.c @@ -1572,11 +1572,9 @@ tmoveto(int x, int y) { miny = 0; maxy = term.row - 1; } - LIMIT(x, 0, term.col-1); - LIMIT(y, miny, maxy); term.c.state &= ~CURSOR_WRAPNEXT; - term.c.x = x; - term.c.y = y; + term.c.x = LIMIT(x, 0, term.col-1); + term.c.y = LIMIT(y, miny, maxy); } void -- 1.8.4
[dev] [st] [PATCH 2/3] Do not use tmoveto in tputtab.
tmoveto resets CURSOR_WRAPNEXT. Simple testcase: for i in $(seq 1 200); do printf '\t.'; usleep 10; printf '\t@'; usleep 10; done In st executing this script causes @ and . to overwrite each other in the last column. --- st.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/st.c b/st.c index db35e71..e01df66 100644 --- a/st.c +++ b/st.c @@ -2393,7 +2393,7 @@ tputtab(int n) { for(--x; x > 0 && !term.tabs[x]; --x) /* nothing */ ; } - tmoveto(x, term.c.y); + term.c.x = LIMIT(x, 0, term.col-1); } void -- 1.8.4
[dev] [st] [PATCH] Remove useless if in tstrsequence.
--- st.c | 28 +--- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/st.c b/st.c index b2bcfe9..154dd52 100644 --- a/st.c +++ b/st.c @@ -2446,21 +2446,19 @@ tdectest(char c) { 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; - } + 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; -- 1.8.4