/*************************************************************************
* Library: lcurses - Lua 5.1 interface to the curses library *
* *
* (c) Reuben Thomas <rrt@sc3d.org> 2009-2010 *
* (c) Tiago Dionizio <tiago.dionizio AT gmail.com> 2004-2007 *
* *
* 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. *
************************************************************************/
#include "config.h"
#include <stdlib.h>
#include <string.h>
#include <lua.h>
#include <lauxlib.h>
#ifdef HAVE_NCURSES_H
#include <ncurses.h>
#else
#include <curses.h>
#endif
#include <term.h>
/* strlcpy() implementation for non-BSD based Unices.
strlcpy() is a safer less error-prone replacement for strncpy(). */
#include "strlcpy.c"
/*
** =======================================================
** defines
** =======================================================
*/
static const char *STDSCR_REGISTRY = "curses:stdscr";
static const char *WINDOWMETA = "curses:window";
static const char *CHSTRMETA = "curses:chstr";
static const char *RIPOFF_TABLE = "curses:ripoffline";
#define B(v) ((((int) (v)) == ERR))
/* ======================================================= */
#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; \
}
/*
** =======================================================
** 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 offset)
{
WINDOW **w = (WINDOW**)luaL_checkudata(L, offset, WINDOWMETA);
if (w == NULL) luaL_argerror(L, offset, "bad curses window");
return w;
}
static WINDOW *lcw_check(lua_State *L, int offset)
{
WINDOW **w = lcw_get(L, offset);
if (*w == NULL) luaL_argerror(L, offset, "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 offset)
{
if (lua_type(L, offset) == LUA_TNUMBER)
return (chtype)luaL_checknumber(L, offset);
if (lua_type(L, offset) == LUA_TSTRING)
return *lua_tostring(L, offset);
luaL_typerror(L, offset, "chtype");
/* never executes */
return (chtype)0;
}
static chtype lc_optch(lua_State *L, int offset, chtype def)
{
if (lua_isnoneornil(L, offset))
return def;
return lc_checkch(L, offset);
}
/****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 offset)
{
chstr *cs = (chstr*)luaL_checkudata(L, offset, CHSTRMETA);
if (cs) return cs;
luaL_argerror(L, offset, "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 offset = 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 (offset < 0)
return 0;
while (rep-- > 0 && offset <= (int)cs->len)
{
if (offset + len - 1 > (int)cs->len)
len = cs->len - offset + 1;
for (i = 0; i < len; ++i)
cs->str[offset + i] = str[i] | attr;
offset += len;
}
return 0;
}
/****m* chstr/set_ch
* FUNCTION
* Set a character in the buffer.
*
* SYNOPSIS
* chstr:set_ch(offset, 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 offset = 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 (offset < 0 || offset >= (int) cs->len)
return 0;
cs->str[offset] = ch | attr;
++offset;
}
return 0;
}
/* get information from the chstr */
static int chstr_get(lua_State *L)
{
chstr* cs = lc_checkchstr(L, 1);
int offset = luaL_checkint(L, 2);
chtype ch;
if (offset < 0 || offset >= (int) cs->len)
return 0;
ch = cs->str[offset];
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;
}
/*
** =======================================================
** 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)
CC(A_ATTRIBUTES)
/* 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(void)
{
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;
/* 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);
/* install cleanup handler to help in debugging and screen trashing */
atexit(cleanup);
return 1;
}
/* FIXME: Avoid cast to void. */
static int lc_endwin(lua_State *L)
{
(void) L;
endwin();
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);
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);
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 > (int) 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 > (int) 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 woverlay = lua_toboolean(L, 9);
lua_pushboolean(L, B(copywin(srcwin, dstwin, sminrow,
smincol, dminrow, dmincol, dmaxrow, dmaxcol, woverlay)));
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 = wgetch(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 = wgetch(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)
/*
** =======================================================
** query terminfo database
** =======================================================
*/
static char ti_capname[32];
static int ti_getflag (lua_State *L)
{
int res;
strlcpy (ti_capname, luaL_checkstring (L, 1), sizeof (ti_capname));
res = tigetflag (ti_capname);
if (-1 == res)
return luaL_error (L, "`%s' is not a boolean capability", ti_capname);
else
lua_pushboolean (L, res);
return 1;
}
static int ti_getnum (lua_State *L)
{
int res;
strlcpy (ti_capname, luaL_checkstring (L, 1), sizeof (ti_capname));
res = tigetnum (ti_capname);
if (-2 == res)
return luaL_error (L, "`%s' is not a numeric capability", ti_capname);
else if (-1 == res)
lua_pushnil (L);
else
lua_pushnumber(L, res);
return 1;
}
static int ti_getstr (lua_State *L)
{
const char *res;
strlcpy (ti_capname, luaL_checkstring (L, 1), sizeof (ti_capname));
res = tigetstr (ti_capname);
if ((char *) -1 == res)
return luaL_error (L, "`%s' is not a string capability", ti_capname);
else if (NULL == res)
lua_pushnil (L);
else
lua_pushstring(L, res);
return 1;
}
/*
** =======================================================
** 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 */
{ "scrl", lcw_wscrl },
/* refresh */
{ "refresh", lcw_wrefresh },
{ "noutrefresh", lcw_wnoutrefresh },
{ "redrawwin", lcw_redrawwin },
{ "redrawln", lcw_wredrawln },
/* clear */
{ "erase", lcw_werase },
{ "clear", lcw_wclear },
{ "clrtobot", lcw_wclrtobot },
{ "clrtoeol", lcw_wclrtoeol },
/* touch */
{ "touch", lcw_touch },
{ "touchline", lcw_touchline },
{ "is_linetouched", lcw_is_linetouched },
{ "is_wintouched", 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 },
{ "copywin", lcw_copywin },
/* delch */
{ "delch", lcw_wdelch },
{ "mvdelch", lcw_mvwdelch },
/* deleteln */
{ "deleteln", lcw_wdeleteln },
{ "insertln", 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 },
static const luaL_reg curseslib[] =
{
/* chstr helper function */
{ "new_chstr", lc_new_chstr },
/* initscr */
{ "endwin", lc_endwin },
{ "isendwin", lc_isendwin },
{ "stdscr", lc_stdscr },
{ "cols", 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 },
{ "erasechar", lc_erasechar },
{ "killchar", lc_killchar },
{ "has_ic", lc_has_ic },
{ "has_il", lc_has_il },
{ "termattrs", lc_termattrs },
{ "termname", lc_termname },
{ "longname", lc_longname },
/* kernel */
{ "ripoffline", lc_ripoffline },
{ "napms", lc_napms },
{ "curs_set", lc_curs_set },
/* beep */
{ "beep", lc_beep },
{ "flash", lc_flash },
/* window */
{ "newwin", lc_newwin },
/* pad */
{ "newpad", 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 },
{ "flushinp", lc_flushinp },
/* getch */
{ "ungetch", lc_ungetch },
/* outopts */
{ "nl", lc_nl },
/* query terminfo database */
{ "tigetflag", ti_getflag },
{ "tigetnum", ti_getnum },
{ "tigetstr", ti_getstr },
/* 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)
/* terminator */
{NULL, NULL}
};
/* Prototype to keep compiler happy. */
int luaopen_curses_c (lua_State *L);
int luaopen_curses_c (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
*/
luaL_register(L, "curses", curseslib);
lua_pushstring(L, "initscr");
lua_pushvalue(L, -2);
lua_pushcclosure(L, lc_initscr, 1);
lua_settable(L, -3);
return 1;
}
/* Local Variables: */
/* c-basic-offset: 4 */
/* End: */