aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.SRCINFO22
-rw-r--r--PKGBUILD49
-rw-r--r--scrollback.patch338
3 files changed, 409 insertions, 0 deletions
diff --git a/.SRCINFO b/.SRCINFO
new file mode 100644
index 0000000..00eb95c
--- /dev/null
+++ b/.SRCINFO
@@ -0,0 +1,22 @@
1pkgbase = st-git
2 pkgdesc = Simple virtual terminal emulator for X
3 pkgver = 20150603.71fa10f
4 pkgrel = 1
5 url = http://git.suckless.org/st/
6 arch = i686
7 arch = x86_64
8 arch = armv7h
9 license = MIT
10 makedepends = ncurses
11 makedepends = libxext
12 makedepends = git
13 depends = libxft
14 provides = st
15 conflicts = st
16 source = git://git.suckless.org/st
17 source = scrollback.patch
18 sha1sums = SKIP
19 sha1sums = 2e10ac47eb020d50c7f861f3923bb4152255a027
20
21pkgname = st-git
22
diff --git a/PKGBUILD b/PKGBUILD
new file mode 100644
index 0000000..ff5e10c
--- /dev/null
+++ b/PKGBUILD
@@ -0,0 +1,49 @@
1# Maintainer: Gaetan Bisson <bisson@archlinux.org>
2# Contributor: Scytrin dai Kinthra <scytrin@gmail.com>
3
4pkgname=st-git
5_pkgname=st
6pkgver=20150603.71fa10f
7pkgrel=1
8pkgdesc='Simple virtual terminal emulator for X'
9url='http://git.suckless.org/st/'
10arch=('i686' 'x86_64' 'armv7h')
11license=('MIT')
12depends=('libxft')
13makedepends=('ncurses' 'libxext' 'git')
14source=('git://git.suckless.org/st'
15 'scrollback.patch')
16sha1sums=('SKIP'
17 '2e10ac47eb020d50c7f861f3923bb4152255a027')
18
19provides=("${_pkgname}")
20conflicts=("${_pkgname}")
21
22pkgver() {
23 cd "${srcdir}/${_pkgname}"
24 git log -1 --format='%cd.%h' --date=short | tr -d -
25}
26
27prepare() {
28 cd "${srcdir}/${_pkgname}"
29 patch -p1 -i ../scrollback.patch # http://st.suckless.org/patches/st-scrollback.diff
30 sed \
31 -e '/char font/s/= .*/= "Fixed:pixelsize=13:style=SemiCondensed";/' \
32 -e '/char worddelimiters/s/= .*/= " '"'"'`\\\"()[]{}<>|";/' \
33 -e '/int defaultcs/s/= .*/= 1;/' \
34 -i config.def.h
35}
36
37build() {
38 cd "${srcdir}/${_pkgname}"
39 make X11INC=/usr/include/X11 X11LIB=/usr/lib/X11
40}
41
42package() {
43 cd "${srcdir}/${_pkgname}"
44 export TERMINFO="${pkgdir}/usr/share/terminfo"
45 install -d "$TERMINFO"
46 make PREFIX=/usr DESTDIR="${pkgdir}" install
47 install -Dm644 LICENSE "${pkgdir}/usr/share/licenses/${pkgname}/LICENSE"
48 install -Dm644 README "${pkgdir}/usr/share/doc/${pkgname}/README"
49}
diff --git a/scrollback.patch b/scrollback.patch
new file mode 100644
index 0000000..746b83b
--- /dev/null
+++ b/scrollback.patch
@@ -0,0 +1,338 @@
1diff --git a/config.def.h b/config.def.h
2index bb5596e..2df4cbc 100644
3--- a/config.def.h
4+++ b/config.def.h
5@@ -7,6 +7,7 @@
6 */
7 static char font[] = "Liberation Mono:pixelsize=12:antialias=false:autohint=false";
8 static int borderpx = 2;
9+static int histsize = 2000;
10 static char shell[] = "/bin/sh";
11 static char *utmp = NULL;
12 static char stty_args[] = "stty raw -echo -iexten echonl";
13@@ -128,6 +129,8 @@ static Shortcut shortcuts[] = {
14 { MODKEY|ShiftMask, XK_C, clipcopy, {.i = 0} },
15 { MODKEY|ShiftMask, XK_V, clippaste, {.i = 0} },
16 { MODKEY, XK_Num_Lock, numlock, {.i = 0} },
17+ { ShiftMask, XK_Page_Up, kscrollup, {.i = -1} },
18+ { ShiftMask, XK_Page_Down, kscrolldown, {.i = -1} },
19 };
20
21 /*
22diff --git a/st.c b/st.c
23index 0c6b9c3..ab56435 100644
24--- a/st.c
25+++ b/st.c
26@@ -83,6 +83,8 @@ char *argv0;
27 #define TRUERED(x) (((x) & 0xff0000) >> 8)
28 #define TRUEGREEN(x) (((x) & 0xff00))
29 #define TRUEBLUE(x) (((x) & 0xff) << 8)
30+#define TLINE(y) ((y) < term.scr ? term.hist[((y) + term.histi - term.scr \
31+ + histsize + 1) % histsize] : term.line[(y) - term.scr])
32
33
34 enum glyph_attribute {
35@@ -231,6 +233,9 @@ typedef struct {
36 int col; /* nb col */
37 Line *line; /* screen */
38 Line *alt; /* alternate screen */
39+ Line *hist; /* history buffer */
40+ int histi; /* history index */
41+ int scr; /* scroll back */
42 bool *dirty; /* dirtyness of lines */
43 XftGlyphFontSpec *specbuf; /* font spec buffer used for rendering */
44 TCursor c; /* cursor */
45@@ -324,6 +329,8 @@ typedef struct {
46 /* function definitions used in config.h */
47 static void clipcopy(const Arg *);
48 static void clippaste(const Arg *);
49+static void kscrolldown(const Arg *);
50+static void kscrollup(const Arg *);
51 static void numlock(const Arg *);
52 static void selpaste(const Arg *);
53 static void xzoom(const Arg *);
54@@ -395,8 +402,8 @@ static void tputtab(int);
55 static void tputc(Rune);
56 static void treset(void);
57 static void tresize(int, int);
58-static void tscrollup(int, int);
59-static void tscrolldown(int, int);
60+static void tscrollup(int, int, bool);
61+static void tscrolldown(int, int, bool);
62 static void tsetattr(int *, int);
63 static void tsetchar(Rune, Glyph *, int, int);
64 static void tsetscroll(int, int);
65@@ -682,10 +689,10 @@ int
66 tlinelen(int y) {
67 int i = term.col;
68
69- if(term.line[y][i - 1].mode & ATTR_WRAP)
70+ if(TLINE(y)[i - 1].mode & ATTR_WRAP)
71 return i;
72
73- while(i > 0 && term.line[y][i - 1].u == ' ')
74+ while(i > 0 && TLINE(y)[i - 1].u == ' ')
75 --i;
76
77 return i;
78@@ -744,7 +751,7 @@ selsnap(int *x, int *y, int direction) {
79 * Snap around if the word wraps around at the end or
80 * beginning of a line.
81 */
82- prevgp = &term.line[*y][*x];
83+ prevgp = &TLINE(*y)[*x];
84 prevdelim = ISDELIM(prevgp->u);
85 for(;;) {
86 newx = *x + direction;
87@@ -759,14 +766,14 @@ selsnap(int *x, int *y, int direction) {
88 yt = *y, xt = *x;
89 else
90 yt = newy, xt = newx;
91- if(!(term.line[yt][xt].mode & ATTR_WRAP))
92+ if(!(TLINE(yt)[xt].mode & ATTR_WRAP))
93 break;
94 }
95
96 if (newx >= tlinelen(newy))
97 break;
98
99- gp = &term.line[newy][newx];
100+ gp = &TLINE(newy)[newx];
101 delim = ISDELIM(gp->u);
102 if(!(gp->mode & ATTR_WDUMMY) && (delim != prevdelim
103 || (delim && gp->u != prevgp->u)))
104@@ -787,14 +794,14 @@ selsnap(int *x, int *y, int direction) {
105 *x = (direction < 0) ? 0 : term.col - 1;
106 if(direction < 0) {
107 for(; *y > 0; *y += direction) {
108- if(!(term.line[*y-1][term.col-1].mode
109+ if(!(TLINE(*y-1)[term.col-1].mode
110 & ATTR_WRAP)) {
111 break;
112 }
113 }
114 } else if(direction > 0) {
115 for(; *y < term.row-1; *y += direction) {
116- if(!(term.line[*y][term.col-1].mode
117+ if(!(TLINE(*y)[term.col-1].mode
118 & ATTR_WRAP)) {
119 break;
120 }
121@@ -953,13 +960,13 @@ getsel(void) {
122 linelen = tlinelen(y);
123
124 if(sel.type == SEL_RECTANGULAR) {
125- gp = &term.line[y][sel.nb.x];
126+ gp = &TLINE(y)[sel.nb.x];
127 lastx = sel.ne.x;
128 } else {
129- gp = &term.line[y][sel.nb.y == y ? sel.nb.x : 0];
130+ gp = &TLINE(y)[sel.nb.y == y ? sel.nb.x : 0];
131 lastx = (sel.ne.y == y) ? sel.ne.x : term.col-1;
132 }
133- last = &term.line[y][MIN(lastx, linelen-1)];
134+ last = &TLINE(y)[MIN(lastx, linelen-1)];
135 while(last >= gp && last->u == ' ')
136 --last;
137
138@@ -1362,10 +1369,16 @@ ttyread(void) {
139
140 /* keep any uncomplete utf8 char for the next call */
141 memmove(buf, ptr, buflen);
142+ if(term.scr > 0 && term.scr < histsize-1)
143+ term.scr++;
144 }
145
146 void
147 ttywrite(const char *s, size_t n) {
148+ Arg arg = (Arg){ .i = term.scr };
149+
150+ kscrolldown(&arg);
151+
152 if(xwrite(cmdfd, s, n) == -1)
153 die("write error on tty: %s\n", strerror(errno));
154 }
155@@ -1500,13 +1513,52 @@ tswapscreen(void) {
156 }
157
158 void
159-tscrolldown(int orig, int n) {
160+kscrolldown(const Arg* a) {
161+ int n = a->i;
162+
163+ if(n < 0)
164+ n = term.row + n;
165+
166+ if(n > term.scr)
167+ n = term.scr;
168+
169+ if(term.scr > 0) {
170+ term.scr -= n;
171+ selscroll(0, -n);
172+ tfulldirt();
173+ }
174+}
175+
176+void
177+kscrollup(const Arg* a) {
178+ int n = a->i;
179+
180+ if(n < 0)
181+ n = term.row + n;
182+
183+ if(term.scr <= histsize - n) {
184+ term.scr += n;
185+ selscroll(0, n);
186+ tfulldirt();
187+ }
188+}
189+
190+void
191+tscrolldown(int orig, int n, bool copyhist) {
192 int i;
193 Line temp;
194
195 LIMIT(n, 0, term.bot-orig+1);
196
197+ if(copyhist) {
198+ term.histi = (term.histi - 1 + histsize) % histsize;
199+ temp = term.hist[term.histi];
200+ term.hist[term.histi] = term.line[term.bot];
201+ term.line[term.bot] = temp;
202+ }
203+
204 tsetdirt(orig, term.bot-n);
205+
206 tclearregion(0, term.bot-n+1, term.col-1, term.bot);
207
208 for(i = term.bot; i >= orig+n; i--) {
209@@ -1519,12 +1571,19 @@ tscrolldown(int orig, int n) {
210 }
211
212 void
213-tscrollup(int orig, int n) {
214+tscrollup(int orig, int n, bool copyhist) {
215 int i;
216 Line temp;
217
218 LIMIT(n, 0, term.bot-orig+1);
219
220+ if(copyhist) {
221+ term.histi = (term.histi + 1) % histsize;
222+ temp = term.hist[term.histi];
223+ term.hist[term.histi] = term.line[orig];
224+ term.line[orig] = temp;
225+ }
226+
227 tclearregion(0, orig, term.col-1, orig+n-1);
228 tsetdirt(orig+n, term.bot);
229
230@@ -1571,7 +1630,7 @@ tnewline(int first_col) {
231 int y = term.c.y;
232
233 if(y == term.bot) {
234- tscrollup(term.top, 1);
235+ tscrollup(term.top, 1, true);
236 } else {
237 y++;
238 }
239@@ -1728,13 +1787,13 @@ tinsertblank(int n) {
240 void
241 tinsertblankline(int n) {
242 if(BETWEEN(term.c.y, term.top, term.bot))
243- tscrolldown(term.c.y, n);
244+ tscrolldown(term.c.y, n, false);
245 }
246
247 void
248 tdeleteline(int n) {
249 if(BETWEEN(term.c.y, term.top, term.bot))
250- tscrollup(term.c.y, n);
251+ tscrollup(term.c.y, n, false);
252 }
253
254 int32_t
255@@ -2163,11 +2222,11 @@ csihandle(void) {
256 break;
257 case 'S': /* SU -- Scroll <n> line up */
258 DEFAULT(csiescseq.arg[0], 1);
259- tscrollup(term.top, csiescseq.arg[0]);
260+ tscrollup(term.top, csiescseq.arg[0], false);
261 break;
262 case 'T': /* SD -- Scroll <n> line down */
263 DEFAULT(csiescseq.arg[0], 1);
264- tscrolldown(term.top, csiescseq.arg[0]);
265+ tscrolldown(term.top, csiescseq.arg[0], false);
266 break;
267 case 'L': /* IL -- Insert <n> blank lines */
268 DEFAULT(csiescseq.arg[0], 1);
269@@ -2617,7 +2676,7 @@ eschandle(uchar ascii) {
270 return 0;
271 case 'D': /* IND -- Linefeed */
272 if(term.c.y == term.bot) {
273- tscrollup(term.top, 1);
274+ tscrollup(term.top, 1, true);
275 } else {
276 tmoveto(term.c.x, term.c.y+1);
277 }
278@@ -2630,7 +2689,7 @@ eschandle(uchar ascii) {
279 break;
280 case 'M': /* RI -- Reverse index */
281 if(term.c.y == term.top) {
282- tscrolldown(term.top, 1);
283+ tscrolldown(term.top, 1, true);
284 } else {
285 tmoveto(term.c.x, term.c.y-1);
286 }
287@@ -2791,7 +2850,7 @@ tputc(Rune u) {
288
289 void
290 tresize(int col, int row) {
291- int i;
292+ int i, j;
293 int minrow = MIN(row, term.row);
294 int mincol = MIN(col, term.col);
295 bool *bp;
296@@ -2828,9 +2887,18 @@ tresize(int col, int row) {
297 /* resize to new height */
298 term.line = xrealloc(term.line, row * sizeof(Line));
299 term.alt = xrealloc(term.alt, row * sizeof(Line));
300+ term.hist = xrealloc(term.hist, histsize * sizeof(Line));
301 term.dirty = xrealloc(term.dirty, row * sizeof(*term.dirty));
302 term.tabs = xrealloc(term.tabs, col * sizeof(*term.tabs));
303
304+ for(i = 0; i < histsize; i++) {
305+ term.hist[i] = xrealloc(term.hist[i], col * sizeof(Glyph));
306+ for(j = mincol; j < col; j++) {
307+ term.hist[i][j] = term.c.attr;
308+ term.hist[i][j].u = ' ';
309+ }
310+ }
311+
312 /* resize each row to new width, zero-pad if needed */
313 for(i = 0; i < minrow; i++) {
314 term.line[i] = xrealloc(term.line[i], col * sizeof(Glyph));
315@@ -3664,11 +3732,11 @@ drawregion(int x1, int y1, int x2, int y2) {
316 term.dirty[y] = 0;
317
318 specs = term.specbuf;
319- numspecs = xmakeglyphfontspecs(specs, &term.line[y][x1], x2 - x1, x1, y);
320+ numspecs = xmakeglyphfontspecs(specs, &TLINE(y)[x1], x2 - x1, x1, y);
321
322 i = ox = 0;
323 for(x = x1; x < x2 && i < numspecs; x++) {
324- new = term.line[y][x];
325+ new = TLINE(y)[x];
326 if(new.mode == ATTR_WDUMMY)
327 continue;
328 if(ena_sel && selected(x, y))
329@@ -3688,7 +3756,8 @@ drawregion(int x1, int y1, int x2, int y2) {
330 if(i > 0)
331 xdrawglyphfontspecs(specs, base, i, ox, y);
332 }
333- xdrawcursor();
334+ if(term.scr == 0)
335+ xdrawcursor();
336 }
337
338 void