1
0
Fork 0
forked from fun/fun

More notcurses fun. Not stable! (0.39.4)

This commit is contained in:
Johannes Findeisen 2026-03-20 20:57:43 +01:00
commit 18ac230c21
19 changed files with 715 additions and 15 deletions

66
src/vm/notcurses/box.c Normal file
View file

@ -0,0 +1,66 @@
/**
* This file is part of the Fun programming language.
* https://fun-lang.xyz/
*
* Copyright 2026 Johannes Findeisen <you@hanez.org>
* Licensed under the terms of the Apache-2.0 license.
* https://opensource.org/license/apache-2-0
*/
/* NC_BOX */
case OP_NC_BOX: {
Value stylev = pop_value(vm);
Value hv = pop_value(vm);
Value wv = pop_value(vm);
Value yv = pop_value(vm);
Value xv = pop_value(vm);
int style = (stylev.type == VAL_INT ? (int)stylev.i : (stylev.type == VAL_FLOAT ? (int)stylev.d : 0));
int h = (hv.type == VAL_INT ? (int)hv.i : (hv.type == VAL_FLOAT ? (int)hv.d : 0));
int w = (wv.type == VAL_INT ? (int)wv.i : (wv.type == VAL_FLOAT ? (int)wv.d : 0));
int y = (yv.type == VAL_INT ? (int)yv.i : (yv.type == VAL_FLOAT ? (int)yv.d : 0));
int x = (xv.type == VAL_INT ? (int)xv.i : (xv.type == VAL_FLOAT ? (int)xv.d : 0));
free_value(stylev); free_value(hv); free_value(wv); free_value(yv); free_value(xv);
#ifdef FUN_WITH_NOTCURSES
if (_fun_nc && _fun_nc_std && h >= 2 && w >= 2) {
/* Pick characters: style 0 light (ASCII), 1 heavy (Unicode), fallback to ASCII */
uint32_t hch = (style == 1 ? 0x2501 : '-'); // heavy box drawings horizontal
uint32_t vch = (style == 1 ? 0x2503 : '|'); // heavy vertical
uint32_t tl = (style == 1 ? 0x250F : '+');
uint32_t tr = (style == 1 ? 0x2513 : '+');
uint32_t bl = (style == 1 ? 0x2517 : '+');
uint32_t br = (style == 1 ? 0x251B : '+');
/* Draw edges */
// top and bottom
{
char topc[5]; int tlen=0; uint32_t cp=hch;
if (cp<=0x7F){topc[0]=(char)cp;tlen=1;} else if (cp<=0x7FF){topc[0]=(char)(0xC0|(cp>>6)); topc[1]=(char)(0x80|(cp&0x3F)); tlen=2;} else if (cp<=0xFFFF){topc[0]=(char)(0xE0|(cp>>12)); topc[1]=(char)(0x80|((cp>>6)&0x3F)); topc[2]=(char)(0x80|(cp&0x3F)); tlen=3;} else {topc[0]=(char)(0xF0|(cp>>18)); topc[1]=(char)(0x80|((cp>>12)&0x3F)); topc[2]=(char)(0x80|((cp>>6)&0x3F)); topc[3]=(char)(0x80|(cp&0x3F)); tlen=4;}
topc[tlen]='\0';
for (int i=1;i<w-1;i++){ ncplane_putstr_yx(_fun_nc_std, y, x+i, topc); ncplane_putstr_yx(_fun_nc_std, y+h-1, x+i, topc);}
}
// left and right
{
char vertc[5]; int vlen=0; uint32_t cp=vch;
if (cp<=0x7F){vertc[0]=(char)cp;vlen=1;} else if (cp<=0x7FF){vertc[0]=(char)(0xC0|(cp>>6)); vertc[1]=(char)(0x80|(cp&0x3F)); vlen=2;} else if (cp<=0xFFFF){vertc[0]=(char)(0xE0|(cp>>12)); vertc[1]=(char)(0x80|((cp>>6)&0x3F)); vertc[2]=(char)(0x80|(cp&0x3F)); vlen=3;} else {vertc[0]=(char)(0xF0|(cp>>18)); vertc[1]=(char)(0x80|((cp>>12)&0x3F)); vertc[2]=(char)(0x80|((cp>>6)&0x3F)); vertc[3]=(char)(0x80|(cp&0x3F)); vlen=4;}
vertc[vlen]='\0';
for (int i=1;i<h-1;i++){ ncplane_putstr_yx(_fun_nc_std, y+i, x, vertc); ncplane_putstr_yx(_fun_nc_std, y+i, x+w-1, vertc);}
}
// corners
{
char cbuf[5]; int clen=0; uint32_t cp;
cp=tl; if (cp<=0x7F){cbuf[0]=(char)cp;clen=1;} else if (cp<=0x7FF){cbuf[0]=(char)(0xC0|(cp>>6)); cbuf[1]=(char)(0x80|(cp&0x3F)); clen=2;} else if (cp<=0xFFFF){cbuf[0]=(char)(0xE0|(cp>>12)); cbuf[1]=(char)(0x80|((cp>>6)&0x3F)); cbuf[2]=(char)(0x80|(cp&0x3F)); clen=3;} else {cbuf[0]=(char)(0xF0|(cp>>18)); cbuf[1]=(char)(0x80|((cp>>12)&0x3F)); cbuf[2]=(char)(0x80|((cp>>6)&0x3F)); cbuf[3]=(char)(0x80|(cp&0x3F)); clen=4;} cbuf[clen]='\0'; ncplane_putstr_yx(_fun_nc_std, y, x, cbuf);
cp=tr; if (cp<=0x7F){cbuf[0]=(char)cp;clen=1;} else if (cp<=0x7FF){cbuf[0]=(char)(0xC0|(cp>>6)); cbuf[1]=(char)(0x80|(cp&0x3F)); clen=2;} else if (cp<=0xFFFF){cbuf[0]=(char)(0xE0|(cp>>12)); cbuf[1]=(char)(0x80|((cp>>6)&0x3F)); cbuf[2]=(char)(0x80|(cp&0x3F)); clen=3;} else {cbuf[0]=(char)(0xF0|(cp>>18)); cbuf[1]=(char)(0x80|((cp>>12)&0x3F)); cbuf[2]=(char)(0x80|((cp>>6)&0x3F)); cbuf[3]=(char)(0x80|(cp&0x3F)); clen=4;} cbuf[clen]='\0'; ncplane_putstr_yx(_fun_nc_std, y, x+w-1, cbuf);
cp=bl; if (cp<=0x7F){cbuf[0]=(char)cp;clen=1;} else if (cp<=0x7FF){cbuf[0]=(char)(0xC0|(cp>>6)); cbuf[1]=(char)(0x80|(cp&0x3F)); clen=2;} else if (cp<=0xFFFF){cbuf[0]=(char)(0xE0|(cp>>12)); cbuf[1]=(char)(0x80|((cp>>6)&0x3F)); cbuf[2]=(char)(0x80|(cp&0x3F)); clen=3;} else {cbuf[0]=(char)(0xF0|(cp>>18)); cbuf[1]=(char)(0x80|((cp>>12)&0x3F)); cbuf[2]=(char)(0x80|((cp>>6)&0x3F)); cbuf[3]=(char)(0x80|(cp&0x3F)); clen=4;} cbuf[clen]='\0'; ncplane_putstr_yx(_fun_nc_std, y+h-1, x, cbuf);
cp=br; if (cp<=0x7F){cbuf[0]=(char)cp;clen=1;} else if (cp<=0x7FF){cbuf[0]=(char)(0xC0|(cp>>6)); cbuf[1]=(char)(0x80|(cp&0x3F)); clen=2;} else if (cp<=0xFFFF){cbuf[0]=(char)(0xE0|(cp>>12)); cbuf[1]=(char)(0x80|((cp>>6)&0x3F)); cbuf[2]=(char)(0x80|(cp&0x3F)); clen=3;} else {cbuf[0]=(char)(0xF0|(cp>>18)); cbuf[1]=(char)(0x80|((cp>>12)&0x3F)); cbuf[2]=(char)(0x80|((cp>>6)&0x3F)); cbuf[3]=(char)(0x80|(cp&0x3F)); clen=4;} cbuf[clen]='\0'; ncplane_putstr_yx(_fun_nc_std, y+h-1, x+w-1, cbuf);
}
push_value(vm, make_int(0));
} else {
push_value(vm, make_int(-1));
}
#else
(void)style; (void)h; (void)w; (void)y; (void)x;
push_value(vm, make_int(-1));
#endif
break;
}

