sites

public wiki contents of suckless.org
git clone git://git.suckless.org/sites
Log | Files | Refs

st-scrollback-0.7.diff (10362B)


      1 diff --git a/config.def.h b/config.def.h
      2 index b41747f..eae969e 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=true:autohint=true";
      8  static int borderpx = 2;
      9 +#define histsize 2000
     10  
     11  /*
     12   * What program is execed by st depends of these precedence rules:
     13 @@ -172,6 +173,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  /*
     22 diff --git a/st.c b/st.c
     23 index 2594c65..233d301 100644
     24 --- a/st.c
     25 +++ b/st.c
     26 @@ -86,6 +86,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 @@ -228,26 +230,6 @@ typedef struct {
     36  	int narg;              /* nb of args */
     37  } STREscape;
     38  
     39 -/* Internal representation of the screen */
     40 -typedef struct {
     41 -	int row;      /* nb row */
     42 -	int col;      /* nb col */
     43 -	Line *line;   /* screen */
     44 -	Line *alt;    /* alternate screen */
     45 -	int *dirty;  /* dirtyness of lines */
     46 -	XftGlyphFontSpec *specbuf; /* font spec buffer used for rendering */
     47 -	TCursor c;    /* cursor */
     48 -	int top;      /* top    scroll limit */
     49 -	int bot;      /* bottom scroll limit */
     50 -	int mode;     /* terminal mode flags */
     51 -	int esc;      /* escape state flags */
     52 -	char trantbl[4]; /* charset table translation */
     53 -	int charset;  /* current charset */
     54 -	int icharset; /* selected charset for sequence */
     55 -	int numlock; /* lock numbers in keyboard */
     56 -	int *tabs;
     57 -} Term;
     58 -
     59  /* Purely graphic info */
     60  typedef struct {
     61  	Display *dpy;
     62 @@ -327,6 +309,8 @@ typedef struct {
     63  /* function definitions used in config.h */
     64  static void clipcopy(const Arg *);
     65  static void clippaste(const Arg *);
     66 +static void kscrolldown(const Arg *);
     67 +static void kscrollup(const Arg *);
     68  static void numlock(const Arg *);
     69  static void selpaste(const Arg *);
     70  static void xzoom(const Arg *);
     71 @@ -340,6 +324,29 @@ static void sendbreak(const Arg *);
     72  /* Config.h for applying patches and the configuration. */
     73  #include "config.h"
     74  
     75 +/* Internal representation of the screen */
     76 +typedef struct {
     77 +	int row;      /* nb row */
     78 +	int col;      /* nb col */
     79 +	Line *line;   /* screen */
     80 +	Line *alt;    /* alternate screen */
     81 +	Line hist[histsize]; /* history buffer */
     82 +	int histi;    /* history index */
     83 +	int scr;      /* scroll back */
     84 +	int *dirty;  /* dirtyness of lines */
     85 +	XftGlyphFontSpec *specbuf; /* font spec buffer used for rendering */
     86 +	TCursor c;    /* cursor */
     87 +	int top;      /* top    scroll limit */
     88 +	int bot;      /* bottom scroll limit */
     89 +	int mode;     /* terminal mode flags */
     90 +	int esc;      /* escape state flags */
     91 +	char trantbl[4]; /* charset table translation */
     92 +	int charset;  /* current charset */
     93 +	int icharset; /* selected charset for sequence */
     94 +	int numlock; /* lock numbers in keyboard */
     95 +	int *tabs;
     96 +} Term;
     97 +
     98  /* Font structure */
     99  typedef struct {
    100  	int height;
    101 @@ -399,8 +406,8 @@ static void tputtab(int);
    102  static void tputc(Rune);
    103  static void treset(void);
    104  static void tresize(int, int);
    105 -static void tscrollup(int, int);
    106 -static void tscrolldown(int, int);
    107 +static void tscrollup(int, int, int);
    108 +static void tscrolldown(int, int, int);
    109  static void tsetattr(int *, int);
    110  static void tsetchar(Rune, Glyph *, int, int);
    111  static void tsetscroll(int, int);
    112 @@ -731,10 +738,10 @@ tlinelen(int y)
    113  {
    114  	int i = term.col;
    115  
    116 -	if (term.line[y][i - 1].mode & ATTR_WRAP)
    117 +	if (TLINE(y)[i - 1].mode & ATTR_WRAP)
    118  		return i;
    119  
    120 -	while (i > 0 && term.line[y][i - 1].u == ' ')
    121 +	while (i > 0 && TLINE(y)[i - 1].u == ' ')
    122  		--i;
    123  
    124  	return i;
    125 @@ -796,7 +803,7 @@ selsnap(int *x, int *y, int direction)
    126  		 * Snap around if the word wraps around at the end or
    127  		 * beginning of a line.
    128  		 */
    129 -		prevgp = &term.line[*y][*x];
    130 +		prevgp = &TLINE(*y)[*x];
    131  		prevdelim = ISDELIM(prevgp->u);
    132  		for (;;) {
    133  			newx = *x + direction;
    134 @@ -811,14 +818,14 @@ selsnap(int *x, int *y, int direction)
    135  					yt = *y, xt = *x;
    136  				else
    137  					yt = newy, xt = newx;
    138 -				if (!(term.line[yt][xt].mode & ATTR_WRAP))
    139 +				if (!(TLINE(yt)[xt].mode & ATTR_WRAP))
    140  					break;
    141  			}
    142  
    143  			if (newx >= tlinelen(newy))
    144  				break;
    145  
    146 -			gp = &term.line[newy][newx];
    147 +			gp = &TLINE(newy)[newx];
    148  			delim = ISDELIM(gp->u);
    149  			if (!(gp->mode & ATTR_WDUMMY) && (delim != prevdelim
    150  					|| (delim && gp->u != prevgp->u)))
    151 @@ -839,14 +846,14 @@ selsnap(int *x, int *y, int direction)
    152  		*x = (direction < 0) ? 0 : term.col - 1;
    153  		if (direction < 0) {
    154  			for (; *y > 0; *y += direction) {
    155 -				if (!(term.line[*y-1][term.col-1].mode
    156 +				if (!(TLINE(*y-1)[term.col-1].mode
    157  						& ATTR_WRAP)) {
    158  					break;
    159  				}
    160  			}
    161  		} else if (direction > 0) {
    162  			for (; *y < term.row-1; *y += direction) {
    163 -				if (!(term.line[*y][term.col-1].mode
    164 +				if (!(TLINE(*y)[term.col-1].mode
    165  						& ATTR_WRAP)) {
    166  					break;
    167  				}
    168 @@ -1012,13 +1019,13 @@ getsel(void)
    169  		}
    170  
    171  		if (sel.type == SEL_RECTANGULAR) {
    172 -			gp = &term.line[y][sel.nb.x];
    173 +			gp = &TLINE(y)[sel.nb.x];
    174  			lastx = sel.ne.x;
    175  		} else {
    176 -			gp = &term.line[y][sel.nb.y == y ? sel.nb.x : 0];
    177 +			gp = &TLINE(y)[sel.nb.y == y ? sel.nb.x : 0];
    178  			lastx = (sel.ne.y == y) ? sel.ne.x : term.col-1;
    179  		}
    180 -		last = &term.line[y][MIN(lastx, linelen-1)];
    181 +		last = &TLINE(y)[MIN(lastx, linelen-1)];
    182  		while (last >= gp && last->u == ' ')
    183  			--last;
    184  
    185 @@ -1490,6 +1497,9 @@ ttyread(void)
    186  	/* keep any uncomplete utf8 char for the next call */
    187  	memmove(buf, ptr, buflen);
    188  
    189 +	if (term.scr > 0 && term.scr < histsize-1)
    190 +		term.scr++;
    191 +
    192  	return ret;
    193  }
    194  
    195 @@ -1499,6 +1509,9 @@ ttywrite(const char *s, size_t n)
    196  	fd_set wfd, rfd;
    197  	ssize_t r;
    198  	size_t lim = 256;
    199 +	Arg arg = (Arg){ .i = term.scr };
    200 +
    201 +	kscrolldown(&arg);
    202  
    203  	/*
    204  	 * Remember that we are using a pty, which might be a modem line.
    205 @@ -1690,13 +1703,53 @@ tswapscreen(void)
    206  }
    207  
    208  void
    209 -tscrolldown(int orig, int n)
    210 +kscrolldown(const Arg* a)
    211 +{
    212 +	int n = a->i;
    213 +
    214 +	if (n < 0)
    215 +		n = term.row + n;
    216 +
    217 +	if (n > term.scr)
    218 +		n = term.scr;
    219 +
    220 +	if (term.scr > 0) {
    221 +		term.scr -= n;
    222 +		selscroll(0, -n);
    223 +		tfulldirt();
    224 +	}
    225 +}
    226 +
    227 +void
    228 +kscrollup(const Arg* a)
    229 +{
    230 +	int n = a->i;
    231 +
    232 +	if (n < 0)
    233 +		n = term.row + n;
    234 +
    235 +	if (term.scr <= histsize - n) {
    236 +		term.scr += n;
    237 +		selscroll(0, n);
    238 +		tfulldirt();
    239 +	}
    240 +}
    241 +
    242 +void
    243 +tscrolldown(int orig, int n, int copyhist)
    244  {
    245  	int i;
    246  	Line temp;
    247  
    248  	LIMIT(n, 0, term.bot-orig+1);
    249  
    250 +	if (copyhist) {
    251 +		term.histi = (term.histi - 1 + histsize) % histsize;
    252 +		temp = term.hist[term.histi];
    253 +		term.hist[term.histi] = term.line[term.bot];
    254 +		term.line[term.bot] = temp;
    255 +	}
    256 +
    257  	tsetdirt(orig, term.bot-n);
    258  	tclearregion(0, term.bot-n+1, term.col-1, term.bot);
    259  
    260 @@ -1710,13 +1763,20 @@ tscrolldown(int orig, int n)
    261  }
    262  
    263  void
    264 -tscrollup(int orig, int n)
    265 +tscrollup(int orig, int n, int copyhist)
    266  {
    267  	int i;
    268  	Line temp;
    269  
    270  	LIMIT(n, 0, term.bot-orig+1);
    271  
    272 +	if (copyhist) {
    273 +		term.histi = (term.histi + 1) % histsize;
    274 +		temp = term.hist[term.histi];
    275 +		term.hist[term.histi] = term.line[orig];
    276 +		term.line[orig] = temp;
    277 +	}
    278 +
    279  	tclearregion(0, orig, term.col-1, orig+n-1);
    280  	tsetdirt(orig+n, term.bot);
    281  
    282 @@ -1765,7 +1825,7 @@ tnewline(int first_col)
    283  	int y = term.c.y;
    284  
    285  	if (y == term.bot) {
    286 -		tscrollup(term.top, 1);
    287 +		tscrollup(term.top, 1, 1);
    288  	} else {
    289  		y++;
    290  	}
    291 @@ -1930,14 +1990,14 @@ void
    292  tinsertblankline(int n)
    293  {
    294  	if (BETWEEN(term.c.y, term.top, term.bot))
    295 -		tscrolldown(term.c.y, n);
    296 +		tscrolldown(term.c.y, n, 0);
    297  }
    298  
    299  void
    300  tdeleteline(int n)
    301  {
    302  	if (BETWEEN(term.c.y, term.top, term.bot))
    303 -		tscrollup(term.c.y, n);
    304 +		tscrollup(term.c.y, n, 0);
    305  }
    306  
    307  int32_t
    308 @@ -2371,11 +2431,11 @@ csihandle(void)
    309  		break;
    310  	case 'S': /* SU -- Scroll <n> line up */
    311  		DEFAULT(csiescseq.arg[0], 1);
    312 -		tscrollup(term.top, csiescseq.arg[0]);
    313 +		tscrollup(term.top, csiescseq.arg[0], 0);
    314  		break;
    315  	case 'T': /* SD -- Scroll <n> line down */
    316  		DEFAULT(csiescseq.arg[0], 1);
    317 -		tscrolldown(term.top, csiescseq.arg[0]);
    318 +		tscrolldown(term.top, csiescseq.arg[0], 0);
    319  		break;
    320  	case 'L': /* IL -- Insert <n> blank lines */
    321  		DEFAULT(csiescseq.arg[0], 1);
    322 @@ -2871,7 +2931,7 @@ eschandle(uchar ascii)
    323  		return 0;
    324  	case 'D': /* IND -- Linefeed */
    325  		if (term.c.y == term.bot) {
    326 -			tscrollup(term.top, 1);
    327 +			tscrollup(term.top, 1, 1);
    328  		} else {
    329  			tmoveto(term.c.x, term.c.y+1);
    330  		}
    331 @@ -2884,7 +2944,7 @@ eschandle(uchar ascii)
    332  		break;
    333  	case 'M': /* RI -- Reverse index */
    334  		if (term.c.y == term.top) {
    335 -			tscrolldown(term.top, 1);
    336 +			tscrolldown(term.top, 1, 1);
    337  		} else {
    338  			tmoveto(term.c.x, term.c.y-1);
    339  		}
    340 @@ -3047,7 +3107,7 @@ tputc(Rune u)
    341  void
    342  tresize(int col, int row)
    343  {
    344 -	int i;
    345 +	int i, j;
    346  	int minrow = MIN(row, term.row);
    347  	int mincol = MIN(col, term.col);
    348  	int *bp;
    349 @@ -3087,6 +3147,14 @@ tresize(int col, int row)
    350  	term.dirty = xrealloc(term.dirty, row * sizeof(*term.dirty));
    351  	term.tabs = xrealloc(term.tabs, col * sizeof(*term.tabs));
    352  
    353 +	for (i = 0; i < histsize; i++) {
    354 +		term.hist[i] = xrealloc(term.hist[i], col * sizeof(Glyph));
    355 +		for (j = mincol; j < col; j++) {
    356 +			term.hist[i][j] = term.c.attr;
    357 +			term.hist[i][j].u = ' ';
    358 +		}
    359 +	}
    360 +
    361  	/* resize each row to new width, zero-pad if needed */
    362  	for (i = 0; i < minrow; i++) {
    363  		term.line[i] = xrealloc(term.line[i], col * sizeof(Glyph));
    364 @@ -3976,11 +4044,11 @@ drawregion(int x1, int y1, int x2, int y2)
    365  		term.dirty[y] = 0;
    366  
    367  		specs = term.specbuf;
    368 -		numspecs = xmakeglyphfontspecs(specs, &term.line[y][x1], x2 - x1, x1, y);
    369 +		numspecs = xmakeglyphfontspecs(specs, &TLINE(y)[x1], x2 - x1, x1, y);
    370  
    371  		i = ox = 0;
    372  		for (x = x1; x < x2 && i < numspecs; x++) {
    373 -			new = term.line[y][x];
    374 +			new = TLINE(y)[x];
    375  			if (new.mode == ATTR_WDUMMY)
    376  				continue;
    377  			if (ena_sel && selected(x, y))
    378 @@ -4000,7 +4068,8 @@ drawregion(int x1, int y1, int x2, int y2)
    379  		if (i > 0)
    380  			xdrawglyphfontspecs(specs, base, i, ox, y);
    381  	}
    382 -	xdrawcursor();
    383 +	if (term.scr == 0)
    384 +		xdrawcursor();
    385  }
    386  
    387  void