[wiki] [sites] [st] clean up scrollback patch || Jochen Sprickerhof

From: <git_AT_suckless.org>
Date: Wed, 04 Jan 2017 18:23:29 +0100

commit 275b78e02c01d6ae2d98473e2af60ee211e16aa2
Author: Jochen Sprickerhof <git_AT_jochen.sprickerhof.de>
Date: Wed Jan 4 18:20:23 2017 +0100

    [st] clean up scrollback patch
    
    Please have a look into the history before changing the implementation
    details of this patch. For example 916e9e7 for how to put term.hist on
    the heap and ccd3815 why it's on the stack.

diff --git a/st.suckless.org/patches/scrollback.md b/st.suckless.org/patches/scrollback.md
index 8f824a8..78914f6 100644
--- a/st.suckless.org/patches/scrollback.md
+++ b/st.suckless.org/patches/scrollback.md
_AT_@ -10,7 +10,7 @@ Download
 --------
 
 * [st-scrollback-0.7.diff](st-scrollback-0.7.diff)
-* [st-scrollback-20170102-a719e36.diff](st-scrollback-20170102-a719e36.diff)
+* [st-scrollback-20170104-c63a87c.diff](st-scrollback-20170104-c63a87c.diff)
 
 Apply the following patch on top of the previous to allow scrolling
 using `Shift+MouseWheel`.