View file

@ -0,0 +1,40 @@
/**
* This file is part of the Fun programming language.
* https://fun-lang.xyz/
*
* Copyright 2026 Johannes Findeisen <you@hanez.org>
* Licensed under the terms of the Apache-2.0 license.
* https://opensource.org/license/apache-2-0
*/
/* NC_DRAW_CHAR */
case OP_NC_DRAW_CHAR: {
Value yv = pop_value(vm);
Value xv = pop_value(vm);
Value chv = pop_value(vm);
int y = (yv.type == VAL_INT ? (int)yv.i : (yv.type == VAL_FLOAT ? (int)yv.d : 0));
int x = (xv.type == VAL_INT ? (int)xv.i : (xv.type == VAL_FLOAT ? (int)xv.d : 0));
uint32_t cp = (chv.type == VAL_INT ? (uint32_t)chv.i : (chv.type == VAL_FLOAT ? (uint32_t)chv.d : (uint32_t)'?'));
free_value(yv);
free_value(xv);
free_value(chv);
#ifdef FUN_WITH_NOTCURSES
if (_fun_nc && _fun_nc_std) {
char utf8[5];
int len = 0;
if (cp <= 0x7F) { utf8[0] = (char)cp; len = 1; }
else if (cp <= 0x7FF) { utf8[0] = (char)(0xC0 | (cp >> 6)); utf8[1] = (char)(0x80 | (cp & 0x3F)); len = 2; }
else if (cp <= 0xFFFF) { utf8[0] = (char)(0xE0 | (cp >> 12)); utf8[1] = (char)(0x80 | ((cp >> 6) & 0x3F)); utf8[2] = (char)(0x80 | (cp & 0x3F)); len = 3; }
else { utf8[0] = (char)(0xF0 | (cp >> 18)); utf8[1] = (char)(0x80 | ((cp >> 12) & 0x3F)); utf8[2] = (char)(0x80 | ((cp >> 6) & 0x3F)); utf8[3] = (char)(0x80 | (cp & 0x3F)); len = 4; }
utf8[len] = '\0';
ncplane_putstr_yx(_fun_nc_std, y, x, utf8);
push_value(vm, make_int(0));
} else {
push_value(vm, make_int(-1));
}
#else
(void)cp; (void)x; (void)y;
push_value(vm, make_int(-1));
#endif
break;
}

