first
[dcc-suckless-config] / based-simple-term / patches / st-scrollback-20210507-4536f46.diff
1 diff --git a/config.def.h b/config.def.h
2 index 6f05dce..93cbcc0 100644
3 --- a/config.def.h
4 +++ b/config.def.h
5 @@ -199,6 +199,8 @@ static Shortcut shortcuts[] = {
6         { TERMMOD,              XK_Y,           selpaste,       {.i =  0} },
7         { ShiftMask,            XK_Insert,      selpaste,       {.i =  0} },
8         { TERMMOD,              XK_Num_Lock,    numlock,        {.i =  0} },
9 +       { ShiftMask,            XK_Page_Up,     kscrollup,      {.i = -1} },
10 +       { ShiftMask,            XK_Page_Down,   kscrolldown,    {.i = -1} },
11  };
12  
13  /*
14 diff --git a/st.c b/st.c
15 index ebdf360..817cc47 100644
16 --- a/st.c
17 +++ b/st.c
18 @@ -35,6 +35,7 @@
19  #define ESC_ARG_SIZ   16
20  #define STR_BUF_SIZ   ESC_BUF_SIZ
21  #define STR_ARG_SIZ   ESC_ARG_SIZ
22 +#define HISTSIZE      2000
23  
24  /* macros */
25  #define IS_SET(flag)           ((term.mode & (flag)) != 0)
26 @@ -42,6 +43,9 @@
27  #define ISCONTROLC1(c)         (BETWEEN(c, 0x80, 0x9f))
28  #define ISCONTROL(c)           (ISCONTROLC0(c) || ISCONTROLC1(c))
29  #define ISDELIM(u)             (u && wcschr(worddelimiters, u))
30 +#define TLINE(y)               ((y) < term.scr ? term.hist[((y) + term.histi - \
31 +                               term.scr + HISTSIZE + 1) % HISTSIZE] : \
32 +                               term.line[(y) - term.scr])
33  
34  enum term_mode {
35         MODE_WRAP        = 1 << 0,
36 @@ -115,6 +119,9 @@ typedef struct {
37         int col;      /* nb col */
38         Line *line;   /* screen */
39         Line *alt;    /* alternate screen */
40 +       Line hist[HISTSIZE]; /* history buffer */
41 +       int histi;    /* history index */
42 +       int scr;      /* scroll back */
43         int *dirty;   /* dirtyness of lines */
44         TCursor c;    /* cursor */
45         int ocx;      /* old cursor col */
46 @@ -184,8 +191,8 @@ static void tnewline(int);
47  static void tputtab(int);
48  static void tputc(Rune);
49  static void treset(void);
50 -static void tscrollup(int, int);
51 -static void tscrolldown(int, int);
52 +static void tscrollup(int, int, int);
53 +static void tscrolldown(int, int, int);
54  static void tsetattr(const int *, int);
55  static void tsetchar(Rune, const Glyph *, int, int);
56  static void tsetdirt(int, int);
57 @@ -416,10 +423,10 @@ tlinelen(int y)
58  {
59         int i = term.col;
60  
61 -       if (term.line[y][i - 1].mode & ATTR_WRAP)
62 +       if (TLINE(y)[i - 1].mode & ATTR_WRAP)
63                 return i;
64  
65 -       while (i > 0 && term.line[y][i - 1].u == ' ')
66 +       while (i > 0 && TLINE(y)[i - 1].u == ' ')
67                 --i;
68  
69         return i;
70 @@ -528,7 +535,7 @@ selsnap(int *x, int *y, int direction)
71                  * Snap around if the word wraps around at the end or
72                  * beginning of a line.
73                  */
74 -               prevgp = &term.line[*y][*x];
75 +               prevgp = &TLINE(*y)[*x];
76                 prevdelim = ISDELIM(prevgp->u);
77                 for (;;) {
78                         newx = *x + direction;
79 @@ -543,14 +550,14 @@ selsnap(int *x, int *y, int direction)
80                                         yt = *y, xt = *x;
81                                 else
82                                         yt = newy, xt = newx;
83 -                               if (!(term.line[yt][xt].mode & ATTR_WRAP))
84 +                               if (!(TLINE(yt)[xt].mode & ATTR_WRAP))
85                                         break;
86                         }
87  
88                         if (newx >= tlinelen(newy))
89                                 break;
90  
91 -                       gp = &term.line[newy][newx];
92 +                       gp = &TLINE(newy)[newx];
93                         delim = ISDELIM(gp->u);
94                         if (!(gp->mode & ATTR_WDUMMY) && (delim != prevdelim
95                                         || (delim && gp->u != prevgp->u)))
96 @@ -571,14 +578,14 @@ selsnap(int *x, int *y, int direction)
97                 *x = (direction < 0) ? 0 : term.col - 1;
98                 if (direction < 0) {
99                         for (; *y > 0; *y += direction) {
100 -                               if (!(term.line[*y-1][term.col-1].mode
101 +                               if (!(TLINE(*y-1)[term.col-1].mode
102                                                 & ATTR_WRAP)) {
103                                         break;
104                                 }
105                         }
106                 } else if (direction > 0) {
107                         for (; *y < term.row-1; *y += direction) {
108 -                               if (!(term.line[*y][term.col-1].mode
109 +                               if (!(TLINE(*y)[term.col-1].mode
110                                                 & ATTR_WRAP)) {
111                                         break;
112                                 }
113 @@ -609,13 +616,13 @@ getsel(void)
114                 }
115  
116                 if (sel.type == SEL_RECTANGULAR) {
117 -                       gp = &term.line[y][sel.nb.x];
118 +                       gp = &TLINE(y)[sel.nb.x];
119                         lastx = sel.ne.x;
120                 } else {
121 -                       gp = &term.line[y][sel.nb.y == y ? sel.nb.x : 0];
122 +                       gp = &TLINE(y)[sel.nb.y == y ? sel.nb.x : 0];
123                         lastx = (sel.ne.y == y) ? sel.ne.x : term.col-1;
124                 }
125 -               last = &term.line[y][MIN(lastx, linelen-1)];
126 +               last = &TLINE(y)[MIN(lastx, linelen-1)];
127                 while (last >= gp && last->u == ' ')
128                         --last;
129  
130 @@ -850,6 +857,9 @@ void
131  ttywrite(const char *s, size_t n, int may_echo)
132  {
133         const char *next;
134 +       Arg arg = (Arg) { .i = term.scr };
135 +
136 +       kscrolldown(&arg);
137  
138         if (may_echo && IS_SET(MODE_ECHO))
139                 twrite(s, n, 1);
140 @@ -1061,13 +1071,53 @@ tswapscreen(void)
141  }
142  
143  void
144 -tscrolldown(int orig, int n)
145 +kscrolldown(const Arg* a)
146 +{
147 +       int n = a->i;
148 +
149 +       if (n < 0)
150 +               n = term.row + n;
151 +
152 +       if (n > term.scr)
153 +               n = term.scr;
154 +
155 +       if (term.scr > 0) {
156 +               term.scr -= n;
157 +               selscroll(0, -n);
158 +               tfulldirt();
159 +       }
160 +}
161 +
162 +void
163 +kscrollup(const Arg* a)
164 +{
165 +       int n = a->i;
166 +
167 +       if (n < 0)
168 +               n = term.row + n;
169 +
170 +       if (term.scr <= HISTSIZE-n) {
171 +               term.scr += n;
172 +               selscroll(0, n);
173 +               tfulldirt();
174 +       }
175 +}
176 +
177 +void
178 +tscrolldown(int orig, int n, int copyhist)
179  {
180         int i;
181         Line temp;
182  
183         LIMIT(n, 0, term.bot-orig+1);
184  
185 +       if (copyhist) {
186 +               term.histi = (term.histi - 1 + HISTSIZE) % HISTSIZE;
187 +               temp = term.hist[term.histi];
188 +               term.hist[term.histi] = term.line[term.bot];
189 +               term.line[term.bot] = temp;
190 +       }
191 +
192         tsetdirt(orig, term.bot-n);
193         tclearregion(0, term.bot-n+1, term.col-1, term.bot);
194  
195 @@ -1077,17 +1127,28 @@ tscrolldown(int orig, int n)
196                 term.line[i-n] = temp;
197         }
198  
199 -       selscroll(orig, n);
200 +       if (term.scr == 0)
201 +               selscroll(orig, n);
202  }
203  
204  void
205 -tscrollup(int orig, int n)
206 +tscrollup(int orig, int n, int copyhist)
207  {
208         int i;
209         Line temp;
210  
211         LIMIT(n, 0, term.bot-orig+1);
212  
213 +       if (copyhist) {
214 +               term.histi = (term.histi + 1) % HISTSIZE;
215 +               temp = term.hist[term.histi];
216 +               term.hist[term.histi] = term.line[orig];
217 +               term.line[orig] = temp;
218 +       }
219 +
220 +       if (term.scr > 0 && term.scr < HISTSIZE)
221 +               term.scr = MIN(term.scr + n, HISTSIZE-1);
222 +
223         tclearregion(0, orig, term.col-1, orig+n-1);
224         tsetdirt(orig+n, term.bot);
225  
226 @@ -1097,7 +1158,8 @@ tscrollup(int orig, int n)
227                 term.line[i+n] = temp;
228         }
229  
230 -       selscroll(orig, -n);
231 +       if (term.scr == 0)
232 +               selscroll(orig, -n);
233  }
234  
235  void
236 @@ -1126,7 +1188,7 @@ tnewline(int first_col)
237         int y = term.c.y;
238  
239         if (y == term.bot) {
240 -               tscrollup(term.top, 1);
241 +               tscrollup(term.top, 1, 1);
242         } else {
243                 y++;
244         }
245 @@ -1291,14 +1353,14 @@ void
246  tinsertblankline(int n)
247  {
248         if (BETWEEN(term.c.y, term.top, term.bot))
249 -               tscrolldown(term.c.y, n);
250 +               tscrolldown(term.c.y, n, 0);
251  }
252  
253  void
254  tdeleteline(int n)
255  {
256         if (BETWEEN(term.c.y, term.top, term.bot))
257 -               tscrollup(term.c.y, n);
258 +               tscrollup(term.c.y, n, 0);
259  }
260  
261  int32_t
262 @@ -1735,11 +1797,11 @@ csihandle(void)
263                 break;
264         case 'S': /* SU -- Scroll <n> line up */
265                 DEFAULT(csiescseq.arg[0], 1);
266 -               tscrollup(term.top, csiescseq.arg[0]);
267 +               tscrollup(term.top, csiescseq.arg[0], 0);
268                 break;
269         case 'T': /* SD -- Scroll <n> line down */
270                 DEFAULT(csiescseq.arg[0], 1);
271 -               tscrolldown(term.top, csiescseq.arg[0]);
272 +               tscrolldown(term.top, csiescseq.arg[0], 0);
273                 break;
274         case 'L': /* IL -- Insert <n> blank lines */
275                 DEFAULT(csiescseq.arg[0], 1);
276 @@ -2251,7 +2313,7 @@ eschandle(uchar ascii)
277                 return 0;
278         case 'D': /* IND -- Linefeed */
279                 if (term.c.y == term.bot) {
280 -                       tscrollup(term.top, 1);
281 +                       tscrollup(term.top, 1, 1);
282                 } else {
283                         tmoveto(term.c.x, term.c.y+1);
284                 }
285 @@ -2264,7 +2326,7 @@ eschandle(uchar ascii)
286                 break;
287         case 'M': /* RI -- Reverse index */
288                 if (term.c.y == term.top) {
289 -                       tscrolldown(term.top, 1);
290 +                       tscrolldown(term.top, 1, 1);
291                 } else {
292                         tmoveto(term.c.x, term.c.y-1);
293                 }
294 @@ -2474,7 +2536,7 @@ twrite(const char *buf, int buflen, int show_ctrl)
295  void
296  tresize(int col, int row)
297  {
298 -       int i;
299 +       int i, j;
300         int minrow = MIN(row, term.row);
301         int mincol = MIN(col, term.col);
302         int *bp;
303 @@ -2511,6 +2573,14 @@ tresize(int col, int row)
304         term.dirty = xrealloc(term.dirty, row * sizeof(*term.dirty));
305         term.tabs = xrealloc(term.tabs, col * sizeof(*term.tabs));
306  
307 +       for (i = 0; i < HISTSIZE; i++) {
308 +               term.hist[i] = xrealloc(term.hist[i], col * sizeof(Glyph));
309 +               for (j = mincol; j < col; j++) {
310 +                       term.hist[i][j] = term.c.attr;
311 +                       term.hist[i][j].u = ' ';
312 +               }
313 +       }
314 +
315         /* resize each row to new width, zero-pad if needed */
316         for (i = 0; i < minrow; i++) {
317                 term.line[i] = xrealloc(term.line[i], col * sizeof(Glyph));
318 @@ -2569,7 +2639,7 @@ drawregion(int x1, int y1, int x2, int y2)
319                         continue;
320  
321                 term.dirty[y] = 0;
322 -               xdrawline(term.line[y], x1, y, x2);
323 +               xdrawline(TLINE(y), x1, y, x2);
324         }
325  }
326  
327 @@ -2590,8 +2660,9 @@ draw(void)
328                 cx--;
329  
330         drawregion(0, 0, term.col, term.row);
331 -       xdrawcursor(cx, term.c.y, term.line[term.c.y][cx],
332 -                       term.ocx, term.ocy, term.line[term.ocy][term.ocx]);
333 +       if (term.scr == 0)
334 +               xdrawcursor(cx, term.c.y, term.line[term.c.y][cx],
335 +                               term.ocx, term.ocy, term.line[term.ocy][term.ocx]);
336         term.ocx = cx;
337         term.ocy = term.c.y;
338         xfinishdraw();
339 diff --git a/st.h b/st.h
340 index fa2eddf..adda2db 100644
341 --- a/st.h
342 +++ b/st.h
343 @@ -81,6 +81,8 @@ void die(const char *, ...);
344  void redraw(void);
345  void draw(void);
346  
347 +void kscrolldown(const Arg *);
348 +void kscrollup(const Arg *);
349  void printscreen(const Arg *);
350  void printsel(const Arg *);
351  void sendbreak(const Arg *);