quakeforge/ruamoko/qwaq/builtins/curses.c
Bill Currie 973ae0ad54 [gamecode] Add PR_Shutdown for tearing down a VM
This is meant for a "permanent" tear-down before freeing the memory
holding the VM state or at program shutdown. As a consequence, builtin
sub-systems registering resources are now required to pass a "destroy"
function pointer that will be called just before the memory holding
those resources is freed by the VM resource manager (ie, the manager
owns the resource memory block, but each subsystem is responsible for
cleaning up any resources held within that block).

This even enhances thread-safety in rua_obj (there are some problems
with cmd, cvar, and gib).
2022-05-12 19:58:18 +09:00

1975 lines
48 KiB
C

/*
curses.c
Ruamoko ncurses wrapper using threading
Copyright (C) 2020 Bill Currie <bill@taniwha.org>
Author: Bill Currie <bill@taniwha.org>
Date: 2020/03/01
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <sys/time.h>
#include <curses.h>
#include <errno.h>
#include <panel.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "QF/dstring.h"
#include "QF/progs.h"
#include "QF/ringbuffer.h"
#include "QF/sys.h"
#include "rua_internal.h"
#include "ruamoko/qwaq/qwaq.h"
#include "ruamoko/qwaq/ui/curses.h"
#include "ruamoko/qwaq/ui/rect.h"
#include "ruamoko/qwaq/ui/textcontext.h"
#define always_inline inline __attribute__((__always_inline__))
#define CMD_SIZE(x) sizeof(x)/sizeof(x[0])
typedef enum qwaq_commands_e {
qwaq_cmd_syncprint,
qwaq_cmd_newwin,
qwaq_cmd_delwin,
qwaq_cmd_getwrect,
qwaq_cmd_new_panel,
qwaq_cmd_del_panel,
qwaq_cmd_hide_panel,
qwaq_cmd_show_panel,
qwaq_cmd_top_panel,
qwaq_cmd_bottom_panel,
qwaq_cmd_move_panel,
qwaq_cmd_panel_window,
qwaq_cmd_replace_panel,
qwaq_cmd_update_panels,
qwaq_cmd_doupdate,
qwaq_cmd_mvwaddstr,
qwaq_cmd_waddstr,
qwaq_cmd_mvwaddch,
qwaq_cmd_waddch,
qwaq_cmd_wrefresh,
qwaq_cmd_init_pair,
qwaq_cmd_wbkgd,
qwaq_cmd_werase,
qwaq_cmd_scrollok,
qwaq_cmd_wmove,
qwaq_cmd_move,
qwaq_cmd_curs_set,
qwaq_cmd_wborder,
qwaq_cmd_mvwblit_line,
qwaq_cmd_wresize,
qwaq_cmd_resizeterm,
qwaq_cmd_mvwhline,
qwaq_cmd_mvwvline,
} qwaq_commands;
static const char *qwaq_command_names[]= {
"syncprint",
"newwin",
"delwin",
"getwrect",
"new_panel",
"del_panel",
"hide_panel",
"show_panel",
"top_panel",
"bottom_panel",
"move_panel",
"panel_window",
"replace_panel",
"update_panels",
"doupdate",
"mvwaddstr",
"waddstr",
"mvwaddch",
"waddch",
"wrefresh",
"init_pair",
"wbkgd",
"werase",
"scrollok",
"wmove",
"move",
"curs_set",
"wborder",
"mvwblit_line",
"wresize",
"resizeterm",
"mvwhline",
"mvwvline",
"send_connected_devices",
"get_device_info",
};
static window_t *
window_new (qwaq_resources_t *res)
{
return PR_RESNEW (res->window_map);
}
static void
window_free (qwaq_resources_t *res, window_t *win)
{
PR_RESFREE (res->window_map, win);
}
static void
window_reset (qwaq_resources_t *res)
{
PR_RESRESET (res->window_map);
}
static inline window_t *
window_get (qwaq_resources_t *res, unsigned index)
{
return PR_RESGET(res->window_map, index);
}
static inline int __attribute__((pure))
window_index (qwaq_resources_t *res, window_t *win)
{
return PR_RESINDEX (res->window_map, win);
}
static always_inline window_t * __attribute__((pure))
get_window (qwaq_resources_t *res, const char *name, int handle)
{
if (handle == 1) {
return &res->stdscr;
}
window_t *window = window_get (res, handle);
if (!window || !window->win) {
PR_RunError (res->pr, "invalid window %d passed to %s",
handle, name + 5);
}
return window;
}
static panel_t *
panel_new (qwaq_resources_t *res)
{
return PR_RESNEW (res->panel_map);
}
static void
panel_free (qwaq_resources_t *res, panel_t *win)
{
PR_RESFREE (res->panel_map, win);
}
static void
panel_reset (qwaq_resources_t *res)
{
PR_RESRESET (res->panel_map);
}
static inline panel_t *
panel_get (qwaq_resources_t *res, unsigned index)
{
return PR_RESGET(res->panel_map, index);
}
static inline int __attribute__((pure))
panel_index (qwaq_resources_t *res, panel_t *win)
{
return PR_RESINDEX (res->panel_map, win);
}
static always_inline panel_t * __attribute__((pure))
get_panel (qwaq_resources_t *res, const char *name, int handle)
{
panel_t *panel = panel_get (res, handle);
if (!panel || !panel->panel) {
PR_RunError (res->pr, "invalid panel passed to %s", name + 3);
}
return panel;
}
static int
qwaq_cmd_peek (qwaq_resources_t *res, int ahead)
{
return *RB_PEEK_DATA (res->commands.pipe, ahead);
}
static dstring_t *
qwaq_cmd_string (qwaq_resources_t *res, int string_id)
{
return res->commands.strings + string_id;
}
static void
cmd_syncprint (qwaq_resources_t *res)
{
int string_id = qwaq_cmd_peek (res, 2);
Sys_Printf ("%s\n", qwaq_cmd_string (res, string_id)->str);
qwaq_pipe_release_string (&res->commands, string_id);
}
static void
cmd_newwin (qwaq_resources_t *res)
{
int xpos = qwaq_cmd_peek (res, 2);
int ypos = qwaq_cmd_peek (res, 3);
int xlen = qwaq_cmd_peek (res, 4);
int ylen = qwaq_cmd_peek (res, 5);
window_t *window = window_new (res);
window->win = newwin (ylen, xlen, ypos, xpos);
keypad (window->win, FALSE); // do it ourselves
int window_id = window_index (res, window);
int cmd_result[] = { qwaq_cmd_newwin, window_id };
qwaq_pipe_submit (&res->results, cmd_result, CMD_SIZE (cmd_result));
}
static void
cmd_delwin (qwaq_resources_t *res)
{
int window_id = qwaq_cmd_peek (res, 2);
window_t *window = get_window (res, __FUNCTION__, window_id);
delwin (window->win);
window_free (res, window);
}
static void
cmd_getwrect (qwaq_resources_t *res)
{
int window_id = qwaq_cmd_peek (res, 2);
int xpos, ypos;
int xlen, ylen;
window_t *window = get_window (res, __FUNCTION__, window_id);
getparyx (window->win, ypos, xpos);
if (xpos == -1 && ypos ==-1) {
getbegyx (window->win, ypos, xpos);
}
getmaxyx (window->win, ylen, xlen);
int cmd_result[] = { qwaq_cmd_getwrect, xpos, ypos, xlen, ylen };
qwaq_pipe_submit (&res->results, cmd_result, CMD_SIZE (cmd_result));
}
static void
cmd_new_panel (qwaq_resources_t *res)
{
int window_id = qwaq_cmd_peek (res, 2);
window_t *window = get_window (res, __FUNCTION__, window_id);
panel_t *panel = panel_new (res);
panel->panel = new_panel (window->win);
panel->window_id = window_id;
int panel_id = panel_index (res, panel);
int cmd_result[] = { qwaq_cmd_new_panel, panel_id };
qwaq_pipe_submit (&res->results, cmd_result, CMD_SIZE (cmd_result));
}
static void
cmd_del_panel (qwaq_resources_t *res)
{
int panel_id = qwaq_cmd_peek (res, 2);
panel_t *panel = get_panel (res, __FUNCTION__, panel_id);
del_panel (panel->panel);
panel_free (res, panel);
}
static void
cmd_hide_panel (qwaq_resources_t *res)
{
int panel_id = qwaq_cmd_peek (res, 2);
panel_t *panel = get_panel (res, __FUNCTION__, panel_id);
hide_panel (panel->panel);
}
static void
cmd_show_panel (qwaq_resources_t *res)
{
int panel_id = qwaq_cmd_peek (res, 2);
panel_t *panel = get_panel (res, __FUNCTION__, panel_id);
show_panel (panel->panel);
}
static void
cmd_top_panel (qwaq_resources_t *res)
{
int panel_id = qwaq_cmd_peek (res, 2);
panel_t *panel = get_panel (res, __FUNCTION__, panel_id);
top_panel (panel->panel);
}
static void
cmd_bottom_panel (qwaq_resources_t *res)
{
int panel_id = qwaq_cmd_peek (res, 2);
panel_t *panel = get_panel (res, __FUNCTION__, panel_id);
bottom_panel (panel->panel);
}
static void
cmd_move_panel (qwaq_resources_t *res)
{
int panel_id = qwaq_cmd_peek (res, 2);
int x = qwaq_cmd_peek (res, 3);
int y = qwaq_cmd_peek (res, 4);
panel_t *panel = get_panel (res, __FUNCTION__, panel_id);
move_panel (panel->panel, y, x);
}
static void
cmd_panel_window (qwaq_resources_t *res)
{
int panel_id = qwaq_cmd_peek (res, 2);
panel_t *panel = get_panel (res, __FUNCTION__, panel_id);
int window_id = panel->window_id;
int cmd_result[] = { qwaq_cmd_panel_window, window_id, };
qwaq_pipe_submit (&res->results, cmd_result, CMD_SIZE (cmd_result));
}
static void
cmd_replace_panel (qwaq_resources_t *res)
{
int panel_id = qwaq_cmd_peek (res, 2);
int window_id = qwaq_cmd_peek (res, 3);
panel_t *panel = get_panel (res, __FUNCTION__, panel_id);
window_t *window = get_window (res, __FUNCTION__, window_id);
replace_panel (panel->panel, window->win);
}
static void
cmd_update_panels (qwaq_resources_t *res)
{
update_panels ();
}
static void
cmd_doupdate (qwaq_resources_t *res)
{
doupdate ();
}
static void
cmd_mvwaddstr (qwaq_resources_t *res)
{
int window_id = qwaq_cmd_peek (res, 2);
int x = qwaq_cmd_peek (res, 3);
int y = qwaq_cmd_peek (res, 4);
int string_id = qwaq_cmd_peek (res, 5);
window_t *window = get_window (res, __FUNCTION__, window_id);
mvwaddstr (window->win, y, x, qwaq_cmd_string (res, string_id)->str);
qwaq_pipe_release_string (&res->commands, string_id);
}
static void
cmd_waddstr (qwaq_resources_t *res)
{
int window_id = qwaq_cmd_peek (res, 2);
int string_id = qwaq_cmd_peek (res, 3);
window_t *window = get_window (res, __FUNCTION__, window_id);
waddstr (window->win, qwaq_cmd_string (res, string_id)->str);
qwaq_pipe_release_string (&res->commands, string_id);
}
static void
cmd_mvwaddch (qwaq_resources_t *res)
{
int window_id = qwaq_cmd_peek (res, 2);
int x = qwaq_cmd_peek (res, 3);
int y = qwaq_cmd_peek (res, 4);
int ch = qwaq_cmd_peek (res, 5);
window_t *window = get_window (res, __FUNCTION__, window_id);
mvwaddch (window->win, y, x, ch);
}
static void
cmd_waddch (qwaq_resources_t *res)
{
int window_id = qwaq_cmd_peek (res, 2);
int ch = qwaq_cmd_peek (res, 3);
window_t *window = get_window (res, __FUNCTION__, window_id);
waddch (window->win, ch);
}
static void
cmd_wrefresh (qwaq_resources_t *res)
{
int window_id = qwaq_cmd_peek (res, 2);
window_t *window = get_window (res, __FUNCTION__, window_id);
wrefresh (window->win);
}
static void
cmd_init_pair (qwaq_resources_t *res)
{
int pair = qwaq_cmd_peek (res, 2);
int f = qwaq_cmd_peek (res, 3);
int b = qwaq_cmd_peek (res, 4);
init_pair (pair, f, b);
}
static void
cmd_wbkgd (qwaq_resources_t *res)
{
int window_id = qwaq_cmd_peek (res, 2);
int ch = qwaq_cmd_peek (res, 3);
window_t *window = get_window (res, __FUNCTION__, window_id);
wbkgd (window->win, ch);
}
static void
cmd_werase (qwaq_resources_t *res)
{
int window_id = qwaq_cmd_peek (res, 2);
window_t *window = get_window (res, __FUNCTION__, window_id);
werase (window->win);
}
static void
cmd_scrollok (qwaq_resources_t *res)
{
int window_id = qwaq_cmd_peek (res, 2);
int flag = qwaq_cmd_peek (res, 3);
window_t *window = get_window (res, __FUNCTION__, window_id);
scrollok (window->win, flag);
}
static void
cmd_wmove (qwaq_resources_t *res)
{
int window_id = qwaq_cmd_peek (res, 2);
int x = qwaq_cmd_peek (res, 3);
int y = qwaq_cmd_peek (res, 4);
window_t *window = get_window (res, __FUNCTION__, window_id);
wmove (window->win, y, x);
}
static void
cmd_move (qwaq_resources_t *res)
{
int x = qwaq_cmd_peek (res, 2);
int y = qwaq_cmd_peek (res, 3);
move (y, x);
}
static void
cmd_curs_set (qwaq_resources_t *res)
{
int visibility = qwaq_cmd_peek (res, 2);
curs_set (visibility);
}
static void
cmd_wborder (qwaq_resources_t *res)
{
int window_id = qwaq_cmd_peek (res, 2);
int ls = qwaq_cmd_peek (res, 3);
int rs = qwaq_cmd_peek (res, 4);
int ts = qwaq_cmd_peek (res, 5);
int bs = qwaq_cmd_peek (res, 6);
int tl = qwaq_cmd_peek (res, 7);
int tr = qwaq_cmd_peek (res, 8);
int bl = qwaq_cmd_peek (res, 9);
int br = qwaq_cmd_peek (res, 10);
window_t *window = get_window (res, __FUNCTION__, window_id);
wborder (window->win, ls, rs, ts, bs, tl, tr, bl, br);
}
static void
cmd_mvwblit_line (qwaq_resources_t *res)
{
int window_id = qwaq_cmd_peek (res, 2);
int x = qwaq_cmd_peek (res, 3);
int y = qwaq_cmd_peek (res, 4);
int chs_id = qwaq_cmd_peek (res, 5);
int len = qwaq_cmd_peek (res, 6);
int *chs = (int *) qwaq_cmd_string (res, chs_id)->str;
int save_x;
int save_y;
window_t *window = get_window (res, __FUNCTION__, window_id);
getyx (window->win, save_y, save_x);
for (int i = 0; i < len; i++) {
if (chs[i] & 0xff) {
mvwaddch (window->win, y, x + i, chs[i]);
}
}
wmove (window->win, save_y, save_x);
qwaq_pipe_release_string (&res->commands, chs_id);
}
static void
cmd_wresize (qwaq_resources_t *res)
{
int window_id = qwaq_cmd_peek (res, 2);
int width = qwaq_cmd_peek (res, 3);
int height = qwaq_cmd_peek (res, 4);
window_t *window = get_window (res, __FUNCTION__, window_id);
wresize (window->win, height, width);
}
static void
cmd_resizeterm (qwaq_resources_t *res)
{
int width = qwaq_cmd_peek (res, 2);
int height = qwaq_cmd_peek (res, 3);
resizeterm (height, width);
}
static void
cmd_mvwhline (qwaq_resources_t *res)
{
int window_id = qwaq_cmd_peek (res, 2);
int x = qwaq_cmd_peek (res, 3);
int y = qwaq_cmd_peek (res, 4);
int ch = qwaq_cmd_peek (res, 5);
int n = qwaq_cmd_peek (res, 6);
window_t *window = get_window (res, __FUNCTION__, window_id);
mvwhline (window->win, y, x, ch, n);
}
static void
cmd_mvwvline (qwaq_resources_t *res)
{
int window_id = qwaq_cmd_peek (res, 2);
int x = qwaq_cmd_peek (res, 3);
int y = qwaq_cmd_peek (res, 4);
int ch = qwaq_cmd_peek (res, 5);
int n = qwaq_cmd_peek (res, 6);
window_t *window = get_window (res, __FUNCTION__, window_id);
mvwvline (window->win, y, x, ch, n);
}
static void
dump_command (qwaq_resources_t *res, int len)
{
if (0) {
qwaq_commands cmd = qwaq_cmd_peek (res, 0);
Sys_Printf ("%s[%d]", qwaq_command_names[cmd], len);
if (cmd == qwaq_cmd_syncprint) {
Sys_Printf (" ");
} else {
for (int i = 2; i < len; i++) {
Sys_Printf (" %d", qwaq_cmd_peek (res, i));
}
Sys_Printf ("\n");
}
}
}
static void
process_commands (qwaq_resources_t *res)
{
struct timespec timeout;
int avail;
int len;
int ret = 0;
pthread_mutex_lock (&res->commands.pipe_cond.mut);
qwaq_init_timeout (&timeout, 20 * 1000000);
while (RB_DATA_AVAILABLE (res->commands.pipe) < 2 && ret == 0) {
ret = pthread_cond_timedwait (&res->commands.pipe_cond.rcond,
&res->commands.pipe_cond.mut, &timeout);
}
// The mutex is unlocked at the top of the loop and locked again
// (for broadcast) at the bottom, then finally unlocked after the loop.
// It should be only the data availability check that's not threadsafe
// as the mutex is not released until after the data has been written to
// the buffer.
while ((avail = RB_DATA_AVAILABLE (res->commands.pipe)) >= 2
&& avail >= (len = qwaq_cmd_peek (res, 1))) {
pthread_mutex_unlock (&res->commands.pipe_cond.mut);
dump_command (res, len);
qwaq_commands cmd = qwaq_cmd_peek (res, 0);
switch (cmd) {
case qwaq_cmd_syncprint:
cmd_syncprint (res);
break;
case qwaq_cmd_newwin:
cmd_newwin (res);
break;
case qwaq_cmd_delwin:
cmd_delwin (res);
break;
case qwaq_cmd_getwrect:
cmd_getwrect (res);
break;
case qwaq_cmd_new_panel:
cmd_new_panel (res);
break;
case qwaq_cmd_del_panel:
cmd_del_panel (res);
break;
case qwaq_cmd_hide_panel:
cmd_hide_panel (res);
break;
case qwaq_cmd_show_panel:
cmd_show_panel (res);
break;
case qwaq_cmd_top_panel:
cmd_top_panel (res);
break;
case qwaq_cmd_bottom_panel:
cmd_bottom_panel (res);
break;
case qwaq_cmd_move_panel:
cmd_move_panel (res);
break;
case qwaq_cmd_panel_window:
cmd_panel_window (res);
break;
case qwaq_cmd_replace_panel:
cmd_replace_panel (res);
break;
case qwaq_cmd_update_panels:
cmd_update_panels (res);
break;
case qwaq_cmd_doupdate:
cmd_doupdate (res);
break;
case qwaq_cmd_mvwaddstr:
cmd_mvwaddstr (res);
break;
case qwaq_cmd_waddstr:
cmd_waddstr (res);
break;
case qwaq_cmd_mvwaddch:
cmd_mvwaddch (res);
break;
case qwaq_cmd_waddch:
cmd_waddch (res);
break;
case qwaq_cmd_wrefresh:
cmd_wrefresh (res);
break;
case qwaq_cmd_init_pair:
cmd_init_pair (res);
break;
case qwaq_cmd_wbkgd:
cmd_wbkgd (res);
break;
case qwaq_cmd_werase:
cmd_werase (res);
break;
case qwaq_cmd_scrollok:
cmd_scrollok (res);
break;
case qwaq_cmd_wmove:
cmd_wmove (res);
break;
case qwaq_cmd_move:
cmd_move (res);
break;
case qwaq_cmd_curs_set:
cmd_curs_set (res);
break;
case qwaq_cmd_wborder:
cmd_wborder (res);
break;
case qwaq_cmd_mvwblit_line:
cmd_mvwblit_line (res);
break;
case qwaq_cmd_wresize:
cmd_wresize (res);
break;
case qwaq_cmd_resizeterm:
cmd_resizeterm (res);
break;
case qwaq_cmd_mvwhline:
cmd_mvwhline (res);
break;
case qwaq_cmd_mvwvline:
cmd_mvwvline (res);
break;
}
pthread_mutex_lock (&res->commands.pipe_cond.mut);
RB_RELEASE (res->commands.pipe, len);
pthread_cond_broadcast (&res->commands.pipe_cond.wcond);
// unlocked at top of top if there's more data, otherwise just after
// the loop
}
pthread_mutex_unlock (&res->commands.pipe_cond.mut);
}
static int need_endwin;
static void
bi_shutdown (void *_pr)
{
if (need_endwin) {
qwaq_input_disable_mouse ();
endwin ();
}
}
static void
bi_syncprintf (progs_t *pr, void *_res)
{
qwaq_resources_t *res = _res;
int string_id = qwaq_pipe_acquire_string (&res->commands);
dstring_t *print_buffer = qwaq_cmd_string (res, string_id);
int command[] = { qwaq_cmd_syncprint, 0, string_id };
command[1] = CMD_SIZE(command);
dstring_clearstr (print_buffer);
RUA_Sprintf (pr, print_buffer, "syncprintf", 0);
qwaq_pipe_submit (&res->commands, command, command[1]);
}
static void
bi_create_window (progs_t *pr, void *_res)
{
qwaq_resources_t *res = _res;
int xpos = P_INT (pr, 0);
int ypos = P_INT (pr, 1);
int xlen = P_INT (pr, 2);
int ylen = P_INT (pr, 3);
int command[] = {
qwaq_cmd_newwin, 0,
xpos, ypos, xlen, ylen,
};
command[1] = CMD_SIZE(command);
qwaq_pipe_submit (&res->commands, command, command[1]);
int cmd_result[2];
qwaq_pipe_receive (&res->results, cmd_result, qwaq_cmd_newwin,
CMD_SIZE (cmd_result));
R_INT (pr) = cmd_result[1];
}
static void
bi_destroy_window (progs_t *pr, void *_res)
{
qwaq_resources_t *res = _res;
int window_id = P_INT (pr, 0);
if (get_window (res, __FUNCTION__, window_id)) {
int command[] = { qwaq_cmd_delwin, 0, window_id, };
command[1] = CMD_SIZE(command);
qwaq_pipe_submit (&res->commands, command, command[1]);
}
}
static void
qwaq_getwrect (qwaq_resources_t *res, int window_id)
{
progs_t *pr = res->pr;
if (get_window (res, __FUNCTION__, window_id)) {
int command[] = { qwaq_cmd_getwrect, 0, window_id, };
command[1] = CMD_SIZE(command);
qwaq_pipe_submit (&res->commands, command, command[1]);
int cmd_result[5];
qwaq_pipe_receive (&res->results, cmd_result, qwaq_cmd_getwrect,
CMD_SIZE (cmd_result));
// return xpos, ypos, xlen, ylen
(&R_INT (pr))[0] = cmd_result[1];
(&R_INT (pr))[1] = cmd_result[2];
(&R_INT (pr))[2] = cmd_result[3];
(&R_INT (pr))[3] = cmd_result[4];
}
}
static void
bi_getwrect (progs_t *pr, void *_res)
{
qwaq_resources_t *res = _res;
qwaq_getwrect (res, P_INT (pr, 0));
}
static void
bi_create_panel (progs_t *pr, void *_res)
{
qwaq_resources_t *res = _res;
int window_id = P_INT (pr, 0);
if (get_window (res, __FUNCTION__, window_id)) {
int command[] = { qwaq_cmd_new_panel, 0, window_id, };
command[1] = CMD_SIZE(command);
qwaq_pipe_submit (&res->commands, command, command[1]);
int cmd_result[2];
qwaq_pipe_receive (&res->results, cmd_result, qwaq_cmd_new_panel,
CMD_SIZE (cmd_result));
R_INT (pr) = cmd_result[1];
}
}
static void
panel_command (progs_t *pr, qwaq_resources_t *res, qwaq_commands cmd)
{
int panel_id = P_INT (pr, 0);
if (get_panel (res, __FUNCTION__, panel_id)) {
int command[] = { cmd, 0, panel_id, };
command[1] = CMD_SIZE(command);
qwaq_pipe_submit (&res->commands, command, command[1]);
}
}
static void
bi_destroy_panel (progs_t *pr, void *_res)
{
qwaq_resources_t *res = _res;
panel_command (pr, res, qwaq_cmd_del_panel);
}
static void
bi_hide_panel (progs_t *pr, void *_res)
{
qwaq_resources_t *res = _res;
panel_command (pr, res, qwaq_cmd_hide_panel);
}
static void
bi_show_panel (progs_t *pr, void *_res)
{
qwaq_resources_t *res = _res;
panel_command (pr, res, qwaq_cmd_show_panel);
}
static void
bi_top_panel (progs_t *pr, void *_res)
{
qwaq_resources_t *res = _res;
panel_command (pr, res, qwaq_cmd_top_panel);
}
static void
bi_bottom_panel (progs_t *pr, void *_res)
{
qwaq_resources_t *res = _res;
panel_command (pr, res, qwaq_cmd_bottom_panel);
}
static void
bi_move_panel (progs_t *pr, void *_res)
{
qwaq_resources_t *res = _res;
int panel_id = P_INT (pr, 0);
int x = P_INT (pr, 1);
int y = P_INT (pr, 2);
if (get_panel (res, __FUNCTION__, panel_id)) {
int command[] = { qwaq_cmd_move_panel, 0, panel_id, x, y, };
command[1] = CMD_SIZE(command);
qwaq_pipe_submit (&res->commands, command, command[1]);
}
}
static void
bi_panel_window (progs_t *pr, void *_res)
{
qwaq_resources_t *res = _res;
int panel_id = P_INT (pr, 0);
if (get_panel (res, __FUNCTION__, panel_id)) {
int command[] = { qwaq_cmd_panel_window, 0, panel_id, };
command[1] = CMD_SIZE(command);
qwaq_pipe_submit (&res->commands, command, command[1]);
int cmd_result[2];
qwaq_pipe_receive (&res->results, cmd_result, qwaq_cmd_panel_window,
CMD_SIZE (cmd_result));
(&R_INT (pr))[0] = cmd_result[1];
}
}
static void
bi_replace_panel (progs_t *pr, void *_res)
{
qwaq_resources_t *res = _res;
int panel_id = P_INT (pr, 0);
int window_id = P_INT (pr, 1);
if (get_panel (res, __FUNCTION__, panel_id)
&& get_window (res, __FUNCTION__, window_id)) {
int command[] = { qwaq_cmd_replace_panel, 0,
panel_id, window_id};
command[1] = CMD_SIZE(command);
qwaq_pipe_submit (&res->commands, command, command[1]);
}
}
static void
qwaq_update_panels (progs_t *pr, void *_res)
{
qwaq_resources_t *res = _res;
int command[] = { qwaq_cmd_update_panels, 0, };
command[1] = CMD_SIZE(command);
qwaq_pipe_submit (&res->commands, command, command[1]);
}
static void
bi_update_panels (progs_t *pr, void *_res)
{
qwaq_resources_t *res = _res;
qwaq_update_panels (pr, res);
}
static void
qwaq_doupdate (progs_t *pr, void *_res)
{
qwaq_resources_t *res = _res;
int command[] = { qwaq_cmd_doupdate, 0, };
command[1] = CMD_SIZE(command);
qwaq_pipe_submit (&res->commands, command, command[1]);
}
static void
bi_doupdate (progs_t *pr, void *_res)
{
qwaq_resources_t *res = _res;
qwaq_doupdate (pr, res);
}
static void
qwaq_waddstr (qwaq_resources_t *res, int window_id, const char *str)
{
if (get_window (res, __FUNCTION__, window_id)) {
int string_id = qwaq_pipe_acquire_string (&res->commands);
dstring_t *print_buffer = qwaq_cmd_string (res, string_id);
int command[] = {
qwaq_cmd_waddstr, 0,
window_id, string_id
};
command[1] = CMD_SIZE(command);
dstring_copystr (print_buffer, str);
qwaq_pipe_submit (&res->commands, command, command[1]);
}
}
static void
bi_waddstr (progs_t *pr, void *_res)
{
qwaq_resources_t *res = _res;
int window_id = P_INT (pr, 0);
const char *str = P_GSTRING (pr, 1);
qwaq_waddstr (res, window_id, str);
}
static void
qwaq_wresize (qwaq_resources_t *res, int window_id, int width, int height)
{
if (get_window (res, __FUNCTION__, window_id)) {
int command[] = {
qwaq_cmd_wresize, 0,
window_id, width, height
};
command[1] = CMD_SIZE(command);
qwaq_pipe_submit (&res->commands, command, command[1]);
}
}
static void
bi_wresize (progs_t *pr, void *_res)
{
qwaq_resources_t *res = _res;
int window_id = P_STRUCT (pr, qwaq_textcontext_t, 0).window;
int width = P_INT (pr, 1);
int height = P_INT (pr, 2);
qwaq_wresize (res, window_id, width, height);
}
static void
qwaq_resizeterm (qwaq_resources_t *res, int width, int height)
{
int command[] = { qwaq_cmd_resizeterm, 0, width, height };
command[1] = CMD_SIZE(command);
qwaq_pipe_submit (&res->commands, command, command[1]);
}
static void
bi_resizeterm (progs_t *pr, void *_res)
{
qwaq_resources_t *res = _res;
int width = P_INT (pr, 0);
int height = P_INT (pr, 1);
qwaq_resizeterm (res, width, height);
}
static void
qwaq_mvwhline (qwaq_resources_t *res, int window_id,
int x, int y, int ch, int n)
{
if (get_window (res, __FUNCTION__, window_id)) {
int command[] = {
qwaq_cmd_mvwhline, 0,
window_id, x, y, ch, n
};
command[1] = CMD_SIZE(command);
qwaq_pipe_submit (&res->commands, command, command[1]);
}
}
static void
bi_mvwhline (progs_t *pr, void *_res)
{
qwaq_resources_t *res = _res;
int window_id = P_STRUCT (pr, qwaq_textcontext_t, 0).window;
int x = P_INT (pr, 1);
int y = P_INT (pr, 2);
int ch = P_INT (pr, 3);
int n = P_INT (pr, 4);
qwaq_mvwhline (res, window_id, x, y, ch, n);
}
static void
qwaq_mvwvline (qwaq_resources_t *res, int window_id,
int x, int y, int ch, int n)
{
if (get_window (res, __FUNCTION__, window_id)) {
int command[] = {
qwaq_cmd_mvwvline, 0,
window_id, x, y, ch, n
};
command[1] = CMD_SIZE(command);
qwaq_pipe_submit (&res->commands, command, command[1]);
}
}
static void
bi_mvwvline (progs_t *pr, void *_res)
{
qwaq_resources_t *res = _res;
int window_id = P_STRUCT (pr, qwaq_textcontext_t, 0).window;
int x = P_INT (pr, 1);
int y = P_INT (pr, 2);
int ch = P_INT (pr, 3);
int n = P_INT (pr, 4);
qwaq_mvwvline (res, window_id, x, y, ch, n);
}
static void
qwaq_mvwaddstr (qwaq_resources_t *res, int window_id,
int x, int y, const char *str)
{
if (get_window (res, __FUNCTION__, window_id)) {
int string_id = qwaq_pipe_acquire_string (&res->commands);
dstring_t *print_buffer = qwaq_cmd_string (res, string_id);
int command[] = {
qwaq_cmd_mvwaddstr, 0,
window_id, x, y, string_id
};
command[1] = CMD_SIZE(command);
dstring_copystr (print_buffer, str);
qwaq_pipe_submit (&res->commands, command, command[1]);
}
}
static void
bi_mvwaddstr (progs_t *pr, void *_res)
{
qwaq_resources_t *res = _res;
int window_id = P_INT (pr, 0);
int x = P_INT (pr, 1);
int y = P_INT (pr, 2);
const char *str = P_GSTRING (pr, 3);
qwaq_mvwaddstr (res, window_id, x, y, str);
}
static void
qwaq_mvwprintf (qwaq_resources_t *res, int window_id,
int x, int y, int fmt_arg)
{
progs_t *pr = res->pr;
if (get_window (res, __FUNCTION__, window_id)) {
int string_id = qwaq_pipe_acquire_string (&res->commands);
dstring_t *print_buffer = qwaq_cmd_string (res, string_id);
int command[] = {
qwaq_cmd_mvwaddstr, 0,
window_id, x, y, string_id
};
command[1] = CMD_SIZE(command);
dstring_clearstr (print_buffer);
RUA_Sprintf (pr, print_buffer, "mvwaddstr", fmt_arg);
qwaq_pipe_submit (&res->commands, command, command[1]);
}
}
static void
bi_mvwprintf (progs_t *pr, void *_res)
{
qwaq_resources_t *res = _res;
int window_id = P_INT (pr, 0);
int x = P_INT (pr, 1);
int y = P_INT (pr, 2);
qwaq_mvwprintf (res, window_id, x, y, 3);
}
static void
qwaq_wprintf (qwaq_resources_t *res, int window_id, int fmt_arg)
{
progs_t *pr = res->pr;
if (get_window (res, __FUNCTION__, window_id)) {
int string_id = qwaq_pipe_acquire_string (&res->commands);
dstring_t *print_buffer = qwaq_cmd_string (res, string_id);
int command[] = {
qwaq_cmd_waddstr, 0,
window_id, string_id
};
command[1] = CMD_SIZE(command);
dstring_clearstr (print_buffer);
RUA_Sprintf (pr, print_buffer, "wprintf", fmt_arg);
qwaq_pipe_submit (&res->commands, command, command[1]);
}
}
static void
bi_wprintf (progs_t *pr, void *_res)
{
qwaq_resources_t *res = _res;
int window_id = P_INT (pr, 0);
qwaq_wprintf (res, window_id, 1);
}
static void
qwaq_wvprintf (qwaq_resources_t *res, int window_id,
const char *fmt, pr_va_list_t *args)
{
progs_t *pr = res->pr;
pr_type_t *list_start = PR_GetPointer (pr, args->list);
pr_type_t **list = alloca (args->count * sizeof (*list));
for (int i = 0; i < args->count; i++) {
list[i] = list_start + i * pr->pr_param_size;
}
if (get_window (res, __FUNCTION__, window_id)) {
int string_id = qwaq_pipe_acquire_string (&res->commands);
dstring_t *print_buffer = qwaq_cmd_string (res, string_id);
int command[] = {
qwaq_cmd_waddstr, 0,
window_id, string_id
};
command[1] = CMD_SIZE(command);
dstring_clearstr (print_buffer);
PR_Sprintf (pr, print_buffer, "wvprintf", fmt, args->count, list);
qwaq_pipe_submit (&res->commands, command, command[1]);
}
}
static void
bi_wvprintf (progs_t *pr, void *_res)
{
qwaq_resources_t *res = _res;
int window_id = P_INT (pr, 0);
const char *fmt = P_GSTRING (pr, 1);
__auto_type args = (pr_va_list_t *) &P_POINTER (pr, 2);
qwaq_wvprintf (res, window_id, fmt, args);
}
static void
qwaq_waddch (qwaq_resources_t *res, int window_id, int ch)
{
if (get_window (res, __FUNCTION__, window_id)) {
int command[] = { qwaq_cmd_waddch, 0, window_id, ch };
command[1] = CMD_SIZE(command);
qwaq_pipe_submit (&res->commands, command, command[1]);
}
}
static void
bi_waddch (progs_t *pr, void *_res)
{
qwaq_resources_t *res = _res;
int window_id = P_INT (pr, 0);
int ch = P_INT (pr, 0);
qwaq_waddch (res, window_id, ch);
}
static void
qwaq_mvwvprintf (qwaq_resources_t *res, int window_id, int x, int y,
const char *fmt, pr_va_list_t *args)
{
progs_t *pr = res->pr;
pr_type_t *list_start = PR_GetPointer (pr, args->list);
pr_type_t **list = alloca (args->count * sizeof (*list));
for (int i = 0; i < args->count; i++) {
list[i] = list_start + i * pr->pr_param_size;
}
if (get_window (res, __FUNCTION__, window_id)) {
int string_id = qwaq_pipe_acquire_string (&res->commands);
dstring_t *print_buffer = qwaq_cmd_string (res, string_id);
int command[] = {
qwaq_cmd_mvwaddstr, 0,
window_id, x, y, string_id
};
command[1] = CMD_SIZE(command);
dstring_clearstr (print_buffer);
PR_Sprintf (pr, print_buffer, "mvwvprintf", fmt, args->count, list);
qwaq_pipe_submit (&res->commands, command, command[1]);
}
}
static void
bi_mvwvprintf (progs_t *pr, void *_res)
{
qwaq_resources_t *res = _res;
int window_id = P_INT (pr, 0);
int x = P_INT (pr, 1);
int y = P_INT (pr, 2);
const char *fmt = P_GSTRING (pr, 2);
__auto_type args = (pr_va_list_t *) &P_POINTER (pr, 3);
qwaq_mvwvprintf (res, window_id, x, y, fmt, args);
}
static void
qwaq_mvwaddch (qwaq_resources_t *res, int window_id, int x, int y, int ch)
{
if (get_window (res, __FUNCTION__, window_id)) {
int command[] = {
qwaq_cmd_mvwaddch, 0,
window_id, x, y, ch
};
command[1] = CMD_SIZE(command);
qwaq_pipe_submit (&res->commands, command, command[1]);
}
}
static void
bi_mvwaddch (progs_t *pr, void *_res)
{
qwaq_resources_t *res = _res;
int window_id = P_INT (pr, 0);
int x = P_INT (pr, 1);
int y = P_INT (pr, 2);
int ch = P_INT (pr, 3);
qwaq_mvwaddch (res, window_id, x, y, ch);
}
static void
qwaq_wrefresh (qwaq_resources_t *res, int window_id)
{
if (get_window (res, __FUNCTION__, window_id)) {
int command[] = { qwaq_cmd_wrefresh, 0, window_id, };
command[1] = CMD_SIZE(command);
qwaq_pipe_submit (&res->commands, command, command[1]);
}
}
static void
bi_wrefresh (progs_t *pr, void *_res)
{
qwaq_resources_t *res = _res;
int window_id = P_INT (pr, 0);
qwaq_wrefresh (res, window_id);
}
static void
bi_max_colors (progs_t *pr, void *_res)
{
R_INT (pr) = COLORS;
}
static void
bi_max_color_pairs (progs_t *pr, void *_res)
{
R_INT (pr) = COLOR_PAIRS;
}
static void
qwaq_init_pair (qwaq_resources_t *res, int pair, int f, int b)
{
int command[] = { qwaq_cmd_init_pair, 0, pair, f, b, };
command[1] = CMD_SIZE(command);
qwaq_pipe_submit (&res->commands, command, command[1]);
}
static void
bi_init_pair (progs_t *pr, void *_res)
{
qwaq_resources_t *res = _res;
int pair = P_INT (pr, 0);
int f = P_INT (pr, 1);
int b = P_INT (pr, 2);
qwaq_init_pair (res, pair, f, b);
}
static void
qwaq_wbkgd (qwaq_resources_t *res, int window_id, int ch)
{
if (get_window (res, __FUNCTION__, window_id)) {
int command[] = { qwaq_cmd_wbkgd, 0, window_id, ch, };
command[1] = CMD_SIZE(command);
qwaq_pipe_submit (&res->commands, command, command[1]);
}
}
static void
bi_wbkgd (progs_t *pr, void *_res)
{
qwaq_resources_t *res = _res;
int window_id = P_INT (pr, 0);
int ch = P_INT (pr, 1);
qwaq_wbkgd (res, window_id, ch);
}
static void
qwaq_werase (qwaq_resources_t *res, int window_id, int ch)
{
if (get_window (res, __FUNCTION__, window_id)) {
int command[] = { qwaq_cmd_werase, 0, window_id, };
command[1] = CMD_SIZE(command);
qwaq_pipe_submit (&res->commands, command, command[1]);
}
}
static void
bi_werase (progs_t *pr, void *_res)
{
qwaq_resources_t *res = _res;
int window_id = P_INT (pr, 0);
int ch = P_INT (pr, 1);
qwaq_werase (res, window_id, ch);
}
static void
qwaq_scrollok (qwaq_resources_t *res, int window_id, int flag)
{
if (get_window (res, __FUNCTION__, window_id)) {
int command[] = { qwaq_cmd_scrollok, 0, window_id, flag, };
command[1] = CMD_SIZE(command);
qwaq_pipe_submit (&res->commands, command, command[1]);
}
}
static void
bi_scrollok (progs_t *pr, void *_res)
{
qwaq_resources_t *res = _res;
int window_id = P_INT (pr, 0);
int flag = P_INT (pr, 1);
qwaq_scrollok (res, window_id, flag);
}
static void
qwaq_wmove (qwaq_resources_t *res, int window_id, int x, int y)
{
if (get_window (res, __FUNCTION__, window_id)) {
int command[] = { qwaq_cmd_wmove, 0, window_id, x, y, };
command[1] = CMD_SIZE(command);
qwaq_pipe_submit (&res->commands, command, command[1]);
}
}
static void
bi_wmove (progs_t *pr, void *_res)
{
qwaq_resources_t *res = _res;
int window_id = P_INT (pr, 0);
int x = P_INT (pr, 1);
int y = P_INT (pr, 2);
qwaq_wmove (res, window_id, x, y);
}
static const char qwaq_acs_char_map[] = "lmkjtuvwqxnos`afg~,+.-hi0pryz{|}";
static void
qwaq_acs_char (progs_t *pr, unsigned acs)
{
if (acs < 256) {
R_INT (pr) = NCURSES_ACS(acs);
} else if (acs - 256 < sizeof (qwaq_acs_char_map)) {
R_INT (pr) = NCURSES_ACS(qwaq_acs_char_map[acs - 256]);
} else {
R_INT (pr) = 0;
}
}
static void
bi_acs_char (progs_t *pr, void *_res)
{
int acs = P_INT (pr, 0);
qwaq_acs_char (pr, acs);
}
static void
qwaq_move (qwaq_resources_t *res, int x, int y)
{
int command[] = { qwaq_cmd_move, 0, x, y, };
command[1] = CMD_SIZE(command);
qwaq_pipe_submit (&res->commands, command, command[1]);
}
static void
bi_move (progs_t *pr, void *_res)
{
qwaq_resources_t *res = _res;
int x = P_INT (pr, 0);
int y = P_INT (pr, 1);
qwaq_move (res, x, y);
}
static void
qwaq_curs_set (qwaq_resources_t *res, int visibility)
{
int command[] = { qwaq_cmd_curs_set, 0, visibility, };
command[1] = CMD_SIZE(command);
qwaq_pipe_submit (&res->commands, command, command[1]);
}
static void
bi_curs_set (progs_t *pr, void *_res)
{
qwaq_resources_t *res = _res;
int visibility = P_INT (pr, 0);
qwaq_curs_set (res, visibility);
}
static void
qwaq_wborder (qwaq_resources_t *res, int window_id,
box_sides_t sides, box_corners_t corns)
{
if (get_window (res, __FUNCTION__, window_id)) {
int command[] = { qwaq_cmd_wborder, 0, window_id,
sides.ls, sides.rs, sides.ts, sides.bs,
corns.tl, corns.tr, corns.bl, corns.br, };
command[1] = CMD_SIZE(command);
qwaq_pipe_submit (&res->commands, command, command[1]);
}
}
static void
bi_wborder (progs_t *pr, void *_res)
{
qwaq_resources_t *res = _res;
int window_id = P_INT (pr, 0);
__auto_type sides = P_PACKED (pr, box_sides_t, 1);
__auto_type corns = P_PACKED (pr, box_corners_t, 2);
qwaq_wborder (res, window_id, sides, corns);
}
static void
qwaq__mvwblit_line (qwaq_resources_t *res, int window_id, int x, int y,
int *chs, int len)
{
if (get_window (res, __FUNCTION__, window_id)) {
int chs_id = qwaq_pipe_acquire_string (&res->commands);
dstring_t *chs_buf = qwaq_cmd_string (res, chs_id);
int command[] = { qwaq_cmd_mvwblit_line, 0, window_id,
x, y, chs_id, len,};
command[1] = CMD_SIZE(command);
chs_buf->size = len * sizeof (int);
dstring_adjust (chs_buf);
memcpy (chs_buf->str, chs, len * sizeof (int));
qwaq_pipe_submit (&res->commands, command, command[1]);
}
}
static void
bi_mvwblit_line (progs_t *pr, void *_res)
{
qwaq_resources_t *res = _res;
int window_id = P_INT (pr, 0);
int x = P_INT (pr, 1);
int y = P_INT (pr, 2);
int *chs = (int *) P_GPOINTER (pr, 3);
int len = P_INT (pr, 4);
qwaq__mvwblit_line (res, window_id, x, y, chs, len);
}
static void *
qwaq_curses_thread (qwaq_thread_t *thread)
{
qwaq_resources_t *res = thread->data;
while (1) {
process_commands (res);
}
thread->return_code = 0;
return thread;
}
static void
bi_initialize (progs_t *pr, void *data)
{
qwaq_resources_t *res = PR_Resources_Find (pr, "curses");
initscr ();
need_endwin = 1;
res->initialized = 1;
start_color ();
raw ();
keypad (stdscr, FALSE); // do it ourselves
noecho ();
nonl ();
nodelay (stdscr, TRUE);
mousemask(ALL_MOUSE_EVENTS | REPORT_MOUSE_POSITION, NULL);
refresh();
qwaq_input_enable_mouse ();
res->stdscr.win = stdscr;
create_thread (qwaq_curses_thread, res);
}
static void
bi__c_TextContext__is_initialized (progs_t *pr, void *_res)
{
qwaq_resources_t *res = _res;
R_INT (pr) = res->initialized;
}
static void
bi__c_TextContext__max_colors (progs_t *pr, void *_res)
{
qwaq_resources_t *res = _res;
bi_max_colors (pr, res);
}
static void
bi__c_TextContext__max_color_pairs (progs_t *pr, void *_res)
{
qwaq_resources_t *res = _res;
bi_max_color_pairs (pr, res);
}
static void
bi__c_TextContext__init_pair_ (progs_t *pr, void *_res)
{
qwaq_resources_t *res = _res;
int pair = P_INT (pr, 2);
int f = P_INT (pr, 3);
int b = P_INT (pr, 4);
qwaq_init_pair (res, pair, f, b);
}
static void
bi__c_TextContext__acs_char_ (progs_t *pr, void *_res)
{
int acs = P_INT (pr, 2);
qwaq_acs_char (pr, acs);
}
static void
bi__c_TextContext__move_ (progs_t *pr, void *_res)
{
qwaq_resources_t *res = _res;
Point *pos = &P_PACKED (pr, Point, 2);
qwaq_move (res, pos->x, pos->y);
}
static void
bi__c_TextContext__curs_set_ (progs_t *pr, void *_res)
{
qwaq_resources_t *res = _res;
int visibility = P_INT (pr, 2);
qwaq_curs_set (res, visibility);
}
static void
bi__c_TextContext__doupdate (progs_t *pr, void *_res)
{
qwaq_resources_t *res = _res;
bi_doupdate (pr, res);
}
static void
bi__i_TextContext__mvprintf_ (progs_t *pr, void *_res)
{
qwaq_resources_t *res = _res;
int window_id = P_STRUCT (pr, qwaq_textcontext_t, 0).window;
Point *pos = &P_PACKED (pr, Point, 2);
qwaq_mvwprintf (res, window_id, pos->x, pos->y, 3);
}
static void
bi__i_TextContext__printf_ (progs_t *pr, void *_res)
{
qwaq_resources_t *res = _res;
int window_id = P_STRUCT (pr, qwaq_textcontext_t, 0).window;
qwaq_wprintf (res, window_id, 2);
}
static void
bi__i_TextContext__vprintf_ (progs_t *pr, void *_res)
{
qwaq_resources_t *res = _res;
int window_id = P_STRUCT (pr, qwaq_textcontext_t, 0).window;
const char *fmt = P_GSTRING (pr, 2);
__auto_type args = (pr_va_list_t *) &P_POINTER (pr, 3);
qwaq_wvprintf (res, window_id, fmt, args);
}
static void
bi__i_TextContext__addch_ (progs_t *pr, void *_res)
{
qwaq_resources_t *res = _res;
int window_id = P_STRUCT (pr, qwaq_textcontext_t, 0).window;
int ch = P_INT (pr, 2);
qwaq_waddch (res, window_id, ch);
}
static void
bi__i_TextContext__addstr_ (progs_t *pr, void *_res)
{
qwaq_resources_t *res = _res;
int window_id = P_STRUCT (pr, qwaq_textcontext_t, 0).window;
const char *str = P_GSTRING (pr, 2);
qwaq_waddstr (res, window_id, str);
}
static void
bi__i_TextContext__mvvprintf_ (progs_t *pr, void *_res)
{
qwaq_resources_t *res = _res;
int window_id = P_STRUCT (pr, qwaq_textcontext_t, 0).window;
Point *pos = &P_PACKED (pr, Point, 2);
const char *fmt = P_GSTRING (pr, 3);
__auto_type args = &P_PACKED (pr, pr_va_list_t, 4);
qwaq_mvwvprintf (res, window_id, pos->x, pos->y, fmt, args);
}
static void
bi__i_TextContext__resizeTo_ (progs_t *pr, void *_res)
{
qwaq_resources_t *res = _res;
__auto_type self = &P_STRUCT (pr, qwaq_textcontext_t, 0);
int window_id = self->window;
self->size = P_PACKED (pr, Extent, 2);
qwaq_wresize (res, window_id, self->size.width, self->size.height);
if (window_id == 1) {
qwaq_wbkgd (res, window_id, self->background);
}
}
static void
bi__c_TextContext__refresh (progs_t *pr, void *_res)
{
qwaq_resources_t *res = _res;
qwaq_update_panels (pr, res);
qwaq_doupdate (pr, res);
}
static void
bi__i_TextContext__refresh (progs_t *pr, void *_res)
{
qwaq_resources_t *res = _res;
int window_id = P_STRUCT (pr, qwaq_textcontext_t, 0).window;
qwaq_update_panels (pr, res);
if (window_id == 1) {
qwaq_wrefresh (res, window_id);
qwaq_doupdate (pr, res);
}
}
static void
bi__i_TextContext__mvaddch_ (progs_t *pr, void *_res)
{
qwaq_resources_t *res = _res;
int window_id = P_STRUCT (pr, qwaq_textcontext_t, 0).window;
Point *pos = &P_PACKED (pr, Point, 2);
int ch = P_INT (pr, 3);
qwaq_mvwaddch (res, window_id, pos->x, pos->y, ch);
}
static void
bi__i_TextContext__mvaddstr_ (progs_t *pr, void *_res)
{
qwaq_resources_t *res = _res;
int window_id = P_STRUCT (pr, qwaq_textcontext_t, 0).window;
Point *pos = &P_PACKED (pr, Point, 2);
const char *str = P_GSTRING (pr, 3);
qwaq_mvwaddstr (res, window_id, pos->x, pos->y, str);
}
static void
bi__i_TextContext__bkgd_ (progs_t *pr, void *_res)
{
qwaq_resources_t *res = _res;
__auto_type self = &P_STRUCT (pr, qwaq_textcontext_t, 0);
int window_id = self->window;
int ch = P_INT (pr, 2);
self->background = ch;
qwaq_wbkgd (res, window_id, ch);
}
static void
bi__i_TextContext__clear (progs_t *pr, void *_res)
{
qwaq_resources_t *res = _res;
__auto_type self = &P_STRUCT (pr, qwaq_textcontext_t, 0);
int window_id = self->window;
int ch = self->background;
qwaq_werase (res, window_id, ch);
}
static void
bi__i_TextContext__scrollok_ (progs_t *pr, void *_res)
{
qwaq_resources_t *res = _res;
int window_id = P_STRUCT (pr, qwaq_textcontext_t, 0).window;
int flag = P_INT (pr, 2);
qwaq_scrollok (res, window_id, flag);
}
static void
bi__i_TextContext__border_ (progs_t *pr, void *_res)
{
qwaq_resources_t *res = _res;
int window_id = P_STRUCT (pr, qwaq_textcontext_t, 0).window;
__auto_type sides = P_PACKED (pr, box_sides_t, 2);
__auto_type corns = P_PACKED (pr, box_corners_t, 3);
qwaq_wborder (res, window_id, sides, corns);
}
static void
bi__i_TextContext__mvhline_ (progs_t *pr, void *_res)
{
qwaq_resources_t *res = _res;
__auto_type self = &P_STRUCT (pr, qwaq_textcontext_t, 0);
int window_id = self->window;
__auto_type pos = &P_PACKED (pr, Point, 2);
int ch = P_INT (pr, 3);
int n = P_INT (pr, 4);
qwaq_mvwhline (res, window_id, pos->x, pos->y, ch, n);
}
static void
bi__i_TextContext__mvvline_ (progs_t *pr, void *_res)
{
qwaq_resources_t *res = _res;
__auto_type self = &P_STRUCT (pr, qwaq_textcontext_t, 0);
int window_id = self->window;
__auto_type pos = &P_PACKED (pr, Point, 2);
int ch = P_INT (pr, 3);
int n = P_INT (pr, 4);
qwaq_mvwvline (res, window_id, pos->x, pos->y, ch, n);
}
static void
bi_curses_clear (progs_t *pr, void *_res)
{
__auto_type res = (qwaq_resources_t *) _res;
if (res->initialized) {
qwaq_input_disable_mouse ();
endwin ();
}
need_endwin = 0;
window_reset (res);
panel_reset (res);
}
static void
bi_curses_destroy (progs_t *pr, void *_res)
{
}
#define bi(x,np,params...) {#x, bi_##x, -1, np, {params}}
#define p(type) PR_PARAM(type)
#define P(a, s) { .size = (s), .alignment = BITOP_LOG2 (a), }
static builtin_t builtins[] = {
bi(initialize, 0),
bi(syncprintf, -2, p(string)),
bi(create_window, 4, p(int), p(int), p(int), p(int)),
bi(destroy_window, 1, p(ptr)),
bi(getwrect, 1, p(ptr)),
bi(create_panel, 1, p(ptr)),
bi(destroy_panel, 1, p(ptr)),
bi(hide_panel, 1, p(ptr)),
bi(show_panel, 1, p(ptr)),
bi(top_panel, 1, p(ptr)),
bi(bottom_panel, 1, p(ptr)),
bi(move_panel, 3, p(ptr), p(int), p(int)),
bi(panel_window, 1, p(ptr)),
bi(replace_panel, 2, p(ptr), p(ptr)),
bi(update_panels, 0),
bi(doupdate, 0),
bi(mvwprintf, -5, p(ptr), p(int), p(int), p(string)),
bi(wprintf, -3, p(ptr), p(string)),
bi(wvprintf, 3, p(ptr), p(string), P(1, 2)),
bi(mvwvprintf, 5, p(ptr), p(int), p(int), p(string), P(1, 2)),
bi(mvwaddch, 4, p(ptr), p(int), p(int), p(int)),
bi(waddch, 2, p(ptr), p(int)),
bi(mvwaddstr, 4, p(ptr), p(int), p(int), p(string)),
bi(waddstr, 2, p(ptr), p(string)),
bi(wrefresh, 1, p(ptr)),
bi(max_colors, 0),
bi(max_color_pairs, 0),
bi(init_pair, 3, p(int), p(int), p(int)),
bi(wbkgd, 2, p(ptr), p(int)),
bi(werase, 1, p(ptr)),
bi(scrollok, 2, p(ptr), p(int)),
bi(wmove, 3, p(ptr), p(int), p(int), p(int)),
bi(acs_char, 1, p(int)),
bi(move, 2, p(int), p(int)),
bi(curs_set, 1, p(int)),
bi(wborder, 3, p(ptr), P(1, 4), P(1, 4)),
bi(mvwblit_line, 5, p(ptr), p(int), p(int), p(ptr), p(int)),
bi(wresize, 3, p(ptr), p(int), p(int)),
bi(resizeterm, 2, p(int), p(int)),
bi(mvwhline, 5, p(ptr), p(int), p(int), p(int), p(int)),
bi(mvwvline, 5, p(ptr), p(int), p(int), p(int), p(int)),
bi(_c_TextContext__is_initialized, 2, p(ptr), p(ptr)),
bi(_c_TextContext__max_colors, 2, p(ptr), p(ptr)),
bi(_c_TextContext__max_color_pairs, 2, p(ptr), p(ptr)),
bi(_c_TextContext__init_pair_, 5, p(ptr), p(ptr),
p(int), p(int), p(int)),
bi(_c_TextContext__acs_char_, 3, p(ptr), p(ptr),
p(int)),
bi(_c_TextContext__move_, 3, p(ptr), p(ptr),
P(1, 2)),
bi(_c_TextContext__curs_set_, 3, p(ptr), p(ptr),
p(int)),
bi(_c_TextContext__doupdate, 2, p(ptr), p(ptr)),
bi(_i_TextContext__mvprintf_, -5, p(ptr), p(ptr),
P(1, 2), p(string)),
bi(_i_TextContext__printf_, -4, p(ptr), p(ptr),
p(string)),
bi(_i_TextContext__vprintf_, 4, p(ptr), p(ptr),
p(string), P(1, 2)),
bi(_i_TextContext__addch_, 3, p(ptr), p(ptr),
p(int)),
bi(_i_TextContext__addstr_, 3, p(ptr), p(ptr),
p(string)),
bi(_i_TextContext__mvvprintf_, 5, p(ptr), p(ptr),
P(1, 2), p(string), P(1, 2)),
bi(_i_TextContext__resizeTo_, 3, p(ptr), p(ptr),
P(1, 2)),
bi(_c_TextContext__refresh, 2, p(ptr), p(ptr)),
bi(_i_TextContext__refresh, 2, p(ptr), p(ptr)),
bi(_i_TextContext__mvaddch_, 4, p(ptr), p(ptr),
P(1, 2), p(int)),
bi(_i_TextContext__mvaddstr_, 4, p(ptr), p(ptr),
P(1, 2), p(string)),
bi(_i_TextContext__bkgd_, 3, p(ptr), p(ptr),
p(int)),
bi(_i_TextContext__clear, 2, p(ptr), p(ptr)),
bi(_i_TextContext__scrollok_, 3, p(ptr), p(ptr),
p(int)),
bi(_i_TextContext__border_, 4, p(ptr), p(ptr),
P(1, 4), P(1, 4)),
bi(_i_TextContext__mvhline_, 5, p(ptr), p(ptr),
P(1, 2), p(int), p(int)),
bi(_i_TextContext__mvvline_, 5, p(ptr), p(ptr),
P(1, 2), p(int), p(int)),
{0}
};
void
BI_Curses_Init (progs_t *pr)
{
qwaq_resources_t *res = calloc (sizeof (*res), 1);
res->pr = pr;
qwaq_init_pipe (&res->commands);
qwaq_init_pipe (&res->results);
PR_Resources_Register (pr, "curses", res, bi_curses_clear,
bi_curses_destroy);
PR_RegisterBuiltins (pr, builtins, res);
Sys_RegisterShutdown (bi_shutdown, pr);
}