Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
*.o
*.os
113 changes: 98 additions & 15 deletions tmt.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ struct TMT{
TMTSCREEN screen;
TMTLINE *tabs;

TMTSCREEN scroll;

TMTCALLBACK cb;
void *p;
const wchar_t *acschars;
Expand All @@ -70,7 +72,7 @@ struct TMT{
size_t pars[PAR_MAX];
size_t npar;
size_t arg;
enum {S_NUL, S_ESC, S_ARG} state;
enum {S_NUL, S_ESC, S_ARG, S_OS} state;
};

static TMTATTRS defattrs = {.fg = TMT_COLOR_DEFAULT, .bg = TMT_COLOR_DEFAULT};
Expand Down Expand Up @@ -116,22 +118,36 @@ clearlines(TMT *vt, size_t r, size_t n)
clearline(vt, vt->screen.lines[i], 0, vt->screen.ncol);
}

static void
savescroll(TMT *vt, TMTLINE **lines, size_t n)
{
for (int i=0; i<n; i++) {
vt->scroll.lines[i]->dirty = true;
memcpy(vt->scroll.lines[i]->chars, lines[i]->chars, vt->screen.ncol * sizeof(TMTCHAR));
}
CB(vt, TMT_MSG_SCROLL, &vt->scroll);
}

static void
scrup(TMT *vt, size_t r, size_t n)
{
n = MIN(n, vt->screen.nline - 1 - r);

if (n){
TMTLINE *buf[n];
TMTLINE** buf = malloc(n * sizeof(TMTLINE*));

memcpy(buf, vt->screen.lines + r, n * sizeof(TMTLINE *));
memmove(vt->screen.lines + r, vt->screen.lines + r + n,
(vt->screen.nline - n - r) * sizeof(TMTLINE *));
memcpy(vt->screen.lines + (vt->screen.nline - n),
buf, n * sizeof(TMTLINE *));

if (r == 0) {
savescroll(vt, buf, n);
}
clearlines(vt, vt->screen.nline - n, n);
dirtylines(vt, r, vt->screen.nline);
free(buf);
}
}

Expand All @@ -141,7 +157,7 @@ scrdn(TMT *vt, size_t r, size_t n)
n = MIN(n, vt->screen.nline - 1 - r);

if (n){
TMTLINE *buf[n];
TMTLINE** buf = malloc(n * sizeof(TMTLINE*));

memcpy(buf, vt->screen.lines + (vt->screen.nline - n),
n * sizeof(TMTLINE *));
Expand All @@ -151,6 +167,7 @@ scrdn(TMT *vt, size_t r, size_t n)

clearlines(vt, r, n);
dirtylines(vt, r, vt->screen.nline);
free(buf);
}
}

Expand All @@ -161,7 +178,9 @@ HANDLER(ed)
switch (P0(0)){
case 0: b = c->r + 1; clearline(vt, l, c->c, vt->screen.ncol); break;
case 1: e = c->r - 1; clearline(vt, l, 0, c->c); break;
case 2: /* use defaults */ break;
case 2:
savescroll(vt, vt->screen.lines, vt->screen.nline);
break;
default: /* do nothing */ return;
}

Expand Down Expand Up @@ -202,7 +221,11 @@ HANDLER(el)
}

