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