commit 8955d95

uint  ·  2026-05-14 09:11:43 +0000 UTC
parent c430e3a
only draw damaged runes
3 files changed,  +107, -16
+51, -10
  1@@ -1,9 +1,11 @@
  2 #define RGFW_IMPLEMENTATION
  3 #include <errno.h>
  4 #include <fcntl.h>
  5+#include <stdbool.h>
  6 #include <stdint.h>
  7 #include <stdlib.h>
  8 #include <sys/ioctl.h>
  9+#include <time.h>
 10 #ifdef __linux__
 11 #include <pty.h>
 12 #else
 13@@ -25,7 +27,7 @@
 14 static void cleanup(void);
 15 static void handle_key(RGFW_event ev);
 16 static void init(void);
 17-static void ptyread(void);
 18+static bool ptyread(void);
 19 static void ptywrite(const char* s, size_t n);
 20 static void resize_pty(void);
 21 static int resize_surface(int w, int h);
 22@@ -159,9 +161,10 @@ static void init(void)
 23 /**
 24  * @brief read data from master pty
 25  */
 26-static void ptyread(void)
 27+static bool ptyread(void)
 28 {
 29 	char buf[4096];
 30+	bool damaged = false;
 31 
 32 	for (;;) {
 33 		ssize_t n = read(term.ptyfd, buf, sizeof(buf));
 34@@ -170,13 +173,16 @@ static void ptyread(void)
 35 		if (n < 0 && (errno == EAGAIN || errno == EWOULDBLOCK))
 36 			break;
 37 		if (n > 0) {
 38-			term_write(&term, &car, buf, n);
 39+			if (term_write(&term, &car, buf, n))
 40+				damaged = true;
 41 			continue;
 42 		}
 43 
 44 		/* EOF or other error */
 45 		break;
 46 	}
 47+
 48+	return damaged;
 49 }
 50 
 51 /**
 52@@ -279,6 +285,9 @@ static void resize_terminal(int w, int h)
 53 static void run(void)
 54 {
 55 	RGFW_event ev;
 56+	Caret ocar = { -1, -1 };
 57+	bool dirty = true;
 58+	bool redraw_all = true;
 59 
 60 	while (!RGFW_window_shouldClose(win)) {
 61 		while (RGFW_window_checkEvent(win, &ev)) {
 62@@ -286,33 +295,61 @@ static void run(void)
 63 				if (resize_surface(ev.update.w, ev.update.h) < 0)
 64 					die(EXIT_FAILURE, "failed to resize surface");
 65 				resize_terminal(ev.update.w, ev.update.h);
 66+				term_damage_all(&term);
 67+				dirty = true;
 68+				continue;
 69+			}
 70+
 71+			if (ev.type == RGFW_windowRefresh ||
 72+			    ev.type == RGFW_windowFocusIn ||
 73+			    ev.type == RGFW_windowRestored) {
 74+				term_damage_all(&term);
 75+				dirty = true;
 76+				redraw_all = true;
 77 				continue;
 78 			}
 79 
 80 			handle_key(ev);
 81 		}
 82 
 83-		ptyread();
 84+		if (ptyread())
 85+			dirty = true;
 86+
 87+		if (ocar.x != car.x || ocar.y != car.y) {
 88+			term_damage_rune(&term, ocar.x, ocar.y);
 89+			term_damage_rune(&term, car.x, car.y);
 90+			dirty = true;
 91+		}
 92+
 93+		if (!dirty)
 94+			continue;
 95+
 96+		if (redraw_all)
 97+			draw_clear(pixels, winw, winh, rgba(0, 0, 0, 255));
 98 
 99-		/* drawing */
