commit cursetree

This commit is contained in:
Emile Clark-Boman 2025-09-27 20:46:05 +10:00
parent 7f4f9941de
commit 9b0e752b8a
8 changed files with 95 additions and 37 deletions

47
flake.nix Normal file
View file

@ -0,0 +1,47 @@
{
description = "devshell-cursetree";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.05";
};
outputs = inputs @ {
self,
nixpkgs,
}: let
defaultSystems = ["aarch64-darwin" "aarch64-linux" "i686-linux" "x86_64-darwin" "x86_64-linux"];
forAllSystems = f:
nixpkgs.lib.genAttrs defaultSystems (system:
f system (import nixpkgs {
inherit system;
overlays = builtins.attrValues self.overlays;
}));
in {
overlays.default = final: prev: {};
devShells = forAllSystems (
system: pkgs: let
lib = pkgs.lib;
in {
default = pkgs.mkShell {
packages = with pkgs; [
gnumake
gcc
# Language/Development Tooling
clang-tools
bear # clang compile_commands.json
valgrind
];
};
}
);
checks = self.packages;
packages = forAllSystems (system: pkgs: rec {
default = cursetree;
cursetree = pkgs.cursetree;
});
};
}

View file

@ -1,7 +1,15 @@
#ifndef _CURSETREE__SHARED_H #ifndef _CURSETREE__SHARED_H
#define _CURSETREE__SHARED_H #define _CURSETREE__SHARED_H
/* Standard success/failure status codes. */
#define OK (0) #define OK (0)
#define ERR (1) #define ERR (1)
/* Initial row and column coordinates. */
#define ROW0 1
#define COL0 1
typedef unsigned short pos;
typedef unsigned char glyph;
#endif /* _CURSETREE__SHARED_H */ #endif /* _CURSETREE__SHARED_H */

6
src/ansi.h Normal file
View file

@ -0,0 +1,6 @@
#ifndef CURSETREE_ANSI_H
#define CURSETREE_ANSI_H
#endif /* CURSETREE_ANSI_H */

View file