HANDLER(sgr)
#define FGBG(c) *(P0(i) < 40? &vt->attrs.fg : &vt->attrs.bg) = c
#define FGBG(c) *(P0(i) < 40? &vt->attrs.fg.code : &vt->attrs.bg.code) = c
#define FGBGB(c) *(P0(i) < 100? &vt->attrs.fg.code : &vt->attrs.bg.code) = c
#define FGBGRED() *(P0(i) < 40? &vt->attrs.fg.red : &vt->attrs.bg.red) = (i < vt->npar-2) ? vt->pars[i+2] : 0
#define FGBGGRN() *(P0(i) < 40? &vt->attrs.fg.green : &vt->attrs.bg.green) = (i < vt->npar-3) ? vt->pars[i+3] : 0
#define FGBGBLU() *(P0(i) < 40? &vt->attrs.fg.blue : &vt->attrs.bg.blue) = (i < vt->npar-4) ? vt->pars[i+4] : 0
for (size_t i = 0; i < vt->npar; i++) switch (P0(i)){
case 0: vt->attrs = defattrs; break;
case 1: case 22: vt->attrs.bold = P0(0) < 20; break;
Expand All @@ -220,7 +243,22 @@ HANDLER(sgr)
case 35: case 45: FGBG(TMT_COLOR_MAGENTA); break;
case 36: case 46: FGBG(TMT_COLOR_CYAN); break;
case 37: case 47: FGBG(TMT_COLOR_WHITE); break;
case 38: case 48: if ((i < vt->npar-1) && (vt->pars[i+1] == 2)) {
FGBG(TMT_COLOR_RGB);
FGBGRED();
FGBGGRN();
FGBGBLU();
}
break;
case 39: case 49: FGBG(TMT_COLOR_DEFAULT); break;
case 90: case 100: FGBGB(TMT_COLOR_BRIGHT_BLACK); break;
case 91: case 101: FGBGB(TMT_COLOR_BRIGHT_RED); break;
case 92: case 102: FGBGB(TMT_COLOR_BRIGHT_GREEN); break;
case 93: case 103: FGBGB(TMT_COLOR_BRIGHT_YELLOW); break;
case 94: case 104: FGBGB(TMT_COLOR_BRIGHT_BLUE); break;
case 95: case 105: FGBGB(TMT_COLOR_BRIGHT_MAGENTA); break;
case 96: case 106: FGBGB(TMT_COLOR_BRIGHT_CYAN); break;
case 97: case 107: FGBGB(TMT_COLOR_BRIGHT_WHITE); break;
}
}

Expand Down Expand Up @@ -262,6 +300,7 @@ handlechar(TMT *vt, char i)
#define ON(S, C, A) if (vt->state == (S) && strchr(C, i)){ A; return true;}
#define DO(S, C, A) ON(S, C, consumearg(vt); if (!vt->ignored) {A;} \
fixcursor(vt); resetparser(vt););
#define SK(S) if (vt->state == (S)) { return true; }

DO(S_NUL, "\x07", CB(vt, TMT_MSG_BELL, NULL))
DO(S_NUL, "\x08", if (c->c) c->c--)
Expand All @@ -276,6 +315,10 @@ handlechar(TMT *vt, char i)
ON(S_ESC, "+*()", vt->ignored = true; vt->state = S_ARG)
DO(S_ESC, "c", tmt_reset(vt))
ON(S_ESC, "[", vt->state = S_ARG)
ON(S_ESC, "]", vt->state = S_OS)
ON(S_OS, "\x1b", vt->state = S_ESC)
ON(S_OS, "\x07", vt->state = S_NUL)
SK(S_OS)
ON(S_ARG, "\x1b", vt->state = S_ESC)
ON(S_ARG, ";", consumearg(vt))
ON(S_ARG, "?", (void)0)
Expand Down Expand Up @@ -315,10 +358,12 @@ handlechar(TMT *vt, char i)
}

static void
//notify(TMT *vt, bool update, bool moved, bool scroll)
notify(TMT *vt, bool update, bool moved)
{
if (update) CB(vt, TMT_MSG_UPDATE, &vt->screen);
if (moved) CB(vt, TMT_MSG_MOVED, &vt->curs);
//if (scroll) CB(vt, TMT_MSG_SCROLL, &vt->scroll);
}

static TMTLINE *
Expand All @@ -339,6 +384,12 @@ freelines(TMT *vt, size_t s, size_t n, bool screen)
vt->screen.lines[i] = NULL;
}
if (screen) free(vt->screen.lines);

for (size_t i = s; vt->scroll.lines && i < s + n; i++){
free(vt->scroll.lines[i]);
vt->scroll.lines[i] = NULL;
}
if (screen) free(vt->scroll.lines);
}

TMT *
Expand Down Expand Up @@ -386,10 +437,29 @@ tmt_resize(TMT *vt, size_t nline, size_t ncol)
nl = allocline(vt, vt->screen.lines[i], ncol, pc);

if (!nl) return false;

vt->screen.lines[i] = nl;
}
vt->screen.nline = nline;

TMTLINE **sl = realloc(vt->scroll.lines, nline * sizeof(TMTLINE *));
if (!sl) return false;

vt->scroll.lines = sl;
vt->scroll.ncol = ncol;
for (size_t i = 0; i < nline; i++){
TMTLINE *nl = NULL;
if (i >= vt->scroll.nline)
nl = vt->scroll.lines[i] = allocline(vt, NULL, ncol, 0);
else
nl = allocline(vt, vt->scroll.lines[i], ncol, pc);

if (!nl) return false;
nl->dirty = false;
vt->scroll.lines[i] = nl;
}
vt->scroll.nline = nline;

