st_c.diff 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676
  1. diff --git a/st.c b/st.c
  2. index b9f66e7..d9b163e 100644
  3. --- a/st.c
  4. +++ b/st.c
  5. @@ -43,6 +43,10 @@
  6. #define ISCONTROL(c) (ISCONTROLC0(c) || ISCONTROLC1(c))
  7. #define ISDELIM(u) (u && wcschr(worddelimiters, u))
  8. +#define TSCREEN term.screen[IS_SET(MODE_ALTSCREEN)]
  9. +#define TLINEOFFSET(y) (((y) + TSCREEN.cur - TSCREEN.off + TSCREEN.size) % TSCREEN.size)
  10. +#define TLINE(y) (TSCREEN.buffer[TLINEOFFSET(y)])
  11. +
  12. enum term_mode {
  13. MODE_WRAP = 1 << 0,
  14. MODE_INSERT = 1 << 1,
  15. @@ -109,12 +113,21 @@ typedef struct {
  16. int alt;
  17. } Selection;
  18. +/* Screen lines */
  19. +typedef struct {
  20. + Line* buffer; /* ring buffer */
  21. + int size; /* size of buffer */
  22. + int cur; /* start of active screen */
  23. + int off; /* scrollback line offset */
  24. + TCursor sc; /* saved cursor */
  25. +} LineBuffer;
  26. +
  27. /* Internal representation of the screen */
  28. typedef struct {
  29. int row; /* nb row */
  30. int col; /* nb col */
  31. - Line *line; /* screen */
  32. - Line *alt; /* alternate screen */
  33. + LineBuffer screen[2]; /* screen and alternate screen */
  34. + int linelen; /* allocated line length */
  35. int *dirty; /* dirtyness of lines */
  36. TCursor c; /* cursor */
  37. int ocx; /* old cursor col */
  38. @@ -203,6 +216,8 @@ static void tdeftran(char);
  39. static void tstrsequence(uchar);
  40. static void drawregion(int, int, int, int);
  41. +static void clearline(Line, Glyph, int, int);
  42. +static Line ensureline(Line);
  43. static void selnormalize(void);
  44. static void selscroll(int, int);
  45. @@ -408,11 +423,12 @@ int
  46. tlinelen(int y)
  47. {
  48. int i = term.col;
  49. + Line line = TLINE(y);
  50. - if (term.line[y][i - 1].mode & ATTR_WRAP)
  51. + if (line[i - 1].mode & ATTR_WRAP)
  52. return i;
  53. - while (i > 0 && term.line[y][i - 1].u == ' ')
  54. + while (i > 0 && line[i - 1].u == ' ')
  55. --i;
  56. return i;
  57. @@ -521,7 +537,7 @@ selsnap(int *x, int *y, int direction)
  58. * Snap around if the word wraps around at the end or
  59. * beginning of a line.
  60. */
  61. - prevgp = &term.line[*y][*x];
  62. + prevgp = &TLINE(*y)[*x];
  63. prevdelim = ISDELIM(prevgp->u);
  64. for (;;) {
  65. newx = *x + direction;
  66. @@ -536,14 +552,14 @@ selsnap(int *x, int *y, int direction)
  67. yt = *y, xt = *x;
  68. else
  69. yt = newy, xt = newx;
  70. - if (!(term.line[yt][xt].mode & ATTR_WRAP))
  71. + if (!(TLINE(yt)[xt].mode & ATTR_WRAP))
  72. break;
  73. }
  74. if (newx >= tlinelen(newy))
  75. break;
  76. - gp = &term.line[newy][newx];
  77. + gp = &TLINE(newy)[newx];
  78. delim = ISDELIM(gp->u);
  79. if (!(gp->mode & ATTR_WDUMMY) && (delim != prevdelim
  80. || (delim && gp->u != prevgp->u)))
  81. @@ -564,14 +580,14 @@ selsnap(int *x, int *y, int direction)
  82. *x = (direction < 0) ? 0 : term.col - 1;
  83. if (direction < 0) {
  84. for (; *y > 0; *y += direction) {
  85. - if (!(term.line[*y-1][term.col-1].mode
  86. + if (!(TLINE(*y-1)[term.col-1].mode
  87. & ATTR_WRAP)) {
  88. break;
  89. }
  90. }
  91. } else if (direction > 0) {
  92. for (; *y < term.row-1; *y += direction) {
  93. - if (!(term.line[*y][term.col-1].mode
  94. + if (!(TLINE(*y)[term.col-1].mode
  95. & ATTR_WRAP)) {
  96. break;
  97. }
  98. @@ -602,13 +618,13 @@ getsel(void)
  99. }
  100. if (sel.type == SEL_RECTANGULAR) {
  101. - gp = &term.line[y][sel.nb.x];
  102. + gp = &TLINE(y)[sel.nb.x];
  103. lastx = sel.ne.x;
  104. } else {
  105. - gp = &term.line[y][sel.nb.y == y ? sel.nb.x : 0];
  106. + gp = &TLINE(y)[sel.nb.y == y ? sel.nb.x : 0];
  107. lastx = (sel.ne.y == y) ? sel.ne.x : term.col-1;
  108. }
  109. - last = &term.line[y][MIN(lastx, linelen-1)];
  110. + last = &TLINE(y)[MIN(lastx, linelen-1)];
  111. while (last >= gp && last->u == ' ')
  112. --last;
  113. @@ -949,12 +965,15 @@ int
  114. tattrset(int attr)
  115. {
  116. int i, j;
  117. + int y = TLINEOFFSET(0);
  118. for (i = 0; i < term.row-1; i++) {
  119. + Line line = TSCREEN.buffer[y];
  120. for (j = 0; j < term.col-1; j++) {
  121. - if (term.line[i][j].mode & attr)
  122. + if (line[j].mode & attr)
  123. return 1;
  124. }
  125. + y = (y+1) % TSCREEN.size;
  126. }
  127. return 0;
  128. @@ -976,14 +995,17 @@ void
  129. tsetdirtattr(int attr)
  130. {
  131. int i, j;
  132. + int y = TLINEOFFSET(0);
  133. for (i = 0; i < term.row-1; i++) {
  134. + Line line = TSCREEN.buffer[y];
  135. for (j = 0; j < term.col-1; j++) {
  136. - if (term.line[i][j].mode & attr) {
  137. + if (line[j].mode & attr) {
  138. tsetdirt(i, i);
  139. break;
  140. }
  141. }
  142. + y = (y+1) % TSCREEN.size;
  143. }
  144. }
  145. @@ -996,27 +1018,19 @@ tfulldirt(void)
  146. void
  147. tcursor(int mode)
  148. {
  149. - static TCursor c[2];
  150. - int alt = IS_SET(MODE_ALTSCREEN);
  151. -
  152. if (mode == CURSOR_SAVE) {
  153. - c[alt] = term.c;
  154. + TSCREEN.sc = term.c;
  155. } else if (mode == CURSOR_LOAD) {
  156. - term.c = c[alt];
  157. - tmoveto(c[alt].x, c[alt].y);
  158. + term.c = TSCREEN.sc;
  159. + tmoveto(term.c.x, term.c.y);
  160. }
  161. }
  162. void
  163. treset(void)
  164. {
  165. - uint i;
  166. -
  167. - term.c = (TCursor){{
  168. - .mode = ATTR_NULL,
  169. - .fg = defaultfg,
  170. - .bg = defaultbg
  171. - }, .x = 0, .y = 0, .state = CURSOR_DEFAULT};
  172. + int i, j;
  173. + Glyph g = (Glyph){ .fg = defaultfg, .bg = defaultbg};
  174. memset(term.tabs, 0, term.col * sizeof(*term.tabs));
  175. for (i = tabspaces; i < term.col; i += tabspaces)
  176. @@ -1028,17 +1042,37 @@ treset(void)
  177. term.charset = 0;
  178. for (i = 0; i < 2; i++) {
  179. - tmoveto(0, 0);
  180. - tcursor(CURSOR_SAVE);
  181. - tclearregion(0, 0, term.col-1, term.row-1);
  182. - tswapscreen();
  183. + term.screen[i].sc = (TCursor){{
  184. + .fg = defaultfg,
  185. + .bg = defaultbg
  186. + }};
  187. + term.screen[i].cur = 0;
  188. + term.screen[i].off = 0;
  189. + for (j = 0; j < term.row; ++j) {
  190. + if (term.col != term.linelen)
  191. + term.screen[i].buffer[j] = xrealloc(term.screen[i].buffer[j], term.col * sizeof(Glyph));
  192. + clearline(term.screen[i].buffer[j], g, 0, term.col);
  193. + }
  194. + for (j = term.row; j < term.screen[i].size; ++j) {
  195. + free(term.screen[i].buffer[j]);
  196. + term.screen[i].buffer[j] = NULL;
  197. + }
  198. }
  199. + tcursor(CURSOR_LOAD);
  200. + term.linelen = term.col;
  201. + tfulldirt();
  202. }
  203. void
  204. tnew(int col, int row)
  205. {
  206. - term = (Term){ .c = { .attr = { .fg = defaultfg, .bg = defaultbg } } };
  207. + int i;
  208. + term = (Term){};
  209. + term.screen[0].buffer = xmalloc(HISTSIZE * sizeof(Line));
  210. + term.screen[0].size = HISTSIZE;
  211. + term.screen[1].buffer = NULL;
  212. + for (i = 0; i < HISTSIZE; ++i) term.screen[0].buffer[i] = NULL;
  213. +
  214. tresize(col, row);
  215. treset();
  216. }
  217. @@ -1046,14 +1080,42 @@ tnew(int col, int row)
  218. void
  219. tswapscreen(void)
  220. {
  221. - Line *tmp = term.line;
  222. -
  223. - term.line = term.alt;
  224. - term.alt = tmp;
  225. term.mode ^= MODE_ALTSCREEN;
  226. tfulldirt();
  227. }
  228. +void
  229. +kscrollup(const Arg *a)
  230. +{
  231. + int n = a->i;
  232. +
  233. + if (IS_SET(MODE_ALTSCREEN))
  234. + return;
  235. +
  236. + if (n < 0) n = (-n) * term.row;
  237. + if (n > TSCREEN.size - term.row - TSCREEN.off) n = TSCREEN.size - term.row - TSCREEN.off;
  238. + while (!TLINE(-n)) --n;
  239. + TSCREEN.off += n;
  240. + selscroll(0, n);
  241. + tfulldirt();
  242. +}
  243. +
  244. +void
  245. +kscrolldown(const Arg *a)
  246. +{
  247. +
  248. + int n = a->i;
  249. +
  250. + if (IS_SET(MODE_ALTSCREEN))
  251. + return;
  252. +
  253. + if (n < 0) n = (-n) * term.row;
  254. + if (n > TSCREEN.off) n = TSCREEN.off;
  255. + TSCREEN.off -= n;
  256. + selscroll(0, -n);
  257. + tfulldirt();
  258. +}
  259. +
  260. void
  261. tscrolldown(int orig, int n)
  262. {
  263. @@ -1062,15 +1124,29 @@ tscrolldown(int orig, int n)
  264. LIMIT(n, 0, term.bot-orig+1);
  265. - tsetdirt(orig, term.bot-n);
  266. - tclearregion(0, term.bot-n+1, term.col-1, term.bot);
  267. + /* Ensure that lines are allocated */
  268. + for (i = -n; i < 0; i++) {
  269. + TLINE(i) = ensureline(TLINE(i));
  270. + }
  271. - for (i = term.bot; i >= orig+n; i--) {
  272. - temp = term.line[i];
  273. - term.line[i] = term.line[i-n];
  274. - term.line[i-n] = temp;
  275. + /* Shift non-scrolling areas in ring buffer */
  276. + for (i = term.bot+1; i < term.row; i++) {
  277. + temp = TLINE(i);
  278. + TLINE(i) = TLINE(i-n);
  279. + TLINE(i-n) = temp;
  280. + }
  281. + for (i = 0; i < orig; i++) {
  282. + temp = TLINE(i);
  283. + TLINE(i) = TLINE(i-n);
  284. + TLINE(i-n) = temp;
  285. }
  286. + /* Scroll buffer */
  287. + TSCREEN.cur = (TSCREEN.cur + TSCREEN.size - n) % TSCREEN.size;
  288. + /* Clear lines that have entered the view */
  289. + tclearregion(0, orig, term.linelen-1, orig+n-1);
  290. + /* Redraw portion of the screen that has scrolled */
  291. + tsetdirt(orig+n-1, term.bot);
  292. selscroll(orig, n);
  293. }
  294. @@ -1082,15 +1158,29 @@ tscrollup(int orig, int n)
  295. LIMIT(n, 0, term.bot-orig+1);
  296. - tclearregion(0, orig, term.col-1, orig+n-1);
  297. - tsetdirt(orig+n, term.bot);
  298. + /* Ensure that lines are allocated */
  299. + for (i = term.row; i < term.row + n; i++) {
  300. + TLINE(i) = ensureline(TLINE(i));
  301. + }
  302. - for (i = orig; i <= term.bot-n; i++) {
  303. - temp = term.line[i];
  304. - term.line[i] = term.line[i+n];
  305. - term.line[i+n] = temp;
  306. + /* Shift non-scrolling areas in ring buffer */
  307. + for (i = orig-1; i >= 0; i--) {
  308. + temp = TLINE(i);
  309. + TLINE(i) = TLINE(i+n);
  310. + TLINE(i+n) = temp;
  311. + }
  312. + for (i = term.row-1; i >term.bot; i--) {
  313. + temp = TLINE(i);
  314. + TLINE(i) = TLINE(i+n);
  315. + TLINE(i+n) = temp;
  316. }
  317. + /* Scroll buffer */
  318. + TSCREEN.cur = (TSCREEN.cur + n) % TSCREEN.size;
  319. + /* Clear lines that have entered the view */
  320. + tclearregion(0, term.bot-n+1, term.linelen-1, term.bot);
  321. + /* Redraw portion of the screen that has scrolled */
  322. + tsetdirt(orig, term.bot-n+1);
  323. selscroll(orig, -n);
  324. }
  325. @@ -1194,6 +1284,7 @@ tsetchar(Rune u, const Glyph *attr, int x, int y)
  326. "⎻", "─", "⎼", "⎽", "├", "┤", "┴", "┬", /* p - w */
  327. "│", "≤", "≥", "π", "≠", "£", "·", /* x - ~ */
  328. };
  329. + Line line = TLINE(y);
  330. /*
  331. * The table is proudly stolen from rxvt.
  332. @@ -1202,25 +1293,25 @@ tsetchar(Rune u, const Glyph *attr, int x, int y)
  333. BETWEEN(u, 0x41, 0x7e) && vt100_0[u - 0x41])
  334. utf8decode(vt100_0[u - 0x41], &u, UTF_SIZ);
  335. - if (term.line[y][x].mode & ATTR_WIDE) {
  336. + if (line[x].mode & ATTR_WIDE) {
  337. if (x+1 < term.col) {
  338. - term.line[y][x+1].u = ' ';
  339. - term.line[y][x+1].mode &= ~ATTR_WDUMMY;
  340. + line[x+1].u = ' ';
  341. + line[x+1].mode &= ~ATTR_WDUMMY;
  342. }
  343. - } else if (term.line[y][x].mode & ATTR_WDUMMY) {
  344. - term.line[y][x-1].u = ' ';
  345. - term.line[y][x-1].mode &= ~ATTR_WIDE;
  346. + } else if (line[x].mode & ATTR_WDUMMY) {
  347. + line[x-1].u = ' ';
  348. + line[x-1].mode &= ~ATTR_WIDE;
  349. }
  350. term.dirty[y] = 1;
  351. - term.line[y][x] = *attr;
  352. - term.line[y][x].u = u;
  353. + line[x] = *attr;
  354. + line[x].u = u;
  355. }
  356. void
  357. tclearregion(int x1, int y1, int x2, int y2)
  358. {
  359. - int x, y, temp;
  360. + int x, y, L, S, temp;
  361. Glyph *gp;
  362. if (x1 > x2)
  363. @@ -1228,15 +1319,16 @@ tclearregion(int x1, int y1, int x2, int y2)
  364. if (y1 > y2)
  365. temp = y1, y1 = y2, y2 = temp;
  366. - LIMIT(x1, 0, term.col-1);
  367. - LIMIT(x2, 0, term.col-1);
  368. + LIMIT(x1, 0, term.linelen-1);
  369. + LIMIT(x2, 0, term.linelen-1);
  370. LIMIT(y1, 0, term.row-1);
  371. LIMIT(y2, 0, term.row-1);
  372. + L = TLINEOFFSET(y1);
  373. for (y = y1; y <= y2; y++) {
  374. term.dirty[y] = 1;
  375. for (x = x1; x <= x2; x++) {
  376. - gp = &term.line[y][x];
  377. + gp = &TSCREEN.buffer[L][x];
  378. if (selected(x, y))
  379. selclear();
  380. gp->fg = term.c.attr.fg;
  381. @@ -1244,6 +1336,7 @@ tclearregion(int x1, int y1, int x2, int y2)
  382. gp->mode = 0;
  383. gp->u = ' ';
  384. }
  385. + L = (L + 1) % TSCREEN.size;
  386. }
  387. }
  388. @@ -1258,7 +1351,7 @@ tdeletechar(int n)
  389. dst = term.c.x;
  390. src = term.c.x + n;
  391. size = term.col - src;
  392. - line = term.line[term.c.y];
  393. + line = TLINE(term.c.y);
  394. memmove(&line[dst], &line[src], size * sizeof(Glyph));
  395. tclearregion(term.col-n, term.c.y, term.col-1, term.c.y);
  396. @@ -1275,7 +1368,7 @@ tinsertblank(int n)
  397. dst = term.c.x + n;
  398. src = term.c.x;
  399. size = term.col - dst;
  400. - line = term.line[term.c.y];
  401. + line = TLINE(term.c.y);
  402. memmove(&line[dst], &line[src], size * sizeof(Glyph));
  403. tclearregion(src, term.c.y, dst - 1, term.c.y);
  404. @@ -2079,7 +2172,7 @@ tdumpline(int n)
  405. char buf[UTF_SIZ];
  406. const Glyph *bp, *end;
  407. - bp = &term.line[n][0];
  408. + bp = &TLINE(n)[0];
  409. end = &bp[MIN(tlinelen(n), term.col) - 1];
  410. if (bp != end || bp->u != ' ') {
  411. for ( ; bp <= end; ++bp)
  412. @@ -2466,11 +2559,11 @@ check_control_code:
  413. if (selected(term.c.x, term.c.y))
  414. selclear();
  415. - gp = &term.line[term.c.y][term.c.x];
  416. + gp = &TLINE(term.c.y)[term.c.x];
  417. if (IS_SET(MODE_WRAP) && (term.c.state & CURSOR_WRAPNEXT)) {
  418. gp->mode |= ATTR_WRAP;
  419. tnewline(1);
  420. - gp = &term.line[term.c.y][term.c.x];
  421. + gp = &TLINE(term.c.y)[term.c.x];
  422. }
  423. if (IS_SET(MODE_INSERT) && term.c.x+width < term.col) {
  424. @@ -2483,7 +2576,7 @@ check_control_code:
  425. tnewline(1);
  426. else
  427. tmoveto(term.col - width, term.c.y);
  428. - gp = &term.line[term.c.y][term.c.x];
  429. + gp = &TLINE(term.c.y)[term.c.x];
  430. }
  431. tsetchar(u, &term.c.attr, term.c.x, term.c.y);
  432. @@ -2514,6 +2607,11 @@ twrite(const char *buf, int buflen, int show_ctrl)
  433. Rune u;
  434. int n;
  435. + if (TSCREEN.off) {
  436. + TSCREEN.off = 0;
  437. + tfulldirt();
  438. + }
  439. +
  440. for (n = 0; n < buflen; n += charsize) {
  441. if (IS_SET(MODE_UTF8)) {
  442. /* process a complete utf8 char */
  443. @@ -2540,56 +2638,85 @@ twrite(const char *buf, int buflen, int show_ctrl)
  444. }
  445. void
  446. -tresize(int col, int row)
  447. +clearline(Line line, Glyph g, int x, int xend)
  448. {
  449. int i;
  450. + g.mode = 0;
  451. + g.u = ' ';
  452. + for (i = x; i < xend; ++i) {
  453. + line[i] = g;
  454. + }
  455. +}
  456. +
  457. +Line
  458. +ensureline(Line line)
  459. +{
  460. + if (!line) {
  461. + line = xmalloc(term.linelen * sizeof(Glyph));
  462. + }
  463. + return line;
  464. +}
  465. +
  466. +void
  467. +tresize(int col, int row)
  468. +{
  469. + int i, j;
  470. int minrow = MIN(row, term.row);
  471. int mincol = MIN(col, term.col);
  472. + int linelen = MAX(col, term.linelen);
  473. int *bp;
  474. - TCursor c;
  475. - if (col < 1 || row < 1) {
  476. + if (col < 1 || row < 1 || row > HISTSIZE) {
  477. fprintf(stderr,
  478. "tresize: error resizing to %dx%d\n", col, row);
  479. return;
  480. }
  481. - /*
  482. - * slide screen to keep cursor where we expect it -
  483. - * tscrollup would work here, but we can optimize to
  484. - * memmove because we're freeing the earlier lines
  485. - */
  486. - for (i = 0; i <= term.c.y - row; i++) {
  487. - free(term.line[i]);
  488. - free(term.alt[i]);
  489. + /* Shift buffer to keep the cursor where we expect it */
  490. + if (row <= term.c.y) {
  491. + term.screen[0].cur = (term.screen[0].cur - row + term.c.y + 1) % term.screen[0].size;
  492. + }
  493. +
  494. + /* Resize and clear line buffers as needed */
  495. + if (linelen > term.linelen) {
  496. + for (i = 0; i < term.screen[0].size; ++i) {
  497. + if (term.screen[0].buffer[i]) {
  498. + term.screen[0].buffer[i] = xrealloc(term.screen[0].buffer[i], linelen * sizeof(Glyph));
  499. + clearline(term.screen[0].buffer[i], term.c.attr, term.linelen, linelen);
  500. + }
  501. + }
  502. + for (i = 0; i < minrow; ++i) {
  503. + term.screen[1].buffer[i] = xrealloc(term.screen[1].buffer[i], linelen * sizeof(Glyph));
  504. + clearline(term.screen[1].buffer[i], term.c.attr, term.linelen, linelen);
  505. + }
  506. }
  507. - /* ensure that both src and dst are not NULL */
  508. - if (i > 0) {
  509. - memmove(term.line, term.line + i, row * sizeof(Line));
  510. - memmove(term.alt, term.alt + i, row * sizeof(Line));
  511. + /* Allocate all visible lines for regular line buffer */
  512. + for (j = term.screen[0].cur, i = 0; i < row; ++i, j = (j + 1) % term.screen[0].size)
  513. + {
  514. + if (!term.screen[0].buffer[j]) {
  515. + term.screen[0].buffer[j] = xmalloc(linelen * sizeof(Glyph));
  516. + }
  517. + if (i >= term.row) {
  518. + clearline(term.screen[0].buffer[j], term.c.attr, 0, linelen);
  519. + }
  520. }
  521. - for (i += row; i < term.row; i++) {
  522. - free(term.line[i]);
  523. - free(term.alt[i]);
  524. + /* Resize alt screen */
  525. + term.screen[1].cur = 0;
  526. + term.screen[1].size = row;
  527. + for (i = row; i < term.row; ++i) {
  528. + free(term.screen[1].buffer[i]);
  529. + }
  530. + term.screen[1].buffer = xrealloc(term.screen[1].buffer, row * sizeof(Line));
  531. + for (i = term.row; i < row; ++i) {
  532. + term.screen[1].buffer[i] = xmalloc(linelen * sizeof(Glyph));
  533. + clearline(term.screen[1].buffer[i], term.c.attr, 0, linelen);
  534. }
  535. /* resize to new height */
  536. - term.line = xrealloc(term.line, row * sizeof(Line));
  537. - term.alt = xrealloc(term.alt, row * sizeof(Line));
  538. term.dirty = xrealloc(term.dirty, row * sizeof(*term.dirty));
  539. term.tabs = xrealloc(term.tabs, col * sizeof(*term.tabs));
  540. - /* resize each row to new width, zero-pad if needed */
  541. - for (i = 0; i < minrow; i++) {
  542. - term.line[i] = xrealloc(term.line[i], col * sizeof(Glyph));
  543. - term.alt[i] = xrealloc(term.alt[i], col * sizeof(Glyph));
  544. - }
  545. -
  546. - /* allocate any new rows */
  547. - for (/* i = minrow */; i < row; i++) {
  548. - term.line[i] = xmalloc(col * sizeof(Glyph));
  549. - term.alt[i] = xmalloc(col * sizeof(Glyph));
  550. - }
  551. + /* fix tabstops */
  552. if (col > term.col) {
  553. bp = term.tabs + term.col;
  554. @@ -2599,26 +2726,16 @@ tresize(int col, int row)
  555. for (bp += tabspaces; bp < term.tabs + col; bp += tabspaces)
  556. *bp = 1;
  557. }
  558. +
  559. /* update terminal size */
  560. term.col = col;
  561. term.row = row;
  562. + term.linelen = linelen;
  563. /* reset scrolling region */
  564. tsetscroll(0, row-1);
  565. /* make use of the LIMIT in tmoveto */
  566. tmoveto(term.c.x, term.c.y);
  567. - /* Clearing both screens (it makes dirty all lines) */
  568. - c = term.c;
  569. - for (i = 0; i < 2; i++) {
  570. - if (mincol < col && 0 < minrow) {
  571. - tclearregion(mincol, 0, col - 1, minrow - 1);
  572. - }
  573. - if (0 < col && minrow < row) {
  574. - tclearregion(0, minrow, col - 1, row - 1);
  575. - }
  576. - tswapscreen();
  577. - tcursor(CURSOR_LOAD);
  578. - }
  579. - term.c = c;
  580. + tfulldirt();
  581. }
  582. void
  583. @@ -2630,14 +2747,15 @@ resettitle(void)
  584. void
  585. drawregion(int x1, int y1, int x2, int y2)
  586. {
  587. - int y;
  588. + int y, L;
  589. + L = TLINEOFFSET(y1);
  590. for (y = y1; y < y2; y++) {
  591. - if (!term.dirty[y])
  592. - continue;
  593. -
  594. - term.dirty[y] = 0;
  595. - xdrawline(term.line[y], x1, y, x2);
  596. + if (term.dirty[y]) {
  597. + term.dirty[y] = 0;
  598. + xdrawline(TSCREEN.buffer[L], x1, y, x2);
  599. + }
  600. + L = (L + 1) % TSCREEN.size;
  601. }
  602. }
  603. @@ -2652,14 +2770,15 @@ draw(void)
  604. /* adjust cursor position */
  605. LIMIT(term.ocx, 0, term.col-1);
  606. LIMIT(term.ocy, 0, term.row-1);
  607. - if (term.line[term.ocy][term.ocx].mode & ATTR_WDUMMY)
  608. + if (TLINE(term.ocy)[term.ocx].mode & ATTR_WDUMMY)
  609. term.ocx--;
  610. - if (term.line[term.c.y][cx].mode & ATTR_WDUMMY)
  611. + if (TLINE(term.c.y)[cx].mode & ATTR_WDUMMY)
  612. cx--;
  613. drawregion(0, 0, term.col, term.row);
  614. - xdrawcursor(cx, term.c.y, term.line[term.c.y][cx],
  615. - term.ocx, term.ocy, term.line[term.ocy][term.ocx]);
  616. + if (TSCREEN.off == 0)
  617. + xdrawcursor(cx, term.c.y, TLINE(term.c.y)[cx],
  618. + term.ocx, term.ocy, TLINE(term.ocy)[term.ocx]);
  619. term.ocx = cx;
  620. term.ocy = term.c.y;
  621. xfinishdraw();