45
src/vm/notcurses/fill.c Normal file
View file

@ -0,0 +1,45 @@
/**
* This file is part of the Fun programming language.
* https://fun-lang.xyz/
*
* Copyright 2026 Johannes Findeisen <you@hanez.org>
* Licensed under the terms of the Apache-2.0 license.
* https://opensource.org/license/apache-2-0
*/
/* NC_FILL */
case OP_NC_FILL: {
Value chv = pop_value(vm);
Value hv = pop_value(vm);
Value wv = pop_value(vm);
Value yv = pop_value(vm);
Value xv = pop_value(vm);
int h = (hv.type == VAL_INT ? (int)hv.i : (hv.type == VAL_FLOAT ? (int)hv.d : 0));
int w = (wv.type == VAL_INT ? (int)wv.i : (wv.type == VAL_FLOAT ? (int)wv.d : 0));
int y = (yv.type == VAL_INT ? (int)yv.i : (yv.type == VAL_FLOAT ? (int)yv.d : 0));
int x = (xv.type == VAL_INT ? (int)xv.i : (xv.type == VAL_FLOAT ? (int)xv.d : 0));
uint32_t cp = (chv.type == VAL_INT ? (uint32_t)chv.i : (chv.type == VAL_FLOAT ? (uint32_t)chv.d : (uint32_t)' '));
free_value(chv); free_value(hv); free_value(wv); free_value(yv); free_value(xv);
#ifdef FUN_WITH_NOTCURSES
if (_fun_nc && _fun_nc_std && h > 0 && w > 0) {
char utf8[5]; int ulen = 0;
if (cp <= 0x7F) { utf8[0] = (char)cp; ulen = 1; }
else if (cp <= 0x7FF) { utf8[0]=(char)(0xC0|(cp>>6)); utf8[1]=(char)(0x80|(cp&0x3F)); ulen=2; }
else if (cp <= 0xFFFF) { utf8[0]=(char)(0xE0|(cp>>12)); utf8[1]=(char)(0x80|((cp>>6)&0x3F)); utf8[2]=(char)(0x80|(cp&0x3F)); ulen=3; }
else { utf8[0]=(char)(0xF0|(cp>>18)); utf8[1]=(char)(0x80|((cp>>12)&0x3F)); utf8[2]=(char)(0x80|((cp>>6)&0x3F)); utf8[3]=(char)(0x80|(cp&0x3F)); ulen=4; }
utf8[ulen] = '\0';
for (int yy = 0; yy < h; yy++) {
for (int xx = 0; xx < w; xx++) {
ncplane_putstr_yx(_fun_nc_std, y + yy, x + xx, utf8);
}
}
push_value(vm, make_int(0));
} else {
push_value(vm, make_int(-1));
}
#else
(void)cp; (void)x; (void)y; (void)w; (void)h;
push_value(vm, make_int(-1));
#endif
break;
}

