···2233#include "cell.h"
4455-void cells_clear(Cell *buf, int w, int h) {
55+void cells_fill(Cell *buf, int w, int h, uint32_t ch, uint32_t fg,
66+ uint32_t bg) {
67 for (int i = 0; i < w * h; i++) {
77- buf[i].ch = ' ';
88- buf[i].fg = ATTR_DEFAULT;
99- buf[i].bg = ATTR_DEFAULT;
88+ buf[i].ch = ch;
99+ buf[i].fg = fg;
1010+ buf[i].bg = bg;
1011 }
1112}
1213
+1-1
src/cell.h
···2424#define ATTR_MASK 0xFF000000
2525#define COLOR_MASK 0x00FFFFFF
26262727-void cells_clear(Cell *buf, int w, int h);
2727+void cells_fill(Cell *buf, int w, int h, uint32_t ch, uint32_t fg, uint32_t bg);
2828int cell_cmp(Cell *a, Cell *b);
29293030#endif
+21-7
src/clayterm.c
···149149 buf_char(&ct->out, ch);
150150}
151151152152-/* โโ Double-buffer diff (from termbox2 tb_present) โโโโโโโโโโโโโโโโโโ */
153153-154154-static void present(struct Clayterm *ct) {
152152+/**
153153+ * Diff back buffer against front buffer and emit only changed cells
154154+ * using absolute CUP positioning (\x1b[row;colH). Unchanged cells are
155155+ * skipped, making this efficient for subsequent frames where most of
156156+ * the screen is static. Derived from termbox2 tb_present.
157157+ */
158158+static void present_cups(struct Clayterm *ct) {
155159 ct->lastx = -1;
156160 ct->lasty = -1;
157161···191195 }
192196}
193197198198+/**
199199+ * Emit back buffer as newline-separated rows without CUP positioning.
200200+ * Every cell is written (no diffing), and the front buffer is primed
201201+ * so that a subsequent present() call can diff efficiently. This is
202202+ * used for inline "region" rendering where the caller manages cursor
203203+ * positioning externally and the output must work in pipes.
204204+ */
194205static void present_lines(struct Clayterm *ct) {
195206 for (int y = 0; y < ct->h; y++) {
196207 if (y > 0)
···416427 .lasty = -1,
417428 };
418429419419- cells_clear(ct->front, w, h);
420420- cells_clear(ct->back, w, h);
430430+ // initialize back buffer with spaces and default fg/bg
431431+ cells_fill(ct->back, w, h, ' ', ATTR_DEFAULT, ATTR_DEFAULT);
432432+433433+ // initialize front buffer with zeros. Every cell will be
434434+ cells_fill(ct->front, w, h, 0, 0, 0);
421435 return ct;
422436}
423437···551565 ct->lastfg = ct->lastbg = 0xffffffff;
552566 ct->lastx = ct->lasty = -1;
553567554554- cells_clear(ct->back, ct->w, ct->h);
568568+ cells_fill(ct->back, ct->w, ct->h, ' ', ATTR_DEFAULT, ATTR_DEFAULT);
555569556570 /* walk Clay render commands into back buffer */
557571 for (int32_t j = 0; j < cmds.length; j++) {
···590604 if (mode == 1) {
591605 present_lines(ct);
592606 } else {
593593- present(ct);
607607+ present_cups(ct);
594608 }
595609}
596610