commit 8af9efb
uint
·
2026-05-11 15:50:26 +0000 UTC
parent 55e3c7e
add scrolling, proper cells array, placing characters NOTE: `Cell` is already a struct in macOS carbon framework for some reason so i need a new name for it >:( `Font` also seems to be taken by X11 which is also annoying
4 files changed,
+190,
-24
M
Makefile
+1,
-0
1@@ -6,6 +6,7 @@ LDFLAGS = -lschrift -lgrapheme -framework Cocoa -framework CoreVideo -framework
2 SRCS = source/cterm.c \
3 source/util.c \
4 source/font.c \
5+ source/term.c \
6 source/draw.c
7 OUT = cterm
8
+53,
-24
1@@ -8,15 +8,30 @@
2
3 #include "draw.h"
4 #include "font.h"
5+#include "term.h"
6 #include "util.h"
7
8 #define WIDTH 800
9 #define HEIGHT 600
10
11-Font font;
12-RGFW_window* win = NULL;
13-RGFW_surface* surf = NULL;
14-uint32_t* pixels = NULL;
15+#define COLS 80
16+#define ROWS 24
17+
18+static Font font;
19+static Cursor cur;
20+static RGFW_window* win = NULL;
21+static RGFW_surface* surf = NULL;
22+static uint32_t* pixels = NULL;
23+
24+static struct Cell termcells[COLS*ROWS];
25+static Term term = {
26+ .cells = termcells,
27+ .cols = COLS,
28+ .rows = ROWS,
29+ .ptyfd = -1, /* TODO: pty */
30+ .fg = 0xffffffff,
31+ .bg = 0xff222222,
32+};
33
34 static void cleanup(void);
35 static void init(void);
36@@ -58,9 +73,17 @@ static void init(void)
37
38 /* font */
39 /* TODO: paths */
40- if (font_load(&font, "/System/Library/Fonts/Supplemental/Andale Mono.ttf", 48.0) < 0)
41+ if (font_load(&font, "/System/Library/Fonts/Supplemental/Andale Mono.ttf", 24.0) < 0)
42 die(1, "failed to load font");
43 font.aa = false;
44+
45+ /* tmp */
46+ term_clear(&term, &cur);
47+ const char* s =
48+ "cterm test\n"
49+ "terminal buffer!";
50+ for (const char* p = s; *p; p++)
51+ term_putc(&term, &cur, (unsigned char)*p);
52 }
53
54 /**
55@@ -74,25 +97,31 @@ static void run(void)
56 while (RGFW_window_checkEvent(win, &ev))
57 ;
58
59- draw_clear(pixels, WIDTH, HEIGHT, rgba(0, 0, 0, 255)); /* TODO: opacity */
60-
61- draw_cell(pixels, WIDTH, HEIGHT, 0, 0, font.cellw, font.cellh, rgba(255, 0, 0, 255));
62- draw_cell(pixels, WIDTH, HEIGHT, 1, 0, font.cellw, font.cellh, rgba(0, 255, 0, 255));
63- draw_cell(pixels, WIDTH, HEIGHT, 2, 0, font.cellw, font.cellh, rgba(0, 0, 255, 255));
64- draw_cursor(pixels, WIDTH, HEIGHT, 3, 0, font.cellw, font.cellh, rgba(255, 255, 255, 255));
65-
66- /* text */
67- draw_codepoint(&font, pixels, WIDTH, HEIGHT,
68- 0 * font.cellw, (int)font.asc, 'r', rgba(0, 0, 0, 255));
69-
70- draw_codepoint(&font, pixels, WIDTH, HEIGHT,
71- 1 * font.cellw, (int)font.asc, 'g', rgba(0, 0, 0, 255));
72-
73- draw_codepoint(&font, pixels, WIDTH, HEIGHT,
74- 2 * font.cellw, (int)font.asc, 'b', rgba(0, 0, 0, 255));
75-
76- draw_codepoint(&font, pixels, WIDTH, HEIGHT,
77- 3 * font.cellw, (int)font.asc, 'c', rgba(0, 0, 0, 255));
78+ draw_clear(pixels, WIDTH, HEIGHT, rgba(0, 0, 0, 255));
79+
80+ for (int y = 0; y < term.rows; y++) {
81+ for (int x = 0; x < term.cols; x++) {
82+ struct Cell* cell = &CELL(&term, x, y);
83+
84+ draw_cell(pixels, WIDTH, HEIGHT,
85+ x, y,
86+ font.cellw, font.cellh,
87+ cell->bg);
88+
89+ if (cell->cp != ' ') {
90+ draw_codepoint(&font, pixels, WIDTH, HEIGHT,
91+ x * font.cellw,
92+ y * font.cellh + (int)font.asc,
93+ cell->cp,
94+ cell->fg);
95+ }
96+ }
97+ }
98+
99+ draw_cursor(pixels, WIDTH, HEIGHT,
100+ cur.x, cur.y,
101+ font.cellw, font.cellh,
102+ rgba(255, 255, 255, 255));
103
104 RGFW_window_blitSurface(win, surf);
105 }
+57,
-0
1@@ -0,0 +1,57 @@
2+#ifndef TERM_H
3+#define TERM_H
4+
5+#include <stdbool.h>
6+#include <stdint.h>
7+
8+/* resolve 1D cell from 2D input */
9+#define CELL(t, x, y) ((t)->cells[(y) * (t)->cols + (x)])
10+
11+struct Cell {
12+ uint32_t cp; /* codepoint */
13+ uint32_t fg;
14+ uint32_t bg;
15+ bool dmg; /* cell damaged */
16+};
17+
18+typedef struct {
19+ int x;
20+ int y;
21+} Cursor;
22+
23+typedef struct {
24+ struct Cell* cells;
25+ uint32_t fg;
26+ uint32_t bg;
27+ int cols;
28+ int rows;
29+ int ptyfd;
30+} Term;
31+
32+/**
33+ * @brief clear screen by filling cells with ' ' and reseting
34+ * to default terminal foreground and background
35+ *
36+ * @param t terminal instance to scroll
37+ * @param c cursor instance to position
38+ */
39+void term_clear(Term* t, Cursor* c);
40+
41+/**
42+ * @brief handle placing special and normal characters
43+ *
44+ * @param t terminal instance
45+ * @param c cursor instance
46+ * @param cp codepoint to place
47+ */
48+void term_putc(Term* t, Cursor* c, uint32_t cp);
49+
50+/**
51+ * @brief scroll viewport down by one
52+ *
53+ * @param t terminal instance to scroll
54+ */
55+void term_scroll(Term* t);
56+
57+#endif /* TERM_H */
58+
+79,
-0
1@@ -0,0 +1,79 @@
2+#include <stdbool.h>
3+#include <string.h>
4+
5+#include "term.h"
6+
7+void term_clear(Term* t, Cursor* c)
8+{
9+ for (int y = 0; y < t->rows; y++) {
10+ for (int x = 0; x < t->cols; x++) {
11+ struct Cell* cell = &CELL(t, x, y);
12+ cell->cp = ' ';
13+ cell->fg = t->fg;
14+ cell->bg = t->bg;
15+ cell->dmg = true;
16+ }
17+ }
18+
19+ c->x = 0;
20+ c->y = 0;
21+}
22+
23+void term_putc(Term* t, Cursor* c, uint32_t cp)
24+{
25+ switch (cp) {
26+ case '\r':
27+ c->x = 0;
28+ break;
29+ case '\n':
30+ c->x = 0;
31+ if (++c->y >= t->rows) {
32+ term_scroll(t);
33+ /* move to bottom */
34+ c->y = t->rows - 1;
35+ }
36+ break;
37+ case '\b':
38+ if (c->x > 0)
39+ c->x--;
40+ break;
41+ case '\t':
42+ /* move cursor to next tabstop */
43+ c->x = (c->x+8) & ~0x7;
44+ if (c->x >= t->cols)
45+ term_putc(t, c, '\n');
46+ break;
47+ default:
48+ if (cp < 32)
49+ break;
50+
51+ CELL(t, c->x, c->y).cp = cp;
52+ CELL(t, c->x, c->y).fg = t->fg;
53+ CELL(t, c->x, c->y).bg = t->bg;
54+ CELL(t, c->x, c->y).dmg = true;
55+ c->x++;
56+ if (c->x >= t->cols)
57+ term_putc(t, c, '\n');
58+
59+ break;
60+ }
61+}
62+
63+void term_scroll(Term* t)
64+{
65+ struct Cell* cells = t->cells;
66+ int cols = t->cols;
67+ int rows = t->rows;
68+
69+ /* TODO: inefficient */
70+ memmove(cells, cells + cols, sizeof(struct Cell)*cols * (rows - 1));
71+
72+ for (int x = 0; x < t->cols; x++) {
73+ struct Cell* cell = &CELL(t, x, t->rows - 1);
74+ cell->cp = ' ';
75+ cell->fg = t->fg;
76+ cell->bg = t->bg;
77+ cell->dmg = true;
78+ }
79+}
80+