View file

@ -0,0 +1,29 @@
/**
* This file is part of the Fun programming language.
* https://fun-lang.xyz/
*
* Copyright 2026 Johannes Findeisen <you@hanez.org>
* Licensed under the terms of the Apache-2.0 license.
* https://opensource.org/license/apache-2-0
*/
/* NC_GET_SIZE */
case OP_NC_GET_SIZE: {
#ifdef FUN_WITH_NOTCURSES
if (_fun_nc_std) {
int rows = 0, cols = 0;
ncplane_dim_yx(_fun_nc_std, &rows, &cols);
Value tmp[2];
tmp[0] = make_int(rows);
tmp[1] = make_int(cols);
Value arr = make_array_from_values(tmp, 2);
push_value(vm, arr);
} else {
push_value(vm, make_int(-1));
}
#else
(void)_fun_nc_std;
push_value(vm, make_int(-1));
#endif
break;
}

39
src/vm/notcurses/hline.c Normal file
View file

@ -0,0 +1,39 @@
/**
* This file is part of the Fun programming language.
* https://fun-lang.xyz/
*
* Copyright 2026 Johannes Findeisen <you@hanez.org>
* Licensed under the terms of the Apache-2.0 license.
* https://opensource.org/license/apache-2-0
*/
/* NC_DRAW_HLINE */
case OP_NC_DRAW_HLINE: {
Value chv = pop_value(vm);
Value lenv = pop_value(vm);
Value xv = pop_value(vm);
Value yv = pop_value(vm);
int len = (lenv.type == VAL_INT ? (int)lenv.i : (lenv.type == VAL_FLOAT ? (int)lenv.d : 0));
int x = (xv.type == VAL_INT ? (int)xv.i : (xv.type == VAL_FLOAT ? (int)xv.d : 0));
int y = (yv.type == VAL_INT ? (int)yv.i : (yv.type == VAL_FLOAT ? (int)yv.d : 0));
uint32_t cp = (chv.type == VAL_INT ? (uint32_t)chv.i : (chv.type == VAL_FLOAT ? (uint32_t)chv.d : (uint32_t)'-'));
free_value(lenv); free_value(xv); free_value(yv); free_value(chv);
#ifdef FUN_WITH_NOTCURSES
if (_fun_nc && _fun_nc_std && len > 0) {
char utf8[5]; int ulen = 0;
if (cp <= 0x7F) { utf8[0] = (char)cp; ulen = 1; }
else if (cp <= 0x7FF) { utf8[0]=(char)(0xC0|(cp>>6)); utf8[1]=(char)(0x80|(cp&0x3F)); ulen=2; }
else if (cp <= 0xFFFF) { utf8[0]=(char)(0xE0|(cp>>12)); utf8[1]=(char)(0x80|((cp>>6)&0x3F)); utf8[2]=(char)(0x80|(cp&0x3F)); ulen=3; }
else { utf8[0]=(char)(0xF0|(cp>>18)); utf8[1]=(char)(0x80|((cp>>12)&0x3F)); utf8[2]=(char)(0x80|((cp>>6)&0x3F)); utf8[3]=(char)(0x80|(cp&0x3F)); ulen=4; }
utf8[ulen] = '\0';
for (int i = 0; i < len; i++) ncplane_putstr_yx(_fun_nc_std, y, x + i, utf8);
push_value(vm, make_int(0));
} else {
push_value(vm, make_int(-1));
}
#else
(void)cp; (void)x; (void)y; (void)len;
push_value(vm, make_int(-1));
#endif
break;
}