100-		draw_clear(pixels, winw, winh, rgba(0, 0, 0, 255));
101 		for (int y = 0; y < term.rows; y++) {
102 			for (int x = 0; x < term.cols; x++) {
103-				Rune* rune  = &RUNE(&term, x, y);
104+				Rune* r = &RUNE(&term, x, y);
105+
106+				if (!r->dmg)
107+					continue;
108 
109 				draw_rune(
110 					pixels, winw, winh, x, y,
111-					font.cellw, font.cellh, rune->bg
112+					font.cellw, font.cellh, r->bg
113 				);
114 
115-				if (rune->cp != ' ') {
116+				if (r->cp != ' ') {
117 					draw_codepoint(
118 						&font, pixels, winw, winh,
119 						x * font.cellw,
120 						y * font.cellh + (int)font.asc,
121-						rune->cp, rune->fg
122+						r->cp,
123+						r->fg
124 					);
125 				}
126+
127+				r->dmg = false;
128 			}
129 		}
130 
131@@ -324,6 +361,10 @@ static void run(void)
132 		);
133 
134 		RGFW_window_blitSurface(win, surf);
135+
136+		ocar = car;
137+		dirty = false;
138+		redraw_all = false;
139 	}
140 }
141 
+12, -1
 1@@ -52,6 +52,15 @@ typedef struct {
 2  */
 3 void term_clear(Term* t, Caret* c);
 4 
 5+/**
 6+ * @brief damage all the runes on terminal
 7+ */
 8+void term_damage_all(Term* t);
 9+
10+/** @brief damage a single cell on terminal
11+ */
12+void term_damage_rune(Term* t, int x, int y);
13+
14 /**
15  * @brief handle placing special and normal characters
16  *
17@@ -79,8 +88,10 @@ void term_scroll(Term* t);
18  * @param c cursor instance
19  * @param s string buffer to write
20  * @param n length of string buffer
21+ * 
22+ * @return whether it has been damaged
23  */
24-void term_write(Term* t, Caret* c, const char* s, size_t n);
25+bool term_write(Term* t, Caret* c, const char* s, size_t n);
26 
27 #endif /* TERM_H */
28 
+44, -5
 1@@ -212,6 +212,21 @@ void term_clear(Term* t, Caret* c)
 2 	c->y = 0;
 3 }
 4 
 5+void term_damage_all(Term* t)
 6+{
 7+	for (int y = 0; y < t->rows; y++) {
 8+		for (int x = 0; x < t->cols; x++)
 9+			RUNE(t, x, y).dmg = true;
10+	}
11+}
12+
13+void term_damage_rune(Term* t, int x, int y)
14+{
15+	if (x < 0 || y < 0 || x >= t->cols || y >= t->rows)
16+		return;
17+	RUNE(t, x, y).dmg = true;
18+}
19+
20 void term_putc(Term* t, Caret* c, uint32_t cp)
21 {
22 	switch (cp) {
23@@ -240,10 +255,13 @@ void term_putc(Term* t, Caret* c, uint32_t cp)
24 		if (cp < 32)
25 			break;
26 
27-		RUNE(t, c->x, c->y).cp = cp;
28-		RUNE(t, c->x, c->y).fg = t->fg;
29-		RUNE(t, c->x, c->y).bg = t->bg;
30-		RUNE(t, c->x, c->y).dmg = true;
31+		Rune* r = &RUNE(t, c->x, c->y);
32+		if (r->cp != cp || r->fg != t->fg || r->bg != t->bg) {
33+			r->cp = cp;
34+			r->fg = t->fg;
35+			r->bg = t->bg;
36+			r->dmg = true;
37+		}
38 		c->x++;
39 		if (c->x >= t->cols)
40 			term_putc(t, c, '\n');
41@@ -291,6 +309,11 @@ int term_resize(Term* t, Caret* c, int cols, int rows)
42 		}
43 	}
44 
45+	for (int y = 0; y < rows; y++) {
46+		for (int x = 0; x < cols; x++)
47+			nr[y * cols + x].dmg = true;
48+	}
49+
50 	free(or);
51 
52 	t->runes = nr;
53@@ -317,6 +340,7 @@ void term_scroll(Term* t)
54 
55 	/* TODO: inefficient */
56 	memmove(runes, runes + cols, sizeof(Rune)*cols * (rows - 1));
57+	term_damage_all(t);
58 
59 	for (int x = 0; x < t->cols; x++) {
60 		Rune* rune = &RUNE(t, x, t->rows - 1);
61@@ -327,10 +351,13 @@ void term_scroll(Term* t)
62 	}
63 }
64 
65-void term_write(Term* t, Caret* c, const char* s, size_t n)
66+bool term_write(Term* t, Caret* c, const char* s, size_t n)
67 {
68+	bool damaged = false;
69+
70 	for (size_t i = 0; i < n; i++) {
71 		unsigned char ch = (unsigned char)s[i];
72+		Caret old = *c;
73 
74 		switch (t->state) {
75 		case TSTATE_NORMAL:
76@@ -370,6 +397,18 @@ void term_write(Term* t, Caret* c, const char* s, size_t n)
77 			}
78 			break;
79 		}
80+
81+		if (old.x != c->x || old.y != c->y)
82+			damaged = true;
83+	}
84+
85+	for (int y = 0; y < t->rows; y++) {
86+		for (int x = 0; x < t->cols; x++) {
87+			if (RUNE(t, x, y).dmg)
88+				return true;
89+		}
90 	}
91+
92+	return damaged;
93 }
94