summaryrefslogtreecommitdiff
path: root/core/src
diff options
context:
space:
mode:
authorruki <[email protected]>2017-12-04 22:51:13 +0800
committerruki <[email protected]>2017-12-08 14:10:23 +0800
commitf0aaa81c62671dbea5457021c699b76c364c8db3 (patch)
tree4bd4112b2c7b2c49c6c279b6d1dc89f0593b7ab1 /core/src
parent43a7ef4eaa0a0347beee6f6cc4ef919b80e457cb (diff)
add lcurses binding
Diffstat (limited to 'core/src')
-rw-r--r--core/src/lcurses/LICENSE20
-rw-r--r--core/src/lcurses/lcurses.c2417
-rw-r--r--core/src/lcurses/makefile21
-rw-r--r--core/src/lcurses/xmake.lua19
-rw-r--r--core/src/makefile2
5 files changed, 2478 insertions, 1 deletions
diff --git a/core/src/lcurses/LICENSE b/core/src/lcurses/LICENSE
new file mode 100644
index 000000000..ece499fdc
--- /dev/null
+++ b/core/src/lcurses/LICENSE
@@ -0,0 +1,20 @@
+Author: Tiago Dionizio <tiago.dionizio (AT) gmail.com>
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/core/src/lcurses/lcurses.c b/core/src/lcurses/lcurses.c
new file mode 100644
index 000000000..8f791c18a
--- /dev/null
+++ b/core/src/lcurses/lcurses.c
@@ -0,0 +1,2417 @@
+/************************************************************************
+* Author : Tiago Dionizio <tiago.dionizio AT gmail.com> *
+* Library : lcurses - Lua 5.1 interface to the curses library *
+* *
+* Permission is hereby granted, free of charge, to any person obtaining *
+* a copy of this software and associated documentation files (the *
+* "Software"), to deal in the Software without restriction, including *
+* without limitation the rights to use, copy, modify, merge, publish, *
+* distribute, sublicense, and/or sell copies of the Software, and to *
+* permit persons to whom the Software is furnished to do so, subject to *
+* the following conditions: *
+* *
+* The above copyright notice and this permission notice shall be *
+* included in all copies or substantial portions of the Software. *
+* *
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, *
+* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*
+* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY *
+* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, *
+* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE *
+* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
+************************************************************************/
+
+/************************************************************************
+$Id: lcurses.c 17 2007-06-21 15:30:45Z tngd $
+History:
+
+************************************************************************/
+
+/************************************************************************
+Wish-list:
+************************************************************************/
+
+/************************************************************************
+Notes:
+* when user presses a modifier key on WIN32, it seems that the program
+ freezes waiting for another keypress... probably waiting to do some
+ work on the modifiers and the (next) pressed key (normal key) acting
+ as a blocking operation even if delay settings are turned off
+
+ + solved. but now modifier keys will be returned on WIN32. shouldn't a
+ problem though, just ignore them.
+
+* printing control characters on unix will not produce printable
+ characters like WIN32 does. better use only 'isprint' characters and
+ ACS characters (curses characters)
+
+ + solved. to filter characters being output to the screen, set
+ curses.map_output(true). this will filter all characters where a
+ chtype or chstr is used
+
+ mostly for cui usage.
+
+* on WIN32 ALT keys need to be mapped, so to make sure you get the wanted
+ keys, execute curses.map_keyboard(true). only makes sense when using
+ keypad(true) and echo(false)
+
+ mostly for cui usage.
+************************************************************************/
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "luajit.h"
+#include "lualib.h"
+#include "lauxlib.h"
+
+#include <curses.h>
+#include <signal.h>
+
+#if defined(PDCURSES) && (PDC_BUILD < 3100)
+# error Please upgrade to PDCurses 3.1 or later
+#endif
+
+
+/*
+ * Title: curses
+ * Provides a binding to the curses library for Lua.
+ *
+ */
+
+/*
+** =======================================================
+** defines
+** =======================================================
+*/
+static const char *STDSCR_REGISTRY = "cui:curses:stdscr";
+static const char *WINDOWMETA = "cui:curses:window";
+static const char *CHSTRMETA = "cui:curses:chstr";
+static const char *RIPOFF_TABLE = "cui:curses:ripoffline";
+
+#define B(v) ((v == ERR) ? 0 : 1)
+
+/* ======================================================= */
+
+#define LC_NUMBER(v) \
+ static int lc_ ## v(lua_State *L) \
+ { \
+ lua_pushnumber(L, v()); \
+ return 1; \
+ }
+
+#define LC_NUMBER2(n,v) \
+ static int lc_ ## n(lua_State *L) \
+ { \
+ lua_pushnumber(L, v); \
+ return 1; \
+ }
+
+/* ======================================================= */
+
+#define LC_STRING(v) \
+ static int lc_ ## v(lua_State *L) \
+ { \
+ lua_pushstring(L, v()); \
+ return 1; \
+ }
+
+#define LC_STRING2(n,v) \
+ static int lc_ ## n(lua_State *L) \
+ { \
+ lua_pushstring(L, v); \
+ return 1; \
+ }
+
+/* ======================================================= */
+
+#define LC_BOOL(v) \
+ static int lc_ ## v(lua_State *L) \
+ { \
+ lua_pushboolean(L, v()); \
+ return 1; \
+ }
+
+#define LC_BOOL2(n,v) \
+ static int lc_ ## n(lua_State *L) \
+ { \
+ lua_pushboolean(L, v); \
+ return 1; \
+ }
+
+/* ======================================================= */
+
+#define LC_BOOLOK(v) \
+ static int lc_ ## v(lua_State *L) \
+ { \
+ lua_pushboolean(L, B(v())); \
+ return 1; \
+ }
+
+#define LC_BOOLOK2(n,v) \
+ static int lc_ ## n(lua_State *L) \
+ { \
+ lua_pushboolean(L, B(v)); \
+ return 1; \
+ }
+
+/* ======================================================= */
+
+#define LCW_BOOLOK(n) \
+ static int lcw_ ## n(lua_State *L) \
+ { \
+ WINDOW *w = lcw_check(L, 1); \
+ lua_pushboolean(L, B(n(w))); \
+ return 1; \
+ }
+
+
+#ifdef DEBUG
+
+#include <stdarg.h>
+int clog(char* f, ...)
+{
+ va_list args;
+ FILE *l;
+
+ va_start(args, f);
+ l = fopen("lcurses.log", "a");
+ vfprintf(l, f, args);
+ fprintf(l, "\n");
+ fclose(l);
+ va_end(args);
+ return 1;
+}
+
+#endif /* DEBUG */
+
+/* ascii map table
+** used on chstr:set and where a chstr is given as a parameter
+** if curses.map_output(true) is set */
+static chtype ascii_map[256];
+static int map_output = FALSE;
+static void init_ascii_map();
+
+/* keyboard mapping. to make key association more consistent
+** between curses implementations (PDCURSES and ncurses atm) */
+static int map_keyboard = FALSE;
+
+/* (un)set usage of output map table */
+static int lc_map_keyboard(lua_State *L)
+{
+ lua_pushboolean(L, map_keyboard);
+
+ if (!lua_isnoneornil(L, 1))
+ {
+ luaL_checktype(L, 1, LUA_TBOOLEAN);
+ map_keyboard = lua_toboolean(L, 1);
+ }
+
+ return 1;
+}
+
+/* keyboard mapping function, only active if map_keyboard = TRUE */
+static int map_getch(WINDOW *w)
+{
+#ifdef PDCURSES
+ static int has_key = FALSE;
+ static int temp_key = 0;
+
+ int key;
+
+ if (map_keyboard && has_key)
+ {
+ has_key = FALSE;
+ return temp_key;
+ }
+
+ key = wgetch(w);
+
+ /* in case of error or not using key mapping, return the key */
+ if (key == ERR || !map_keyboard) return key;
+
+ if (key >= ALT_A && key <= ALT_Z)
+ {
+ has_key = TRUE;
+ temp_key = key - ALT_A + 'A';
+ }
+ else if (key >= ALT_0 && key <= ALT_9)
+ {
+ has_key = TRUE;
+ temp_key = key - ALT_0 + '0';
+ }
+ else switch (key)
+ {
+ case ALT_DEL: temp_key = KEY_DC; break;
+ case ALT_INS: temp_key = KEY_IC; break;
+ case ALT_HOME: temp_key = KEY_HOME; break;
+ case ALT_END: temp_key = KEY_END; break;
+ case ALT_PGUP: temp_key = KEY_PPAGE; break;
+ case ALT_PGDN: temp_key = KEY_NPAGE; break;
+ case ALT_UP: temp_key = KEY_UP; break;
+ case ALT_DOWN: temp_key = KEY_DOWN; break;
+ case ALT_RIGHT: temp_key = KEY_RIGHT; break;
+ case ALT_LEFT: temp_key = KEY_LEFT; break;
+ case ALT_BKSP: temp_key = KEY_BACKSPACE; break;
+
+ default: return key;
+ }
+ has_key = TRUE;
+ return 27;
+#else
+ return wgetch(w);
+#endif
+}
+
+/*
+** =======================================================
+** privates
+** =======================================================
+*/
+static void lcw_new(lua_State *L, WINDOW *nw)
+{
+ if (nw)
+ {
+ WINDOW **w = lua_newuserdata(L, sizeof(WINDOW*));
+ luaL_getmetatable(L, WINDOWMETA);
+ lua_setmetatable(L, -2);
+ *w = nw;
+ }
+ else
+ {
+ lua_pushliteral(L, "failed to create window");
+ lua_error(L);
+ }
+}
+
+static WINDOW **lcw_get(lua_State *L, int index)
+{
+ WINDOW **w = (WINDOW**)luaL_checkudata(L, index, WINDOWMETA);
+ if (w == NULL) luaL_argerror(L, index, "bad curses window");
+ return w;
+}
+
+static WINDOW *lcw_check(lua_State *L, int index)
+{
+ WINDOW **w = lcw_get(L, index);
+ if (*w == NULL) luaL_argerror(L, index, "attempt to use closed curses window");
+ return *w;
+}
+
+static int lcw_tostring(lua_State *L)
+{
+ WINDOW **w = lcw_get(L, 1);
+ char buff[34];
+ if (*w == NULL)
+ strcpy(buff, "closed");
+ else
+ sprintf(buff, "%p", lua_touserdata(L, 1));
+ lua_pushfstring(L, "curses window (%s)", buff);
+ return 1;
+}
+
+/*
+** =======================================================
+** chtype handling
+** =======================================================
+*/
+static chtype lc_checkch(lua_State *L, int index)
+{
+ if (lua_type(L, index) == LUA_TNUMBER)
+ return (chtype)luaL_checknumber(L, index);
+ if (lua_type(L, index) == LUA_TSTRING)
+ return *lua_tostring(L, index);
+
+ luaL_typerror(L, index, "chtype");
+ /* never executes */
+ return (chtype)0;
+}
+
+static chtype lc_optch(lua_State *L, int index, chtype def)
+{
+ if (lua_isnoneornil(L, index))
+ return def;
+ return lc_checkch(L, index);
+}
+
+/****c* classes/chstr
+ * FUNCTION
+ * Line drawing buffer.
+ *
+ * SEE ALSO
+ * curses.new_chstr
+ ****/
+
+typedef struct
+{
+ unsigned int len;
+ chtype str[1];
+} chstr;
+#define CHSTR_SIZE(len) (sizeof(chstr) + len * sizeof(chtype))
+
+
+/* create new chstr object and leave it in the lua stack */
+static chstr* chstr_new(lua_State *L, int len)
+{
+ if (len < 1)
+ {
+ lua_pushliteral(L, "invalid chstr length");
+ lua_error(L);
+ }
+ {
+ chstr *cs = lua_newuserdata(L, CHSTR_SIZE(len));
+ luaL_getmetatable(L, CHSTRMETA);
+ lua_setmetatable(L, -2);
+ cs->len = len;
+ return cs;
+ }
+}
+
+/* get chstr from lua (convert if needed) */
+static chstr* lc_checkchstr(lua_State *L, int index)
+{
+ chstr *cs = (chstr*)luaL_checkudata(L, index, CHSTRMETA);
+ if (cs) return cs;
+
+ luaL_argerror(L, index, "bad curses chstr");
+ return NULL;
+}
+
+/****f* curses/curses.new_chstr
+ * FUNCTION
+ * Create a new line drawing buffer instance.
+ *
+ * SEE ALSO
+ * chstr
+ ****/
+static int lc_new_chstr(lua_State *L)
+{
+ int len = luaL_checkint(L, 1);
+ chstr* ncs = chstr_new(L, len);
+ memset(ncs->str, ' ', len*sizeof(chtype));
+ return 1;
+}
+
+/* change the contents of the chstr */
+static int chstr_set_str(lua_State *L)
+{
+ chstr *cs = lc_checkchstr(L, 1);
+ int index = luaL_checkint(L, 2);
+ const char *str = luaL_checkstring(L, 3);
+ int len = lua_strlen(L, 3);
+ int attr = (chtype)luaL_optnumber(L, 4, A_NORMAL);
+ int rep = luaL_optint(L, 5, 1);
+ int i;
+
+ if (index < 0)
+ return 0;
+
+ while (rep-- > 0 && index <= cs->len)
+ {
+ if (index + len - 1 > cs->len)
+ len = cs->len - index + 1;
+
+ if (map_output)
+ {
+ for (i = 0; i < len; ++i)
+ cs->str[index + i] = ascii_map[(unsigned char)str[i]] | attr;
+ }
+ else
+ {
+ for (i = 0; i < len; ++i)
+ cs->str[index + i] = str[i] | attr;
+ }
+ index += len;
+ }
+
+ return 0;
+}
+
+
+/****m* chstr/set_ch
+ * FUNCTION
+ * Set a character in the buffer.
+ *
+ * SYNOPSIS
+ * chstr:set_ch(index, char, attribute [, repeat])
+ *
+ * EXAMPLE
+ * Set the buffer with 'a's where the first one is capitalized
+ * and has bold.
+ * size = 10
+ * str = curses.new_chstr(10)
+ * str:set_ch(0, 'A', curses.A_BOLD)
+ * str:set_ch(1, 'a', curses.A_NORMAL, size - 1)
+ ****/
+static int chstr_set_ch(lua_State *L)
+{
+ chstr* cs = lc_checkchstr(L, 1);
+ int index = luaL_checkint(L, 2);
+ chtype ch = lc_checkch(L, 3);
+ int attr = (chtype)luaL_optnumber(L, 4, A_NORMAL);
+ int rep = luaL_optint(L, 5, 1);
+
+ while (rep-- > 0)
+ {
+ if (index < 0 || index >= cs->len)
+ return 0;
+
+ if (map_output && ch <= 255)
+ cs->str[index] = ascii_map[ch] | attr;
+ else
+ cs->str[index] = ch | attr;
+
+ ++index;
+ }
+ return 0;
+}
+
+/* get information from the chstr */
+static int chstr_get(lua_State *L)
+{
+ chstr* cs = lc_checkchstr(L, 1);
+ int index = luaL_checkint(L, 2);
+ chtype ch;
+
+ if (index < 0 || index >= cs->len)
+ return 0;
+
+ ch = cs->str[index];
+
+ lua_pushnumber(L, ch & A_CHARTEXT);
+ lua_pushnumber(L, ch & A_ATTRIBUTES);
+ lua_pushnumber(L, ch & A_COLOR);
+ return 3;
+}
+
+/* retrieve chstr length */
+static int chstr_len(lua_State *L)
+{
+ chstr *cs = lc_checkchstr(L, 1);
+ lua_pushnumber(L, cs->len);
+ return 1;
+}
+
+/* duplicate chstr */
+static int chstr_dup(lua_State *L)
+{
+ chstr *cs = lc_checkchstr(L, 1);
+ chstr *ncs = chstr_new(L, cs->len);
+
+ memcpy(ncs->str, cs->str, CHSTR_SIZE(cs->len));
+ return 1;
+}
+
+/* (un)set usage of output map table */
+static int lc_map_output(lua_State *L)
+{
+ lua_pushboolean(L, map_output);
+
+ if (!lua_isnoneornil(L, 1))
+ {
+ luaL_checktype(L, 1, LUA_TBOOLEAN);
+ map_output = lua_toboolean(L, 1);
+ }
+
+ return 1;
+}
+
+/*
+** =======================================================
+** initscr
+** =======================================================
+*/
+
+#define CCR(n, v) \
+ lua_pushstring(L, n); \
+ lua_pushnumber(L, v); \
+ lua_settable(L, lua_upvalueindex(1));
+
+#define CC(s) CCR(#s, s)
+#define CC2(s, v) CCR(#s, v)
+
+/*
+** these values may be fixed only after initialization, so this is
+** called from lc_initscr, after the curses driver is initialized
+**
+** curses table is kept at upvalue position 1, in case the global
+** name is changed by the user or even in the registration phase by
+** the developer
+**
+** some of these values are not constant so need to register
+** them directly instead of using a table
+*/
+static void register_curses_constants(lua_State *L)
+{
+ /* colors */
+ CC(COLOR_BLACK) CC(COLOR_RED) CC(COLOR_GREEN)
+ CC(COLOR_YELLOW) CC(COLOR_BLUE) CC(COLOR_MAGENTA)
+ CC(COLOR_CYAN) CC(COLOR_WHITE)
+
+ /* alternate character set */
+ CC(ACS_BLOCK) CC(ACS_BOARD)
+
+ CC(ACS_BTEE) CC(ACS_TTEE)
+ CC(ACS_LTEE) CC(ACS_RTEE)
+ CC(ACS_LLCORNER) CC(ACS_LRCORNER)
+ CC(ACS_URCORNER) CC(ACS_ULCORNER)
+
+ CC(ACS_LARROW) CC(ACS_RARROW)
+ CC(ACS_UARROW) CC(ACS_DARROW)
+
+ CC(ACS_HLINE) CC(ACS_VLINE)
+
+ CC(ACS_BULLET) CC(ACS_CKBOARD) CC(ACS_LANTERN)
+ CC(ACS_DEGREE) CC(ACS_DIAMOND)
+
+ CC(ACS_PLMINUS) CC(ACS_PLUS)
+ CC(ACS_S1) CC(ACS_S9)
+
+ /* attributes */
+ CC(A_NORMAL) CC(A_STANDOUT) CC(A_UNDERLINE)
+ CC(A_REVERSE) CC(A_BLINK) CC(A_DIM)
+ CC(A_BOLD) CC(A_PROTECT) CC(A_INVIS)
+ CC(A_ALTCHARSET) CC(A_CHARTEXT)
+
+ /* key functions */
+ CC(KEY_BREAK) CC(KEY_DOWN) CC(KEY_UP)
+ CC(KEY_LEFT) CC(KEY_RIGHT) CC(KEY_HOME)
+ CC(KEY_BACKSPACE)
+
+ CC(KEY_DL) CC(KEY_IL) CC(KEY_DC)
+ CC(KEY_IC) CC(KEY_EIC) CC(KEY_CLEAR)
+ CC(KEY_EOS) CC(KEY_EOL) CC(KEY_SF)
+ CC(KEY_SR) CC(KEY_NPAGE) CC(KEY_PPAGE)
+ CC(KEY_STAB) CC(KEY_CTAB) CC(KEY_CATAB)
+ CC(KEY_ENTER) CC(KEY_SRESET) CC(KEY_RESET)
+ CC(KEY_PRINT) CC(KEY_LL) CC(KEY_A1)
+ CC(KEY_A3) CC(KEY_B2) CC(KEY_C1)
+ CC(KEY_C3) CC(KEY_BTAB) CC(KEY_BEG)
+ CC(KEY_CANCEL) CC(KEY_CLOSE) CC(KEY_COMMAND)
+ CC(KEY_COPY) CC(KEY_CREATE) CC(KEY_END)
+ CC(KEY_EXIT) CC(KEY_FIND) CC(KEY_HELP)
+ CC(KEY_MARK) CC(KEY_MESSAGE) CC(KEY_MOUSE)
+ CC(KEY_MOVE) CC(KEY_NEXT) CC(KEY_OPEN)
+ CC(KEY_OPTIONS) CC(KEY_PREVIOUS) CC(KEY_REDO)
+ CC(KEY_REFERENCE) CC(KEY_REFRESH) CC(KEY_REPLACE)
+ CC(KEY_RESIZE) CC(KEY_RESTART) CC(KEY_RESUME)
+ CC(KEY_SAVE) CC(KEY_SBEG) CC(KEY_SCANCEL)
+ CC(KEY_SCOMMAND) CC(KEY_SCOPY) CC(KEY_SCREATE)
+ CC(KEY_SDC) CC(KEY_SDL) CC(KEY_SELECT)
+ CC(KEY_SEND) CC(KEY_SEOL) CC(KEY_SEXIT)
+ CC(KEY_SFIND) CC(KEY_SHELP) CC(KEY_SHOME)
+ CC(KEY_SIC) CC(KEY_SLEFT) CC(KEY_SMESSAGE)
+ CC(KEY_SMOVE) CC(KEY_SNEXT) CC(KEY_SOPTIONS)
+ CC(KEY_SPREVIOUS) CC(KEY_SPRINT) CC(KEY_SREDO)
+ CC(KEY_SREPLACE) CC(KEY_SRIGHT) CC(KEY_SRSUME)
+ CC(KEY_SSAVE) CC(KEY_SSUSPEND) CC(KEY_SUNDO)
+ CC(KEY_SUSPEND) CC(KEY_UNDO)
+
+ /* KEY_Fx 0 <= x <= 63 */
+ CC(KEY_F0) CC2(KEY_F1, KEY_F(1)) CC2(KEY_F2, KEY_F(2))
+ CC2(KEY_F3, KEY_F(3)) CC2(KEY_F4, KEY_F(4)) CC2(KEY_F5, KEY_F(5))
+ CC2(KEY_F6, KEY_F(6)) CC2(KEY_F7, KEY_F(7)) CC2(KEY_F8, KEY_F(8))
+ CC2(KEY_F9, KEY_F(9)) CC2(KEY_F10, KEY_F(10)) CC2(KEY_F11, KEY_F(11))
+ CC2(KEY_F12, KEY_F(12))
+}
+
+/*
+** make sure screen is restored (and cleared) at exit
+** (for the situations where program is aborted without a
+** proper cleanup)
+*/
+static void cleanup()
+{
+ if (!isendwin())
+ {
+ wclear(stdscr);
+ wrefresh(stdscr);
+ endwin();
+ }
+}
+
+static int lc_initscr(lua_State *L)
+{
+ WINDOW *w;
+
+ /* initialize curses */
+ w = initscr();
+
+ /* no longer used, so clean it up */
+ lua_pushstring(L, RIPOFF_TABLE);
+ lua_pushnil(L);
+ lua_settable(L, LUA_REGISTRYINDEX);
+
+ /* failed to initialize */
+ if (w == NULL)
+ return 0;
+
+ #if defined(NCURSES_VERSION)
+ /* acomodate this value for cui keyboard handling */
+ ESCDELAY = 0;
+ #endif
+
+ /* return stdscr - main window */
+ lcw_new(L, w);
+
+ /* save main window on registry */
+ lua_pushstring(L, STDSCR_REGISTRY);
+ lua_pushvalue(L, -2);
+ lua_rawset(L, LUA_REGISTRYINDEX);
+
+ /* setup curses constants - curses.xxx numbers */
+ register_curses_constants(L);
+ /* setup ascii map table */
+ init_ascii_map();
+
+ /* install cleanup handler to help in debugging and screen trashing */
+ atexit(cleanup);
+ /* disable interrupt signal
+ signal(SIGINT, SIG_IGN);
+ signal(SIGBREAK, SIG_IGN);
+ signal(SIGTERM, SIG_IGN);*/
+ return 1;
+}
+
+static int lc_endwin(lua_State *L)
+{
+ endwin();
+#ifdef XCURSES
+ XCursesExit();
+ exit(0);
+#endif
+ return 0;
+}
+
+LC_BOOL(isendwin)
+
+static int lc_stdscr(lua_State *L)
+{
+ lua_pushstring(L, STDSCR_REGISTRY);
+ lua_rawget(L, LUA_REGISTRYINDEX);
+ return 1;
+}
+
+LC_NUMBER2(COLS, COLS)
+LC_NUMBER2(LINES, LINES)
+
+/*
+** =======================================================
+** color
+** =======================================================
+*/
+
+LC_BOOLOK(start_color)
+LC_BOOL(has_colors)
+
+static int lc_init_pair(lua_State *L)
+{
+ short pair = luaL_checkint(L, 1);
+ short f = luaL_checkint(L, 2);
+ short b = luaL_checkint(L, 3);
+
+ lua_pushboolean(L, B(init_pair(pair, f, b)));
+ return 1;
+}
+
+static int lc_pair_content(lua_State *L)
+{
+ short pair = luaL_checkint(L, 1);
+ short f;
+ short b;
+ int ret = pair_content(pair, &f, &b);
+
+ if (ret == ERR)
+ return 0;
+
+ lua_pushnumber(L, f);
+ lua_pushnumber(L, b);
+ return 2;
+}
+
+LC_NUMBER2(COLORS, COLORS)
+LC_NUMBER2(COLOR_PAIRS, COLOR_PAIRS)
+
+static int lc_COLOR_PAIR(lua_State *L)
+{
+ int n = luaL_checkint(L, 1);
+ lua_pushnumber(L, COLOR_PAIR(n));
+ return 1;
+}
+
+/*
+** =======================================================
+** termattrs
+** =======================================================
+*/
+
+LC_NUMBER(baudrate)
+LC_NUMBER(erasechar)
+LC_BOOL(has_ic)
+LC_BOOL(has_il)
+LC_NUMBER(killchar)
+
+static int lc_termattrs(lua_State *L)
+{
+ if (lua_gettop(L) < 1)
+ {
+ lua_pushnumber(L, termattrs());
+ }
+ else
+ {
+ int a = luaL_checkint(L, 1);
+ lua_pushboolean(L, termattrs() & a);
+ }
+ return 1;
+}
+
+LC_STRING(termname)
+LC_STRING(longname)
+
+/*
+** =======================================================
+** kernel
+** =======================================================
+*/
+
+/* there is no easy way to implement this... */
+static lua_State *rip_L = NULL;
+static int ripoffline_cb(WINDOW* w, int cols)
+{
+ static int line = 0;
+ int top = lua_gettop(rip_L);
+
+ /* better be safe */
+ if (!lua_checkstack(rip_L, 5))
+ return 0;
+
+ /* get the table from the registry */
+ lua_pushstring(rip_L, RIPOFF_TABLE);
+ lua_gettable(rip_L, LUA_REGISTRYINDEX);
+
+ /* get user callback function */
+ if (lua_isnil(rip_L, -1)) {
+ lua_pop(rip_L, 1);
+ return 0;
+ }
+
+ lua_rawgeti(rip_L, -1, ++line); /* function to be called */
+ lcw_new(rip_L, w); /* create window object */
+ lua_pushnumber(rip_L, cols); /* push number of columns */
+
+ lua_pcall(rip_L, 2, 0, 0); /* call the lua function */
+
+ lua_settop(rip_L, top);
+ return 1;
+}
+
+static int lc_ripoffline(lua_State *L)
+{
+ static int rip = 0;
+ int top_line = lua_toboolean(L, 1);
+
+ if (!lua_isfunction(L, 2))
+ {
+ lua_pushliteral(L, "invalid callback passed as second parameter");
+ lua_error(L);
+ }
+
+ /* need to save the lua state somewhere... */
+ rip_L = L;
+
+ /* get the table where we are going to save the callbacks */
+ lua_pushstring(L, RIPOFF_TABLE);
+ lua_gettable(L, LUA_REGISTRYINDEX);
+
+ if (lua_isnil(L, -1))
+ {
+ lua_pop(L, 1);
+ lua_newtable(L);
+
+ lua_pushstring(L, RIPOFF_TABLE);
+ lua_pushvalue(L, -2);
+ lua_settable(L, LUA_REGISTRYINDEX);
+ }
+
+ /* save function callback in registry table */
+ lua_pushvalue(L, 2);
+ lua_rawseti(L, -2, ++rip);
+
+ /* and tell curses we are going to take the line */
+ lua_pushboolean(L, B(ripoffline(top_line ? 1 : -1, ripoffline_cb)));
+ return 1;
+}
+
+static int lc_curs_set(lua_State *L)
+{
+ int vis = luaL_checkint(L, 1);
+ int state = curs_set(vis);
+ if (state == ERR)
+ return 0;
+
+ lua_pushnumber(L, state);
+ return 1;
+}
+
+static int lc_napms(lua_State *L)
+{
+ int ms = luaL_checkint(L, 1);
+ lua_pushboolean(L, B(napms(ms)));
+ return 1;
+}
+
+/*
+** =======================================================
+** beep
+** =======================================================
+*/
+LC_BOOLOK(beep)
+LC_BOOLOK(flash)
+
+
+/*
+** =======================================================
+** window
+** =======================================================
+*/
+
+static int lc_newwin(lua_State *L)
+{
+ int nlines = luaL_checkint(L, 1);
+ int ncols = luaL_checkint(L, 2);
+ int begin_y = luaL_checkint(L, 3);
+ int begin_x = luaL_checkint(L, 4);
+
+ lcw_new(L, newwin(nlines, ncols, begin_y, begin_x));
+ return 1;
+}
+
+static int lcw_delwin(lua_State *L)
+{
+ WINDOW **w = lcw_get(L, 1);
+ if (*w != NULL && *w != stdscr)
+ {
+ delwin(*w);
+ *w = NULL;
+ }
+ return 0;
+}
+
+static int lcw_mvwin(lua_State *L)
+{
+ WINDOW *w = lcw_check(L, 1);
+ int y = luaL_checkint(L, 2);
+ int x = luaL_checkint(L, 3);
+ lua_pushboolean(L, B(mvwin(w, y, x)));
+ return 1;
+}
+
+static int lcw_subwin(lua_State *L)
+{
+ WINDOW *orig = lcw_check(L, 1);
+ int nlines = luaL_checkint(L, 2);
+ int ncols = luaL_checkint(L, 3);
+ int begin_y = luaL_checkint(L, 4);
+ int begin_x = luaL_checkint(L, 5);
+
+ lcw_new(L, subwin(orig, nlines, ncols, begin_y, begin_x));
+ return 1;
+}
+
+static int lcw_derwin(lua_State *L)
+{
+ WINDOW *orig = lcw_check(L, 1);
+ int nlines = luaL_checkint(L, 2);
+ int ncols = luaL_checkint(L, 3);
+ int begin_y = luaL_checkint(L, 4);
+ int begin_x = luaL_checkint(L, 5);
+
+ lcw_new(L, derwin(orig, nlines, ncols, begin_y, begin_x));
+ return 1;
+}
+
+static int lcw_mvderwin(lua_State *L)
+{
+ WINDOW *w = lcw_check(L, 1);
+ int par_y = luaL_checkint(L, 2);
+ int par_x = luaL_checkint(L, 3);
+ lua_pushboolean(L, B(mvderwin(w, par_y, par_x)));
+ return 1;
+}
+
+static int lcw_dupwin(lua_State *L)
+{
+ WINDOW *w = lcw_check(L, 1);
+ lcw_new(L, dupwin(w));
+ return 1;
+}
+
+static int lcw_wsyncup(lua_State *L)
+{
+ WINDOW *w = lcw_check(L, 1);
+ wsyncup(w);
+ return 0;
+}
+
+static int lcw_syncok(lua_State *L)
+{
+ WINDOW *w = lcw_check(L, 1);
+ int bf = lua_toboolean(L, 2);
+ lua_pushboolean(L, B(syncok(w, bf)));
+ return 1;
+}
+
+static int lcw_wcursyncup(lua_State *L)
+{
+ WINDOW *w = lcw_check(L, 1);
+ wcursyncup(w);
+ return 0;
+}
+
+static int lcw_wsyncdown(lua_State *L)
+{
+ WINDOW *w = lcw_check(L, 1);
+ wsyncdown(w);
+ return 0;
+}
+
+/*
+** =======================================================
+** refresh
+** =======================================================
+*/
+LCW_BOOLOK(wrefresh)
+LCW_BOOLOK(wnoutrefresh)
+LCW_BOOLOK(redrawwin)
+
+static int lcw_wredrawln(lua_State *L)
+{
+ WINDOW *w = lcw_check(L, 1);
+ int beg_line = luaL_checkint(L, 2);
+ int num_lines = luaL_checkint(L, 3);
+ lua_pushboolean(L, B(wredrawln(w, beg_line, num_lines)));
+ return 1;
+}
+
+LC_BOOLOK(doupdate)
+
+/*
+** =======================================================
+** move
+** =======================================================
+*/
+
+static int lcw_wmove(lua_State *L)
+{
+ WINDOW *w = lcw_check(L, 1);
+ int y = luaL_checkint(L, 2);
+ int x = luaL_checkint(L, 3);
+ lua_pushboolean(L, B(wmove(w, y, x)));
+ return 1;
+}
+
+/*
+** =======================================================
+** scroll
+** =======================================================
+*/
+
+static int lcw_wscrl(lua_State *L)
+{
+ WINDOW *w = lcw_check(L, 1);
+ int n = luaL_checkint(L, 2);
+ lua_pushboolean(L, B(wscrl(w, n)));
+ return 1;
+}
+
+/*
+** =======================================================
+** touch
+** =======================================================
+*/
+
+static int lcw_touch(lua_State *L)
+{
+ WINDOW *w = lcw_check(L, 1);
+ int changed;
+ if (lua_isnoneornil(L, 2))
+ changed = TRUE;
+ else
+ changed = lua_toboolean(L, 2);
+
+ if (changed)
+ lua_pushboolean(L, B(touchwin(w)));
+ else
+ lua_pushboolean(L, B(untouchwin(w)));
+ return 1;
+}
+
+static int lcw_touchline(lua_State *L)
+{
+ WINDOW *w = lcw_check(L, 1);
+ int y = luaL_checkint(L, 2);
+ int n = luaL_checkint(L, 3);
+ int changed;
+ if (lua_isnoneornil(L, 4))
+ changed = TRUE;
+ else
+ changed = lua_toboolean(L, 4);
+ lua_pushboolean(L, B(wtouchln(w, y, n, changed)));
+ return 1;
+}
+
+static int lcw_is_linetouched(lua_State *L)
+{
+ WINDOW *w = lcw_check(L, 1);
+ int line = luaL_checkint(L, 2);
+ lua_pushboolean(L, is_linetouched(w, line));
+ return 1;
+}
+
+static int lcw_is_wintouched(lua_State *L)
+{
+ WINDOW *w = lcw_check(L, 1);
+ lua_pushboolean(L, is_wintouched(w));
+ return 1;
+}
+
+/*
+** =======================================================
+** getyx
+** =======================================================
+*/
+
+static int lcw_getyx(lua_State *L)
+{
+ WINDOW *w = lcw_check(L, 1);
+ int y, x;
+ getyx(w, y, x);
+ lua_pushnumber(L, y);
+ lua_pushnumber(L, x);
+ return 2;
+}
+
+static int lcw_getparyx(lua_State *L)
+{
+ WINDOW *w = lcw_check(L, 1);
+ int y, x;
+ getparyx(w, y, x);
+ lua_pushnumber(L, y);
+ lua_pushnumber(L, x);
+ return 2;
+}
+
+static int lcw_getbegyx(lua_State *L)
+{
+ WINDOW *w = lcw_check(L, 1);
+ int y, x;
+ getbegyx(w, y, x);
+ lua_pushnumber(L, y);
+ lua_pushnumber(L, x);
+ return 2;
+}
+
+static int lcw_getmaxyx(lua_State *L)
+{
+ WINDOW *w = lcw_check(L, 1);
+ int y, x;
+ getmaxyx(w, y, x);
+ lua_pushnumber(L, y);
+ lua_pushnumber(L, x);
+ return 2;
+}
+
+/*
+** =======================================================
+** border
+** =======================================================
+*/
+
+static int lcw_wborder(lua_State *L)
+{
+ WINDOW *w = lcw_check(L, 1);
+ chtype ls = lc_optch(L, 2, 0);
+ chtype rs = lc_optch(L, 3, 0);
+ chtype ts = lc_optch(L, 4, 0);
+ chtype bs = lc_optch(L, 5, 0);
+ chtype tl = lc_optch(L, 6, 0);
+ chtype tr = lc_optch(L, 7, 0);
+ chtype bl = lc_optch(L, 8, 0);
+ chtype br = lc_optch(L, 9, 0);
+
+ lua_pushnumber(L, B(wborder(w, ls, rs, ts, bs, tl, tr, bl, br)));
+ return 1;
+}
+
+static int lcw_box(lua_State *L)
+{
+ WINDOW *w = lcw_check(L, 1);
+ chtype verch = lc_checkch(L, 2);
+ chtype horch = lc_checkch(L, 3);
+
+ lua_pushnumber(L, B(box(w, verch, horch)));
+ return 1;
+}
+
+static int lcw_whline(lua_State *L)
+{
+ WINDOW *w = lcw_check(L, 1);
+ chtype ch = lc_checkch(L, 2);
+ int n = luaL_checkint(L, 3);
+
+ lua_pushnumber(L, B(whline(w, ch, n)));
+ return 1;
+}
+
+static int lcw_wvline(lua_State *L)
+{
+ WINDOW *w = lcw_check(L, 1);
+ chtype ch = lc_checkch(L, 2);
+ int n = luaL_checkint(L, 3);
+
+ lua_pushnumber(L, B(wvline(w, ch, n)));
+ return 1;
+}
+
+
+static int lcw_mvwhline(lua_State *L)
+{
+ WINDOW *w = lcw_check(L, 1);
+ int y = luaL_checkint(L, 2);
+ int x = luaL_checkint(L, 3);
+ chtype ch = lc_checkch(L, 4);
+ int n = luaL_checkint(L, 5);
+
+ lua_pushnumber(L, B(mvwhline(w, y, x, ch, n)));
+ return 1;
+}
+
+static int lcw_mvwvline(lua_State *L)
+{
+ WINDOW *w = lcw_check(L, 1);
+ int y = luaL_checkint(L, 2);
+ int x = luaL_checkint(L, 3);
+ chtype ch = lc_checkch(L, 4);
+ int n = luaL_checkint(L, 5);
+
+ lua_pushnumber(L, B(mvwvline(w, y, x, ch, n)));
+ return 1;
+}
+
+/*
+** =======================================================
+** clear
+** =======================================================
+*/
+
+LCW_BOOLOK(werase)
+LCW_BOOLOK(wclear)
+LCW_BOOLOK(wclrtobot)
+LCW_BOOLOK(wclrtoeol)
+
+/*
+** =======================================================
+** slk
+** =======================================================
+*/
+static int lc_slk_init(lua_State *L)
+{
+ int fmt = luaL_checkint(L, 1);
+ lua_pushboolean(L, B(slk_init(fmt)));
+ return 1;
+}
+
+static int lc_slk_set(lua_State *L)
+{
+ int labnum = luaL_checkint(L, 1);
+ const char* label = luaL_checkstring(L, 2);
+ int fmt = luaL_checkint(L, 3);
+
+ lua_pushboolean(L, B(slk_set(labnum, label, fmt)));
+ return 1;
+}
+
+LC_BOOLOK(slk_refresh)
+LC_BOOLOK(slk_noutrefresh)
+
+static int lc_slk_label(lua_State *L)
+{
+ int labnum = luaL_checkint(L, 1);
+ lua_pushstring(L, slk_label(labnum));
+ return 1;
+}
+
+LC_BOOLOK(slk_clear)
+LC_BOOLOK(slk_restore)
+LC_BOOLOK(slk_touch)
+
+static int lc_slk_attron(lua_State *L)
+{
+ chtype attrs = lc_checkch(L, 1);
+ lua_pushboolean(L, B(slk_attron(attrs)));
+ return 1;
+}
+
+static int lc_slk_attroff(lua_State *L)
+{
+ chtype attrs = lc_checkch(L, 1);
+ lua_pushboolean(L, B(slk_attroff(attrs)));
+ return 1;
+}
+
+static int lc_slk_attrset(lua_State *L)
+{
+ chtype attrs = lc_checkch(L, 1);
+ lua_pushboolean(L, B(slk_attrset(attrs)));
+ return 1;
+}
+
+/*
+** =======================================================
+** addch
+** =======================================================
+*/
+
+static int lcw_waddch(lua_State *L)
+{
+ WINDOW *w = lcw_check(L, 1);
+ chtype ch = lc_checkch(L, 2);
+ if (map_output && ch < 256) ch = ascii_map[ch];
+ lua_pushboolean(L, B(waddch(w, ch)));
+ return 1;
+}
+
+static int lcw_mvwaddch(lua_State *L)
+{
+ WINDOW *w = lcw_check(L, 1);
+ int y = luaL_checkint(L, 2);
+ int x = luaL_checkint(L, 3);
+ chtype ch = lc_checkch(L, 4);
+
+ if (map_output && ch < 256) ch = ascii_map[ch];
+ lua_pushboolean(L, B(mvwaddch(w, y, x, ch)));
+ return 1;
+}
+
+static int lcw_wechochar(lua_State *L)
+{
+ WINDOW *w = lcw_check(L, 1);
+ chtype ch = lc_checkch(L, 2);
+
+ lua_pushboolean(L, B(wechochar(w, ch)));
+ return 1;
+}
+
+/*
+** =======================================================
+** addchstr
+** =======================================================
+*/
+
+static int lcw_waddchnstr(lua_State *L)
+{
+ WINDOW *w = lcw_check(L, 1);
+ int n = luaL_optint(L, 3, -1);
+ chstr *cs = lc_checkchstr(L, 2);
+
+ if (n < 0 || n > cs->len)
+ n = cs->len;
+
+ lua_pushboolean(L, B(waddchnstr(w, cs->str, n)));
+ return 1;
+}
+
+static int lcw_mvwaddchnstr(lua_State *L)
+{
+ WINDOW *w = lcw_check(L, 1);
+ int y = luaL_checkint(L, 2);
+ int x = luaL_checkint(L, 3);
+ int n = luaL_optint(L, 5, -1);
+ chstr *cs = lc_checkchstr(L, 4);
+
+ if (n < 0 || n > cs->len)
+ n = cs->len;
+
+ lua_pushboolean(L, B(mvwaddchnstr(w, y, x, cs->str, n)));
+ return 1;
+}
+
+/*
+** =======================================================
+** addstr
+** =======================================================
+*/
+
+static int lcw_waddnstr(lua_State *L)
+{
+ WINDOW *w = lcw_check(L, 1);
+ const char *str = luaL_checkstring(L, 2);
+ int n = luaL_optint(L, 3, -1);
+
+ if (n < 0) n = lua_strlen(L, 2);
+
+ lua_pushboolean(L, B(waddnstr(w, str, n)));
+ return 1;
+}
+
+static int lcw_mvwaddnstr(lua_State *L)
+{
+ WINDOW *w = lcw_check(L, 1);
+ int y = luaL_checkint(L, 2);
+ int x = luaL_checkint(L, 3);
+ const char *str = luaL_checkstring(L, 4);
+ int n = luaL_optint(L, 5, -1);
+
+ if (n < 0) n = lua_strlen(L, 4);
+
+ lua_pushboolean(L, B(mvwaddnstr(w, y, x, str, n)));
+ return 1;
+}
+
+/*
+** =======================================================
+** bkgd
+** =======================================================
+*/
+
+static int lcw_wbkgdset(lua_State *L)
+{
+ WINDOW *w = lcw_check(L, 1);
+ chtype ch = lc_checkch(L, 2);
+ wbkgdset(w, ch);
+ return 0;
+}
+
+static int lcw_wbkgd(lua_State *L)
+{
+ WINDOW *w = lcw_check(L, 1);
+ chtype ch = lc_checkch(L, 2);
+ lua_pushboolean(L, B(wbkgd(w, ch)));
+ return 1;
+}
+
+static int lcw_getbkgd(lua_State *L)
+{
+ WINDOW *w = lcw_check(L, 1);
+ lua_pushnumber(L, B(getbkgd(w)));
+ return 1;
+}
+
+/*
+** =======================================================
+** inopts
+** =======================================================
+*/
+
+static int lc_cbreak(lua_State *L)
+{
+ if (lua_isnoneornil(L, 1) || lua_toboolean(L, 1))
+ lua_pushboolean(L, B(cbreak()));
+ else
+ lua_pushboolean(L, B(nocbreak()));
+ return 1;
+}
+
+static int lc_echo(lua_State *L)
+{
+ if (lua_isnoneornil(L, 1) || lua_toboolean(L, 1))
+ lua_pushboolean(L, B(echo()));
+ else
+ lua_pushboolean(L, B(noecho()));
+ return 1;
+}
+
+static int lc_raw(lua_State *L)
+{
+ if (lua_isnoneornil(L, 1) || lua_toboolean(L, 1))
+ lua_pushboolean(L, B(raw()));
+ else
+ lua_pushboolean(L, B(noraw()));
+ return 1;
+}
+
+static int lc_halfdelay(lua_State *L)
+{
+ int tenths = luaL_checkint(L, 1);
+ lua_pushboolean(L, B(halfdelay(tenths)));
+ return 1;
+}
+
+static int lcw_intrflush(lua_State *L)
+{
+ WINDOW *w = lcw_check(L, 1);
+ int bf = lua_toboolean(L, 2);
+ lua_pushboolean(L, B(intrflush(w, bf)));
+ return 1;
+}
+
+static int lcw_keypad(lua_State *L)
+{
+ WINDOW *w = lcw_check(L, 1);
+ int bf = lua_isnoneornil(L, 2) ? 1 : lua_toboolean(L, 2);
+ lua_pushboolean(L, B(keypad(w, bf)));
+ return 1;
+}
+
+static int lcw_meta(lua_State *L)
+{
+ WINDOW *w = lcw_check(L, 1);
+ int bf = lua_toboolean(L, 2);
+ lua_pushboolean(L, B(meta(w, bf)));
+ return 1;
+}
+
+static int lcw_nodelay(lua_State *L)
+{
+ WINDOW *w = lcw_check(L, 1);
+ int bf = lua_toboolean(L, 2);
+ lua_pushboolean(L, B(nodelay(w, bf)));
+ return 1;
+}
+
+static int lcw_timeout(lua_State *L)
+{
+ WINDOW *w = lcw_check(L, 1);
+ int delay = luaL_checkint(L, 2);
+ wtimeout(w, delay);
+ return 0;
+}
+
+static int lcw_notimeout(lua_State *L)
+{
+ WINDOW *w = lcw_check(L, 1);
+ int bf = lua_toboolean(L, 2);
+ lua_pushboolean(L, B(notimeout(w, bf)));
+ return 1;
+}
+
+/*
+** =======================================================
+** outopts
+** =======================================================
+*/
+
+static int lc_nl(lua_State *L)
+{
+ if (lua_isnoneornil(L, 1) || lua_toboolean(L, 1))
+ lua_pushboolean(L, B(nl()));
+ else
+ lua_pushboolean(L, B(nonl()));
+ return 1;
+}
+
+static int lcw_clearok(lua_State *L)
+{
+ WINDOW *w = lcw_check(L, 1);
+ int bf = lua_toboolean(L, 2);
+ lua_pushboolean(L, B(clearok(w, bf)));
+ return 1;
+}
+
+static int lcw_idlok(lua_State *L)
+{
+ WINDOW *w = lcw_check(L, 1);
+ int bf = lua_toboolean(L, 2);
+ lua_pushboolean(L, B(idlok(w, bf)));
+ return 1;
+}
+
+static int lcw_leaveok(lua_State *L)
+{
+ WINDOW *w = lcw_check(L, 1);
+ int bf = lua_toboolean(L, 2);
+ lua_pushboolean(L, B(leaveok(w, bf)));
+ return 1;
+}
+
+static int lcw_scrollok(lua_State *L)
+{
+ WINDOW *w = lcw_check(L, 1);
+ int bf = lua_toboolean(L, 2);
+ lua_pushboolean(L, B(scrollok(w, bf)));
+ return 1;
+}
+
+static int lcw_idcok(lua_State *L)
+{
+ WINDOW *w = lcw_check(L, 1);
+ int bf = lua_toboolean(L, 2);
+ idcok(w, bf);
+ return 0;
+}
+
+static int lcw_immedok(lua_State *L)
+{
+ WINDOW *w = lcw_check(L, 1);
+ int bf = lua_toboolean(L, 2);
+ immedok(w, bf);
+ return 0;
+}
+
+static int lcw_wsetscrreg(lua_State *L)
+{
+ WINDOW *w = lcw_check(L, 1);
+ int top = luaL_checkint(L, 2);
+ int bot = luaL_checkint(L, 3);
+ lua_pushboolean(L, B(wsetscrreg(w, top, bot)));
+ return 1;
+}
+
+/*
+** =======================================================
+** overlay
+** =======================================================
+*/
+
+static int lcw_overlay(lua_State *L)
+{
+ WINDOW *srcwin = lcw_check(L, 1);
+ WINDOW *dstwin = lcw_check(L, 2);
+
+ lua_pushboolean(L, B(overlay(srcwin, dstwin)));
+ return 1;
+}
+
+static int lcw_overwrite(lua_State *L)
+{
+ WINDOW *srcwin = lcw_check(L, 1);
+ WINDOW *dstwin = lcw_check(L, 2);
+
+ lua_pushboolean(L, B(overwrite(srcwin, dstwin)));
+ return 1;
+}
+
+static int lcw_copywin(lua_State *L)
+{
+ WINDOW *srcwin = lcw_check(L, 1);
+ WINDOW *dstwin = lcw_check(L, 2);
+ int sminrow = luaL_checkint(L, 3);
+ int smincol = luaL_checkint(L, 4);
+ int dminrow = luaL_checkint(L, 5);
+ int dmincol = luaL_checkint(L, 6);
+ int dmaxrow = luaL_checkint(L, 7);
+ int dmaxcol = luaL_checkint(L, 8);
+ int overlay = lua_toboolean(L, 9);
+
+ lua_pushboolean(L, B(copywin(srcwin, dstwin, sminrow,
+ smincol, dminrow, dmincol, dmaxrow, dmaxcol, overlay)));
+
+ return 1;
+}
+
+/*
+** =======================================================
+** util
+** =======================================================
+*/
+
+static int lc_unctrl(lua_State *L)
+{
+ chtype c = (chtype)luaL_checknumber(L, 1);
+ lua_pushstring(L, unctrl(c));
+ return 1;
+}
+
+static int lc_keyname(lua_State *L)
+{
+ int c = luaL_checkint(L, 1);
+ lua_pushstring(L, keyname(c));
+ return 1;
+}
+
+static int lc_delay_output(lua_State *L)
+{
+ int ms = luaL_checkint(L, 1);
+ lua_pushboolean(L, B(delay_output(ms)));
+ return 1;
+}
+
+static int lc_flushinp(lua_State *L)
+{
+ lua_pushboolean(L, B(flushinp()));
+ return 1;
+}
+
+/*
+** =======================================================
+** delch
+** =======================================================
+*/
+
+LCW_BOOLOK(wdelch)
+
+static int lcw_mvwdelch(lua_State *L)
+{
+ WINDOW *w = lcw_check(L, 1);
+ int y = luaL_checkint(L, 2);
+ int x = luaL_checkint(L, 3);
+
+ lua_pushboolean(L, B(mvwdelch(w, y, x)));
+ return 1;
+}
+
+/*
+** =======================================================
+** deleteln
+** =======================================================
+*/
+
+LCW_BOOLOK(wdeleteln)
+LCW_BOOLOK(winsertln)
+
+static int lcw_winsdelln(lua_State *L)
+{
+ WINDOW *w = lcw_check(L, 1);
+ int n = luaL_checkint(L, 2);
+ lua_pushboolean(L, B(winsdelln(w, n)));
+ return 1;
+}
+
+/*
+** =======================================================
+** getch
+** =======================================================
+*/
+
+static int lcw_wgetch(lua_State *L)
+{
+ WINDOW *w = lcw_check(L, 1);
+ int c = map_getch(w);
+
+ if (c == ERR) return 0;
+
+ lua_pushnumber(L, c);
+ return 1;
+}
+
+static int lcw_mvwgetch(lua_State *L)
+{
+ WINDOW *w = lcw_check(L, 1);
+ int y = luaL_checkint(L, 2);
+ int x = luaL_checkint(L, 3);
+ int c;
+
+ if (wmove(w, y, x) == ERR) return 0;
+
+ c = map_getch(w);
+
+ if (c == ERR) return 0;
+
+ lua_pushnumber(L, c);
+ return 1;
+}
+
+static int lc_ungetch(lua_State *L)
+{
+ int c = luaL_checkint(L, 1);
+ lua_pushboolean(L, B(ungetch(c)));
+ return 1;
+}
+
+/*
+** =======================================================
+** getstr
+** =======================================================
+*/
+
+static int lcw_wgetnstr(lua_State *L)
+{
+ WINDOW *w = lcw_check(L, 1);
+ int n = luaL_optint(L, 2, 0);
+ char buf[LUAL_BUFFERSIZE];
+
+ if (n == 0 || n >= LUAL_BUFFERSIZE) n = LUAL_BUFFERSIZE - 1;
+ if (wgetnstr(w, buf, n) == ERR)
+ return 0;
+
+ lua_pushstring(L, buf);
+ return 1;
+}
+
+static int lcw_mvwgetnstr(lua_State *L)
+{
+ WINDOW *w = lcw_check(L, 1);
+ int y = luaL_checkint(L, 2);
+ int x = luaL_checkint(L, 3);
+ int n = luaL_optint(L, 4, -1);
+ char buf[LUAL_BUFFERSIZE];
+
+ if (n == 0 || n >= LUAL_BUFFERSIZE) n = LUAL_BUFFERSIZE - 1;
+ if (mvwgetnstr(w, y, x, buf, n) == ERR)
+ return 0;
+
+ lua_pushstring(L, buf);
+ return 1;
+}
+
+/*
+** =======================================================
+** inch
+** =======================================================
+*/
+
+static int lcw_winch(lua_State *L)
+{
+ WINDOW *w = lcw_check(L, 1);
+ lua_pushnumber(L, winch(w));
+ return 1;
+}
+
+static int lcw_mvwinch(lua_State *L)
+{
+ WINDOW *w = lcw_check(L, 1);
+ int y = luaL_checkint(L, 2);
+ int x = luaL_checkint(L, 3);
+ lua_pushnumber(L, mvwinch(w, y, x));
+ return 1;
+}
+
+/*
+** =======================================================
+** inchstr
+** =======================================================
+*/
+
+static int lcw_winchnstr(lua_State *L)
+{
+ WINDOW *w = lcw_check(L, 1);
+ int n = luaL_checkint(L, 2);
+ chstr *cs = chstr_new(L, n);
+
+ if (winchnstr(w, cs->str, n) == ERR)
+ return 0;
+
+ return 1;
+}
+
+static int lcw_mvwinchnstr(lua_State *L)
+{
+ WINDOW *w = lcw_check(L, 1);
+ int y = luaL_checkint(L, 2);
+ int x = luaL_checkint(L, 3);
+ int n = luaL_checkint(L, 4);
+ chstr *cs = chstr_new(L, n);
+
+ if (mvwinchnstr(w, y, x, cs->str, n) == ERR)
+ return 0;
+
+ return 1;
+}
+
+/*
+** =======================================================
+** instr
+** =======================================================
+*/
+
+static int lcw_winnstr(lua_State *L)
+{
+ WINDOW *w = lcw_check(L, 1);
+ int n = luaL_checkint(L, 2);
+ char buf[LUAL_BUFFERSIZE];
+
+ if (n >= LUAL_BUFFERSIZE) n = LUAL_BUFFERSIZE - 1;
+ if (winnstr(w, buf, n) == ERR)
+ return 0;
+
+ lua_pushlstring(L, buf, n);
+ return 1;
+}
+
+static int lcw_mvwinnstr(lua_State *L)
+{
+ WINDOW *w = lcw_check(L, 1);
+ int y = luaL_checkint(L, 2);
+ int x = luaL_checkint(L, 3);
+ int n = luaL_checkint(L, 4);
+ char buf[LUAL_BUFFERSIZE];
+
+ if (n >= LUAL_BUFFERSIZE) n = LUAL_BUFFERSIZE - 1;
+ if (mvwinnstr(w, y, x, buf, n) == ERR)
+ return 0;
+
+ lua_pushlstring(L, buf, n);
+ return 1;
+}
+
+/*
+** =======================================================
+** insch
+** =======================================================
+*/
+
+static int lcw_winsch(lua_State *L)
+{
+ WINDOW *w = lcw_check(L, 1);
+ chtype ch = lc_checkch(L, 2);
+ lua_pushboolean(L, B(winsch(w, ch)));
+ return 1;
+}
+
+static int lcw_mvwinsch(lua_State *L)
+{
+ WINDOW *w = lcw_check(L, 1);
+ int y = luaL_checkint(L, 2);
+ int x = luaL_checkint(L, 3);
+ chtype ch = lc_checkch(L, 4);
+ lua_pushboolean(L, B(mvwinsch(w, y, x, ch)));
+ return 1;
+}
+
+/*
+** =======================================================
+** insstr
+** =======================================================
+*/
+
+static int lcw_winsstr(lua_State *L)
+{
+ WINDOW *w = lcw_check(L, 1);
+ const char *str = luaL_checkstring(L, 2);
+ lua_pushboolean(L, B(winsnstr(w, str, lua_strlen(L, 2))));
+ return 1;
+}
+
+static int lcw_mvwinsstr(lua_State *L)
+{
+ WINDOW *w = lcw_check(L, 1);
+ int y = luaL_checkint(L, 2);
+ int x = luaL_checkint(L, 3);
+ const char *str = luaL_checkstring(L, 4);
+ lua_pushboolean(L, B(mvwinsnstr(w, y, x, str, lua_strlen(L, 2))));
+ return 1;
+}
+
+static int lcw_winsnstr(lua_State *L)
+{
+ WINDOW *w = lcw_check(L, 1);
+ const char *str = luaL_checkstring(L, 2);
+ int n = luaL_checkint(L, 3);
+ lua_pushboolean(L, B(winsnstr(w, str, n)));
+ return 1;
+}
+
+static int lcw_mvwinsnstr(lua_State *L)
+{
+ WINDOW *w = lcw_check(L, 1);
+ int y = luaL_checkint(L, 2);
+ int x = luaL_checkint(L, 3);
+ const char *str = luaL_checkstring(L, 4);
+ int n = luaL_checkint(L, 5);
+ lua_pushboolean(L, B(mvwinsnstr(w, y, x, str, n)));
+ return 1;
+}
+
+/*
+** =======================================================
+** pad
+** =======================================================
+*/
+
+static int lc_newpad(lua_State *L)
+{
+ int nlines = luaL_checkint(L, 1);
+ int ncols = luaL_checkint(L, 2);
+ lcw_new(L, newpad(nlines, ncols));
+ return 1;
+}
+
+static int lcw_subpad(lua_State *L)
+{
+ WINDOW *orig = lcw_check(L, 1);
+ int nlines = luaL_checkint(L, 2);
+ int ncols = luaL_checkint(L, 3);
+ int begin_y = luaL_checkint(L, 4);
+ int begin_x = luaL_checkint(L, 5);
+
+ lcw_new(L, subpad(orig, nlines, ncols, begin_y, begin_x));
+ return 1;
+}
+
+static int lcw_prefresh(lua_State *L)
+{
+ WINDOW *p = lcw_check(L, 1);
+ int pminrow = luaL_checkint(L, 2);
+ int pmincol = luaL_checkint(L, 3);
+ int sminrow = luaL_checkint(L, 4);
+ int smincol = luaL_checkint(L, 5);
+ int smaxrow = luaL_checkint(L, 6);
+ int smaxcol = luaL_checkint(L, 7);
+
+ lua_pushboolean(L, B(prefresh(p, pminrow, pmincol,
+ sminrow, smincol, smaxrow, smaxcol)));
+ return 1;
+}
+
+static int lcw_pnoutrefresh(lua_State *L)
+{
+ WINDOW *p = lcw_check(L, 1);
+ int pminrow = luaL_checkint(L, 2);
+ int pmincol = luaL_checkint(L, 3);
+ int sminrow = luaL_checkint(L, 4);
+ int smincol = luaL_checkint(L, 5);
+ int smaxrow = luaL_checkint(L, 6);
+ int smaxcol = luaL_checkint(L, 7);
+
+ lua_pushboolean(L, B(pnoutrefresh(p, pminrow, pmincol,
+ sminrow, smincol, smaxrow, smaxcol)));
+ return 1;
+}
+
+
+static int lcw_pechochar(lua_State *L)
+{
+ WINDOW *p = lcw_check(L, 1);
+ chtype ch = lc_checkch(L, 2);
+
+ lua_pushboolean(L, B(pechochar(p, ch)));
+ return 1;
+}
+
+/*
+** =======================================================
+** attr
+** =======================================================
+*/
+
+static int lcw_wattroff(lua_State *L)
+{
+ WINDOW *w = lcw_check(L, 1);
+ int attrs = luaL_checkint(L, 2);
+ lua_pushboolean(L, B(wattroff(w, attrs)));
+ return 1;
+}
+
+static int lcw_wattron(lua_State *L)
+{
+ WINDOW *w = lcw_check(L, 1);
+ int attrs = luaL_checkint(L, 2);
+ lua_pushboolean(L, B(wattron(w, attrs)));
+ return 1;
+}
+
+static int lcw_wattrset(lua_State *L)
+{
+ WINDOW *w = lcw_check(L, 1);
+ int attrs = luaL_checkint(L, 2);
+ lua_pushboolean(L, B(wattrset(w, attrs)));
+ return 1;
+}
+
+LCW_BOOLOK(wstandend)
+LCW_BOOLOK(wstandout)
+
+
+/*
+** =======================================================
+** text functions
+** =======================================================
+*/
+
+#define LCT(name) \
+ static int lca_ ## name(lua_State* L) \
+ { \
+ const char *s = luaL_checkstring(L, 1); \
+ lua_pushboolean(L, name(*s)); \
+ return 1; \
+ }
+
+LCT(isalnum)
+LCT(isalpha)
+/*LCT(isblank)*/
+LCT(iscntrl)
+LCT(isdigit)
+LCT(isgraph)
+LCT(islower)
+LCT(isprint)
+LCT(ispunct)
+LCT(isspace)
+LCT(isupper)
+LCT(isxdigit)
+
+/*
+** =======================================================
+** register functions
+** =======================================================
+*/
+/* chstr members */
+static const luaL_reg chstrlib[] =
+{
+ { "len", chstr_len },
+ { "set_ch", chstr_set_ch },
+ { "set_str", chstr_set_str },
+ { "get", chstr_get },
+ { "dup", chstr_dup },
+
+ { NULL, NULL }
+};
+
+#define EWF(name) { #name, lcw_ ## name },
+static const luaL_reg windowlib[] =
+{
+ /* window */
+ { "close", lcw_delwin },
+ { "sub", lcw_subwin },
+ { "derive", lcw_derwin },
+ { "move_window", lcw_mvwin },
+ { "move_derived", lcw_mvderwin },
+ { "clone", lcw_dupwin },
+ { "syncup", lcw_wsyncup },
+ { "syncdown", lcw_wsyncdown },
+ { "syncok", lcw_syncok },
+ { "cursyncup", lcw_wcursyncup },
+
+ /* inopts */
+ EWF(intrflush)
+ EWF(keypad)
+ EWF(meta)
+ EWF(nodelay)
+ EWF(timeout)
+ EWF(notimeout)
+
+ /* outopts */
+ EWF(clearok)
+ EWF(idlok)
+ EWF(leaveok)
+ EWF(scrollok)
+ EWF(idcok)
+ EWF(immedok)
+ EWF(wsetscrreg)
+
+ /* pad */
+ EWF(subpad)
+ EWF(prefresh)
+ EWF(pnoutrefresh)
+ EWF(pechochar)
+
+ /* move */
+ { "move", lcw_wmove },
+
+ /* scroll */
+ { "scroll", lcw_wscrl },
+
+ /* refresh */
+ { "refresh", lcw_wrefresh },
+ { "noutrefresh", lcw_wnoutrefresh },
+ { "redraw", lcw_redrawwin },
+ { "redraw_line", lcw_wredrawln },
+
+ /* clear */
+ { "erase", lcw_werase },
+ { "clear", lcw_wclear },
+ { "clear_to_bottom", lcw_wclrtobot },
+ { "clear_to_eol", lcw_wclrtoeol },
+
+ /* touch */
+ { "touch", lcw_touch },
+ { "touch_line", lcw_touchline },
+ { "is_line_touched", lcw_is_linetouched },
+ { "is_touched", lcw_is_wintouched },
+
+ /* attrs */
+ { "attroff", lcw_wattroff },
+ { "attron", lcw_wattron },
+ { "attrset", lcw_wattrset },
+ { "standout", lcw_wstandout },
+ { "standend", lcw_wstandend },
+
+ /* getch */
+ { "getch", lcw_wgetch },
+ { "mvgetch", lcw_mvwgetch },
+
+ /* getyx */
+ EWF(getyx)
+ EWF(getparyx)
+ EWF(getbegyx)
+ EWF(getmaxyx)
+
+ /* border */
+ { "border", lcw_wborder },
+ { "box", lcw_box },
+ { "hline", lcw_whline },
+ { "vline", lcw_wvline },
+ { "mvhline", lcw_mvwhline },
+ { "mvvline", lcw_mvwvline },
+
+ /* addch */
+ { "addch", lcw_waddch },
+ { "mvaddch", lcw_mvwaddch },
+ { "echoch", lcw_wechochar },
+
+ /* addchstr */
+ { "addchstr", lcw_waddchnstr },
+ { "mvaddchstr", lcw_mvwaddchnstr },
+
+ /* addstr */
+ { "addstr", lcw_waddnstr },
+ { "mvaddstr", lcw_mvwaddnstr },
+
+ /* bkgd */
+ EWF(wbkgdset)
+ EWF(wbkgd)
+ EWF(getbkgd)
+
+ /* overlay */
+ { "overlay", lcw_overlay },
+ { "overwrite", lcw_overwrite },
+ { "copy", lcw_copywin },
+
+ /* delch */
+ { "delch", lcw_wdelch },
+ { "mvdelch", lcw_mvwdelch },
+
+ /* deleteln */
+ { "delete_line", lcw_wdeleteln },
+ { "insert_line", lcw_winsertln },
+ EWF(winsdelln)
+
+ /* getstr */
+ { "getstr", lcw_wgetnstr },
+ { "mvgetstr", lcw_mvwgetnstr },
+
+ /* inch */
+ EWF(winch)
+ EWF(mvwinch)
+ EWF(winchnstr)
+ EWF(mvwinchnstr)
+
+ /* instr */
+ EWF(winnstr)
+ EWF(mvwinnstr)
+
+ /* insch */
+ EWF(winsch)
+ EWF(mvwinsch)
+
+ /* insstr */
+ EWF(winsstr)
+ EWF(winsnstr)
+ EWF(mvwinsstr)
+ EWF(mvwinsnstr)
+
+ /* misc */
+ {"__gc", lcw_delwin }, /* rough safety net */
+ {"__tostring", lcw_tostring},
+ {NULL, NULL}
+};
+
+#define ECF(name) { #name, lc_ ## name },
+#define ETF(name) { #name, lca_ ## name },
+static const luaL_reg curseslib[] =
+{
+ /* chstr helper function */
+ { "new_chstr", lc_new_chstr },
+ { "map_output", lc_map_output },
+
+ /* keyboard mapping */
+ { "map_keyboard", lc_map_keyboard },
+
+ /* initscr */
+ #if 0
+ { "init", lc_initscr },
+ #endif
+ { "done", lc_endwin },
+ { "isdone", lc_isendwin },
+ { "main_window", lc_stdscr },
+ { "columns", lc_COLS },
+ { "lines", lc_LINES },
+
+ /* color */
+ { "start_color", lc_start_color },
+ { "has_colors", lc_has_colors },
+ { "init_pair", lc_init_pair },
+ { "pair_content", lc_pair_content },
+ { "colors", lc_COLORS },
+ { "color_pairs", lc_COLOR_PAIRS },
+ { "color_pair", lc_COLOR_PAIR },
+
+ /* termattrs */
+ { "baudrate", lc_baudrate },
+ { "erase_char", lc_erasechar },
+ { "kill_char", lc_killchar },
+ { "has_insert_char",lc_has_ic },
+ { "has_insert_line",lc_has_il },
+ { "termattrs", lc_termattrs },
+ { "termname", lc_termname },
+ { "longname", lc_longname },
+
+ /* kernel */
+ { "ripoffline", lc_ripoffline },
+ { "napms", lc_napms },
+ { "cursor_set", lc_curs_set },
+
+ /* beep */
+ { "beep", lc_beep },
+ { "flash", lc_flash },
+
+ /* window */
+ { "new_window", lc_newwin },
+
+ /* pad */
+ { "new_pad", lc_newpad },
+
+ /* refresh */
+ { "doupdate", lc_doupdate },
+
+ /* inopts */
+ { "cbreak", lc_cbreak },
+ { "echo", lc_echo },
+ { "raw", lc_raw },
+ { "halfdelay", lc_halfdelay },
+
+ /* util */
+ { "unctrl", lc_unctrl },
+ { "keyname", lc_keyname },
+ { "delay_output", lc_delay_output },
+ { "flush_input", lc_flushinp },
+
+ /* getch */
+ { "ungetch", lc_ungetch },
+
+ /* outopts */
+ { "nl", lc_nl },
+
+ /* slk */
+ ECF(slk_init)
+ ECF(slk_set)
+ ECF(slk_refresh)
+ ECF(slk_noutrefresh)
+ ECF(slk_label)
+ ECF(slk_clear)
+ ECF(slk_restore)
+ ECF(slk_touch)
+ ECF(slk_attron)
+ ECF(slk_attroff)
+ ECF(slk_attrset)
+
+ /* text functions */
+ ETF(isalnum)
+ ETF(isalpha)
+ /*ETF(isblank)*/
+ ETF(iscntrl)
+ ETF(isdigit)
+ ETF(isgraph)
+ ETF(islower)
+ ETF(isprint)
+ ETF(ispunct)
+ ETF(isspace)
+ ETF(isupper)
+ ETF(isxdigit)
+
+ /* terminator */
+ {NULL, NULL}
+};
+
+
+int luaopen_cui_curses (lua_State *L)
+{
+ /*
+ ** create new metatable for window objects
+ */
+ luaL_newmetatable(L, WINDOWMETA);
+ lua_pushliteral(L, "__index");
+ lua_pushvalue(L, -2); /* push metatable */
+ lua_rawset(L, -3); /* metatable.__index = metatable */
+ luaL_openlib(L, NULL, windowlib, 0);
+
+ lua_pop(L, 1); /* remove metatable from stack */
+
+ /*
+ ** create new metatable for chstr objects
+ */
+ luaL_newmetatable(L, CHSTRMETA);
+ lua_pushliteral(L, "__index");
+ lua_pushvalue(L, -2); /* push metatable */
+ lua_rawset(L, -3); /* metatable.__index = metatable */
+ luaL_openlib(L, NULL, chstrlib, 0);
+
+ lua_pop(L, 1); /* remove metatable from stack */
+
+
+ /*
+ ** create global table with curses methods/variables/constants
+ */
+ lua_newtable(L);
+ luaL_register(L, NULL, curseslib);
+
+ lua_pushstring(L, "init");
+ lua_pushvalue(L, -2);
+ lua_pushcclosure(L, lc_initscr, 1);
+ lua_settable(L, -3);
+
+ return 1;
+}
+
+
+/* initialize the character map table with the known values after
+** curses initialization (for ACS_xxx values) */
+static void init_ascii_map()
+{
+ ascii_map[ 0] = 32; ascii_map[ 1] = 79; ascii_map[ 2] = 79; ascii_map[ 3] = 111;
+ ascii_map[ 4] = ACS_DIAMOND; ascii_map[ 5] = 111; ascii_map[ 6] = 111; ascii_map[ 7] = 111;
+ ascii_map[ 8] = 111; ascii_map[ 9] = 111; ascii_map[ 10] = 111; ascii_map[ 11] = 111;
+ ascii_map[ 12] = 33; ascii_map[ 13] = 33; ascii_map[ 14] = 33; ascii_map[ 15] = 42;
+ ascii_map[ 16] = ACS_RARROW; ascii_map[ 17] = ACS_LARROW; ascii_map[ 18] = 124; ascii_map[ 19] = 33;
+ ascii_map[ 20] = 33; ascii_map[ 21] = 79; ascii_map[ 22] = 95; ascii_map[ 23] = 124;
+ ascii_map[ 24] = ACS_UARROW; ascii_map[ 25] = ACS_DARROW; ascii_map[ 26] = ACS_RARROW; ascii_map[ 27] = ACS_LARROW;
+ ascii_map[ 28] = ACS_LLCORNER; ascii_map[ 29] = 45; ascii_map[ 30] = ACS_UARROW; ascii_map[ 31] = ACS_DARROW;
+ ascii_map[ 32] = 32; ascii_map[ 33] = 33; ascii_map[ 34] = 34; ascii_map[ 35] = 35;
+ ascii_map[ 36] = 36; ascii_map[ 37] = 37; ascii_map[ 38] = 38; ascii_map[ 39] = 39;
+ ascii_map[ 40] = 40; ascii_map[ 41] = 41; ascii_map[ 42] = 42; ascii_map[ 43] = 43;
+ ascii_map[ 44] = 44; ascii_map[ 45] = 45; ascii_map[ 46] = 46; ascii_map[ 47] = 47;
+ ascii_map[ 48] = 48; ascii_map[ 49] = 49; ascii_map[ 50] = 50; ascii_map[ 51] = 51;
+ ascii_map[ 52] = 52; ascii_map[ 53] = 53; ascii_map[ 54] = 54; ascii_map[ 55] = 55;
+ ascii_map[ 56] = 56; ascii_map[ 57] = 57; ascii_map[ 58] = 58; ascii_map[ 59] = 59;
+ ascii_map[ 60] = 60; ascii_map[ 61] = 61; ascii_map[ 62] = 62; ascii_map[ 63] = 63;
+ ascii_map[ 64] = 64; ascii_map[ 65] = 65; ascii_map[ 66] = 66; ascii_map[ 67] = 67;
+ ascii_map[ 68] = 68; ascii_map[ 69] = 69; ascii_map[ 70] = 70; ascii_map[ 71] = 71;
+ ascii_map[ 72] = 72; ascii_map[ 73] = 73; ascii_map[ 74] = 74; ascii_map[ 75] = 75;
+ ascii_map[ 76] = 76; ascii_map[ 77] = 77; ascii_map[ 78] = 78; ascii_map[ 79] = 79;
+ ascii_map[ 80] = 80; ascii_map[ 81] = 81; ascii_map[ 82] = 82; ascii_map[ 83] = 83;
+ ascii_map[ 84] = 84; ascii_map[ 85] = 85; ascii_map[ 86] = 86; ascii_map[ 87] = 87;
+ ascii_map[ 88] = 88; ascii_map[ 89] = 89; ascii_map[ 90] = 90; ascii_map[ 91] = 91;
+ ascii_map[ 92] = 92; ascii_map[ 93] = 93; ascii_map[ 94] = 94; ascii_map[ 95] = 95;
+ ascii_map[ 96] = 96; ascii_map[ 97] = 97; ascii_map[ 98] = 98; ascii_map[ 99] = 99;
+ ascii_map[100] = 100; ascii_map[101] = 101; ascii_map[102] = 102; ascii_map[103] = 103;
+ ascii_map[104] = 104; ascii_map[105] = 105; ascii_map[106] = 106; ascii_map[107] = 107;
+ ascii_map[108] = 108; ascii_map[109] = 109; ascii_map[110] = 110; ascii_map[111] = 111;
+ ascii_map[112] = 112; ascii_map[113] = 113; ascii_map[114] = 114; ascii_map[115] = 115;
+ ascii_map[116] = 116; ascii_map[117] = 117; ascii_map[118] = 118; ascii_map[119] = 119;
+ ascii_map[120] = 120; ascii_map[121] = 121; ascii_map[122] = 122; ascii_map[123] = 123;
+ ascii_map[124] = 124; ascii_map[125] = 125; ascii_map[126] = 126; ascii_map[127] = 100;
+ ascii_map[128] = 99; ascii_map[129] = 117; ascii_map[130] = 101; ascii_map[131] = 97;
+ ascii_map[132] = 97; ascii_map[133] = 97; ascii_map[134] = 97; ascii_map[135] = 99;
+ ascii_map[136] = 101; ascii_map[137] = 101; ascii_map[138] = 101; ascii_map[139] = 105;
+ ascii_map[140] = 105; ascii_map[141] = 105; ascii_map[142] = 97; ascii_map[143] = 97;
+ ascii_map[144] = 101; ascii_map[145] = 97; ascii_map[146] = 102; ascii_map[147] = 111;
+ ascii_map[148] = 111; ascii_map[149] = 111; ascii_map[150] = 117; ascii_map[151] = 117;
+ ascii_map[152] = 121; ascii_map[153] = 79; ascii_map[154] = 85; ascii_map[155] = 99;
+ ascii_map[156] = 76; ascii_map[157] = 89; ascii_map[158] = 80; ascii_map[159] = 102;
+ ascii_map[160] = 97; ascii_map[161] = 105; ascii_map[162] = 111; ascii_map[163] = 117;
+ ascii_map[164] = 110; ascii_map[165] = 78; ascii_map[166] = 45; ascii_map[167] = 45;
+ ascii_map[168] = 63; ascii_map[169] = ACS_ULCORNER; ascii_map[170] = ACS_URCORNER; ascii_map[171] = 47;
+ ascii_map[172] = 47; ascii_map[173] = 33; ascii_map[174] = ACS_LARROW; ascii_map[175] = ACS_RARROW;
+ ascii_map[176] = ACS_BOARD; ascii_map[177] = ACS_CKBOARD; ascii_map[178] = ACS_CKBOARD; ascii_map[179] = ACS_VLINE;
+ ascii_map[180] = ACS_RTEE; ascii_map[181] = ACS_RTEE; ascii_map[182] = ACS_RTEE; ascii_map[183] = ACS_URCORNER;
+ ascii_map[184] = ACS_URCORNER; ascii_map[185] = ACS_RTEE; ascii_map[186] = ACS_VLINE; ascii_map[187] = ACS_URCORNER;
+ ascii_map[188] = ACS_LRCORNER; ascii_map[189] = ACS_LRCORNER; ascii_map[190] = ACS_LRCORNER; ascii_map[191] = ACS_URCORNER;
+ ascii_map[192] = ACS_LLCORNER; ascii_map[193] = ACS_BTEE; ascii_map[194] = ACS_TTEE; ascii_map[195] = ACS_LTEE;
+ ascii_map[196] = ACS_HLINE; ascii_map[197] = ACS_PLUS; ascii_map[198] = ACS_LTEE; ascii_map[199] = ACS_LTEE;
+ ascii_map[200] = ACS_LLCORNER; ascii_map[201] = ACS_ULCORNER; ascii_map[202] = ACS_BTEE; ascii_map[203] = ACS_TTEE;
+ ascii_map[204] = ACS_LTEE; ascii_map[205] = ACS_HLINE; ascii_map[206] = ACS_PLUS; ascii_map[207] = ACS_BTEE;
+ ascii_map[208] = ACS_BTEE; ascii_map[209] = ACS_TTEE; ascii_map[210] = ACS_TTEE; ascii_map[211] = ACS_LLCORNER;
+ ascii_map[212] = ACS_LLCORNER; ascii_map[213] = ACS_ULCORNER; ascii_map[214] = ACS_ULCORNER; ascii_map[215] = ACS_PLUS;
+ ascii_map[216] = ACS_PLUS; ascii_map[217] = ACS_LRCORNER; ascii_map[218] = ACS_ULCORNER; ascii_map[219] = ACS_BLOCK;
+ ascii_map[220] = ACS_BLOCK; ascii_map[221] = ACS_BLOCK; ascii_map[222] = ACS_BLOCK; ascii_map[223] = ACS_BLOCK;
+ ascii_map[224] = 97; ascii_map[225] = 98; ascii_map[226] = 105; ascii_map[227] = 112;
+ ascii_map[228] = 101; ascii_map[229] = 111; ascii_map[230] = 117; ascii_map[231] = 121;
+ ascii_map[232] = 111; ascii_map[233] = 111; ascii_map[234] = 111; ascii_map[235] = 111;
+ ascii_map[236] = 111; ascii_map[237] = 111; ascii_map[238] = 69; ascii_map[239] = 110;
+ ascii_map[240] = 61; ascii_map[241] = 43; ascii_map[242] = 62; ascii_map[243] = 60;
+ ascii_map[244] = 40; ascii_map[245] = 41; ascii_map[246] = 45; ascii_map[247] = 61;
+ ascii_map[248] = ACS_DEGREE; ascii_map[249] = 46; ascii_map[250] = 46; ascii_map[251] = 86;
+ ascii_map[252] = 110; ascii_map[253] = 50; ascii_map[254] = ACS_BULLET; ascii_map[255] = 32;
+}
+
diff --git a/core/src/lcurses/makefile b/core/src/lcurses/makefile
new file mode 100644
index 000000000..a7be7933c
--- /dev/null
+++ b/core/src/lcurses/makefile
@@ -0,0 +1,21 @@
+# prefix
+include $(PRO_DIR)/prefix.mak
+
+# module name
+NAMES = lcurses
+
+# module type
+lcurses_TYPE = LIB
+
+# config
+lcurses_CONFIG = n
+
+# core files
+lcurses_C_FILES += lcurses
+
+# includes
+lcurses_INC_DIRS += ../luajit/src
+
+# suffix
+include $(PRO_DIR)/suffix.mak
+
diff --git a/core/src/lcurses/xmake.lua b/core/src/lcurses/xmake.lua
new file mode 100644
index 000000000..a63f2aa7e
--- /dev/null
+++ b/core/src/lcurses/xmake.lua
@@ -0,0 +1,19 @@
+-- add target
+target("lcurses")
+
+ -- make as a static library
+ set_kind("static")
+
+ -- add deps
+ add_deps("luajit")
+
+ -- set the object files directory
+ set_objectdir("$(buildir)/.objs")
+
+ -- add includes directory
+ add_includedirs("$(buildir)/luajit")
+
+ -- add the common source files
+ add_files("*.c")
+
+
diff --git a/core/src/makefile b/core/src/makefile
index 7a04edb24..5793c13b7 100644
--- a/core/src/makefile
+++ b/core/src/makefile
@@ -3,7 +3,7 @@ include $(PRO_DIR)/prefix.mak
# projects
SUB_PROS += demo
-DEP_PROS += sv luajit tbox xmake
+DEP_PROS += lcurses sv luajit tbox xmake
# suffix
include $(PRO_DIR)/suffix.mak