Migrate chez-scintilla to jerboa-scintilla: 10 libs under (jerboa-scintilla ...). C shim renamed jerboa_scintilla_shim.c. Source 10/10 transpile clean; shim build needs gerbil-scintilla vendor archives (Linux/CI).
ober
faad1833d938c3e2da81181a281e3c961e45e732
--- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ *.so *.wpo +.jerbuild-hashes --- a/Makefile +++ b/Makefile @@ -1,21 +1,37 @@ -.PHONY: all build shim clean test vendor-deps +JERBOA_HOME ?= $(HOME)/mine/jerboa +SCHEME ?= $(JERBOA_HOME)/.chez/bin/scheme +JERBUILD ?= $(JERBOA_HOME)/jerbuild +LIBDIRS = lib:$(JERBOA_HOME)/lib -# Gerbil-scintilla vendor directory (reuse already-built artifacts) +# Vendor (gerbil-scintilla static archives) GERBIL_SCINTILLA ?= $(HOME)/mine/gerbil-scintilla +VENDOR = $(GERBIL_SCINTILLA)/vendor +SCI_DIR = $(VENDOR)/scintilla +SCI_TB_DIR = $(SCI_DIR)/termbox +TERMBOX_DIR = $(SCI_TB_DIR)/termbox_next +LEXILLA_DIR = $(VENDOR)/lexilla +SCINTILLA_A = $(SCI_DIR)/bin/scintilla.a +TERMBOX_A = $(TERMBOX_DIR)/bin/termbox.a +LEXILLA_A = $(LEXILLA_DIR)/bin/liblexilla.a -# Vendor paths -VENDOR = $(GERBIL_SCINTILLA)/vendor -SCI_DIR = $(VENDOR)/scintilla -SCI_TB_DIR = $(SCI_DIR)/termbox -TERMBOX_DIR = $(SCI_TB_DIR)/termbox_next -LEXILLA_DIR = $(VENDOR)/lexilla +CC ?= cc +UNAME_S := $(shell uname -s) +ifeq ($(UNAME_S),Darwin) + SHARED_FLAG = -dynamiclib + SO_EXT = .so + LD_VAR = DYLD_LIBRARY_PATH + WHOLE_ARCHIVE_OPEN = -Wl,-force_load, + WHOLE_ARCHIVE_CLOSE = +else + SHARED_FLAG = -shared + SO_EXT = .so + LD_VAR = LD_LIBRARY_PATH + WHOLE_ARCHIVE_OPEN = -Wl,--whole-archive + WHOLE_ARCHIVE_CLOSE = -Wl,--no-whole-archive +endif -# Static archives -SCINTILLA_A = $(SCI_DIR)/bin/scintilla.a -TERMBOX_A = $(TERMBOX_DIR)/bin/termbox.a -LEXILLA_A = $(LEXILLA_DIR)/bin/liblexilla.a +SHIM := jerboa_scintilla_shim$(SO_EXT) -# Include paths CC_INCLUDES = \ -I$(SCI_DIR)/include \ -I$(SCI_DIR)/src \ @@ -23,43 +39,40 @@ CC_INCLUDES = \ -I$(TERMBOX_DIR)/src \ -I$(LEXILLA_DIR)/include -# Chez Scheme library path -CHEZ_LIB = src -SHIM_SO = chez_scintilla_shim.so +.PHONY: all build transpile test clean shim vendor-deps vendor-check all: build -# Build the C shim shared object -shim: $(SHIM_SO) +vendor-check: + @if [ ! -f $(SCINTILLA_A) ] || [ ! -f $(LEXILLA_A) ] || [ ! -f $(TERMBOX_A) ]; then \ + echo "WARN: vendor archives missing (expected under $(GERBIL_SCINTILLA))."; \ + echo "WARN: skip shim build; run 'make vendor-deps' guidance in $(GERBIL_SCINTILLA)."; exit 1; \ + fi -$(SHIM_SO): chez_scintilla_shim.c $(SCINTILLA_A) $(LEXILLA_A) $(TERMBOX_A) - gcc -shared -fPIC -o $@ $< \ - $(CC_INCLUDES) \ - -Wl,--whole-archive $(SCINTILLA_A) $(LEXILLA_A) $(TERMBOX_A) -Wl,--no-whole-archive \ +shim: vendor-check $(SHIM) + +ifeq ($(UNAME_S),Darwin) +$(SHIM): jerboa_scintilla_shim.c + $(CC) $(SHARED_FLAG) -fPIC -O2 -o $@ $< $(CC_INCLUDES) \ + $(WHOLE_ARCHIVE_OPEN)$(SCINTILLA_A) $(WHOLE_ARCHIVE_OPEN)$(LEXILLA_A) $(WHOLE_ARCHIVE_OPEN)$(TERMBOX_A) \ + -lc++ -lpthread +else +$(SHIM): jerboa_scintilla_shim.c + $(CC) $(SHARED_FLAG) -fPIC -O2 -o $@ $< $(CC_INCLUDES) \ + $(WHOLE_ARCHIVE_OPEN) $(SCINTILLA_A) $(LEXILLA_A) $(TERMBOX_A) $(WHOLE_ARCHIVE_CLOSE) \ -lstdc++ -lpthread +endif -# Build everything: shim + compile Scheme libraries -build: $(SHIM_SO) - @echo "Compiling Scheme libraries..." - @CHEZ_SCINTILLA_LIB=$(CURDIR) \ - scheme --libdirs $(CHEZ_LIB) --compile-imported-libraries --program /dev/null \ - < <(echo '(import (chez-scintilla ffi) (chez-scintilla constants) (chez-scintilla scintilla) (chez-scintilla tui) (chez-scintilla lexer) (chez-scintilla style) (chez-scintilla search) (chez-scintilla folding) (chez-scintilla autocomplete) (chez-scintilla markers))') \ - 2>&1 || true - @echo "Build complete." +transpile: + $(JERBUILD) transpile src lib --force -# Run tests -test: build - CHEZ_SCINTILLA_LIB=$(CURDIR) \ - scheme --libdirs $(CHEZ_LIB) --script tests/run-tests.ss +build: transpile shim -# Check that vendor deps exist -vendor-deps: - @test -f $(SCINTILLA_A) || (echo "ERROR: scintilla.a not found. Run 'make vendor-deps' in $(GERBIL_SCINTILLA)" && exit 1) - @test -f $(LEXILLA_A) || (echo "ERROR: liblexilla.a not found." && exit 1) - @test -f $(TERMBOX_A) || (echo "ERROR: termbox.a not found." && exit 1) - @echo "Vendor dependencies OK." +test: build + JERBOA_SCINTILLA_LIB=$(CURDIR) \ + $(LD_VAR)=$(CURDIR) \ + $(SCHEME) --libdirs "$(LIBDIRS)" --script tests/run-tests.ss clean: - rm -f $(SHIM_SO) - find src -name '*.so' -delete - find src -name '*.wpo' -delete + rm -f $(SHIM) chez_scintilla_shim.so + rm -rf lib deleted file mode 100644 --- a/chez_scintilla_shim.c +++ /dev/null @@ -1,341 +0,0 @@ -/* chez_scintilla_shim.c — C shim for Chez Scheme FFI to Scintilla + termbox - * - * Extracted from gerbil-scintilla/ffi.ss c-declare block. - * Provides: instance lifecycle, message passing, notification ring buffer, - * input, display, clipboard, lexilla, and termbox wrappers. - * - * All functions use simple C types (void*, int, long, const char*) - * compatible with Chez Scheme's foreign-procedure. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <stdint.h> -#include <stdbool.h> - -#include "Scintilla.h" -#include "ScintillaTermbox.h" -#include "Lexilla.h" -#include "termbox.h" - -/* ================================================================ - Types - ================================================================ */ -typedef intptr_t sptr_t; -typedef uintptr_t uptr_t; -typedef void Scintilla; - -/* ================================================================ - Notification ring buffer (per-instance) - ================================================================ */ -#define NOTIFY_RING_SIZE 64 - -typedef struct { - int code; - long position; - int ch; - int modifiers; - int modification_type; - char text[256]; - long length; - long lines_added; - int message; - long line; - int fold_level_now; - int fold_level_prev; - int margin; - int list_type; - int x; - int y; - int token; - int updated; -} notify_entry_t; - -typedef struct instance_node { - Scintilla *view; - notify_entry_t ring[NOTIFY_RING_SIZE]; - int ring_head; - int ring_tail; - struct instance_node *next; -} instance_node_t; - -static instance_node_t *instance_list = NULL; - -/* Current notification (static, for drain_one -> accessor pattern) */ -static notify_entry_t current_scn; - -/* Find instance node by view pointer */ -static instance_node_t *find_instance(Scintilla *view) { - instance_node_t *n = instance_list; - while (n) { - if (n->view == view) return n; - n = n->next; - } - return NULL; -} - -/* Notification callback — called synchronously from C++ */ -static void notification_callback(Scintilla *view, int msg, - SCNotification *scn, void *userdata) { - instance_node_t *inst = find_instance(view); - if (!inst) return; - - int next_head = (inst->ring_head + 1) % NOTIFY_RING_SIZE; - if (next_head == inst->ring_tail) { - /* Ring full — drop oldest */ - inst->ring_tail = (inst->ring_tail + 1) % NOTIFY_RING_SIZE; - } - - notify_entry_t *e = &inst->ring[inst->ring_head]; - e->code = scn->nmhdr.code; - e->position = (long)scn->position; - e->ch = scn->ch; - e->modifiers = scn->modifiers; - e->modification_type = scn->modificationType; - e->length = (long)scn->length; - e->lines_added = (long)scn->linesAdded; - e->message = scn->message; - e->line = (long)scn->line; - e->fold_level_now = scn->foldLevelNow; - e->fold_level_prev = scn->foldLevelPrev; - e->margin = scn->margin; - e->list_type = scn->listType; - e->x = scn->x; - e->y = scn->y; - e->token = scn->token; - e->updated = scn->updated; - - if (scn->text && scn->length > 0) { - int copy_len = scn->length < 255 ? scn->length : 255; - memcpy(e->text, scn->text, copy_len); - e->text[copy_len] = '\0'; - } else { - e->text[0] = '\0'; - } - - inst->ring_head = next_head; -} - -/* ================================================================ - Instance lifecycle - ================================================================ */ -void *chez_scintilla_new(void) { - Scintilla *sci = scintilla_new(notification_callback, NULL); - if (!sci) return NULL; - - instance_node_t *node = (instance_node_t *)malloc(sizeof(instance_node_t)); - node->view = sci; - node->ring_head = 0; - node->ring_tail = 0; - node->next = instance_list; - instance_list = node; - - return (void *)sci; -} - -void chez_scintilla_delete(void *handle) { - Scintilla *sci = (Scintilla *)handle; - /* Remove from instance list */ - instance_node_t **pp = &instance_list; - while (*pp) { - if ((*pp)->view == sci) { - instance_node_t *rm = *pp; - *pp = rm->next; - free(rm); - break; - } - pp = &(*pp)->next; - } - scintilla_delete(sci); -} - -/* ================================================================ - Message passing - ================================================================ */ -long chez_scintilla_send_message(void *handle, unsigned int msg, - unsigned long wparam, long lparam) { - return (long)scintilla_send_message((Scintilla *)handle, msg, - (uptr_t)wparam, (sptr_t)lparam); -} - -/* Send message with string as lparam (cast char* to sptr_t) */ -long chez_scintilla_send_message_string(void *handle, unsigned int msg, - unsigned long wparam, const char *str) { - return (long)scintilla_send_message((Scintilla *)handle, msg, - (uptr_t)wparam, (sptr_t)str); -} - -/* Receive string: call msg twice (get length, then fill buffer) */ -#define RECV_BUF_SIZE 65536 -static char recv_buf[RECV_BUF_SIZE]; - -const char *chez_scintilla_receive_string(void *handle, unsigned int msg, - unsigned long wparam) { - long len = (long)scintilla_send_message((Scintilla *)handle, msg, - (uptr_t)wparam, (sptr_t)NULL); - if (len <= 0) { - recv_buf[0] = '\0'; - return recv_buf; - } - if (len >= RECV_BUF_SIZE) len = RECV_BUF_SIZE - 1; - scintilla_send_message((Scintilla *)handle, msg, - (uptr_t)wparam, (sptr_t)recv_buf); - recv_buf[len] = '\0'; - return recv_buf; -} - -/* Set property: wparam = key string, lparam = value string */ -long chez_scintilla_set_property(void *handle, unsigned int msg, - const char *key, const char *value) { - return (long)scintilla_send_message((Scintilla *)handle, msg, - (uptr_t)key, (sptr_t)value); -} - -/* ================================================================ - Input - ================================================================ */ -void chez_scintilla_send_key(void *handle, int key, - int shift, int ctrl, int alt) { - scintilla_send_key((Scintilla *)handle, key, shift, ctrl, alt); -} - -int chez_scintilla_send_mouse(void *handle, int event, int button, - int y, int x, - int shift, int ctrl, int alt) { - return scintilla_send_mouse((Scintilla *)handle, event, button, - y, x, shift, ctrl, alt); -} - -/* ================================================================ - Display - ================================================================ */ -void chez_scintilla_refresh(void *handle) { - scintilla_refresh((Scintilla *)handle); -} - -void chez_scintilla_resize(void *handle, int width, int height) { - scintilla_resize((Scintilla *)handle, width, height); -} - -void chez_scintilla_move(void *handle, int x, int y) { - scintilla_move((Scintilla *)handle, x, y); -} - -/* ================================================================ - Clipboard - ================================================================ */ -const char *chez_scintilla_get_clipboard(void *handle) { - int len = 0; - char *buf = scintilla_get_clipboard((Scintilla *)handle, &len); - if (!buf) return ""; - /* Copy into static buffer so Chez can read it, then free */ - if (len >= RECV_BUF_SIZE) len = RECV_BUF_SIZE - 1; - memcpy(recv_buf, buf, len); - recv_buf[len] = '\0'; - free(buf); - return recv_buf; -} - -/* ================================================================ - Lexilla integration - ================================================================ */ -#define SCI_SETILEXER_MSG 4033 - -void chez_scintilla_set_lexer_language(void *handle, const char *lang) { - ILexer5 *lexer = CreateLexer(lang); - scintilla_send_message((Scintilla *)handle, SCI_SETILEXER_MSG, - 0, (sptr_t)lexer); -} - -/* ================================================================ - Notification drain - ================================================================ */ -int chez_scintilla_drain_one(void *handle) { - instance_node_t *inst = find_instance((Scintilla *)handle); - if (!inst) return 0; - if (inst->ring_head == inst->ring_tail) return 0; - - current_scn = inst->ring[inst->ring_tail]; - inst->ring_tail = (inst->ring_tail + 1) % NOTIFY_RING_SIZE; - return 1; -} - -int chez_scn_code(void) { return current_scn.code; } -long chez_scn_position(void) { return current_scn.position; } -int chez_scn_ch(void) { return current_scn.ch; } -int chez_scn_modifiers(void) { return current_scn.modifiers; } -int chez_scn_modification_type(void) { return current_scn.modification_type; } -const char *chez_scn_text(void) { return current_scn.text; } -long chez_scn_length(void) { return current_scn.length; } -long chez_scn_lines_added(void) { return current_scn.lines_added; } -int chez_scn_message(void) { return current_scn.message; } -long chez_scn_line(void) { return current_scn.line; } -int chez_scn_fold_level_now(void) { return current_scn.fold_level_now; } -int chez_scn_fold_level_prev(void) { return current_scn.fold_level_prev; } -int chez_scn_margin(void) { return current_scn.margin; } -int chez_scn_list_type(void) { return current_scn.list_type; } -int chez_scn_x(void) { return current_scn.x; } -int chez_scn_y(void) { return current_scn.y; } -int chez_scn_token(void) { return current_scn.token; } -int chez_scn_updated(void) { return current_scn.updated; } - -/* ================================================================ - Termbox wrappers - ================================================================ */ -static struct tb_event last_tb_event; - -int chez_tb_init(void) { return tb_init(); } -void chez_tb_shutdown(void) { tb_shutdown(); } -int chez_tb_width(void) { return tb_width(); } -int chez_tb_height(void) { return tb_height(); } -void chez_tb_clear(void) { tb_clear(); } -void chez_tb_present(void) { tb_present(); } -void chez_tb_set_cursor(int x, int y) { tb_set_cursor(x, y); } - -int chez_tb_poll_event(void) { - return tb_poll_event(&last_tb_event); -} - -int chez_tb_peek_event(int timeout_ms) { - return tb_peek_event(&last_tb_event, timeout_ms); -} - -int chez_tb_event_type(void) { return last_tb_event.type; } -int chez_tb_event_mod(void) { return last_tb_event.mod; } -int chez_tb_event_key(void) { return last_tb_event.key; } -unsigned int chez_tb_event_ch(void) { return last_tb_event.ch; } -int chez_tb_event_w(void) { return last_tb_event.w; } -int chez_tb_event_h(void) { return last_tb_event.h; } -int chez_tb_event_x(void) { return last_tb_event.x; } -int chez_tb_event_y(void) { return last_tb_event.y; } - -/* ================================================================ - Termbox extended wrappers - ================================================================ */ -void chez_tb_change_cell(int x, int y, uint32_t ch, uint32_t fg, uint32_t bg) { - tb_change_cell(x, y, ch, fg, bg); -} - -void chez_tb_set_clear_attributes(uint32_t fg, uint32_t bg) { - tb_set_clear_attributes(fg, bg); -} - -int chez_tb_select_input_mode(int mode) { - return tb_select_input_mode(mode); -} - -int chez_tb_select_output_mode(int mode) { - return tb_select_output_mode(mode); -} - -void chez_tb_print_string(int x, int y, uint32_t fg, uint32_t bg, const char *str) { - uint32_t ch; - while (*str) { - int len = utf8_char_to_unicode(&ch, str); - if (len <= 0) break; - tb_change_cell(x, y, ch, fg, bg); - x++; - str += len; - } -} new file mode 100644 --- /dev/null +++ b/jerboa_scintilla_shim.c @@ -0,0 +1,341 @@ +/* jerboa_scintilla_shim.c — C shim for Chez Scheme FFI to Scintilla + termbox + * + * Extracted from gerbil-scintilla/ffi.ss c-declare block. + * Provides: instance lifecycle, message passing, notification ring buffer, + * input, display, clipboard, lexilla, and termbox wrappers. + * + * All functions use simple C types (void*, int, long, const char*) + * compatible with Chez Scheme's foreign-procedure. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdint.h> +#include <stdbool.h> + +#include "Scintilla.h" +#include "ScintillaTermbox.h" +#include "Lexilla.h" +#include "termbox.h" + +/* ================================================================ + Types + ================================================================ */ +typedef intptr_t sptr_t; +typedef uintptr_t uptr_t; +typedef void Scintilla; + +/* ================================================================ + Notification ring buffer (per-instance) + ================================================================ */ +#define NOTIFY_RING_SIZE 64 + +typedef struct { + int code; + long position; + int ch; + int modifiers; + int modification_type; + char text[256]; + long length; + long lines_added; + int message; + long line; + int fold_level_now; + int fold_level_prev; + int margin; + int list_type; + int x; + int y; + int token; + int updated; +} notify_entry_t; + +typedef struct instance_node { + Scintilla *view; + notify_entry_t ring[NOTIFY_RING_SIZE]; + int ring_head; + int ring_tail; + struct instance_node *next; +} instance_node_t; + +static instance_node_t *instance_list = NULL; + +/* Current notification (static, for drain_one -> accessor pattern) */ +static notify_entry_t current_scn; + +/* Find instance node by view pointer */ +static instance_node_t *find_instance(Scintilla *view) { + instance_node_t *n = instance_list; + while (n) { + if (n->view == view) return n; + n = n->next; + } + return NULL; +} + +/* Notification callback — called synchronously from C++ */ +static void notification_callback(Scintilla *view, int msg, + SCNotification *scn, void *userdata) { + instance_node_t *inst = find_instance(view); + if (!inst) return; + + int next_head = (inst->ring_head + 1) % NOTIFY_RING_SIZE; + if (next_head == inst->ring_tail) { + /* Ring full — drop oldest */ + inst->ring_tail = (inst->ring_tail + 1) % NOTIFY_RING_SIZE; + } + + notify_entry_t *e = &inst->ring[inst->ring_head]; + e->code = scn->nmhdr.code; + e->position = (long)scn->position; + e->ch = scn->ch; + e->modifiers = scn->modifiers; + e->modification_type = scn->modificationType; + e->length = (long)scn->length; + e->lines_added = (long)scn->linesAdded; + e->message = scn->message; + e->line = (long)scn->line; + e->fold_level_now = scn->foldLevelNow; + e->fold_level_prev = scn->foldLevelPrev; + e->margin = scn->margin; + e->list_type = scn->listType; + e->x = scn->x; + e->y = scn->y; + e->token = scn->token; + e->updated = scn->updated; + + if (scn->text && scn->length > 0) { + int copy_len = scn->length < 255 ? scn->length : 255; + memcpy(e->text, scn->text, copy_len); + e->text[copy_len] = '\0'; + } else { + e->text[0] = '\0'; + } + + inst->ring_head = next_head; +} + +/* ================================================================ + Instance lifecycle + ================================================================ */ +void *jerboa_scintilla_new(void) { + Scintilla *sci = scintilla_new(notification_callback, NULL); + if (!sci) return NULL; + + instance_node_t *node = (instance_node_t *)malloc(sizeof(instance_node_t)); + node->view = sci; + node->ring_head = 0; + node->ring_tail = 0; + node->next = instance_list; + instance_list = node; + + return (void *)sci; +} + +void jerboa_scintilla_delete(void *handle) { + Scintilla *sci = (Scintilla *)handle; + /* Remove from instance list */ + instance_node_t **pp = &instance_list; + while (*pp) { + if ((*pp)->view == sci) { + instance_node_t *rm = *pp; + *pp = rm->next; + free(rm); + break; + } + pp = &(*pp)->next; + } + scintilla_delete(sci); +} + +/* ================================================================ + Message passing + ================================================================ */ +long jerboa_scintilla_send_message(void *handle, unsigned int msg, + unsigned long wparam, long lparam) { + return (long)scintilla_send_message((Scintilla *)handle, msg, + (uptr_t)wparam, (sptr_t)lparam); +} + +/* Send message with string as lparam (cast char* to sptr_t) */ +long jerboa_scintilla_send_message_string(void *handle, unsigned int msg, + unsigned long wparam, const char *str) { + return (long)scintilla_send_message((Scintilla *)handle, msg, + (uptr_t)wparam, (sptr_t)str); +} + +/* Receive string: call msg twice (get length, then fill buffer) */ +#define RECV_BUF_SIZE 65536 +static char recv_buf[RECV_BUF_SIZE]; + +const char *jerboa_scintilla_receive_string(void *handle, unsigned int msg, + unsigned long wparam) { + long len = (long)scintilla_send_message((Scintilla *)handle, msg, + (uptr_t)wparam, (sptr_t)NULL); + if (len <= 0) { + recv_buf[0] = '\0'; + return recv_buf; + } + if (len >= RECV_BUF_SIZE) len = RECV_BUF_SIZE - 1; + scintilla_send_message((Scintilla *)handle, msg, + (uptr_t)wparam, (sptr_t)recv_buf); + recv_buf[len] = '\0'; + return recv_buf; +} + +/* Set property: wparam = key string, lparam = value string */ +long jerboa_scintilla_set_property(void *handle, unsigned int msg, + const char *key, const char *value) { + return (long)scintilla_send_message((Scintilla *)handle, msg, + (uptr_t)key, (sptr_t)value); +} + +/* ================================================================ + Input + ================================================================ */ +void jerboa_scintilla_send_key(void *handle, int key, + int shift, int ctrl, int alt) { + scintilla_send_key((Scintilla *)handle, key, shift, ctrl, alt); +} + +int jerboa_scintilla_send_mouse(void *handle, int event, int button, + int y, int x, + int shift, int ctrl, int alt) { + return scintilla_send_mouse((Scintilla *)handle, event, button, + y, x, shift, ctrl, alt); +} + +/* ================================================================ + Display + ================================================================ */ +void jerboa_scintilla_refresh(void *handle) { + scintilla_refresh((Scintilla *)handle); +} + +void jerboa_scintilla_resize(void *handle, int width, int height) { + scintilla_resize((Scintilla *)handle, width, height); +} + +void jerboa_scintilla_move(void *handle, int x, int y) { + scintilla_move((Scintilla *)handle, x, y); +} + +/* ================================================================ + Clipboard + ================================================================ */ +const char *jerboa_scintilla_get_clipboard(void *handle) { + int len = 0; + char *buf = scintilla_get_clipboard((Scintilla *)handle, &len); + if (!buf) return ""; + /* Copy into static buffer so Chez can read it, then free */ + if (len >= RECV_BUF_SIZE) len = RECV_BUF_SIZE - 1; + memcpy(recv_buf, buf, len); + recv_buf[len] = '\0'; + free(buf); + return recv_buf; +} + +/* ================================================================ + Lexilla integration + ================================================================ */ +#define SCI_SETILEXER_MSG 4033 + +void jerboa_scintilla_set_lexer_language(void *handle, const char *lang) { + ILexer5 *lexer = CreateLexer(lang); + scintilla_send_message((Scintilla *)handle, SCI_SETILEXER_MSG, + 0, (sptr_t)lexer); +} + +/* ================================================================ + Notification drain + ================================================================ */ +int jerboa_scintilla_drain_one(void *handle) { + instance_node_t *inst = find_instance((Scintilla *)handle); + if (!inst) return 0; + if (inst->ring_head == inst->ring_tail) return 0; + + current_scn = inst->ring[inst->ring_tail]; + inst->ring_tail = (inst->ring_tail + 1) % NOTIFY_RING_SIZE; + return 1; +} + +int jerboa_scn_code(void) { return current_scn.code; } +long jerboa_scn_position(void) { return current_scn.position; } +int jerboa_scn_ch(void) { return current_scn.ch; } +int jerboa_scn_modifiers(void) { return current_scn.modifiers; } +int jerboa_scn_modification_type(void) { return current_scn.modification_type; } +const char *jerboa_scn_text(void) { return current_scn.text; } +long jerboa_scn_length(void) { return current_scn.length; } +long jerboa_scn_lines_added(void) { return current_scn.lines_added; } +int jerboa_scn_message(void) { return current_scn.message; } +long jerboa_scn_line(void) { return current_scn.line; } +int jerboa_scn_fold_level_now(void) { return current_scn.fold_level_now; } +int jerboa_scn_fold_level_prev(void) { return current_scn.fold_level_prev; } +int jerboa_scn_margin(void) { return current_scn.margin; } +int jerboa_scn_list_type(void) { return current_scn.list_type; } +int jerboa_scn_x(void) { return current_scn.x; } +int jerboa_scn_y(void) { return current_scn.y; } +int jerboa_scn_token(void) { return current_scn.token; } +int jerboa_scn_updated(void) { return current_scn.updated; } + +/* ================================================================ + Termbox wrappers + ================================================================ */ +static struct tb_event last_tb_event; + +int jerboa_tb_init(void) { return tb_init(); } +void jerboa_tb_shutdown(void) { tb_shutdown(); } +int jerboa_tb_width(void) { return tb_width(); } +int jerboa_tb_height(void) { return tb_height(); } +void jerboa_tb_clear(void) { tb_clear(); } +void jerboa_tb_present(void) { tb_present(); } +void jerboa_tb_set_cursor(int x, int y) { tb_set_cursor(x, y); } + +int jerboa_tb_poll_event(void) { + return tb_poll_event(&last_tb_event); +} + +int jerboa_tb_peek_event(int timeout_ms) { + return tb_peek_event(&last_tb_event, timeout_ms); +} + +int jerboa_tb_event_type(void) { return last_tb_event.type; } +int jerboa_tb_event_mod(void) { return last_tb_event.mod; } +int jerboa_tb_event_key(void) { return last_tb_event.key; } +unsigned int jerboa_tb_event_ch(void) { return last_tb_event.ch; } +int jerboa_tb_event_w(void) { return last_tb_event.w; } +int jerboa_tb_event_h(void) { return last_tb_event.h; } +int jerboa_tb_event_x(void) { return last_tb_event.x; } +int jerboa_tb_event_y(void) { return last_tb_event.y; } + +/* ================================================================ + Termbox extended wrappers + ================================================================ */ +void jerboa_tb_change_cell(int x, int y, uint32_t ch, uint32_t fg, uint32_t bg) { + tb_change_cell(x, y, ch, fg, bg); +} + +void jerboa_tb_set_clear_attributes(uint32_t fg, uint32_t bg) { + tb_set_clear_attributes(fg, bg); +} + +int jerboa_tb_select_input_mode(int mode) { + return tb_select_input_mode(mode); +} + +int jerboa_tb_select_output_mode(int mode) { + return tb_select_output_mode(mode); +} + +void jerboa_tb_print_string(int x, int y, uint32_t fg, uint32_t bg, const char *str) { + uint32_t ch; + while (*str) { + int len = utf8_char_to_unicode(&ch, str); + if (len <= 0) break; + tb_change_cell(x, y, ch, fg, bg); + x++; + str += len; + } +} new file mode 100644 --- /dev/null +++ b/lib/jerboa-scintilla/autocomplete.sls @@ -0,0 +1,147 @@ +#!chezscheme +;;; Generated by jerbuild — DO NOT EDIT +;;; Source: src/jerboa-scintilla/autocomplete.ss + +(library (jerboa-scintilla autocomplete) + (export editor-autocomplete-show editor-autocomplete-cancel + editor-autocomplete-active? editor-autocomplete-pos-start + editor-autocomplete-complete editor-autocomplete-select + editor-autocomplete-get-current editor-autocomplete-stops + editor-autocomplete-set-separator + editor-autocomplete-get-separator + editor-autocomplete-set-ignore-case + editor-autocomplete-get-ignore-case? + editor-autocomplete-set-choose-single + editor-autocomplete-get-choose-single? + editor-autocomplete-set-auto-hide + editor-autocomplete-get-auto-hide? + editor-autocomplete-set-drop-rest-of-word + editor-autocomplete-get-drop-rest-of-word? + editor-autocomplete-set-cancel-at-start + editor-autocomplete-get-cancel-at-start? + editor-autocomplete-set-order editor-autocomplete-get-order + editor-autocomplete-set-max-width + editor-autocomplete-get-max-width + editor-autocomplete-set-max-height + editor-autocomplete-get-max-height + editor-autocomplete-set-fill-ups editor-calltip-show + editor-calltip-cancel editor-calltip-active? + editor-calltip-pos-start editor-calltip-set-highlight + editor-calltip-set-background editor-calltip-set-foreground + editor-calltip-set-foreground-highlight) + (import + (except (chezscheme) make-hash-table hash-table? sort sort! + printf fprintf format path-extension path-absolute? + with-input-from-string with-output-to-string iota \x31;+ + \x31;- partition make-date make-time meta atom?) + (jerboa prelude) + (jerboa-scintilla constants) + (jerboa-scintilla scintilla)) + (def (editor-autocomplete-show editor len-entered items) + (send-message/string editor SCI_AUTOCSHOW items)) + (def (editor-autocomplete-cancel editor) + (send-message editor SCI_AUTOCCANCEL)) + (def (editor-autocomplete-active? editor) + (not (zero? (send-message editor SCI_AUTOCACTIVE)))) + (def (editor-autocomplete-pos-start editor) + (send-message editor SCI_AUTOCPOSSTART)) + (def (editor-autocomplete-complete editor) + (send-message editor SCI_AUTOCCOMPLETE)) + (def (editor-autocomplete-select editor text) + (send-message/string editor SCI_AUTOCSELECT text)) + (def (editor-autocomplete-get-current editor) + (send-message editor SCI_AUTOCGETCURRENT)) + (def (editor-autocomplete-stops editor chars) + (send-message/string editor SCI_AUTOCSTOPS chars)) + (def (editor-autocomplete-set-separator editor char-code) + (send-message editor SCI_AUTOCSETSEPARATOR char-code)) + (def (editor-autocomplete-get-separator editor) + (send-message editor SCI_AUTOCGETSEPARATOR)) + (def (editor-autocomplete-set-ignore-case editor ignore?) + (send-message + editor + SCI_AUTOCSETIGNORECASE + (if ignore? 1 0))) + (def (editor-autocomplete-get-ignore-case? editor) + (not (zero? (send-message editor SCI_AUTOCGETIGNORECASE)))) + (def (editor-autocomplete-set-choose-single editor choose?) + (send-message + editor + SCI_AUTOCSETCHOOSESINGLE + (if choose? 1 0))) + (def (editor-autocomplete-get-choose-single? editor) + (not (zero? + (send-message editor SCI_AUTOCGETCHOOSESINGLE)))) + (def (editor-autocomplete-set-auto-hide editor hide?) + (send-message editor SCI_AUTOCSETAUTOHIDE (if hide? 1 0))) + (def (editor-autocomplete-get-auto-hide? editor) + (not (zero? (send-message editor SCI_AUTOCGETAUTOHIDE)))) + (def (editor-autocomplete-set-drop-rest-of-word + editor + drop?) + (send-message + editor + SCI_AUTOCSETDROPRESTOFWORD + (if drop? 1 0))) + (def (editor-autocomplete-get-drop-rest-of-word? editor) + (not (zero? + (send-message editor SCI_AUTOCGETDROPRESTOFWORD)))) + (def (editor-autocomplete-set-cancel-at-start + editor + cancel?) + (send-message + editor + SCI_AUTOCSETCANCELATSTART + (if cancel? 1 0))) + (def (editor-autocomplete-get-cancel-at-start? editor) + (not (zero? + (send-message editor SCI_AUTOCGETCANCELATSTART)))) + (def (editor-autocomplete-set-order editor order) + (send-message + editor + SCI_AUTOCSETORDER + (case order + [(presorted) SC_ORDER_PRESORTED] + [(perform-sort) SC_ORDER_PERFORMSORT] + [(custom) SC_ORDER_CUSTOM] + [else SC_ORDER_PRESORTED]))) + (def (editor-autocomplete-get-order editor) + (let ([mode (send-message editor SCI_AUTOCGETORDER)]) + (cond + [(= mode SC_ORDER_PRESORTED) 'presorted] + [(= mode SC_ORDER_PERFORMSORT) 'perform-sort] + [(= mode SC_ORDER_CUSTOM) 'custom] + [else 'presorted]))) + (def (editor-autocomplete-set-max-width editor chars) + (send-message editor SCI_AUTOCSETMAXWIDTH chars)) + (def (editor-autocomplete-get-max-width editor) + (send-message editor SCI_AUTOCGETMAXWIDTH)) + (def (editor-autocomplete-set-max-height editor rows) + (send-message editor SCI_AUTOCSETMAXHEIGHT rows)) + (def (editor-autocomplete-get-max-height editor) + (send-message editor SCI_AUTOCGETMAXHEIGHT)) + (def (editor-autocomplete-set-fill-ups editor chars) + (send-message/string editor SCI_AUTOCSETFILLUPS chars)) + (def (editor-calltip-show editor pos text) + (send-message/string editor SCI_CALLTIPSHOW text)) + (def (editor-calltip-cancel editor) + (send-message editor SCI_CALLTIPCANCEL)) + (def (editor-calltip-active? editor) + (not (zero? (send-message editor SCI_CALLTIPACTIVE)))) + (def (editor-calltip-pos-start editor) + (send-message editor SCI_CALLTIPPOSSTART)) + (def (editor-calltip-set-highlight + editor + highlight-start + highlight-end) + (send-message + editor + SCI_CALLTIPSETHLT + highlight-start + highlight-end)) + (def (editor-calltip-set-background editor color) + (send-message editor SCI_CALLTIPSETBACK color)) + (def (editor-calltip-set-foreground editor color) + (send-message editor SCI_CALLTIPSETFORE color)) + (def (editor-calltip-set-foreground-highlight editor color) + (send-message editor SCI_CALLTIPSETFOREHLT color))) new file mode 100644 --- /dev/null +++ b/lib/jerboa-scintilla/constants.sls @@ -0,0 +1,1184 @@ +#!chezscheme +;;; Generated by jerbuild — DO NOT EDIT +;;; Source: src/jerboa-scintilla/constants.ss + +(library (jerboa-scintilla constants) + (export SCI_SETTEXT SCI_GETTEXT SCI_GETTEXTLENGTH + SCI_GETCHARACTERPOINTER SCI_ADDTEXT SCI_ADDSTYLEDTEXT + SCI_INSERTTEXT SCI_CHANGEINSERTION SCI_CLEARALL + SCI_DELETERANGE SCI_CLEARDOCUMENTSTYLE SCI_APPENDTEXT + SCI_REPLACESEL SCI_TAB SCI_BACKTAB SCI_GETLENGTH + SCI_GETCHARAT SCI_GETCURRENTPOS SCI_GETANCHOR SCI_SETANCHOR + SCI_SETCURRENTPOS SCI_SETSEL SCI_GETSELTEXT SCI_SELECTALL + SCI_GOTOPOS SCI_GOTOLINE SCI_GETSELECTIONSTART + SCI_GETSELECTIONEND SCI_SETSELECTIONSTART + SCI_SETSELECTIONEND SCI_GETSELECTIONEMPTY + SCI_SETMOVEEXTENDSSELECTION SCI_GETMOVEEXTENDSSELECTION + SCI_GETLINE SCI_GETLINECOUNT SCI_LINEFROMPOSITION + SCI_POSITIONFROMLINE SCI_GETLINEENDPOSITION + SCI_LINESONSCREEN SCI_LINELENGTH SCI_GETCOLUMN + SCI_FINDCOLUMN SCI_POSITIONFROMPOINT + SCI_POSITIONFROMPOINTCLOSE SCI_POINTXFROMPOSITION + SCI_POINTYFROMPOSITION SCI_GETSTYLEAT SCI_STYLECLEARALL + SCI_STYLESETFORE SCI_STYLESETBACK SCI_STYLESETBOLD + SCI_STYLESETITALIC SCI_STYLESETSIZE SCI_STYLESETFONT + SCI_STYLESETEOLFILLED SCI_STYLERESETDEFAULT + SCI_STYLESETUNDERLINE SCI_STYLEGETFORE SCI_STYLEGETBACK + SCI_STYLEGETBOLD SCI_STYLEGETITALIC SCI_STYLEGETSIZE + SCI_STYLEGETFONT SCI_STYLEGETUNDERLINE SCI_STYLESETCASE + SCI_STYLEGETCASE SCI_STYLESETCHARACTERSET + SCI_STYLESETVISIBLE SCI_STYLEGETVISIBLE + SCI_STYLESETCHANGEABLE SCI_STYLEGETCHANGEABLE + SCI_STYLESETHOTSPOT SCI_STYLEGETHOTSPOT SCI_STYLESETWEIGHT + SCI_STYLEGETWEIGHT STYLE_DEFAULT STYLE_LINENUMBER + STYLE_BRACELIGHT STYLE_BRACEBAD STYLE_CONTROLCHAR