Some cleanups. Added download page to ./web/. No code changes. (0.40.5)
This commit is contained in:
parent
d8540a33eb
commit
d2f673bf24
33 changed files with 34 additions and 1194 deletions
|
|
@ -10,7 +10,7 @@ function(_fun_print_feature name flag)
|
|||
endif()
|
||||
endfunction()
|
||||
|
||||
# Include each extension module (Tcl/Tk removed)
|
||||
# Include each extension module
|
||||
include(${CMAKE_SOURCE_DIR}/cmake/Extensions/SQLITE.cmake)
|
||||
include(${CMAKE_SOURCE_DIR}/cmake/Extensions/PCSC.cmake)
|
||||
include(${CMAKE_SOURCE_DIR}/cmake/Extensions/JSON.cmake)
|
||||
|
|
|
|||
|
|
@ -1,33 +0,0 @@
|
|||
/*
|
||||
* 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
|
||||
*
|
||||
* Added: 2026-02-19
|
||||
*/
|
||||
|
||||
/**
|
||||
* LibreSSL MD5 builtin
|
||||
*/
|
||||
case OP_LIBRESSL_MD5: {
|
||||
Value vdata = pop_value(vm);
|
||||
char *s = value_to_string_alloc(&vdata);
|
||||
free_value(vdata);
|
||||
if (!s) {
|
||||
push_value(vm, make_string(""));
|
||||
break;
|
||||
}
|
||||
char *hex = fun_libressl_md5_hex((const unsigned char *)s, strlen(s));
|
||||
free(s);
|
||||
if (!hex) {
|
||||
push_value(vm, make_string(""));
|
||||
break;
|
||||
}
|
||||
Value out = make_string(hex);
|
||||
free(hex);
|
||||
push_value(vm, out);
|
||||
break;
|
||||
}
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
/*
|
||||
* 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
|
||||
*
|
||||
* Added: 2026-02-19
|
||||
*/
|
||||
|
||||
/**
|
||||
* LibreSSL RIPEMD-160 builtin
|
||||
*/
|
||||
case OP_LIBRESSL_RIPEMD160: {
|
||||
Value vdata = pop_value(vm);
|
||||
char *s = value_to_string_alloc(&vdata);
|
||||
free_value(vdata);
|
||||
if (!s) {
|
||||
push_value(vm, make_string(""));
|
||||
break;
|
||||
}
|
||||
char *hex = fun_libressl_ripemd160_hex((const unsigned char *)s, strlen(s));
|
||||
free(s);
|
||||
if (!hex) {
|
||||
push_value(vm, make_string(""));
|
||||
break;
|
||||
}
|
||||
Value out = make_string(hex);
|
||||
free(hex);
|
||||
push_value(vm, out);
|
||||
break;
|
||||
}
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
/*
|
||||
* 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
|
||||
*
|
||||
* Added: 2026-02-19
|
||||
*/
|
||||
|
||||
/**
|
||||
* LibreSSL SHA-256 builtin
|
||||
*/
|
||||
case OP_LIBRESSL_SHA256: {
|
||||
Value vdata = pop_value(vm);
|
||||
char *s = value_to_string_alloc(&vdata);
|
||||
free_value(vdata);
|
||||
if (!s) {
|
||||
push_value(vm, make_string(""));
|
||||
break;
|
||||
}
|
||||
char *hex = fun_libressl_sha256_hex((const unsigned char *)s, strlen(s));
|
||||
free(s);
|
||||
if (!hex) {
|
||||
push_value(vm, make_string(""));
|
||||
break;
|
||||
}
|
||||
Value out = make_string(hex);
|
||||
free(hex);
|
||||
push_value(vm, out);
|
||||
break;
|
||||
}
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
/*
|
||||
* 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
|
||||
*
|
||||
* Added: 2026-02-19
|
||||
*/
|
||||
|
||||
/**
|
||||
* LibreSSL SHA-512 builtin
|
||||
*/
|
||||
case OP_LIBRESSL_SHA512: {
|
||||
Value vdata = pop_value(vm);
|
||||
char *s = value_to_string_alloc(&vdata);
|
||||
free_value(vdata);
|
||||
if (!s) {
|
||||
push_value(vm, make_string(""));
|
||||
break;
|
||||
}
|
||||
char *hex = fun_libressl_sha512_hex((const unsigned char *)s, strlen(s));
|
||||
free(s);
|
||||
if (!hex) {
|
||||
push_value(vm, make_string(""));
|
||||
break;
|
||||
}
|
||||
Value out = make_string(hex);
|
||||
free(hex);
|
||||
push_value(vm, out);
|
||||
break;
|
||||
}
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
/*
|
||||
* This file is part of the Fun programming language.
|
||||
* https://fun-lang.xyz/
|
||||
*
|
||||
* Copyright 2025 Johannes Findeisen <you@hanez.org>
|
||||
* Licensed under the terms of the Apache-2.0 license.
|
||||
* https://opensource.org/license/apache-2-0
|
||||
*
|
||||
* Added: 2025-11-26
|
||||
*/
|
||||
|
||||
/**
|
||||
* OP_LIBSQL_CLOSE: (handle:int) -> Nil
|
||||
*/
|
||||
case OP_LIBSQL_CLOSE: {
|
||||
#ifdef FUN_WITH_LIBSQL
|
||||
Value vh = pop_value(vm);
|
||||
int hid = (int)vh.i;
|
||||
free_value(vh);
|
||||
LibSqlHandle *h = libsql_reg_get(hid);
|
||||
if (h && h->db) {
|
||||
sqlite3_close(h->db);
|
||||
h->db = NULL;
|
||||
libsql_reg_del(hid);
|
||||
}
|
||||
push_value(vm, make_nil());
|
||||
#else
|
||||
Value v = pop_value(vm);
|
||||
free_value(v);
|
||||
push_value(vm, make_nil());
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
/*
|
||||
* This file is part of the Fun programming language.
|
||||
* https://fun-lang.xyz/
|
||||
*
|
||||
* Copyright 2025 Johannes Findeisen <you@hanez.org>
|
||||
* Licensed under the terms of the Apache-2.0 license.
|
||||
* https://opensource.org/license/apache-2-0
|
||||
*
|
||||
* Added: 2025-11-26
|
||||
*/
|
||||
|
||||
/**
|
||||
* OP_LIBSQL_EXEC: (handle:int, sql:string) -> int rc (0=OK)
|
||||
*/
|
||||
case OP_LIBSQL_EXEC: {
|
||||
#ifdef FUN_WITH_LIBSQL
|
||||
Value vsql = pop_value(vm);
|
||||
Value vh = pop_value(vm);
|
||||
int hid = (int)vh.i;
|
||||
char *sql = value_to_string_alloc(&vsql);
|
||||
free_value(vh);
|
||||
free_value(vsql);
|
||||
LibSqlHandle *h = libsql_reg_get(hid);
|
||||
if (!h || !h->db || !sql) {
|
||||
if (sql) free(sql);
|
||||
push_value(vm, make_int(SQLITE_MISUSE));
|
||||
break;
|
||||
}
|
||||
char *errmsg = NULL;
|
||||
int rc = sqlite3_exec(h->db, sql, NULL, NULL, &errmsg);
|
||||
if (errmsg) sqlite3_free(errmsg);
|
||||
free(sql);
|
||||
push_value(vm, make_int(rc));
|
||||
#else
|
||||
Value v1 = pop_value(vm);
|
||||
free_value(v1);
|
||||
Value v2 = pop_value(vm);
|
||||
free_value(v2);
|
||||
push_value(vm, make_int(-1));
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
/*
|
||||
* This file is part of the Fun programming language.
|
||||
* https://fun-lang.xyz/
|
||||
*
|
||||
* Copyright 2025 Johannes Findeisen <you@hanez.org>
|
||||
* Licensed under the terms of the Apache-2.0 license.
|
||||
* https://opensource.org/license/apache-2-0
|
||||
*
|
||||
* Added: 2025-11-26
|
||||
*/
|
||||
|
||||
/**
|
||||
* OP_LIBSQL_OPEN: (url_or_path:string) -> handle:int (>0) or 0 on error
|
||||
*/
|
||||
case OP_LIBSQL_OPEN: {
|
||||
#ifdef FUN_WITH_LIBSQL
|
||||
Value vpath = pop_value(vm);
|
||||
char *path = value_to_string_alloc(&vpath);
|
||||
free_value(vpath);
|
||||
if (!path) {
|
||||
push_value(vm, make_int(0));
|
||||
break;
|
||||
}
|
||||
sqlite3 *db = NULL;
|
||||
int rc = sqlite3_open(path, &db);
|
||||
free(path);
|
||||
if (rc != SQLITE_OK || !db) {
|
||||
if (db) sqlite3_close(db);
|
||||
push_value(vm, make_int(0));
|
||||
break;
|
||||
}
|
||||
LibSqlHandle *h = libsql_reg_add(db);
|
||||
if (!h) {
|
||||
sqlite3_close(db);
|
||||
push_value(vm, make_int(0));
|
||||
break;
|
||||
}
|
||||
push_value(vm, make_int(h->id));
|
||||
#else
|
||||
Value v = pop_value(vm);
|
||||
free_value(v);
|
||||
push_value(vm, make_int(0));
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
|
@ -1,76 +0,0 @@
|
|||
/*
|
||||
* This file is part of the Fun programming language.
|
||||
* https://fun-lang.xyz/
|
||||
*
|
||||
* Copyright 2025 Johannes Findeisen <you@hanez.org>
|
||||
* Licensed under the terms of the Apache-2.0 license.
|
||||
* https://opensource.org/license/apache-2-0
|
||||
*
|
||||
* Added: 2025-11-26
|
||||
*/
|
||||
|
||||
/**
|
||||
* OP_LIBSQL_QUERY: (handle:int, sql:string) -> array<map<string,any>>
|
||||
*/
|
||||
case OP_LIBSQL_QUERY: {
|
||||
#ifdef FUN_WITH_LIBSQL
|
||||
Value vsql = pop_value(vm);
|
||||
Value vh = pop_value(vm);
|
||||
int hid = (int)vh.i;
|
||||
char *sql = value_to_string_alloc(&vsql);
|
||||
free_value(vh);
|
||||
free_value(vsql);
|
||||
LibSqlHandle *h = libsql_reg_get(hid);
|
||||
if (!h || !h->db || !sql) {
|
||||
if (sql) free(sql);
|
||||
push_value(vm, make_array_from_values(NULL, 0));
|
||||
break;
|
||||
}
|
||||
sqlite3_stmt *stmt = NULL;
|
||||
if (sqlite3_prepare_v2(h->db, sql, -1, &stmt, NULL) != SQLITE_OK) {
|
||||
free(sql);
|
||||
push_value(vm, make_array_from_values(NULL, 0));
|
||||
break;
|
||||
}
|
||||
free(sql);
|
||||
Value rows = make_array_from_values(NULL, 0);
|
||||
int ncols = sqlite3_column_count(stmt);
|
||||
while (sqlite3_step(stmt) == SQLITE_ROW) {
|
||||
Value row = make_map_empty();
|
||||
for (int i = 0; i < ncols; i++) {
|
||||
const char *name = sqlite3_column_name(stmt, i);
|
||||
int type = sqlite3_column_type(stmt, i);
|
||||
Value kv;
|
||||
switch (type) {
|
||||
case SQLITE_INTEGER:
|
||||
kv = make_int((int64_t)sqlite3_column_int64(stmt, i));
|
||||
break;
|
||||
case SQLITE_FLOAT:
|
||||
kv = make_float(sqlite3_column_double(stmt, i));
|
||||
break;
|
||||
case SQLITE_TEXT:
|
||||
kv = make_string((const char *)sqlite3_column_text(stmt, i));
|
||||
break;
|
||||
case SQLITE_NULL:
|
||||
kv = make_nil();
|
||||
break;
|
||||
default:
|
||||
kv = make_nil();
|
||||
break; /* ignore blobs for now */
|
||||
}
|
||||
(void)map_set(&row, name ? name : "", kv);
|
||||
}
|
||||
(void)array_push(&rows, row);
|
||||
/* Do NOT free 'row' here; owned by rows array. */
|
||||
}
|
||||
sqlite3_finalize(stmt);
|
||||
push_value(vm, rows);
|
||||
#else
|
||||
Value v1 = pop_value(vm);
|
||||
free_value(v1);
|
||||
Value v2 = pop_value(vm);
|
||||
free_value(v2);
|
||||
push_value(vm, make_array_from_values(NULL, 0));
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
|
@ -1,66 +0,0 @@
|
|||
/**
|
||||
* 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;
|
||||
}
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
/**
|
||||
* This file is part of the Fun programming language.
|
||||
* https://fun-lang.xyz/
|
||||
*
|
||||
* Copyright 2025 Johannes Findeisen <you@hanez.org>
|
||||
* Licensed under the terms of the Apache-2.0 license.
|
||||
* https://opensource.org/license/apache-2-0
|
||||
*
|
||||
* Added: 2026-01-03
|
||||
*/
|
||||
|
||||
/* NC_CLEAR */
|
||||
case OP_NC_CLEAR: {
|
||||
#ifdef FUN_WITH_NOTCURSES
|
||||
if (_fun_nc && _fun_nc_std) {
|
||||
ncplane_erase(_fun_nc_std);
|
||||
notcurses_render(_fun_nc);
|
||||
push_value(vm, make_int(0));
|
||||
} else {
|
||||
push_value(vm, make_int(-1));
|
||||
}
|
||||
#else
|
||||
(void)_fun_nc;
|
||||
(void)_fun_nc_std;
|
||||
push_value(vm, make_int(-1));
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
/**
|
||||
* This file is part of the Fun programming language.
|
||||
* https://fun-lang.xyz/
|
||||
*
|
||||
* Copyright 2025 Johannes Findeisen <you@hanez.org>
|
||||
* Licensed under the terms of the Apache-2.0 license.
|
||||
* https://opensource.org/license/apache-2-0
|
||||
*
|
||||
* Added: 2026-01-03
|
||||
*/
|
||||
|
||||
/* Common helpers/state for Notcurses TUI ops */
|
||||
#pragma once
|
||||
|
||||
#include "value.h"
|
||||
|
||||
/* Forward declarations to avoid depending on the notcurses headers unless enabled */
|
||||
struct notcurses;
|
||||
struct ncplane;
|
||||
|
||||
/* Shared static state within vm.c translation unit (header is included into vm.c at file scope) */
|
||||
static struct notcurses *_fun_nc = NULL;
|
||||
static struct ncplane *_fun_nc_std = NULL;
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
/**
|
||||
* 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;
|
||||
}
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
/**
|
||||
* This file is part of the Fun programming language.
|
||||
* https://fun-lang.xyz/
|
||||
*
|
||||
* Copyright 2025 Johannes Findeisen <you@hanez.org>
|
||||
* Licensed under the terms of the Apache-2.0 license.
|
||||
* https://opensource.org/license/apache-2-0
|
||||
*
|
||||
* Added: 2026-01-03
|
||||
*/
|
||||
|
||||
/* NC_DRAW_TEXT */
|
||||
case OP_NC_DRAW_TEXT: {
|
||||
Value textv = pop_value(vm);
|
||||
Value xv = pop_value(vm);
|
||||
Value yv = pop_value(vm);
|
||||
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));
|
||||
char *text = value_to_string_alloc(&textv);
|
||||
free_value(textv);
|
||||
free_value(xv);
|
||||
free_value(yv);
|
||||
#ifdef FUN_WITH_NOTCURSES
|
||||
if (_fun_nc && _fun_nc_std && text) {
|
||||
ncplane_putstr_yx(_fun_nc_std, y, x, text);
|
||||
notcurses_render(_fun_nc);
|
||||
free(text);
|
||||
push_value(vm, make_int(0));
|
||||
} else {
|
||||
if (text) free(text);
|
||||
push_value(vm, make_int(-1));
|
||||
}
|
||||
#else
|
||||
(void)_fun_nc;
|
||||
(void)_fun_nc_std;
|
||||
if (text) free(text);
|
||||
push_value(vm, make_int(-1));
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
/**
|
||||
* 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;
|
||||
}
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
/**
|
||||
* 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;
|
||||
}
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
/**
|
||||
* This file is part of the Fun programming language.
|
||||
* https://fun-lang.xyz/
|
||||
*
|
||||
* Copyright 2025 Johannes Findeisen <you@hanez.org>
|
||||
* Licensed under the terms of the Apache-2.0 license.
|
||||
* https://opensource.org/license/apache-2-0
|
||||
*
|
||||
* Added: 2026-01-03
|
||||
*/
|
||||
|
||||
/* NC_GETCH */
|
||||
case OP_NC_GETCH: {
|
||||
Value to_ms_v = pop_value(vm);
|
||||
int timeout_ms = (to_ms_v.type == VAL_INT ? (int)to_ms_v.i : (to_ms_v.type == VAL_FLOAT ? (int)to_ms_v.d : 0));
|
||||
free_value(to_ms_v);
|
||||
#ifdef FUN_WITH_NOTCURSES
|
||||
if (_fun_nc) {
|
||||
/* For simplicity, use blocking get for now when timeout<=0 */
|
||||
if (timeout_ms <= 0) {
|
||||
ncinput ni;
|
||||
uint32_t id = notcurses_get_blocking(_fun_nc, &ni);
|
||||
push_value(vm, make_int((int)id));
|
||||
} else {
|
||||
/* Polling approximation: render then nonblocking get once */
|
||||
ncinput ni;
|
||||
uint32_t id = notcurses_get_nblock(_fun_nc, &ni);
|
||||
if (id == 0) {
|
||||
/* no input available now: return -1 to indicate timeout */
|
||||
push_value(vm, make_int(-1));
|
||||
} else {
|
||||
push_value(vm, make_int((int)id));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
push_value(vm, make_int(-1));
|
||||
}
|
||||
#else
|
||||
(void)_fun_nc;
|
||||
(void)_fun_nc_std;
|
||||
(void)timeout_ms;
|
||||
push_value(vm, make_int(-1));
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
/**
|
||||
* 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;
|
||||
}
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
/**
|
||||
* This file is part of the Fun programming language.
|
||||
* https://fun-lang.xyz/
|
||||
*
|
||||
* Copyright 2025 Johannes Findeisen <you@hanez.org>
|
||||
* Licensed under the terms of the Apache-2.0 license.
|
||||
* https://opensource.org/license/apache-2-0
|
||||
*
|
||||
* Added: 2026-01-03
|
||||
*/
|
||||
|
||||
/* NC_INIT */
|
||||
case OP_NC_INIT: {
|
||||
#ifdef FUN_WITH_NOTCURSES
|
||||
if (_fun_nc) {
|
||||
push_value(vm, make_int(1));
|
||||
break;
|
||||
}
|
||||
struct notcurses_options opts = {0};
|
||||
_fun_nc = notcurses_core_init(&opts, NULL);
|
||||
if (!_fun_nc) {
|
||||
push_value(vm, make_int(0));
|
||||
break;
|
||||
}
|
||||
_fun_nc_std = notcurses_stdplane(_fun_nc);
|
||||
push_value(vm, make_int(1));
|
||||
#else
|
||||
(void)_fun_nc;
|
||||
(void)_fun_nc_std;
|
||||
fprintf(stderr, "Notcurses support disabled at build time. Reconfigure with -DFUN_WITH_NOTCURSES=ON.\n");
|
||||
push_value(vm, make_int(0));
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
/**
|
||||
* 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;
|
||||
}
|
||||
|
|
@ -1,71 +0,0 @@
|
|||
/**
|
||||
* 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;
|
||||
}
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
/**
|
||||
* This file is part of the Fun programming language.
|
||||
* https://fun-lang.xyz/
|
||||
*
|
||||
* Copyright 2025 Johannes Findeisen <you@hanez.org>
|
||||
* Licensed under the terms of the Apache-2.0 license.
|
||||
* https://opensource.org/license/apache-2-0
|
||||
*
|
||||
* Added: 2026-01-03
|
||||
*/
|
||||
|
||||
/* NC_SHUTDOWN */
|
||||
case OP_NC_SHUTDOWN: {
|
||||
#ifdef FUN_WITH_NOTCURSES
|
||||
if (_fun_nc) {
|
||||
notcurses_stop(_fun_nc);
|
||||
_fun_nc = NULL;
|
||||
_fun_nc_std = NULL;
|
||||
}
|
||||
#else
|
||||
(void)_fun_nc;
|
||||
(void)_fun_nc_std;
|
||||
#endif
|
||||
push_value(vm, make_int(0));
|
||||
break;
|
||||
}
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
/**
|
||||
* 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;
|
||||
}
|
||||
|
|
@ -1,56 +0,0 @@
|
|||
/**
|
||||
* This file is part of the Fun programming language.
|
||||
* https://fun-lang.xyz/
|
||||
*
|
||||
* Copyright 2025 Johannes Findeisen <you@hanez.org>
|
||||
* Licensed under the terms of the Apache-2.0 license.
|
||||
* https://opensource.org/license/apache-2-0
|
||||
*
|
||||
* Added: 2025-12-23
|
||||
*/
|
||||
|
||||
/* TK_BIND */
|
||||
case OP_TK_BIND: {
|
||||
/* stack: ..., id, event, command -> rc */
|
||||
Value cmdv = pop_value(vm);
|
||||
Value eventv = pop_value(vm);
|
||||
Value idv = pop_value(vm);
|
||||
char *cmd = value_to_string_alloc(&cmdv);
|
||||
char *event = value_to_string_alloc(&eventv);
|
||||
char *id = value_to_string_alloc(&idv);
|
||||
free_value(cmdv);
|
||||
free_value(eventv);
|
||||
free_value(idv);
|
||||
|
||||
if (!id || !event || !cmd) {
|
||||
if (id) free(id);
|
||||
if (event) free(event);
|
||||
if (cmd) free(cmd);
|
||||
push_value(vm, make_int(-1));
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Construct: bind .id <event> {command}
|
||||
* Note: for now, command is just raw Tcl as well,
|
||||
* but could be extended to call Fun functions if we had a callback mechanism.
|
||||
*/
|
||||
size_t slen = strlen(id) + strlen(event) + strlen(cmd) + 32;
|
||||
char *script = (char *)malloc(slen);
|
||||
if (!script) {
|
||||
free(id);
|
||||
free(event);
|
||||
free(cmd);
|
||||
push_value(vm, make_int(-1));
|
||||
break;
|
||||
}
|
||||
|
||||
snprintf(script, slen, "bind .%s %s {%s}", id, event, cmd);
|
||||
int rc = fun_tk_eval_script(script);
|
||||
free(script);
|
||||
free(id);
|
||||
free(event);
|
||||
free(cmd);
|
||||
push_value(vm, make_int(rc));
|
||||
break;
|
||||
}
|
||||
|
|
@ -1,58 +0,0 @@
|
|||
/* TK_BUTTON */
|
||||
case OP_TK_BUTTON: {
|
||||
/* stack: ..., id, text -> rc */
|
||||
Value textv = pop_value(vm);
|
||||
Value idv = pop_value(vm);
|
||||
char *text = value_to_string_alloc(&textv);
|
||||
char *id = value_to_string_alloc(&idv);
|
||||
free_value(textv);
|
||||
free_value(idv);
|
||||
if (!id) {
|
||||
if (text) free(text);
|
||||
push_value(vm, make_int(-1));
|
||||
break;
|
||||
}
|
||||
if (!text) {
|
||||
text = strdup("");
|
||||
}
|
||||
size_t n = 0;
|
||||
for (const char *p = text; *p; ++p) {
|
||||
n += (*p == '\\' || *p == '"') ? 2 : 1;
|
||||
}
|
||||
char *et = (char *)malloc(n + 1);
|
||||
if (!et) {
|
||||
free(id);
|
||||
free(text);
|
||||
push_value(vm, make_int(-1));
|
||||
break;
|
||||
}
|
||||
char *q = et;
|
||||
for (const char *p = text; *p; ++p) {
|
||||
if (*p == '\\' || *p == '"') *q++ = '\\';
|
||||
*q++ = *p;
|
||||
}
|
||||
*q = '\0';
|
||||
free(text);
|
||||
size_t slen = strlen(id) + strlen(et) + 196;
|
||||
char *script = (char *)malloc(slen);
|
||||
if (!script) {
|
||||
free(id);
|
||||
free(et);
|
||||
push_value(vm, make_int(-1));
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* Default behavior: clicking the button should terminate the app. We set
|
||||
* -command {catch {destroy .}; exit 0} to both destroy the window and exit
|
||||
* the process. Using 'catch' makes it safe if the window is already gone.
|
||||
*/
|
||||
snprintf(script, slen,
|
||||
"if {[winfo exists .%s]} { .%s configure -text \"%s\" -command {catch {destroy .}; exit 0} } else { button .%s -text \"%s\" -command {catch {destroy .}; exit 0} }",
|
||||
id, id, et, id, et);
|
||||
int rc = fun_tk_eval_script(script);
|
||||
free(script);
|
||||
free(id);
|
||||
free(et);
|
||||
push_value(vm, make_int(rc));
|
||||
break;
|
||||
}
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
/*
|
||||
* This file is part of the Fun programming language.
|
||||
* https://fun-lang.xyz/
|
||||
*
|
||||
* Copyright 2025 Johannes Findeisen <you@hanez.org>
|
||||
* Licensed under the terms of the Apache-2.0 license.
|
||||
* https://opensource.org/license/apache-2-0
|
||||
*
|
||||
* Added: 2025-12-09
|
||||
*/
|
||||
|
||||
/* TK_EVAL */
|
||||
case OP_TK_EVAL: {
|
||||
Value text = pop_value(vm);
|
||||
char *s = value_to_string_alloc(&text);
|
||||
free_value(text);
|
||||
int rc = fun_tk_eval_script(s ? s : "");
|
||||
if (s) free(s);
|
||||
push_value(vm, make_int(rc));
|
||||
break;
|
||||
}
|
||||
|
|
@ -1,55 +0,0 @@
|
|||
/* TK_LABEL */
|
||||
case OP_TK_LABEL: {
|
||||
/* stack: ..., id, text -> rc */
|
||||
Value textv = pop_value(vm);
|
||||
Value idv = pop_value(vm);
|
||||
char *text = value_to_string_alloc(&textv);
|
||||
char *id = value_to_string_alloc(&idv);
|
||||
free_value(textv);
|
||||
free_value(idv);
|
||||
if (!id) {
|
||||
if (text) free(text);
|
||||
push_value(vm, make_int(-1));
|
||||
break;
|
||||
}
|
||||
if (!text) {
|
||||
text = strdup("");
|
||||
}
|
||||
/* escape id minimally (dots and word chars are fine) -> just use as-is */
|
||||
/* escape text for Tcl double quotes */
|
||||
size_t n = 0;
|
||||
for (const char *p = text; *p; ++p) {
|
||||
n += (*p == '\\' || *p == '"') ? 2 : 1;
|
||||
}
|
||||
char *et = (char *)malloc(n + 1);
|
||||
if (!et) {
|
||||
free(id);
|
||||
free(text);
|
||||
push_value(vm, make_int(-1));
|
||||
break;
|
||||
}
|
||||
char *q = et;
|
||||
for (const char *p = text; *p; ++p) {
|
||||
if (*p == '\\' || *p == '"') *q++ = '\\';
|
||||
*q++ = *p;
|
||||
}
|
||||
*q = '\0';
|
||||
free(text);
|
||||
size_t slen = strlen(id) + strlen(et) + 128;
|
||||
char *script = (char *)malloc(slen);
|
||||
if (!script) {
|
||||
free(id);
|
||||
free(et);
|
||||
push_value(vm, make_int(-1));
|
||||
break;
|
||||
}
|
||||
snprintf(script, slen,
|
||||
"if {[winfo exists .%s]} { .%s configure -text \"%s\" } else { label .%s -text \"%s\" }",
|
||||
id, id, et, id, et);
|
||||
int rc = fun_tk_eval_script(script);
|
||||
free(script);
|
||||
free(id);
|
||||
free(et);
|
||||
push_value(vm, make_int(rc));
|
||||
break;
|
||||
}
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
/*
|
||||
* This file is part of the Fun programming language.
|
||||
* https://fun-lang.xyz/
|
||||
*
|
||||
* Copyright 2025 Johannes Findeisen <you@hanez.org>
|
||||
* Licensed under the terms of the Apache-2.0 license.
|
||||
* https://opensource.org/license/apache-2-0
|
||||
*
|
||||
* Added: 2025-12-09
|
||||
*/
|
||||
|
||||
/* TK_LOOP */
|
||||
case OP_TK_LOOP: {
|
||||
fun_tk_loop();
|
||||
#ifdef FUN_WITH_TCLTK
|
||||
/* Ensure the process terminates once the GUI window(s) are closed. */
|
||||
exit(0);
|
||||
#else
|
||||
/* When Tk support is not compiled in, behave as a no-op returning Nil. */
|
||||
push_value(vm, make_nil());
|
||||
#endif
|
||||
break; /* not reached when FUN_WITH_TCLTK */
|
||||
}
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
/* TK_PACK */
|
||||
case OP_TK_PACK: {
|
||||
Value idv = pop_value(vm);
|
||||
char *id = value_to_string_alloc(&idv);
|
||||
free_value(idv);
|
||||
if (!id) {
|
||||
push_value(vm, make_int(-1));
|
||||
break;
|
||||
}
|
||||
size_t slen = strlen(id) + 16;
|
||||
char *script = (char *)malloc(slen);
|
||||
if (!script) {
|
||||
free(id);
|
||||
push_value(vm, make_int(-1));
|
||||
break;
|
||||
}
|
||||
snprintf(script, slen, "pack .%s", id);
|
||||
int rc = fun_tk_eval_script(script);
|
||||
free(script);
|
||||
free(id);
|
||||
push_value(vm, make_int(rc));
|
||||
break;
|
||||
}
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
/*
|
||||
* This file is part of the Fun programming language.
|
||||
* https://fun-lang.xyz/
|
||||
*
|
||||
* Copyright 2025 Johannes Findeisen <you@hanez.org>
|
||||
* Licensed under the terms of the Apache-2.0 license.
|
||||
* https://opensource.org/license/apache-2-0
|
||||
*
|
||||
* Added: 2025-12-09
|
||||
*/
|
||||
|
||||
/* TK_RESULT */
|
||||
case OP_TK_RESULT: {
|
||||
const char *r = fun_tk_get_result();
|
||||
push_value(vm, make_string(r ? r : ""));
|
||||
break;
|
||||
}
|
||||
|
|
@ -1,52 +0,0 @@
|
|||
/*
|
||||
* This file is part of the Fun programming language.
|
||||
* https://fun-lang.xyz/
|
||||
*
|
||||
* Copyright 2025 Johannes Findeisen <you@hanez.org>
|
||||
* Licensed under the terms of the Apache-2.0 license.
|
||||
* https://opensource.org/license/apache-2-0
|
||||
*
|
||||
* Added: 2025-12-09
|
||||
*/
|
||||
|
||||
/* TK_WM_TITLE */
|
||||
case OP_TK_WM_TITLE: {
|
||||
Value titlev = pop_value(vm);
|
||||
char *title = value_to_string_alloc(&titlev);
|
||||
free_value(titlev);
|
||||
if (!title) {
|
||||
push_value(vm, make_int(-1));
|
||||
break;
|
||||
}
|
||||
/* Escape backslashes and double quotes for Tcl double-quoted strings */
|
||||
size_t n = 0;
|
||||
for (const char *p = title; *p; ++p) {
|
||||
n += (*p == '\\' || *p == '"') ? 2 : 1;
|
||||
}
|
||||
char *esc = (char *)malloc(n + 1);
|
||||
if (!esc) {
|
||||
free(title);
|
||||
push_value(vm, make_int(-1));
|
||||
break;
|
||||
}
|
||||
char *q = esc;
|
||||
for (const char *p = title; *p; ++p) {
|
||||
if (*p == '\\' || *p == '"') *q++ = '\\';
|
||||
*q++ = *p;
|
||||
}
|
||||
*q = '\0';
|
||||
free(title);
|
||||
size_t slen = strlen(esc) + 32;
|
||||
char *script = (char *)malloc(slen);
|
||||
if (!script) {
|
||||
free(esc);
|
||||
push_value(vm, make_int(-1));
|
||||
break;
|
||||
}
|
||||
snprintf(script, slen, "wm title . \"%s\"", esc);
|
||||
int rc = fun_tk_eval_script(script);
|
||||
free(script);
|
||||
free(esc);
|
||||
push_value(vm, make_int(rc));
|
||||
break;
|
||||
}
|
||||
|
|
@ -6,18 +6,12 @@
|
|||
<div class="trigger">
|
||||
<h2 style="display:none;">Navigation</h2>
|
||||
<ul style="list-style: none;">
|
||||
<li><a class="page-link" href="/" style="text-decoration:none;" title="/">/</a></li>
|
||||
<li><a class="page-link" href="/about/" style="text-decoration:none;" title="/about/">/about/</a></li>
|
||||
<li><a class="page-link" href="/community/" style="text-decoration:none;" title="/community/">/community/</a></li>
|
||||
<li><a class="page-link" href="/contact/" style="text-decoration:none;" title="/contact/">/contact/</a></li>
|
||||
<!--<li><a class="page-link" href="/development/" style="text-decoration:none;" title="/development/">/development/</a></li>-->
|
||||
<li><a class="page-link" href="/documentation/" style="text-decoration:none;" title="/documentation/">/documentation/</a></li>
|
||||
<!--<li><a class="page-link" href="/examples/" style="text-decoration:none;" title="/examples/">/examples/</a></li>-->
|
||||
<!--<li><a class="page-link" href="/faq/" style="text-decoration:none;" title="/faq/">/faq/</a></li>-->
|
||||
<!--
|
||||
<li>----------------</li>
|
||||
<li><a class="page-link" href="/account/" style="text-decoration:none;" title="/account/">/account/</a></li>
|
||||
-->
|
||||
<li><a class="page-link" href="/" style="text-decoration:none;" title="Homepage">/</a></li>
|
||||
<li><a class="page-link" href="/about/" style="text-decoration:none;" title="About">About</a></li>
|
||||
<li><a class="page-link" href="/community/" style="text-decoration:none;" title="Community">Community</a></li>
|
||||
<li><a class="page-link" href="/contact/" style="text-decoration:none;" title="Contact">Contact</a></li>
|
||||
<li><a class="page-link" href="/documentation/" style="text-decoration:none;" title="Documentation">Documentation</a></li>
|
||||
<li><a class="page-link" href="/download/" style="text-decoration:none;" title="Download">Download</a></li>
|
||||
<!--
|
||||
https://www.w3schools.com/howto/howto_js_toggle_dark_mode.asp
|
||||
https://dev.to/warish/how-to-create-a-dark-mode-toggle-with-html-css-and-javascript-378m
|
||||
|
|
|
|||
27
web/download/download.md
Normal file
27
web/download/download.md
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
---
|
||||
layout: page
|
||||
title: Download
|
||||
subtitle: Download Fun
|
||||
description: Download Fun archives or checkout source code.
|
||||
metasub: news
|
||||
noToc: true
|
||||
noDate: false
|
||||
tags:
|
||||
- fun
|
||||
- programming
|
||||
- language
|
||||
- download
|
||||
_description: The programming language that just makes fun!
|
||||
noComments: true
|
||||
permalink: /download/
|
||||
---
|
||||
|
||||
Actually, no packages for some OS are existing. You need to download the source code and compile it by yourself.
|
||||
|
||||
## Archives
|
||||
|
||||
- [https://git.xw3.org/fun/fun/tags](https://git.xw3.org/fun/fun/tags){:class="git"}
|
||||
|
||||
## Git
|
||||
|
||||
- [https://git.xw3.org/fun/fun/](https://git.xw3.org/fun/fun/){:class="git"}
|
||||
Loading…
Add table
Add a link
Reference in a new issue