vt->tabs = allocline(vt, vt->tabs, ncol, 0);
if (!vt->tabs) return free(l), false;
vt->tabs->chars[0].c = vt->tabs->chars[ncol - 1].c = L'*';
Expand All @@ -398,6 +468,7 @@ tmt_resize(TMT *vt, size_t nline, size_t ncol)

fixcursor(vt);
dirtylines(vt, 0, nline);
//notify(vt, true, true, false);
notify(vt, true, true);
return true;
}
Expand All @@ -413,21 +484,24 @@ writecharatcurs(TMT *vt, wchar_t w)
if (wcwidth(w) < 0) return;
#endif

/* If at end of screen, wrap to next line */
if (c->c >= s->ncol) {
c->c = 0;
c->r++;
}
if (c->r >= s->nline){
c->r = s->nline - 1;
scrup(vt, 0, 1);
}

CLINE(vt)->chars[vt->curs.c].c = w;
CLINE(vt)->chars[vt->curs.c].a = vt->attrs;
CLINE(vt)->dirty = vt->dirty = true;

if (c->c < s->ncol - 1)
c->c++;
else{
c->c = 0;
c->r++;
}
/* Advance cursor to next column
Will wrap if necessary when trying to write next character. */
c->c++;

if (c->r >= s->nline){
c->r = s->nline - 1;
scrup(vt, 0, 1);
}
}

static inline size_t
Expand Down Expand Up @@ -470,6 +544,7 @@ tmt_write(TMT *vt, const char *s, size_t n)
}
}

//notify(vt, vt->dirty, memcmp(&oc, &vt->curs, sizeof(oc)) != 0, (vt->scroll.lines[0]->dirty));
notify(vt, vt->dirty, memcmp(&oc, &vt->curs, sizeof(oc)) != 0);
}

Expand All @@ -492,6 +567,13 @@ tmt_clean(TMT *vt)
vt->dirty = vt->screen.lines[i]->dirty = false;
}

void
tmt_clean_scroll(TMT *vt)
{
for (size_t i = 0; i < vt->scroll.nline; i++)
vt->scroll.lines[i]->dirty = false;
}

void
tmt_reset(TMT *vt)
{
Expand All @@ -501,5 +583,6 @@ tmt_reset(TMT *vt)
memset(&vt->ms, 0, sizeof(vt->ms));
clearlines(vt, 0, vt->screen.nline);
CB(vt, TMT_MSG_CURSOR, "t");
//notify(vt, true, true, false);
notify(vt, true, true);
}
20 changes: 19 additions & 1 deletion tmt.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,23 @@ typedef enum{
TMT_COLOR_MAGENTA,
TMT_COLOR_CYAN,
TMT_COLOR_WHITE,
TMT_COLOR_BRIGHT_BLACK,
TMT_COLOR_BRIGHT_RED,
TMT_COLOR_BRIGHT_GREEN,
TMT_COLOR_BRIGHT_YELLOW,
TMT_COLOR_BRIGHT_BLUE,
TMT_COLOR_BRIGHT_MAGENTA,
TMT_COLOR_BRIGHT_CYAN,
TMT_COLOR_BRIGHT_WHITE,
TMT_COLOR_RGB,
TMT_COLOR_MAX
} tmt_color_code_t;

typedef struct {
tmt_color_code_t code;
unsigned char red;
unsigned char green;
unsigned char blue;
} tmt_color_t;

typedef struct TMTATTRS TMTATTRS;
Expand Down Expand Up @@ -121,7 +137,8 @@ typedef enum{
TMT_MSG_UPDATE,
TMT_MSG_ANSWER,
TMT_MSG_BELL,
TMT_MSG_CURSOR
TMT_MSG_CURSOR,
TMT_MSG_SCROLL
} tmt_msg_t;

typedef void (*TMTCALLBACK)(tmt_msg_t m, struct TMT *v, const void *r, void *p);
Expand All @@ -135,6 +152,7 @@ void tmt_write(TMT *vt, const char *s, size_t n);
const TMTSCREEN *tmt_screen(const TMT *vt);
const TMTPOINT *tmt_cursor(const TMT *vt);
void tmt_clean(TMT *vt);
void tmt_clean_scroll(TMT *vt);
void tmt_reset(TMT *vt);

#endif