summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorZach Potter <zspotting@gmail.com>2023-08-25 05:33:57 +0000
committerZach Potter <zspotting@gmail.com>2023-08-25 05:33:57 +0000
commit7590f4424917e34c01caac722bd97ac28587bcbc (patch)
tree1c23fe9cf10338ec365cc9f15e64609873e613a8 /lib
parentmultiple terminal instances (diff)
downloadfolk-7590f4424917e34c01caac722bd97ac28587bcbc.tar.gz
folk-7590f4424917e34c01caac722bd97ac28587bcbc.zip
cleanup and todos
Diffstat (limited to 'lib')
-rw-r--r--lib/terminal.tcl144
1 files changed, 67 insertions, 77 deletions
diff --git a/lib/terminal.tcl b/lib/terminal.tcl
index fc5f8b87..6276d149 100644
--- a/lib/terminal.tcl
+++ b/lib/terminal.tcl
@@ -3,27 +3,78 @@
# Implements a virtual terminal with basic read/write procs.
#
+namespace eval Terminal {
+ # From `man console_codes`
+ variable keymap [dict create \
+ BACKSPACE "\x08" \
+ TAB "\x09" \
+ ENTER "\x0d" \
+ DELETE "\x7f" \
+ ESC "\x1b" \
+ UP "\x1b\[A" \
+ DOWN "\x1b\[B" \
+ RIGHT "\x1b\[C" \
+ LEFT "\x1b\[D" \
+ ]
+
+ proc _remap {key ctrlPressed} {
+ variable keymap
+ if {[string length $key] == 1} {
+ # Convert ctrl-A through ctrl-Z and others to terminal control characters
+ if {$ctrlPressed} {
+ set charCode [scan [string toupper $key] %c]
+ if {$charCode >= 64 && $charCode <= 95} {
+ set charCode [expr {$charCode - 64}]
+ return [format %c $charCode]
+ }
+ }
+ # All other single char keys can be passed through
+ return $key
+ }
+ if {[dict exists $keymap $key]} {
+ return [dict get $keymap $key]
+ }
+ return ""
+ }
+
+ proc create {} {
+ return [termCreate]
+ }
+
+ # Writes a keyboard key to the terminal, handling control codes
+ proc write {term key ctrlPressed} {
+ set key [_remap $key $ctrlPressed]
+ if {[string length $key] > 0} {
+ termWrite $term $key
+ }
+ }
+
+ # Returns a newline separated string of terminal lines
+ proc read {term} {
+ return [termRead $term]
+ }
+}
+
set cc [c create]
$cc cflags -I./vendor/libtmt ./vendor/libtmt/tmt.c
-# TODO: find the right libutil.so for the system
-c loadlib /lib/aarch64-linux-gnu/libutil.so
+c loadlib [lindex [exec /usr/sbin/ldconfig -p | grep libutil.so] end]
$cc cflags -lutil
$cc include <sys/types.h>
-$cc include <stdio.h>
$cc include <stdlib.h>
$cc include <unistd.h>
$cc include <pty.h>
$cc include <fcntl.h>
$cc include <string.h>
-$cc include <sys/time.h> ;# For gettimeofday()
+$cc include <sys/time.h>
$cc include "tmt.h"
$cc struct VTerminal {
TMT* tmt;
int pty_fd;
+ // Note the screen has 1 more column than the terminal, for newlines
char* screen;
int curs_r;
int curs_c;
@@ -36,12 +87,12 @@ $cc code {
#define PTYBUF 4096
char iobuf[PTYBUF];
- char* char_at(VTerminal *vt, int r, int c) {
+ char* charAt(VTerminal *vt, int r, int c) {
int i = r * (COLS + 1) + c;
return &vt->screen[i];
}
- void tmt_callback(tmt_msg_t m, TMT *tmt, const void *a, void *p) {
+ void tmtEvent(tmt_msg_t m, TMT *tmt, const void *a, void *p) {
VTerminal *vt = (VTerminal*)p;
const TMTSCREEN *s = tmt_screen(tmt);
@@ -49,7 +100,7 @@ $cc code {
for (size_t r = 0; r < s->nline; r++){
if (s->lines[r]->dirty){
for (size_t c = 0; c < s->ncol; c++){
- *char_at(vt, r, c) = s->lines[r]->chars[c].c;
+ *charAt(vt, r, c) = s->lines[r]->chars[c].c;
}
}
}
@@ -57,10 +108,10 @@ $cc code {
}
}
- void updateCursor(VTerminal *vt) {
+ void blinkCursor(VTerminal *vt) {
// Restore char under old cursor
const TMTSCREEN *s = tmt_screen(vt->tmt);
- *char_at(vt, vt->curs_r, vt->curs_c) = s->lines[vt->curs_r]->chars[vt->curs_c].c;
+ *charAt(vt, vt->curs_r, vt->curs_c) = s->lines[vt->curs_r]->chars[vt->curs_c].c;
// Update new cursor
const TMTPOINT *c = tmt_cursor(vt->tmt);
@@ -71,7 +122,7 @@ $cc code {
struct timeval tv;
gettimeofday(&tv, NULL);
if (tv.tv_sec % 2 == 0) {
- *char_at(vt, vt->curs_r, vt->curs_c) = 0xDB; // block char: █
+ *charAt(vt, vt->curs_r, vt->curs_c) = 0xDB; // block char: █
}
}
}
@@ -82,10 +133,12 @@ $cc proc termCreate {} VTerminal* {
vt->curs_c = 0;
vt->screen = malloc(sizeof(char[ROWS][COLS + 1]));
- for (int r = 0; r < ROWS - 1; r++) *char_at(vt, r, COLS) = '\n';
- *char_at(vt, ROWS - 1, COLS) = '\0';
+ for (int r = 0; r < ROWS - 1; r++) {
+ *charAt(vt, r, COLS) = '\n';
+ }
+ *charAt(vt, ROWS - 1, COLS) = '\0';
- vt->tmt = tmt_open(ROWS, COLS, tmt_callback, vt, NULL);
+ vt->tmt = tmt_open(ROWS, COLS, tmtEvent, vt, NULL);
struct winsize ws = {.ws_row = ROWS, .ws_col = COLS};
pid_t pid = forkpty(&vt->pty_fd, NULL, NULL, &ws);
@@ -101,17 +154,13 @@ $cc proc termCreate {} VTerminal* {
return vt;
}
-$cc proc termDestory {VTerminal* vt} void {
- // TODO...
-}
-
$cc proc termRead {VTerminal* vt} char* {
ssize_t r = read(vt->pty_fd, iobuf, PTYBUF);
if (r > 0) {
tmt_write(vt->tmt, iobuf, r);
}
- updateCursor(vt);
+ blinkCursor(vt);
return vt->screen;
}
@@ -120,62 +169,3 @@ $cc proc termWrite {VTerminal* vt char* key} void {
}
$cc compile
-
-# Folk stuff...
-
-namespace eval Terminal {
- # From `man console_codes`
- variable keymap [dict create \
- ENTER "\x0d" \
- TAB "\x09" \
- BACKSPACE "\x08" \
- DELETE "\x7f" \
- ESC "\x1b" \
- UP "\x1b\[A" \
- DOWN "\x1b\[B" \
- RIGHT "\x1b\[C" \
- LEFT "\x1b\[D" \
- ]
-
- proc remap {key ctrlPressed} {
- variable keymap
- if {[string length $key] == 1} {
- # Convert ctrl-A through ctrl-Z and others to terminal control characters
- if {$ctrlPressed} {
- set charCode [scan [string toupper $key] %c]
- if {$charCode >= 64 && $charCode <= 95} {
- set charCode [expr {$charCode - 64}]
- return [format %c $charCode]
- }
- }
- # All other single char keys can be passed through
- return $key
- }
- if {[dict exists $keymap $key]} {
- return [dict get $keymap $key]
- }
- return ""
- }
-
- # Creates a new virtual terminal and returns its ID
- proc create {} {
- return [termCreate]
- }
-
- proc destroy {term} {
- termDestroy $term
- }
-
- # Writes a keyboard key to the terminal, handling control codes
- proc write {term key ctrlPressed} {
- set key [remap $key $ctrlPressed]
- if {[string length $key] > 0} {
- termWrite $term $key
- }
- }
-
- # Returns a newline separated string of terminal lines
- proc read {term} {
- return [termRead $term]
- }
-}