23
src/vm/notcurses/render.c Normal file
View file

@ -0,0 +1,23 @@
/**
* This file is part of the Fun programming language.
* https://fun-lang.xyz/
*
* Copyright 2026 Johannes Findeisen <you@hanez.org>
* Licensed under the terms of the Apache-2.0 license.
* https://opensource.org/license/apache-2-0
*/
/* NC_RENDER */
case OP_NC_RENDER: {
#ifdef FUN_WITH_NOTCURSES
if (_fun_nc) {
int rc = notcurses_render(_fun_nc);
push_value(vm, make_int(rc == 0 ? 0 : -1));
} else {
push_value(vm, make_int(-1));
}
#else
push_value(vm, make_int(-1));
#endif
break;
}

View file

@ -0,0 +1,71 @@
/**
* This file is part of the Fun programming language.
* https://fun-lang.xyz/
*
* Copyright 2026 Johannes Findeisen <you@hanez.org>
* Licensed under the terms of the Apache-2.0 license.
* https://opensource.org/license/apache-2-0
*/
/* NC_SET_STYLE */
case OP_NC_SET_STYLE: {
Value fgv = pop_value(vm);
Value bgv = pop_value(vm);
Value stylev = pop_value(vm);
int style = (stylev.type == VAL_INT ? (int)stylev.i : (stylev.type == VAL_FLOAT ? (int)stylev.d : 0));
int bg = (bgv.type == VAL_INT ? (int)bgv.i : (bgv.type == VAL_FLOAT ? (int)bgv.d : 0));
int fg = (fgv.type == VAL_INT ? (int)fgv.i : (fgv.type == VAL_FLOAT ? (int)fgv.d : 0));
free_value(stylev);
free_value(bgv);
free_value(fgv);
#ifdef FUN_WITH_NOTCURSES
if (_fun_nc && _fun_nc_std) {
/* Extract RGB components */
unsigned fg_r = (unsigned)((fg >> 16) & 0xFF);
unsigned fg_g = (unsigned)((fg >> 8) & 0xFF);
unsigned fg_b = (unsigned)(fg & 0xFF);
unsigned bg_r = (unsigned)((bg >> 16) & 0xFF);
unsigned bg_g = (unsigned)((bg >> 8) & 0xFF);
unsigned bg_b = (unsigned)(bg & 0xFF);
/* Set colors */
ncplane_set_fg_rgb8(_fun_nc_std, fg_r, fg_g, fg_b);
ncplane_set_bg_rgb8(_fun_nc_std, bg_r, bg_g, bg_b);
/* Map simple bitmask to notcurses styles */
/* some notcurses versions spell these differently; provide fallbacks */
#ifndef NCSTYLE_DIM
# ifdef NCSTYLE_FAINT
# define NCSTYLE_DIM NCSTYLE_FAINT
# else
# define NCSTYLE_DIM 0
# endif
#endif
#ifndef NCSTYLE_REVERSE
# ifdef NCSTYLE_REVERSED
# define NCSTYLE_REVERSE NCSTYLE_REVERSED
# else
# define NCSTYLE_REVERSE 0
# endif
#endif
unsigned styles = 0;
if (style & 1) styles |= NCSTYLE_BOLD;
if (style & 2) styles |= NCSTYLE_DIM;
if (style & 4) styles |= NCSTYLE_ITALIC;
if (style & 8) styles |= NCSTYLE_UNDERLINE;
if (style & 16) styles |= NCSTYLE_STRUCK;
if (style & 32) styles |= NCSTYLE_REVERSE;
ncplane_set_styles(_fun_nc_std, styles);
push_value(vm, make_int(0));
} else {
push_value(vm, make_int(-1));
}
#else
(void)style;
(void)bg;
(void)fg;
push_value(vm, make_int(-1));
#endif
break;
}