@ -6,22 +6,19 @@
#include "term.h" #include "term.h"
int main(void) { int main(void) {
struct ct_term *const term = (struct ct_term *)malloc(sizeof(struct ct_term)); struct ct_term *const term;
if (getterm(term)) { int retv = OK;
perror("getterm");
endterm(term); if (stashterm(&term)) {
exit(1); perror("saveterm");
exit(ERR);
} }
if (termsize(term)) { if (termsize(term)) {
perror("termsize"); perror("termsize");
endterm(term); retv = ERR;
exit(1); goto end;
} }
printf("\e[2J\e[1;1H");
char *line = (char *)malloc(sizeof(char) * (term->cols + 1)); char *line = (char *)malloc(sizeof(char) * (term->cols + 1));
memset(line, 'X', term->cols); memset(line, 'X', term->cols);
line[term->cols] = '\0'; line[term->cols] = '\0';
@ -29,8 +26,10 @@ int main(void) {
for (int i=0; i < term->rows; i++) { for (int i=0; i < term->rows; i++) {
printf("%s", line); printf("%s", line);
} }
printf("\n");
sleep(3); sleep(3);
endterm(term); end:
resetterm(term);
return 0; return 0;
} }

View file

@ -4,23 +4,23 @@
#include "_ct_shared.h" #include "_ct_shared.h"
#include "surface.h" #include "surface.h"
#define ALLOC_ROW(w) ((char *)calloc(w, sizeof(char))) #define ALLOC_COLS(w) ((glyph *)calloc(w, sizeof(glyph)))
/* Allocates a new 2D surface buffer with ROWS=h, COLS=w. /* Allocates a new 2D surface buffer with ROWS=h, COLS=w.
* Returns NULL on failure and sets errno, otherwise * Returns NULL on failure and sets errno, otherwise
* a pointer to the new buffer is returned. * a pointer to the new buffer is returned.
*/ */
static inline __attribute__((malloc, warn_unused_result)) char ** static inline __attribute__((malloc, warn_unused_result)) glyph **
sfbuf(const pos w, const pos h) { sfbuf(const pos w, const pos h) {
char **buf; glyph **buf;
pos i; pos i;
buf = (char **)malloc(sizeof(char *) * h); buf = (glyph **)malloc(sizeof(glyph *) * h);
if (buf == NULL) if (buf == NULL)
return buf; return buf;
for (i = 0; i < w; i++) { for (i = 0; i < w; i++) {
buf[i] = ALLOC_ROW(w); buf[i] = ALLOC_COLS(w);
if (buf[i] == NULL) if (buf[i] == NULL)
goto fail; goto fail;
} }
@ -43,7 +43,7 @@ fail:
static inline int sfsetw(const pos w1, surface *const s) { static inline int sfsetw(const pos w1, surface *const s) {
void *ptr; void *ptr;
pos i, w0 = s->w; pos i, w0 = s->w;
char **row; glyph **row;
errno = 0; // sanity check errno = 0; // sanity check
@ -54,11 +54,11 @@ static inline int sfsetw(const pos w1, surface *const s) {
} }
for (i = 0, row = s->buf; i < s->h; i++, row++) { for (i = 0, row = s->buf; i < s->h; i++, row++) {
ptr = (void *)reallocarray(*row, w1, sizeof(char)); ptr = (void *)reallocarray(*row, w1, sizeof(glyph));
if (ptr == NULL) { if (ptr == NULL) {
return errno; return errno;
} }
*row = (char *)ptr; *row = (glyph *)ptr;
} }
s->w = w1; s->w = w1;
@ -73,7 +73,7 @@ static inline int sfsetw(const pos w1, surface *const s) {
static inline int sfseth(const pos h1, surface *const s) { static inline int sfseth(const pos h1, surface *const s) {
void *ptr; void *ptr;
pos i, h0 = s->h; pos i, h0 = s->h;
char **row; glyph **row;
errno = 0; // sanity check errno = 0; // sanity check
@ -91,18 +91,18 @@ static inline int sfseth(const pos h1, surface *const s) {
} }
// use ptr to avoid losing unfreed s->buf // use ptr to avoid losing unfreed s->buf
ptr = (void *)reallocarray(s->buf, h1, sizeof(char)); ptr = (void *)reallocarray(s->buf, h1, sizeof(glyph));
if (ptr == NULL) if (ptr == NULL)
return errno; return errno;
// ENOMEM X_X // ENOMEM X_X
s->buf = (char **)ptr; s->buf = (glyph **)ptr;
s->h = h1; s->h = h1;
// height increased (alloc bottom rows) // height increased (alloc bottom rows)
if (h1 > h0) { if (h1 > h0) {
for (i = h0, row = s->buf; i < h1; i++, row++) { for (i = h0, row = s->buf; i < h1; i++, row++) {
*row = ALLOC_ROW(s->w); *row = ALLOC_COLS(s->w);
if (*row == NULL) if (*row == NULL)
return errno; return errno;
} }
@ -135,7 +135,7 @@ int sfresize(const pos w1, const pos h1, surface *const s) {
__attribute__((malloc, warn_unused_result)) surface *sfalloc(const pos x, const pos y, const pos w, const pos h) { __attribute__((malloc, warn_unused_result)) surface *sfalloc(const pos x, const pos y, const pos w, const pos h) {
surface *s; surface *s;
char **buf = sfbuf(w, h); glyph **buf = sfbuf(w, h);
if (buf == NULL) if (buf == NULL)
return NULL; return NULL;
@ -155,7 +155,7 @@ __attribute__((malloc, warn_unused_result)) surface *sfalloc(const pos x, const
void sffree(surface *const s) { void sffree(surface *const s) {
pos i; pos i;
char **row; glyph **row;
for (i=0, row=s->buf; i < s->h; i++, row++) { for (i=0, row=s->buf; i < s->h; i++, row++) {
free(*row); free(*row);
} }

View file

@ -1,15 +1,11 @@
#ifndef _CURSETREE_SURFACE_H #ifndef _CURSETREE_SURFACE_H
#define _CURSETREE_SURFACE_H #define _CURSETREE_SURFACE_H
/* Initial row and column coordinates */ #include "_ct_shared.h"
#define ROW0 1
#define COL0 1
typedef unsigned short pos;
typedef struct ct_surface { typedef struct ct_surface {
pos x, y, w, h; pos x, y, w, h;
char **buf; glyph **buf;
pos vcx, vcy; /* virtual cursor position */ pos vcx, vcy; /* virtual cursor position */
} surface; } surface;

View file

@ -6,7 +6,7 @@
#include "_ct_shared.h" #include "_ct_shared.h"
#include "term.h" #include "term.h"
int stashterm(const struct ct_term **const term) { int stashterm(struct ct_term **const term) {
struct ct_term *t = (struct ct_term *)malloc(sizeof(struct ct_term)); struct ct_term *t = (struct ct_term *)malloc(sizeof(struct ct_term));
t->fd = open("/dev/tty", O_RDONLY); t->fd = open("/dev/tty", O_RDONLY);

View file

@ -1,18 +1,20 @@
#ifndef _CURSETREE_TERM_H #ifndef _CURSETREE_TERM_H
#define _CURSETREE_TERM_H #define _CURSETREE_TERM_H
#include "termios.h" #include <termios.h>
#include "_ct_shared.h"
struct ct_term { struct ct_term {
int fd; int fd;
unsigned short cols; pos cols;
unsigned short rows; pos rows;
struct termios termios0; struct termios termios0;
struct termios termios; struct termios termios;
}; };
int stashterm(const struct ct_term **const term); int stashterm(struct ct_term **const term);
void resetterm(struct ct_term *const term); void resetterm(struct ct_term *const term);
int termsize(struct ct_term *const term); int termsize(struct ct_term *const term);