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
+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+