39
src/vm/notcurses/vline.c Normal file
View file

@ -0,0 +1,39 @@
/**
* This file is part of the Fun programming language.
* https://fun-lang.xyz/
*
* Copyright 2026 Johannes Findeisen <you@hanez.org>
* Licensed under the terms of the Apache-2.0 license.
* https://opensource.org/license/apache-2-0
*/
/* NC_DRAW_VLINE */
case OP_NC_DRAW_VLINE: {
Value chv = pop_value(vm);
Value lenv = pop_value(vm);
Value xv = pop_value(vm);
Value yv = pop_value(vm);
int len = (lenv.type == VAL_INT ? (int)lenv.i : (lenv.type == VAL_FLOAT ? (int)lenv.d : 0));
int x = (xv.type == VAL_INT ? (int)xv.i : (xv.type == VAL_FLOAT ? (int)xv.d : 0));
int y = (yv.type == VAL_INT ? (int)yv.i : (yv.type == VAL_FLOAT ? (int)yv.d : 0));
uint32_t cp = (chv.type == VAL_INT ? (uint32_t)chv.i : (chv.type == VAL_FLOAT ? (uint32_t)chv.d : (uint32_t)'|'));
free_value(lenv); free_value(xv); free_value(yv); free_value(chv);
#ifdef FUN_WITH_NOTCURSES
if (_fun_nc && _fun_nc_std && len > 0) {
char utf8[5]; int ulen = 0;
if (cp <= 0x7F) { utf8[0] = (char)cp; ulen = 1; }
else if (cp <= 0x7FF) { utf8[0]=(char)(0xC0|(cp>>6)); utf8[1]=(char)(0x80|(cp&0x3F)); ulen=2; }
else if (cp <= 0xFFFF) { utf8[0]=(char)(0xE0|(cp>>12)); utf8[1]=(char)(0x80|((cp>>6)&0x3F)); utf8[2]=(char)(0x80|(cp&0x3F)); ulen=3; }
else { utf8[0]=(char)(0xF0|(cp>>18)); utf8[1]=(char)(0x80|((cp>>12)&0x3F)); utf8[2]=(char)(0x80|((cp>>6)&0x3F)); utf8[3]=(char)(0x80|(cp&0x3F)); ulen=4; }
utf8[ulen] = '\0';
for (int i = 0; i < len; i++) ncplane_putstr_yx(_fun_nc_std, y + i, x, utf8);
push_value(vm, make_int(0));
} else {
push_value(vm, make_int(-1));
}
#else
(void)cp; (void)x; (void)y; (void)len;
push_value(vm, make_int(-1));
#endif
break;
}