diff --git a/st.suckless.org/patches/st-scrollback-20160924-f739843.diff b/st.suckless.org/patches/st-scrollback-20160924-f739843.diff
deleted file mode 100644
index 98cc8da..0000000
--- a/st.suckless.org/patches/st-scrollback-20160924-f739843.diff
+++ /dev/null
_AT_@ -1,387 +0,0 @@
-diff --git a/config.def.h b/config.def.h
-index b41747f..eae969e 100644
---- a/config.def.h
-+++ b/config.def.h
-_AT_@ -7,6 +7,7 @@
- */
- static char font[] = "Liberation Mono:pixelsize=12:antialias=true:autohint=true";
- static int borderpx = 2;
-+#define histsize 2000
-
- /*
- * What program is execed by st depends of these precedence rules:
-_AT_@ -172,6 +173,8 @@ static Shortcut shortcuts[] = {
- { MODKEY|ShiftMask, XK_C, clipcopy, {.i = 0} },
- { MODKEY|ShiftMask, XK_V, clippaste, {.i = 0} },
- { MODKEY, XK_Num_Lock, numlock, {.i = 0} },
-+ { ShiftMask, XK_Page_Up, kscrollup, {.i = -1} },
-+ { ShiftMask, XK_Page_Down, kscrolldown, {.i = -1} },
- };
-
- /*
-diff --git a/st.c b/st.c
-index 6c16386..05e84dc 100644
---- a/st.c
-+++ b/st.c
-_AT_@ -86,6 +86,8 @@ char *argv0;
- #define TRUERED(x) (((x) & 0xff0000) >> 8)
- #define TRUEGREEN(x) (((x) & 0xff00))
- #define TRUEBLUE(x) (((x) & 0xff) << 8)
-+#define TLINE(y) ((y) < term.scr ? term.hist[((y) + term.histi - term.scr \
-+ + histsize + 1) % histsize] : term.line[(y) - term.scr])
-
-
- enum glyph_attribute {
-_AT_@ -232,26 +234,6 @@ typedef struct {
- int narg; /* nb of args */
- } STREscape;
-
--/* Internal representation of the screen */
--typedef struct {
-- int row; /* nb row */
-- int col; /* nb col */
-- Line *line; /* screen */
-- Line *alt; /* alternate screen */
-- int *dirty; /* dirtyness of lines */
-- XftGlyphFontSpec *specbuf; /* font spec buffer used for rendering */
-- TCursor c; /* cursor */
-- int top; /* top scroll limit */
-- int bot; /* bottom scroll limit */
-- int mode; /* terminal mode flags */
-- int esc; /* escape state flags */
-- char trantbl[4]; /* charset table translation */
-- int charset; /* current charset */
-- int icharset; /* selected charset for sequence */
-- int numlock; /* lock numbers in keyboard */
-- int *tabs;
--} Term;
--
- /* Purely graphic info */
- typedef struct {
- 	Display *dpy;
-_AT_@ -331,6 +313,8 @@ typedef struct {
- /* function definitions used in config.h */
- static void clipcopy(const Arg *);
- static void clippaste(const Arg *);
-+static void kscrolldown(const Arg *);
-+static void kscrollup(const Arg *);
- static void numlock(const Arg *);
- static void selpaste(const Arg *);
- static void xzoom(const Arg *);
-_AT_@ -344,6 +328,29 @@ static void sendbreak(const Arg *);
- /* Config.h for applying patches and the configuration. */
- #include "config.h"
- 
-+/* Internal representation of the screen */
-+typedef struct {
-+	int row;      /* nb row */
-+	int col;      /* nb col */
-+	Line *line;   /* screen */
-+	Line *alt;    /* alternate screen */
-+	Line hist[histsize]; /* history buffer */
-+	int histi;    /* history index */
-+	int scr;      /* scroll back */
-+	int *dirty;  /* dirtyness of lines */
-+	XftGlyphFontSpec *specbuf; /* font spec buffer used for rendering */
-+	TCursor c;    /* cursor */
-+	int top;      /* top    scroll limit */
-+	int bot;      /* bottom scroll limit */
-+	int mode;     /* terminal mode flags */
-+	int esc;      /* escape state flags */
-+	char trantbl[4]; /* charset table translation */
-+	int charset;  /* current charset */
-+	int icharset; /* selected charset for sequence */
-+	int numlock; /* lock numbers in keyboard */
-+	int *tabs;
-+} Term;
-+
- /* Font structure */
- typedef struct {
- 	int height;
-_AT_@ -403,8 +410,8 @@ static void tputtab(int);
- static void tputc(Rune);
- static void treset(void);
- static void tresize(int, int);
--static void tscrollup(int, int);
--static void tscrolldown(int, int);
-+static void tscrollup(int, int, int);
-+static void tscrolldown(int, int, int);
- static void tsetattr(int *, int);
- static void tsetchar(Rune, Glyph *, int, int);
- static void tsetscroll(int, int);
-_AT_@ -736,10 +743,10 @@ tlinelen(int y)
- {
- 	int i = term.col;
- 
--	if (term.line[y][i - 1].mode & ATTR_WRAP)
-+	if (TLINE(y)[i - 1].mode & ATTR_WRAP)
- 		return i;
- 
--	while (i > 0 && term.line[y][i - 1].u == ' ')
-+	while (i > 0 && TLINE(y)[i - 1].u == ' ')
- 		--i;
- 
- 	return i;
-_AT_@ -801,7 +808,7 @@ selsnap(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];
-+		prevgp = &TLINE(*y)[*x];
- 		prevdelim = ISDELIM(prevgp->u);
- 		for (;;) {
- 			newx = *x + direction;
-_AT_@ -816,14 +823,14 @@ selsnap(int *x, int *y, int direction)
- 					yt = *y, xt = *x;
- 				else
- 					yt = newy, xt = newx;
--				if (!(term.line[yt][xt].mode & ATTR_WRAP))
-+				if (!(TLINE(yt)[xt].mode & ATTR_WRAP))
- 					break;
- 			}
- 
- 			if (newx >= tlinelen(newy))
- 				break;
- 
--			gp = &term.line[newy][newx];
-+			gp = &TLINE(newy)[newx];
- 			delim = ISDELIM(gp->u);
- 			if (!(gp->mode & ATTR_WDUMMY) && (delim != prevdelim
- 					|| (delim && gp->u != prevgp->u)))
-_AT_@ -844,14 +851,14 @@ selsnap(int *x, int *y, int direction)
- 		*x = (direction < 0) ? 0 : term.col - 1;
- 		if (direction < 0) {
- 			for (; *y > 0; *y += direction) {
--				if (!(term.line[*y-1][term.col-1].mode
-+				if (!(TLINE(*y-1)[term.col-1].mode
- 						& ATTR_WRAP)) {
- 					break;
- 				}
- 			}
- 		} else if (direction > 0) {
- 			for (; *y < term.row-1; *y += direction) {
--				if (!(term.line[*y][term.col-1].mode
-+				if (!(TLINE(*y)[term.col-1].mode
- 						& ATTR_WRAP)) {
- 					break;
- 				}
-_AT_@ -1017,13 +1024,13 @@ getsel(void)
- 		}
- 
- 		if (sel.type == SEL_RECTANGULAR) {
--			gp = &term.line[y][sel.nb.x];
-+			gp = &TLINE(y)[sel.nb.x];
- 			lastx = sel.ne.x;
- 		} else {
--			gp = &term.line[y][sel.nb.y == y ? sel.nb.x : 0];
-+			gp = &TLINE(y)[sel.nb.y == y ? sel.nb.x : 0];
- 			lastx = (sel.ne.y == y) ? sel.ne.x : term.col-1;
- 		}
--		last = &term.line[y][MIN(lastx, linelen-1)];
-+		last = &TLINE(y)[MIN(lastx, linelen-1)];
- 		while (last >= gp && last->u == ' ')
- 			--last;
- 
-_AT_@ -1507,6 +1514,9 @@ ttyread(void)
- 	if (buflen > 0)
- 		memmove(buf, ptr, buflen);
- 
-+	if (term.scr > 0 && term.scr < histsize-1)
-+		term.scr++;
-+
- 	return ret;
- }
- 
-_AT_@ -1516,6 +1526,9 @@ ttywrite(const char *s, size_t n)
- 	fd_set wfd, rfd;
- 	ssize_t r;
- 	size_t lim = 256;
-+	Arg arg = (Arg){ .i = term.scr };
-+
-+	kscrolldown(&arg);
- 
- 	/*
- 	 * Remember that we are using a pty, which might be a modem line.
-_AT_@ -1718,13 +1731,53 @@ tswapscreen(void)
- }
- 
- void
--tscrolldown(int orig, int n)
-+kscrolldown(const Arg* a)
-+{
-+	int n = a->i;
-+
-+	if (n < 0)
-+		n = term.row + n;
-+
-+	if (n > term.scr)
-+		n = term.scr;
-+
-+	if (term.scr > 0) {
-+		term.scr -= n;
-+		selscroll(0, -n);
-+		tfulldirt();
-+	}
-+}
-+
-+void
-+kscrollup(const Arg* a)
-+{
-+	int n = a->i;
-+
-+	if (n < 0)
-+		n = term.row + n;
-+
-+	if (term.scr <= histsize - n) {
-+		term.scr += n;
-+		selscroll(0, n);
-+		tfulldirt();
-+	}
-+}
-+
-+void
-+tscrolldown(int orig, int n, int copyhist)
- {
- 	int i;
- 	Line temp;
- 
- 	LIMIT(n, 0, term.bot-orig+1);
- 
-+	if (copyhist) {
-+		term.histi = (term.histi - 1 + histsize) % histsize;
-+		temp = term.hist[term.histi];
-+		term.hist[term.histi] = term.line[term.bot];
-+		term.line[term.bot] = temp;
-+	}
-+
- 	tsetdirt(orig, term.bot-n);
- 	tclearregion(0, term.bot-n+1, term.col-1, term.bot);
- 
-_AT_@ -1738,13 +1791,20 @@ tscrolldown(int orig, int n)
- }
- 
- void
--tscrollup(int orig, int n)
-+tscrollup(int orig, int n, int copyhist)
- {
- 	int i;
- 	Line temp;
- 
- 	LIMIT(n, 0, term.bot-orig+1);
- 
-+	if (copyhist) {
-+		term.histi = (term.histi + 1) % histsize;
-+		temp = term.hist[term.histi];
-+		term.hist[term.histi] = term.line[orig];
-+		term.line[orig] = temp;
-+	}
-+
- 	tclearregion(0, orig, term.col-1, orig+n-1);
- 	tsetdirt(orig+n, term.bot);
- 
-_AT_@ -1793,7 +1853,7 @@ tnewline(int first_col)
- 	int y = term.c.y;
- 
- 	if (y == term.bot) {
--		tscrollup(term.top, 1);
-+		tscrollup(term.top, 1, 1);
- 	} else {
- 		y++;
- 	}
-_AT_@ -1958,14 +2018,14 @@ void
- tinsertblankline(int n)
- {
- 	if (BETWEEN(term.c.y, term.top, term.bot))
--		tscrolldown(term.c.y, n);
-+		tscrolldown(term.c.y, n, 0);
- }
- 
- void
- tdeleteline(int n)
- {
- 	if (BETWEEN(term.c.y, term.top, term.bot))
--		tscrollup(term.c.y, n);
-+		tscrollup(term.c.y, n, 0);
- }
- 
- int32_t
-_AT_@ -2399,11 +2459,11 @@ csihandle(void)
- 		break;
- 	case 'S': /* SU -- Scroll <n> line up */
- 		DEFAULT(csiescseq.arg[0], 1);
--		tscrollup(term.top, csiescseq.arg[0]);
-+		tscrollup(term.top, csiescseq.arg[0], 0);
- 		break;
- 	case 'T': /* SD -- Scroll <n> line down */
- 		DEFAULT(csiescseq.arg[0], 1);
--		tscrolldown(term.top, csiescseq.arg[0]);
-+		tscrolldown(term.top, csiescseq.arg[0], 0);
- 		break;
- 	case 'L': /* IL -- Insert <n> blank lines */
- 		DEFAULT(csiescseq.arg[0], 1);
-_AT_@ -2914,7 +2974,7 @@ eschandle(uchar ascii)
- 		return 0;
- 	case 'D': /* IND -- Linefeed */
- 		if (term.c.y == term.bot) {
--			tscrollup(term.top, 1);
-+			tscrollup(term.top, 1, 1);
- 		} else {
- 			tmoveto(term.c.x, term.c.y+1);
- 		}
-_AT_@ -2927,7 +2987,7 @@ eschandle(uchar ascii)
- 		break;
- 	case 'M': /* RI -- Reverse index */
- 		if (term.c.y == term.top) {
--			tscrolldown(term.top, 1);
-+			tscrolldown(term.top, 1, 1);
- 		} else {
- 			tmoveto(term.c.x, term.c.y-1);
- 		}
-_AT_@ -3114,7 +3174,7 @@ check_control_code:
- void
- tresize(int col, int row)
- {
--	int i;
-+	int i, j;
- 	int minrow = MIN(row, term.row);
- 	int mincol = MIN(col, term.col);
- 	int *bp;
-_AT_@ -3154,6 +3214,14 @@ tresize(int col, int row)
- 	term.dirty = xrealloc(term.dirty, row * sizeof(*term.dirty));
- 	term.tabs = xrealloc(term.tabs, col * sizeof(*term.tabs));
- 
-+	for (i = 0; i < histsize; i++) {
-+		term.hist[i] = xrealloc(term.hist[i], col * sizeof(Glyph));
-+		for (j = mincol; j < col; j++) {
-+			term.hist[i][j] = term.c.attr;
-+			term.hist[i][j].u = ' ';
-+		}
-+	}
-+
- 	/* resize each row to new width, zero-pad if needed */
- 	for (i = 0; i < minrow; i++) {
- 		term.line[i] = xrealloc(term.line[i], col * sizeof(Glyph));
-_AT_@ -4043,11 +4111,11 @@ drawregion(int x1, int y1, int x2, int y2)
- 		term.dirty[y] = 0;
- 
- 		specs = term.specbuf;
--		numspecs = xmakeglyphfontspecs(specs, &term.line[y][x1], x2 - x1, x1, y);
-+		numspecs = xmakeglyphfontspecs(specs, &TLINE(y)[x1], x2 - x1, x1, y);
- 
- 		i = ox = 0;
- 		for (x = x1; x < x2 && i < numspecs; x++) {
--			new = term.line[y][x];
-+			new = TLINE(y)[x];
- 			if (new.mode == ATTR_WDUMMY)
- 				continue;
- 			if (ena_sel && selected(x, y))
-_AT_@ -4067,7 +4135,8 @@ drawregion(int x1, int y1, int x2, int y2)
- 		if (i > 0)
- 			xdrawglyphfontspecs(specs, base, i, ox, y);
- 	}
--	xdrawcursor();
-+	if (term.scr == 0)
-+		xdrawcursor();
- }
- 
- void
diff --git a/st.suckless.org/patches/st-scrollback-20170102-a719e36.diff b/st.suckless.org/patches/st-scrollback-20170102-a719e36.diff
deleted file mode 100644
index ffd0ee3..0000000
--- a/st.suckless.org/patches/st-scrollback-20170102-a719e36.diff
+++ /dev/null
_AT_@ -1,379 +0,0 @@
-diff --git a/config.def.h b/config.def.h
-index a719e36..a070a3b 100644
---- a/config.def.h
-+++ b/config.def.h
-_AT_@ -7,6 +7,7 @@
-  */
- static char font[] = "Liberation Mono:pixelsize=12:antialias=true:autohint=true";
- static int borderpx = 2;
-+static unsigned int histsize = 2000;
- 
- /*
-  * What program is execed by st depends of these precedence rules:
-_AT_@ -178,6 +179,8 @@ static Shortcut shortcuts[] = {
- 	{ MODKEY|ShiftMask,     XK_V,           clippaste,      {.i =  0} },
- 	{ MODKEY,               XK_Num_Lock,    numlock,        {.i =  0} },
- 	{ MODKEY,               XK_Control_L,   iso14755,       {.i =  0} },
-+	{ ShiftMask,            XK_Page_Up,     kscrollup,      {.i = -1} },
-+	{ ShiftMask,            XK_Page_Down,   kscrolldown,    {.i = -1} },
- };
- 
- /*
-diff --git a/st.c b/st.c
-index fbcd9e0..38256d1 100644
---- a/st.c
-+++ b/st.c
-_AT_@ -87,6 +87,9 @@ char *argv0;
- #define TRUERED(x)		(((x) & 0xff0000) >> 8)
- #define TRUEGREEN(x)		(((x) & 0xff00))
- #define TRUEBLUE(x)		(((x) & 0xff) << 8)
-+#define TLINE(y)		((y) < term.scr ? term.hist[((y) + term.histi \
-+				- term.scr + histsize + 1) % histsize] : term.line[(y) \
-+				- term.scr])
- 
- /* constants */
- #define ISO14755CMD		"dmenu -w %lu -p codepoint: </dev/null"
-_AT_@ -241,7 +244,10 @@ typedef struct {
- 	int col;      /* nb col */
- 	Line *line;   /* screen */
- 	Line *alt;    /* alternate screen */
--	int *dirty;  /* dirtyness of lines */
-+	Line *hist;   /* history buffer */
-+	int histi;    /* history index */
-+	int scr;      /* scroll back */
-+	int *dirty;   /* dirtyness of lines */
- 	XftGlyphFontSpec *specbuf; /* font spec buffer used for rendering */
- 	TCursor c;    /* cursor */
- 	int top;      /* top    scroll limit */
-_AT_@ -251,7 +257,7 @@ typedef struct {
- 	char trantbl[4]; /* charset table translation */
- 	int charset;  /* current charset */
- 	int icharset; /* selected charset for sequence */
--	int numlock; /* lock numbers in keyboard */
-+	int numlock;  /* lock numbers in keyboard */
- 	int *tabs;
- } Term;
- 
-_AT_@ -334,6 +340,8 @@ typedef struct {
- /* function definitions used in config.h */
- static void clipcopy(const Arg *);
- static void clippaste(const Arg *);
-+static void kscrolldown(const Arg *);
-+static void kscrollup(const Arg *);
- static void numlock(const Arg *);
- static void selpaste(const Arg *);
- static void xzoom(const Arg *);
-_AT_@ -409,8 +417,8 @@ static void tputtab(int);
- static void tputc(Rune);
- static void treset(void);
- static void tresize(int, int);
--static void tscrollup(int, int);
--static void tscrolldown(int, int);
-+static void tscrollup(int, int, int);
-+static void tscrolldown(int, int, int);
- static void tsetattr(int *, int);
- static void tsetchar(Rune, Glyph *, int, int);
- static void tsetscroll(int, int);
-_AT_@ -742,10 +750,10 @@ tlinelen(int y)
- {
- 	int i = term.col;
- 
--	if (term.line[y][i - 1].mode & ATTR_WRAP)
-+	if (TLINE(y)[i - 1].mode & ATTR_WRAP)
- 		return i;
- 
--	while (i > 0 && term.line[y][i - 1].u == ' ')
-+	while (i > 0 && TLINE(y)[i - 1].u == ' ')
- 		--i;
- 
- 	return i;
-_AT_@ -807,7 +815,7 @@ selsnap(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];
-+		prevgp = &TLINE(*y)[*x];
- 		prevdelim = ISDELIM(prevgp->u);
- 		for (;;) {
- 			newx = *x + direction;
-_AT_@ -822,14 +830,14 @@ selsnap(int *x, int *y, int direction)
- 					yt = *y, xt = *x;
- 				else
- 					yt = newy, xt = newx;
--				if (!(term.line[yt][xt].mode & ATTR_WRAP))
-+				if (!(TLINE(yt)[xt].mode & ATTR_WRAP))
- 					break;
- 			}
- 
- 			if (newx >= tlinelen(newy))
- 				break;
- 
--			gp = &term.line[newy][newx];
-+			gp = &TLINE(newy)[newx];
- 			delim = ISDELIM(gp->u);
- 			if (!(gp->mode & ATTR_WDUMMY) && (delim != prevdelim
- 					|| (delim && gp->u != prevgp->u)))
-_AT_@ -850,14 +858,14 @@ selsnap(int *x, int *y, int direction)
- 		*x = (direction < 0) ? 0 : term.col - 1;
- 		if (direction < 0) {
- 			for (; *y > 0; *y += direction) {
--				if (!(term.line[*y-1][term.col-1].mode
-+				if (!(TLINE(*y-1)[term.col-1].mode
- 						& ATTR_WRAP)) {
- 					break;
- 				}
- 			}
- 		} else if (direction > 0) {
- 			for (; *y < term.row-1; *y += direction) {
--				if (!(term.line[*y][term.col-1].mode
-+				if (!(TLINE(*y)[term.col-1].mode
- 						& ATTR_WRAP)) {
- 					break;
- 				}
-_AT_@ -1023,13 +1031,13 @@ getsel(void)
- 		}
- 
- 		if (sel.type == SEL_RECTANGULAR) {
--			gp = &term.line[y][sel.nb.x];
-+			gp = &TLINE(y)[sel.nb.x];
- 			lastx = sel.ne.x;
- 		} else {
--			gp = &term.line[y][sel.nb.y == y ? sel.nb.x : 0];
-+			gp = &TLINE(y)[sel.nb.y == y ? sel.nb.x : 0];
- 			lastx = (sel.ne.y == y) ? sel.ne.x : term.col-1;
- 		}
--		last = &term.line[y][MIN(lastx, linelen-1)];
-+		last = &TLINE(y)[MIN(lastx, linelen-1)];
- 		while (last >= gp && last->u == ' ')
- 			--last;
- 
-_AT_@ -1513,6 +1521,9 @@ ttyread(void)
- 	if (buflen > 0)
- 		memmove(buf, ptr, buflen);
- 
-+	if (term.scr > 0 && term.scr < histsize - 1)
-+		term.scr++;
-+
- 	return ret;
- }
- 
-_AT_@ -1522,6 +1533,9 @@ ttywrite(const char *s, size_t n)
- 	fd_set wfd, rfd;
- 	ssize_t r;
- 	size_t lim = 256;
-+	Arg arg = (Arg) { .i = term.scr };
-+
-+	kscrolldown(&arg);
- 
- 	/*
- 	 * Remember that we are using a pty, which might be a modem line.
-_AT_@ -1724,40 +1738,87 @@ tswapscreen(void)
- }
- 
- void
--tscrolldown(int orig, int n)
-+kscrolldown(const Arg* a)
-+{
-+	int n = a->i;
-+
-+	if (n < 0)
-+		n = term.row + n;
-+
-+	if (n > term.scr)
-+		n = term.scr;
-+
-+	if (term.scr > 0) {
-+		term.scr -= n;
-+		selscroll(0, -n);
-+		tfulldirt();
-+	}
-+}
-+
-+void
-+kscrollup(const Arg* a)
-+{
-+	int n = a->i;
-+
-+	if (n < 0)
-+		n = term.row + n;
-+
-+	if (term.scr <= histsize - n) {
-+		term.scr += n;
-+		selscroll(0, n);
-+		tfulldirt();
-+	}
-+}
-+
-+void
-+tscrolldown(int orig, int n, int copyhist)
- {
- 	int i;
- 	Line temp;
- 
--	LIMIT(n, 0, term.bot-orig+1);
-+	LIMIT(n, 0, term.bot - orig + 1);
- 
--	tsetdirt(orig, term.bot-n);
--	tclearregion(0, term.bot-n+1, term.col-1, term.bot);
-+	if (copyhist) {
-+		term.histi = (term.histi - 1 + histsize) % histsize;
-+		temp = term.hist[term.histi];
-+		term.hist[term.histi] = term.line[term.bot];
-+		term.line[term.bot] = temp;
-+	}
- 
--	for (i = term.bot; i >= orig+n; i--) {
-+	tsetdirt(orig, term.bot - n);
-+	tclearregion(0, term.bot - n + 1, term.col - 1, 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.line[i] = term.line[i - n];
-+		term.line[i - n] = temp;
- 	}
- 
- 	selscroll(orig, n);
- }
- 
- void
--tscrollup(int orig, int n)
-+tscrollup(int orig, int n, int copyhist)
- {
- 	int i;
- 	Line temp;
- 
--	LIMIT(n, 0, term.bot-orig+1);
-+	LIMIT(n, 0, term.bot - orig + 1);
-+
-+	if (copyhist) {
-+		term.histi = (term.histi + 1) % histsize;
-+		temp = term.hist[term.histi];
-+		term.hist[term.histi] = term.line[orig];
-+		term.line[orig] = temp;
-+	}
- 
--	tclearregion(0, orig, term.col-1, orig+n-1);
--	tsetdirt(orig+n, term.bot);
-+	tclearregion(0, orig, term.col - 1, orig + n - 1);
-+	tsetdirt(orig + n, term.bot);
- 
--	for (i = orig; i <= term.bot-n; i++) {
-+	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.line[i] = term.line[i + n];
-+		term.line[i + n] = temp;
- 	}
- 
- 	selscroll(orig, -n);
-_AT_@ -1799,7 +1860,7 @@ tnewline(int first_col)
- 	int y = term.c.y;
- 
- 	if (y == term.bot) {
--		tscrollup(term.top, 1);
-+		tscrollup(term.top, 1, 1);
- 	} else {
- 		y++;
- 	}
-_AT_@ -1964,14 +2025,14 @@ void
- tinsertblankline(int n)
- {
- 	if (BETWEEN(term.c.y, term.top, term.bot))
--		tscrolldown(term.c.y, n);
-+		tscrolldown(term.c.y, n, 0);
- }
- 
- void
- tdeleteline(int n)
- {
- 	if (BETWEEN(term.c.y, term.top, term.bot))
--		tscrollup(term.c.y, n);
-+		tscrollup(term.c.y, n, 0);
- }
- 
- int32_t
-_AT_@ -2405,11 +2466,11 @@ csihandle(void)
- 		break;
- 	case 'S': /* SU -- Scroll <n> line up */
- 		DEFAULT(csiescseq.arg[0], 1);
--		tscrollup(term.top, csiescseq.arg[0]);
-+		tscrollup(term.top, csiescseq.arg[0], 0);
- 		break;
- 	case 'T': /* SD -- Scroll <n> line down */
- 		DEFAULT(csiescseq.arg[0], 1);
--		tscrolldown(term.top, csiescseq.arg[0]);
-+		tscrolldown(term.top, csiescseq.arg[0], 0);
- 		break;
- 	case 'L': /* IL -- Insert <n> blank lines */
- 		DEFAULT(csiescseq.arg[0], 1);
-_AT_@ -2945,7 +3006,7 @@ eschandle(uchar ascii)
- 		return 0;
- 	case 'D': /* IND -- Linefeed */
- 		if (term.c.y == term.bot) {
--			tscrollup(term.top, 1);
-+			tscrollup(term.top, 1, 1);
- 		} else {
- 			tmoveto(term.c.x, term.c.y+1);
- 		}
-_AT_@ -2958,7 +3019,7 @@ eschandle(uchar ascii)
- 		break;
- 	case 'M': /* RI -- Reverse index */
- 		if (term.c.y == term.top) {
--			tscrolldown(term.top, 1);
-+			tscrolldown(term.top, 1, 1);
- 		} else {
- 			tmoveto(term.c.x, term.c.y-1);
- 		}
-_AT_@ -3145,7 +3206,7 @@ check_control_code:
- void
- tresize(int col, int row)
- {
--	int i;
-+	int i, j;
- 	int minrow = MIN(row, term.row);
- 	int mincol = MIN(col, term.col);
- 	int *bp;
-_AT_@ -3184,6 +3245,15 @@ tresize(int col, int row)
- 	term.alt  = xrealloc(term.alt,  row * sizeof(Line));
- 	term.dirty = xrealloc(term.dirty, row * sizeof(*term.dirty));
- 	term.tabs = xrealloc(term.tabs, col * sizeof(*term.tabs));
-+	term.hist = xrealloc(term.hist, histsize * sizeof(Line));
-+
-+	for (i = 0; i < histsize; i++) {
-+		term.hist[i] = xrealloc(term.hist[i], col * sizeof(Glyph));
-+		for (j = mincol; j < col; j++) {
-+			term.hist[i][j] = term.c.attr;
-+			term.hist[i][j].u = ' ';
-+		}
-+	}
- 
- 	/* resize each row to new width, zero-pad if needed */
- 	for (i = 0; i < minrow; i++) {
-_AT_@ -4112,11 +4182,11 @@ drawregion(int x1, int y1, int x2, int y2)
- 		term.dirty[y] = 0;
- 
- 		specs = term.specbuf;
--		numspecs = xmakeglyphfontspecs(specs, &term.line[y][x1], x2 - x1, x1, y);
-+		numspecs = xmakeglyphfontspecs(specs, &TLINE(y)[x1], x2 - x1, x1, y);
- 
- 		i = ox = 0;
- 		for (x = x1; x < x2 && i < numspecs; x++) {
--			new = term.line[y][x];
-+			new = TLINE(y)[x];
- 			if (new.mode == ATTR_WDUMMY)
- 				continue;
- 			if (ena_sel && selected(x, y))
-_AT_@ -4136,7 +4206,9 @@ drawregion(int x1, int y1, int x2, int y2)
- 		if (i > 0)
- 			xdrawglyphfontspecs(specs, base, i, ox, y);
- 	}
--	xdrawcursor();
-+
-+	if (term.scr == 0)
-+		xdrawcursor();
- }
- 
- void
diff --git a/st.suckless.org/patches/st-scrollback-20170104-c63a87c.diff b/st.suckless.org/patches/st-scrollback-20170104-c63a87c.diff
new file mode 100644
index 0000000..98cc8da
--- /dev/null
+++ b/st.suckless.org/patches/st-scrollback-20170104-c63a87c.diff
_AT_@ -0,0 +1,387 @@
+diff --git a/config.def.h b/config.def.h
+index b41747f..eae969e 100644
+--- a/config.def.h
++++ b/config.def.h
+_AT_@ -7,6 +7,7 @@
+  */
+ static char font[] = "Liberation Mono:pixelsize=12:antialias=true:autohint=true";
+ static int borderpx = 2;
++#define histsize 2000
+ 
+ /*
+  * What program is execed by st depends of these precedence rules:
+_AT_@ -172,6 +173,8 @@ static Shortcut shortcuts[] = {
+ 	{ MODKEY|ShiftMask,     XK_C,           clipcopy,       {.i =  0} },
+ 	{ MODKEY|ShiftMask,     XK_V,           clippaste,      {.i =  0} },
+ 	{ MODKEY,               XK_Num_Lock,    numlock,        {.i =  0} },
++	{ ShiftMask,            XK_Page_Up,     kscrollup,      {.i = -1} },
++	{ ShiftMask,            XK_Page_Down,   kscrolldown,    {.i = -1} },
+ };
+ 
+ /*
+diff --git a/st.c b/st.c
+index 6c16386..05e84dc 100644
+--- a/st.c
++++ b/st.c
+_AT_@ -86,6 +86,8 @@ char *argv0;
+ #define TRUERED(x)		(((x) & 0xff0000) >> 8)
+ #define TRUEGREEN(x)		(((x) & 0xff00))
+ #define TRUEBLUE(x)		(((x) & 0xff) << 8)
++#define TLINE(y)		((y) < term.scr ? term.hist[((y) + term.histi - term.scr \
++				+ histsize + 1) % histsize] : term.line[(y) - term.scr])
+ 
+ 
+ enum glyph_attribute {
+_AT_@ -232,26 +234,6 @@ typedef struct {
+ 	int narg;              /* nb of args */
+ } STREscape;
+ 
+-/* Internal representation of the screen */
+-typedef struct {
+-	int row;      /* nb row */
+-	int col;      /* nb col */
+-	Line *line;   /* screen */
+-	Line *alt;    /* alternate screen */
+-	int *dirty;  /* dirtyness of lines */
+-	XftGlyphFontSpec *specbuf; /* font spec buffer used for rendering */
+-	TCursor c;    /* cursor */
+-	int top;      /* top    scroll limit */
+-	int bot;      /* bottom scroll limit */
+-	int mode;     /* terminal mode flags */
+-	int esc;      /* escape state flags */
+-	char trantbl[4]; /* charset table translation */
+-	int charset;  /* current charset */
+-	int icharset; /* selected charset for sequence */
+-	int numlock; /* lock numbers in keyboard */
+-	int *tabs;
+-} Term;
+-
+ /* Purely graphic info */
+ typedef struct {
+ 	Display *dpy;
+_AT_@ -331,6 +313,8 @@ typedef struct {
+ /* function definitions used in config.h */
+ static void clipcopy(const Arg *);
+ static void clippaste(const Arg *);
++static void kscrolldown(const Arg *);
++static void kscrollup(const Arg *);
+ static void numlock(const Arg *);
+ static void selpaste(const Arg *);
+ static void xzoom(const Arg *);
+_AT_@ -344,6 +328,29 @@ static void sendbreak(const Arg *);
+ /* Config.h for applying patches and the configuration. */
+ #include "config.h"
+ 
++/* Internal representation of the screen */
++typedef struct {
++	int row;      /* nb row */
++	int col;      /* nb col */
++	Line *line;   /* screen */
++	Line *alt;    /* alternate screen */
++	Line hist[histsize]; /* history buffer */
++	int histi;    /* history index */
++	int scr;      /* scroll back */
++	int *dirty;  /* dirtyness of lines */
++	XftGlyphFontSpec *specbuf; /* font spec buffer used for rendering */
++	TCursor c;    /* cursor */
++	int top;      /* top    scroll limit */
++	int bot;      /* bottom scroll limit */
++	int mode;     /* terminal mode flags */
++	int esc;      /* escape state flags */
++	char trantbl[4]; /* charset table translation */
++	int charset;  /* current charset */
++	int icharset; /* selected charset for sequence */
++	int numlock; /* lock numbers in keyboard */
++	int *tabs;
++} Term;
++
+ /* Font structure */
+ typedef struct {
+ 	int height;
+_AT_@ -403,8 +410,8 @@ static void tputtab(int);
+ static void tputc(Rune);
+ static void treset(void);
+ static void tresize(int, int);
+-static void tscrollup(int, int);
+-static void tscrolldown(int, int);
++static void tscrollup(int, int, int);
++static void tscrolldown(int, int, int);
+ static void tsetattr(int *, int);
+ static void tsetchar(Rune, Glyph *, int, int);
+ static void tsetscroll(int, int);
+_AT_@ -736,10 +743,10 @@ tlinelen(int y)
+ {
+ 	int i = term.col;
+ 
+-	if (term.line[y][i - 1].mode & ATTR_WRAP)
++	if (TLINE(y)[i - 1].mode & ATTR_WRAP)
+ 		return i;
+ 
+-	while (i > 0 && term.line[y][i - 1].u == ' ')
++	while (i > 0 && TLINE(y)[i - 1].u == ' ')
+ 		--i;
+ 
+ 	return i;
+_AT_@ -801,7 +808,7 @@ selsnap(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];
++		prevgp = &TLINE(*y)[*x];
+ 		prevdelim = ISDELIM(prevgp->u);
+ 		for (;;) {
+ 			newx = *x + direction;
+_AT_@ -816,14 +823,14 @@ selsnap(int *x, int *y, int direction)
+ 					yt = *y, xt = *x;
+ 				else
+ 					yt = newy, xt = newx;
+-				if (!(term.line[yt][xt].mode & ATTR_WRAP))
++				if (!(TLINE(yt)[xt].mode & ATTR_WRAP))
+ 					break;
+ 			}
+ 
+ 			if (newx >= tlinelen(newy))
+ 				break;
+ 
+-			gp = &term.line[newy][newx];
++			gp = &TLINE(newy)[newx];
+ 			delim = ISDELIM(gp->u);
+ 			if (!(gp->mode & ATTR_WDUMMY) && (delim != prevdelim
+ 					|| (delim && gp->u != prevgp->u)))
+_AT_@ -844,14 +851,14 @@ selsnap(int *x, int *y, int direction)
+ 		*x = (direction < 0) ? 0 : term.col - 1;
+ 		if (direction < 0) {
+ 			for (; *y > 0; *y += direction) {
+-				if (!(term.line[*y-1][term.col-1].mode
++				if (!(TLINE(*y-1)[term.col-1].mode
+ 						& ATTR_WRAP)) {
+ 					break;
+ 				}
+ 			}
+ 		} else if (direction > 0) {
+ 			for (; *y < term.row-1; *y += direction) {
+-				if (!(term.line[*y][term.col-1].mode
++				if (!(TLINE(*y)[term.col-1].mode
+ 						& ATTR_WRAP)) {
+ 					break;
+ 				}
+_AT_@ -1017,13 +1024,13 @@ getsel(void)
+ 		}
+ 
+ 		if (sel.type == SEL_RECTANGULAR) {
+-			gp = &term.line[y][sel.nb.x];
++			gp = &TLINE(y)[sel.nb.x];
+ 			lastx = sel.ne.x;
+ 		} else {
+-			gp = &term.line[y][sel.nb.y == y ? sel.nb.x : 0];
++			gp = &TLINE(y)[sel.nb.y == y ? sel.nb.x : 0];
+ 			lastx = (sel.ne.y == y) ? sel.ne.x : term.col-1;
+ 		}
+-		last = &term.line[y][MIN(lastx, linelen-1)];
++		last = &TLINE(y)[MIN(lastx, linelen-1)];
+ 		while (last >= gp && last->u == ' ')
+ 			--last;
+ 
+_AT_@ -1507,6 +1514,9 @@ ttyread(void)
+ 	if (buflen > 0)
+ 		memmove(buf, ptr, buflen);
+ 
++	if (term.scr > 0 && term.scr < histsize-1)
++		term.scr++;
++
+ 	return ret;
+ }
+ 
+_AT_@ -1516,6 +1526,9 @@ ttywrite(const char *s, size_t n)
+ 	fd_set wfd, rfd;
+ 	ssize_t r;
+ 	size_t lim = 256;
++	Arg arg = (Arg){ .i = term.scr };
++
++	kscrolldown(&arg);
+ 
+ 	/*
+ 	 * Remember that we are using a pty, which might be a modem line.
+_AT_@ -1718,13 +1731,53 @@ tswapscreen(void)
+ }
+ 
+ void
+-tscrolldown(int orig, int n)
++kscrolldown(const Arg* a)
++{
++	int n = a->i;
++
++	if (n < 0)
++		n = term.row + n;
++
++	if (n > term.scr)
++		n = term.scr;
++
++	if (term.scr > 0) {
++		term.scr -= n;
++		selscroll(0, -n);
++		tfulldirt();
++	}
++}
++
++void
++kscrollup(const Arg* a)
++{
++	int n = a->i;
++
++	if (n < 0)
++		n = term.row + n;
++
++	if (term.scr <= histsize - n) {
++		term.scr += n;
++		selscroll(0, n);
++		tfulldirt();
++	}
++}
++
++void
++tscrolldown(int orig, int n, int copyhist)
+ {
+ 	int i;
+ 	Line temp;
+ 
+ 	LIMIT(n, 0, term.bot-orig+1);
+ 
++	if (copyhist) {
++		term.histi = (term.histi - 1 + histsize) % histsize;
++		temp = term.hist[term.histi];
++		term.hist[term.histi] = term.line[term.bot];
++		term.line[term.bot] = temp;
++	}
++
+ 	tsetdirt(orig, term.bot-n);
+ 	tclearregion(0, term.bot-n+1, term.col-1, term.bot);
+ 
+_AT_@ -1738,13 +1791,20 @@ tscrolldown(int orig, int n)
+ }
+ 
+ void
+-tscrollup(int orig, int n)
++tscrollup(int orig, int n, int copyhist)
+ {
+ 	int i;
+ 	Line temp;
+ 
+ 	LIMIT(n, 0, term.bot-orig+1);
+ 
++	if (copyhist) {
++		term.histi = (term.histi + 1) % histsize;
++		temp = term.hist[term.histi];
++		term.hist[term.histi] = term.line[orig];
++		term.line[orig] = temp;
++	}
++
+ 	tclearregion(0, orig, term.col-1, orig+n-1);
+ 	tsetdirt(orig+n, term.bot);
+ 
+_AT_@ -1793,7 +1853,7 @@ tnewline(int first_col)
+ 	int y = term.c.y;
+ 
+ 	if (y == term.bot) {
+-		tscrollup(term.top, 1);
++		tscrollup(term.top, 1, 1);
+ 	} else {
+ 		y++;
+ 	}
+_AT_@ -1958,14 +2018,14 @@ void
+ tinsertblankline(int n)
+ {
+ 	if (BETWEEN(term.c.y, term.top, term.bot))
+-		tscrolldown(term.c.y, n);
++		tscrolldown(term.c.y, n, 0);
+ }
+ 
+ void
+ tdeleteline(int n)
+ {
+ 	if (BETWEEN(term.c.y, term.top, term.bot))
+-		tscrollup(term.c.y, n);
++		tscrollup(term.c.y, n, 0);
+ }
+ 
+ int32_t
+_AT_@ -2399,11 +2459,11 @@ csihandle(void)
+ 		break;
+ 	case 'S': /* SU -- Scroll <n> line up */
+ 		DEFAULT(csiescseq.arg[0], 1);
+-		tscrollup(term.top, csiescseq.arg[0]);
++		tscrollup(term.top, csiescseq.arg[0], 0);
+ 		break;
+ 	case 'T': /* SD -- Scroll <n> line down */
+ 		DEFAULT(csiescseq.arg[0], 1);
+-		tscrolldown(term.top, csiescseq.arg[0]);
++		tscrolldown(term.top, csiescseq.arg[0], 0);
+ 		break;
+ 	case 'L': /* IL -- Insert <n> blank lines */
+ 		DEFAULT(csiescseq.arg[0], 1);
+_AT_@ -2914,7 +2974,7 @@ eschandle(uchar ascii)
+ 		return 0;
+ 	case 'D': /* IND -- Linefeed */
+ 		if (term.c.y == term.bot) {
+-			tscrollup(term.top, 1);
++			tscrollup(term.top, 1, 1);
+ 		} else {
+ 			tmoveto(term.c.x, term.c.y+1);
+ 		}
+_AT_@ -2927,7 +2987,7 @@ eschandle(uchar ascii)
+ 		break;
+ 	case 'M': /* RI -- Reverse index */
+ 		if (term.c.y == term.top) {
+-			tscrolldown(term.top, 1);
++			tscrolldown(term.top, 1, 1);
+ 		} else {
+ 			tmoveto(term.c.x, term.c.y-1);
+ 		}
+_AT_@ -3114,7 +3174,7 @@ check_control_code:
+ void
+ tresize(int col, int row)
+ {
+-	int i;
++	int i, j;
+ 	int minrow = MIN(row, term.row);
+ 	int mincol = MIN(col, term.col);
+ 	int *bp;
+_AT_@ -3154,6 +3214,14 @@ tresize(int col, int row)
+ 	term.dirty = xrealloc(term.dirty, row * sizeof(*term.dirty));
+ 	term.tabs = xrealloc(term.tabs, col * sizeof(*term.tabs));
+ 
++	for (i = 0; i < histsize; i++) {
++		term.hist[i] = xrealloc(term.hist[i], col * sizeof(Glyph));
++		for (j = mincol; j < col; j++) {
++			term.hist[i][j] = term.c.attr;
++			term.hist[i][j].u = ' ';
++		}
++	}
++
+ 	/* resize each row to new width, zero-pad if needed */
+ 	for (i = 0; i < minrow; i++) {
+ 		term.line[i] = xrealloc(term.line[i], col * sizeof(Glyph));
+_AT_@ -4043,11 +4111,11 @@ drawregion(int x1, int y1, int x2, int y2)
+ 		term.dirty[y] = 0;
+ 
+ 		specs = term.specbuf;
+-		numspecs = xmakeglyphfontspecs(specs, &term.line[y][x1], x2 - x1, x1, y);
++		numspecs = xmakeglyphfontspecs(specs, &TLINE(y)[x1], x2 - x1, x1, y);
+ 
+ 		i = ox = 0;
+ 		for (x = x1; x < x2 && i < numspecs; x++) {
+-			new = term.line[y][x];
++			new = TLINE(y)[x];
+ 			if (new.mode == ATTR_WDUMMY)
+ 				continue;
+ 			if (ena_sel && selected(x, y))
+_AT_@ -4067,7 +4135,8 @@ drawregion(int x1, int y1, int x2, int y2)
+ 		if (i > 0)
+ 			xdrawglyphfontspecs(specs, base, i, ox, y);
+ 	}
+-	xdrawcursor();
++	if (term.scr == 0)
++		xdrawcursor();
+ }
+ 
+ void
Received on Wed Jan 04 2017 - 18:23:29 CET

This archive was generated by hypermail 2.3.0 : Wed Jan 04 2017 - 18:24:18 CET