/*
* Curses binding for Lua 5.1, 5.2 & 5.3.
*
* (c) Gary V. Vaughan <gary@vaughan.pe> 2013-2017
* (c) Reuben Thomas <rrt@sc3d.org> 2009-2012
* (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.
*/
/***
Curses Window objects.
The methods documented on this page are available on any Curses Window
object, such as created by:
stdscr = curses.initscr ()
window = curses.newwin (25, 80, 0, 0)
@classmod curses.window
*/
#include <ctype.h>
#include "../teliva.h"
#include "_helpers.c"
#include "chstr.c"
static const char *WINDOWMETA = "curses:window";
static void
lc_newwin(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 **
lc_getwin(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 *
checkwin(lua_State *L, int offset)
{
WINDOW **w = lc_getwin(L, offset);
if (*w == NULL)
luaL_argerror(L, offset, "attempt to use closed curses window");
return *w;
}
/***
Unique string representation of a @{curses.window}.
@function __tostring
@treturn string unique string representation of the window object.
*/
static int
W__tostring(lua_State *L)
{
WINDOW **w = lc_getwin(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;
}
/***
Free all the resources associated with a window.
@function close
@see delwin(3x)
*/
static int
Wclose(lua_State *L)
{
WINDOW **w = lc_getwin(L, 1);
if (*w != NULL && *w != stdscr)
{
delwin(*w);
*w = NULL;
}
return 0;
}
/***
Move the position of a window.
@function move_window
@int y offset frow top of screen
@int x offset from left of screen
@treturn bool `true`, if successful
@see mvwin(3x)
*/
static int
Wmove_window(lua_State *L)
{
WINDOW *w = checkwin(L, 1);
int y = checkint(L, 2);
int x = checkint(L, 3);
return pushokresult(mvwin(w, y, x));
}
/***
Create a new subwindow.
@function sub
@treturn window a new absolutely positioned subwindow
@int nlines number of window lines
@int ncols number of window columns
@int begin_y top line of window
@int begin_x leftmost column of window
@see subwin(3x)
@see derive
*/
static int
Wsub(lua_State *L)
{
WINDOW *orig = checkwin(L, 1);
int nlines = checkint(L, 2);
int ncols = checkint(L, 3);
int begin_y = checkint(L, 4);
int begin_x = checkint(L, 5);
lc_newwin(L, subwin(orig, nlines, ncols, begin_y, begin_x));
return 1;
}
/***
Create a new derived window.
@function derive
@int nlines number of window lines
@int ncols number of window columns
@int begin_y top line of window
@int begin_x leftmost column of window
@treturn window a new relatively positioned subwindow
@see derwin(3x)
@see sub
*/
static int
Wderive(lua_State *L)
{
WINDOW *orig = checkwin(L, 1);
int nlines = checkint(L, 2);
int ncols = checkint(L, 3);
int begin_y = checkint(L, 4);
int begin_x = checkint(L, 5);
lc_newwin(L, derwin(orig, nlines, ncols, begin_y, begin_x));
return 1;
}
/***
Move the position of a derived window.
@function move_derived
@int par_y lines from top of parent window
@int par_x columns from left of parent window
@treturn bool `true`, if successful
@see mvderwin(3x)
*/
static int
Wmove_derived(lua_State *L)
{
WINDOW *w = checkwin(L, 1);
int par_y = checkint(L, 2);
int par_x = checkint(L, 3);
return pushokresult(mvderwin(w, par_y, par_x));
}
/***
Change the size of a window.
@function resize
@int height new number of lines
@int width new number of columns
@treturn bool `true`, if successful
@fixme ncurses only?
*/
static int
Wresize(lua_State *L)
{
WINDOW *w = checkwin(L, 1);
int height = checkint(L, 2);
int width = checkint(L, 3);
int c = wresize(w, height, width);
if (c == ERR) return 0;
return pushokresult(true);
}
/***
Make a duplicate of a window.
@function clone
@treturn window a new duplicate of this window
@see dupwin(3x)
*/
static int
Wclone(lua_State *L)
{
WINDOW *w = checkwin(L, 1);
lc_newwin(L, dupwin(w));
return 1;
}
/***
Mark ancestors of a window for refresh.
@function syncup
@see wsyncup(3x)
*/
static int
Wsyncup(lua_State *L)
{
wsyncup(checkwin(L, 1));
return 0;
}
/***
Automatically mark ancestors of a changed window for refresh.
@function syncok
@bool bf
@treturn bool `true`, if successful
@fixme ncurses only
*/
static int
Wsyncok(lua_State *L)
{
WINDOW *w = checkwin(L, 1);
int bf = lua_toboolean(L, 2);
return pushokresult(syncok(w, bf));
}
/***
Mark cursor position of ancestors of a window for refresh.
@function cursyncup
@see wcursyncup(3x)
*/
static int
Wcursyncup(lua_State *L)
{
wcursyncup(checkwin(L, 1));
return 0;
}
/***
Mark child windows for refresh.
@function syncdown
@see syncdown(3x)
@see refresh
*/
static int
Wsyncdown(lua_State *L)
{
wsyncdown(checkwin(L, 1));
return 0;
}
/***
Refresh the window terminal display from the virtual screen.
@function refresh
@treturn bool `true`, if successful
@see wrefresh(3x)
@see curses.doupdate
@see noutrefresh
*/
static int
Wrefresh(lua_State *L)
{
int result = wrefresh(checkwin(L, 1));
render_trusted_teliva_data(L);
return pushokresult(result);
}
/***
Copy the window backing screen to the virtual screen.
@function noutrefresh
@treturn bool `true`, if successful
@see wnoutrefresh(3x)
@see curses.doupdate
@see refresh
*/
static int
Wnoutrefresh(lua_State *L)
{
return pushokresult(wnoutrefresh(checkwin(L, 1)));
}
/***
Mark a window as having corrupted display that needs fully redrawing.
@function redrawwin
@treturn bool `true`, if successful
@see redrawwin(3x)
@see redrawln
*/
static int
Wredrawwin(lua_State *L)
{
return pushokresult(redrawwin(checkwin(L, 1)));
}
/***
Mark a range of lines in a window as corrupted and in need of redrawing.
@function redrawln
@int beg_line
@int num_lines
@treturn bool `true`, if successful
@see wredrawln(3x)
*/
static int
Wredrawln(lua_State *L)
{
WINDOW *w = checkwin(L, 1);
int beg_line = checkint(L, 2);
int num_lines = checkint(L, 3);
return pushokresult(wredrawln(w, beg_line, num_lines));
}
/***
Change the cursor position.
@function move
@int y
@int x
@treturn bool `true`, if successful
@see wmove(3x)
*/
static int
Wmove(lua_State *L)
{
WINDOW *w = checkwin(L, 1);
int y = checkint(L, 2);
int x = checkint(L, 3);
return pushokresult(wmove(w, y, x));
}
/***
Scroll the window up *n* lines.
@function scrl
@int n
@treturn bool `true`, if successful
@see wscrl(3x)
*/
static int
Wscrl(lua_State *L)
{
WINDOW *w = checkwin(L, 1);
int n = checkint(L, 2);
return pushokresult(wscrl(w, n));
}
/***
Set the changed state of a window since the last refresh.
@function touch
@param[opt] changed
@treturn bool `true`, if successful
@see touchwin(3x)
*/
static int
Wtouch(lua_State *L)
{
WINDOW *w = checkwin(L, 1);
int changed;
if (lua_isnoneornil(L, 2))
changed = TRUE;
else
changed = lua_toboolean(L, 2);
if (changed)
return pushokresult(touchwin(w));
return pushokresult(untouchwin(w));
}
/***
Mark a range of lines as changed since the last refresh.
@function touchline
@int y
@int n
@param[opt] changed
@treturn bool `true`, if successful
@see wtouchln(3x)
*/
static int
Wtouchline(lua_State *L)
{
WINDOW *w = checkwin(L, 1);
int y = checkint(L, 2);
int n = checkint(L, 3);
int changed;
if (lua_isnoneornil(L, 4))
changed = TRUE;
else
changed = lua_toboolean(L, 4);
return pushokresult(wtouchln(w, y, n, changed));
}
/***
Has a particular window line changed since the last refresh?
@function is_linetouched
@int line
@treturn bool `true`, if successful
@see is_linetouched(3x)
*/
static int
Wis_linetouched(lua_State *L)
{
WINDOW *w = checkwin(L, 1);
int line = checkint(L, 2);
return pushboolresult(is_linetouched(w, line));
}
/***
Has a window changed since the last refresh?
@function is_wintouched
@treturn bool `true`, if successful
@see is_wintouched(3x)
*/
static int
Wis_wintouched(lua_State *L)
{
WINDOW *w = checkwin(L, 1);
return pushboolresult(is_wintouched(w));
}
/***
Fetch the cursor position.
@function getyx
@treturn int y coordinate of top line
@treturn int x coordinate of left column
@see getyx(3x)
*/
static int
Wgetyx(lua_State *L)
{
WINDOW *w = checkwin(L, 1);
int y, x;
getyx(w, y, x);
lua_pushinteger(L, y);
lua_pushinteger(L, x);
return 2;
}
/***
Fetch the parent-relative coordinates of a subwindow.
@function getparyx
@treturn int y coordinate of top line relative to parent window
@treturn int x coordinate of left column relative to parent window
@see getparyx(3x)
*/
static int
Wgetparyx(lua_State *L)
{
WINDOW *w = checkwin(L, 1);
int y, x;
getparyx(w, y, x);
lua_pushinteger(L, y);
lua_pushinteger(L, x);
return 2;
}
/***
Fetch the absolute top-left coordinates of a window.
@function getbegyx
@treturn int y coordinate of top line
@treturn int x coordinate of left column
@see getbegyx(3x)
*/
static int
Wgetbegyx(lua_State *L)
{
WINDOW *w = checkwin(L, 1);
int y, x;
getbegyx(w, y, x);
lua_pushinteger(L, y);
lua_pushinteger(L, x);
return 2;
}
/***
Fetch the absolute bottom-right coordinates of a window.
@function getmaxyx
@treturn int y coordinate of bottom line
@treturn int x coordinate of right column
@see getmaxyx(3x)
*/
static int
Wgetmaxyx(lua_State *L)
{
WINDOW *w = checkwin(L, 1);
int y, x;
getmaxyx(w, y, x);
--y; // set aside space for the menu bar
lua_pushinteger(L, y);
lua_pushinteger(L, x);
return 2;
}
/***
Draw a border around a window.
@function border
@int[opt] ls
@int[opt] rs
@int[opt] ts
@int[opt] bs
@int[opt] tl
@int[opt] tr
@int[opt] bl
@int[opt] br
@treturn bool `true`, if successful
@see wborder(3x)
@usage
win:border (curses.ACS_VLINE, curses.ACS_VLINE,
curses.ACS_HLINE, curses.ACS_HLINE,
curses.ACS_ULCORNER, curses.ACS_URCORNER,
curses.ACS_LLCORNER, curses.ACS_LRCORNER)
*/
static int
Wborder(lua_State *L)
{
WINDOW *w = checkwin(L, 1);
chtype ls = optch(L, 2, 0);
chtype rs = optch(L, 3, 0);
chtype ts = optch(L, 4, 0);
chtype bs = optch(L, 5, 0);
chtype tl = optch(L, 6, 0);
chtype tr = optch(L, 7, 0);
chtype bl = optch(L, 8, 0);
chtype br = optch(L, 9, 0);
return pushokresult(wborder(w, ls, rs, ts, bs, tl, tr, bl, br));
}
/***
Draw a box around a window.
@function box
@int verch
@int horch
@treturn bool `true`, if successful
@see box(3x)
@see border
@usage
win:box (curses.ACS_VLINE, curses.ACS_HLINE)
*/
static int
Wbox(lua_State *L)
{
WINDOW *w = checkwin(L, 1);
chtype verch = checkch(L, 2);
chtype horch = checkch(L, 3);
return pushokresult(box(w, verch, horch));
}
/***
Draw a row of characters from the current cursor position.
@function hline
@int ch
@int n
@treturn bool `true`, if successful
@see whline(3x)
@see mvhline
@see vline
@usage
_, width = win:getmaxyx ()
win:hline (curses.ACS_HLINE, width - curs_x)
*/
static int
Whline(lua_State *L)
{
WINDOW *w = checkwin(L, 1);
chtype ch = checkch(L, 2);
int n = checkint(L, 3);
return pushokresult(whline(w, ch, n));
}
/***
Draw a column of characters from the current cursor position.
@function vline
@int ch
@int n
@treturn bool `true`, if successful
@see wvline(3x)
@see hline
@see mvvline
*/
static int
Wvline(lua_State *L)
{
WINDOW *w = checkwin(L, 1);
chtype ch = checkch(L, 2);
int n = checkint(L, 3);
return pushokresult(wvline(w, ch, n));
}
/***
Move the cursor, then draw a row of characters from the new cursor position.
@function mvhline
@int y
@int x
@int ch
@int n
@treturn bool `true`, if successful
@see mvwhline(3x)
*/
static int
Wmvhline(lua_State *L)
{
WINDOW *w = checkwin(L, 1);
int y = checkint(L, 2);
int x = checkint(L, 3);
chtype ch = checkch(L, 4);
int n = checkint(L, 5);
return pushokresult(mvwhline(w, y, x, ch, n));
}
/***
Move the cursor, then draw a column of characters from the new cursor position.
@function mvvline
@int y
@int x
@int ch
@int n
@treturn bool `true`, if successful
@see mvwvline(3x)
*/
static int
Wmvvline(lua_State *L)
{
WINDOW *w = checkwin(L, 1);
int y = checkint(L, 2);
int x = checkint(L, 3);
chtype ch = checkch(L, 4);
int n = checkint(L, 5);
return pushokresult(mvwvline(w, y, x, ch, n));
}
/***
Write blanks to every character position in the window.
@function erase
@treturn bool `true`, if successful
@see werase(3x)
*/
static int
Werase(lua_State *L)
{
return pushokresult(werase(checkwin(L, 1)));
}
/***
Call @{erase} and then @{clearok}.
@function clear
@treturn bool `true`, if successful
@see wclear(3x)
*/
static int
Wclear(lua_State *L)
{
return pushokresult(wclear(checkwin(L, 1)));
}
/***
Write blanks to every character position after the cursor.
@function clrtobot
@treturn bool `true`, if successful
@see wclrtobot(3x)
*/
static int
Wclrtobot(lua_State *L)
{
return pushokresult(wclrtobot(checkwin(L, 1)));
}
/***
Write blanks from the cursor to the end of the current line.
@function clrtoeol
@treturn bool `true`, if successful
@see wclrtoeol(3x)
*/
static int
Wclrtoeol(lua_State *L)
{
return pushokresult(wclrtoeol(checkwin(L, 1)));
}
/***
Advance the cursor after writing a character at the old position.
@function addch
@int ch
@treturn bool `true`, if successful
@see waddch(3x)
*/
static int
Waddch(lua_State *L)
{
WINDOW *w = checkwin(L, 1);
chtype ch = checkch(L, 2);
return pushokresult(waddch(w, ch));
}
/***
Call @{move}, then @{addch}.
@function mvaddch
@int y
@int x
@int ch
@treturn bool `true`, if successful
@see mvwaddch(3x)
*/
static int
Wmvaddch(lua_State *L)
{
WINDOW *w = checkwin(L, 1);
int y = checkint(L, 2);
int x = checkint(L, 3);
chtype ch = checkch(L, 4);
return pushokresult(mvwaddch(w, y, x, ch));
}
/***
Call @{addch} then @{refresh}.
@function echoch
@int ch
@treturn bool `true`, if successful
@see wechochar(3x)
*/
static int
Wechoch(lua_State *L)
{
WINDOW *w = checkwin(L, 1);
chtype ch = checkch(L, 2);
return pushokresult(wechochar(w, ch));
}
/***
Copy a @{curses.chstr} starting at the current cursor position.
@function addchstr
@int chstr cs
@int[opt] n
@treturn bool `true`, if successful
@see waddchnstr(3x)
*/
static int
Waddchstr(lua_State *L)
{
WINDOW *w = checkwin(L, 1);
int n = optint(L, 3, -1);
chstr *cs = checkchstr(L, 2);
if (n < 0 || n > (int) cs->len)
n = cs->len;
return pushokresult(waddchnstr(w, cs->str, n));
}
/***
Call @{move} then @{addchstr}.
@function mvaddchstr
@int y
@int x
@int[opt] n
@treturn bool `true`, if successful
@see mvwaddchnstr(3x)
*/
static int
Wmvaddchstr(lua_State *L)
{
WINDOW *w = checkwin(L, 1);
int y = checkint(L, 2);
int x = checkint(L, 3);
int n = optint(L, 5, -1);
chstr *cs = checkchstr(L, 4);
if (n < 0 || n > (int) cs->len)
n = cs->len;
return pushokresult(mvwaddchnstr(w, y, x, cs->str, n));
}
/***
Copy a Lua string starting at the current cursor position.
@function addstr
@string str
@int[opt] n
@treturn bool `true`, if successful
@see waddnstr(3x)
*/
static int
Waddstr(lua_State *L)
{
WINDOW *w = checkwin(L, 1);
const char *str = luaL_checkstring(L, 2);
int n = optint(L, 3, -1);
return pushokresult(waddnstr(w, str, n));
}
/***
Call @{move} then @{addstr}.
@function mvaddstr
@int y
@int x
@string str
@int[opt] n
@treturn bool `true`, if successful
@see mvwaddnstr(3x)
*/
static int
Wmvaddstr(lua_State *L)
{
WINDOW *w = checkwin(L, 1);
int y = checkint(L, 2);
int x = checkint(L, 3);
const char *str = luaL_checkstring(L, 4);
int n = optint(L, 5, -1);
return pushokresult(mvwaddnstr(w, y, x, str, n));
}
/***
Set the background attributes for subsequently written characters.
@function wbkgdset
@int ch
@see wbkgdset(3x)
*/
static int
Wwbkgdset(lua_State *L)
{
WINDOW *w = checkwin(L, 1);
chtype ch = checkch(L, 2);
wbkgdset(w, ch);
return 0;
}
/***
Call @{wbkgdset} and then set the background of every position accordingly.
@function wbkgd
@int ch
@treturn bool `true`, if successful
@see wbkgd(3x)
*/
static int
Wwbkgd(lua_State *L)
{
WINDOW *w = checkwin(L, 1);
chtype ch = checkch(L, 2);
return pushokresult(wbkgd(w, ch));
}
/***
Fetch the current background attribute for the window.
@function getbkgd
@treturn int current window background attribute
@see getbkgd(3x)
@see wbkgd
*/
static int
Wgetbkgd(lua_State *L)
{
return pushintresult(getbkgd(checkwin(L, 1)));
}
/***
Set the flush on interrupt behaviour for the window.
@function intrflush
@bool bf
@treturn bool `true`, if successful
@see intrflush(3x)
*/
static int
Wintrflush(lua_State *L)
{
WINDOW *w = checkwin(L, 1);
int bf = lua_toboolean(L, 2);
return pushokresult(intrflush(w, bf));
}
/***
Set the single value keypad keys behaviour for the window.
@function keypad
@bool[opt] on
@treturn bool `true`, if successful
@see keypad(3x)
*/
static int
Wkeypad(lua_State *L)
{
WINDOW *w = checkwin(L, 1);
int bf = lua_isnoneornil(L, 2) ? 1 : lua_toboolean(L, 2);
return pushokresult(keypad(w, bf));
}
/***
Force 8-bit (or 7-bit) input characters for the window.
@function meta
@bool on `true` to force 8-bit input characters
@treturn bool `true`, if successful
@see meta(3x)
*/
static int
Wmeta(lua_State *L)
{
WINDOW *w = checkwin(L, 1);
int bf = lua_toboolean(L, 2);
return pushokresult(meta(w, bf));
}
/***
Force @{getch} to be non-blocking.
@function nodelay
@bool on
@treturn bool `true`, if successful
@see nodelay(3x)
*/
static int
Wnodelay(lua_State *L)
{
WINDOW *w = checkwin(L, 1);
int bf = lua_toboolean(L, 2);
return pushokresult(nodelay(w, bf));
}
/***
For differentiating user input from terminal control sequences.
@function timeout
@int delay milliseconds, `0` for blocking, `-1` for non-blocking
@see wtimeout(3x)
*/
static int
Wtimeout(lua_State *L)
{
WINDOW *w = checkwin(L, 1);
int delay = checkint(L, 2);
wtimeout(w, delay);
return 0;
}
/***
Return input immediately from this window.
@function notimeout
@bool bf
@treturn bool `true`, if successful
@fixme ncurses only?
*/
static int
Wnotimeout(lua_State *L)
{
WINDOW *w = checkwin(L, 1);
int bf = lua_toboolean(L, 2);
return pushokresult(notimeout(w, bf));
}
/***
The next call to @{refresh} will clear and completely redraw the window.
@function clearok
@bool bf
@treturn bool `true`, if successful
@see clearok(3x)
*/
static int
Wclearok(lua_State *L)
{
WINDOW *w = checkwin(L, 1);
int bf = lua_toboolean(L, 2);
return pushokresult(clearok(w, bf));
}
/***
Use hardware character insert and delete on supporting terminals.
@function idcok
@bool bf
@treturn bool `true`, if successful
@see idcok(3x)
*/
static int
Widcok(lua_State *L)
{
WINDOW *w = checkwin(L, 1);
int bf = lua_toboolean(L, 2);
idcok(w, bf);
return 0;
}
/***
Use hardware line insert and delete on supporting terminals.
@function idlok
@bool bf
@treturn bool `true`, if successful
@see idlok(3x)
*/
static int
Widlok(lua_State *L)
{
WINDOW *w = checkwin(L, 1);
int bf = lua_toboolean(L, 2);
return pushokresult(idlok(w, bf));
}
/***
No need to force synchronisation of hardware cursor.
@function leaveok
@bool bf
@treturn bool `true`, if successful
@see leaveok(3x)
*/
static int
Wleaveok(lua_State *L)
{
WINDOW *w = checkwin(L, 1);
int bf = lua_toboolean(L, 2);
return pushokresult(leaveok(w, bf));
}
/***
Scroll up one line when the cursor writes to the last screen position.
@function scrollok
@bool bf
@treturn bool `true`, if successful
@see scrollok(3x)
*/
static int
Wscrollok(lua_State *L)
{
WINDOW *w = checkwin(L, 1);
int bf = lua_toboolean(L, 2);
return pushokresult(scrollok(w, bf));
}
/***
Automatically call @{refresh} whenever the window content is changed.
@function immedok
@bool bf
@treturn bool `true`, if successful
@see immedok(3x)
*/
static int
Wimmedok(lua_State *L)
{
WINDOW *w = checkwin(L, 1);
int bf = lua_toboolean(L, 2);
immedok(w, bf);
return 0;
}
/***
Set a software scrolling region for the window.
@function wsetscrreg
@int top top line of the scrolling region (line 0 is the first line)
@int bot bottom line of the scrolling region
@treturn bool `true`, if successful
@see wsetscrreg(3x)
*/
static int
Wwsetscrreg(lua_State *L)
{
WINDOW *w = checkwin(L, 1);
int top = checkint(L, 2);
int bot = checkint(L, 3);
return pushokresult(wsetscrreg(w, top, bot));
}
/***
Overlay this window on top of another non-destructively.
@function overlay
@tparam window dst destination window
@treturn bool `true`, if successful
@see overlay(3x)
@see overwrite
*/
static int
Woverlay(lua_State *L)
{
WINDOW *srcwin = checkwin(L, 1);
WINDOW *dstwin = checkwin(L, 2);
return pushokresult(overlay(srcwin, dstwin));
}
/***
Destructively overwrite another window with this one.
@function overwrite
@tparam window dst destination window
@treturn bool `true`, if successful
@see overwrite(3x)
*/
static int
Woverwrite(lua_State *L)
{
WINDOW *srcwin = checkwin(L, 1);
WINDOW *dstwin = checkwin(L, 2);
return pushokresult(overwrite(srcwin, dstwin));
}
/***
Overlay a rectangle of this window over another.
@function copywin
@tparam window dst destination window
@int st top row from this window
@int sl left column from this window
@int dt top row of rectangle
@int dl left column of rectangle
@int db bottom row of rectangle
@int dr right column of rectangle
@bool overlay if `true`, copy destructively like @{overlay}
@treturn bool `true`, if successful
@see copywin(3x)
*/
static int
Wcopywin(lua_State *L)
{
WINDOW *srcwin = checkwin(L, 1);
WINDOW *dstwin = checkwin(L, 2);
int sminrow = checkint(L, 3);
int smincol = checkint(L, 4);
int dminrow = checkint(L, 5);
int dmincol = checkint(L, 6);
int dmaxrow = checkint(L, 7);
int dmaxcol = checkint(L, 8);
int woverlay = lua_toboolean(L, 9);
return pushokresult(copywin(srcwin, dstwin, sminrow,
smincol, dminrow, dmincol, dmaxrow, dmaxcol, woverlay));
}
/***
Delete the character under the cursor.
@function delch
@treturn bool `true`, if successful
@see wdelch(3x)
*/
static int
Wdelch(lua_State *L)
{
return pushokresult(wdelch(checkwin(L, 1)));
}
/***
Call @{move} then @{delch}.
@function mvdelch
@int y
@int x
@treturn bool `true`, if successful
@see mvwdelch(3x)
*/
static int
Wmvdelch(lua_State *L)
{
WINDOW *w = checkwin(L, 1);
int y = checkint(L, 2);
int x = checkint(L, 3);
return pushokresult(mvwdelch(w, y, x));
}
/***
Move the lines below the cursor up, to delete the current line.
@function deleteln
@treturn bool `true`, if successful
@see wdeleteln(3x)
*/
static int
Wdeleteln(lua_State *L)
{
return pushokresult(wdeleteln(checkwin(L, 1)));
}
/***
Move the current line and those below down one line, leaving a new blank line.
@function insertln
@treturn bool `true`, if successful
@see wdeleteln(3x)
*/
static int
Winsertln(lua_State *L)
{
return pushokresult(winsertln(checkwin(L, 1)));
}
/***
Call @{deleteln} *n* times.
@function winsdelln
@int n
@treturn bool `true`, if successful
@see winsdelln(3x)
*/
static int
Wwinsdelln(lua_State *L)
{
WINDOW *w = checkwin(L, 1);
int n = checkint(L, 2);
return pushokresult(winsdelln(w, n));
}
/***
Read a character from the window input.
@function getch
@treturn int character read from input buffer
@see wgetch(3x)
@see curses.cbreak
@see curses.echo
@see keypad
*/
static int
Wgetch(lua_State *L)
{
WINDOW *w = checkwin(L, 1);
int y, x;
getyx(w, y, x);
render_trusted_teliva_data(L); /* Apps can draw what they want on screen,
* but Teliva's UI is always visible when
* asking the user to make a decision. */
if (x > COLS-2) x = COLS-2; if (y > LINES-1) y = LINES-1; /* http://gnats.netbsd.org/56664 */
mvaddstr(y, x, "");
int c = wgetch(w);
/* audit log */
static char buffer[1024] = {0};
memset(buffer, '\0', 1024);
if (isspace(c))
snprintf(buffer, 1020, "getch() => %s", character_name(c));
else
snprintf(buffer, 1020, "getch() => %c", c);
append_to_audit_log(L, buffer);
if (c == ERR)
return 0;
/* standard menu hotkeys */
if (c == CTRL_U && editor_view_in_progress(L))
developer_mode(L);
else if (c == CTRL_X || c == CTRL_U || c == CTRL_P) {
/* always confirm; we're going to throw away data past this point */
/* draw a special menu just for this situation */
attron(A_BOLD|A_REVERSE);
color_set(COLOR_PAIR_MENU, NULL);
for (int x = 0; x < COLS; ++x)
mvaddch(LINES-1, x, ' ');
menu_column = 2;
if (c == CTRL_X)
draw_menu_item("^x", "exit");
else if (c == CTRL_U)
draw_menu_item("^u", "edit app code");
else if (c == CTRL_P)
draw_menu_item("^p", "modify app permissions");
draw_menu_item("anything else", "cancel");
color_set(COLOR_PAIR_ERROR, NULL);
mvaddstr(LINES-1, menu_column+1, " Please confirm. App will restart, losing unsaved data. ");
color_set(COLOR_PAIR_NORMAL, NULL);
attroff(A_BOLD|A_REVERSE);
if (wgetch(w) != c)
return pushintresult(0);
if (c == CTRL_X) {
unlink("teliva_editor_state");
exit(0);
}
if (c == CTRL_U)
developer_mode(L);
if (c == CTRL_P)
permissions_mode(L);
}
return pushintresult(c);
}
/***
Put back a character obtained from @{getch}
@function ungetch
@int ch
@treturn OK or ERR
@see mvwgetch(3x)
@see getch
*/
static int
Wungetch(lua_State *L)
{
int ch = checkint(L, 2);
int result = ungetch(ch);
if (result == ERR)
return 0;
return pushintresult(result);
}
/***
Call @{move} then @{getch}
@function mvgetch
@int y
@int x
@treturn int character read from input buffer
@see mvwgetch(3x)
@see getch
*/
static int
Wmvgetch(lua_State *L)
{
WINDOW *w = checkwin(L, 1);
int y = checkint(L, 2);
int x = checkint(L, 3);
int c;
if (wmove(w, y, x) == ERR)
return 0;
c = wgetch(w);
if (c == ERR)
return 0;
return pushintresult(c);
}
/***
Fetch the attributed character at the current cursor position.
@function winch
@treturn int attributed character read from input buffer
@see winch(3x)
*/
static int
Wwinch(lua_State *L)
{
WINDOW *w = checkwin(L, 1);
return pushintresult(winch(w));
}
/***
Call @{move} then @{winch}
@function mvwinch
@int y
@int x
@treturn int attributed character read from input buffer
@see mvwinch(3x)
*/
static int
Wmvwinch(lua_State *L)
{
WINDOW *w = checkwin(L, 1);
int y = checkint(L, 2);
int x = checkint(L, 3);
return pushintresult(mvwinch(w, y, x));
}
/***
Fetch attributed characters from cursor position up to rightmost window position.
@function winchnstr
@int n
@treturn curses.chstr characters from cursor to end of line
@see winchnstr(3x)
@see winnstr
*/
static int
Wwinchnstr(lua_State *L)
{
WINDOW *w = checkwin(L, 1);
int n = checkint(L, 2);
chstr *cs = chstr_new(L, n);
if (winchnstr(w, cs->str, n) == ERR)
return 0;
return 1;
}
/***
Call @{move} then @{winchnstr}.
@function mvwinchnstr
@int y
@int x
@int n
@treturn curses.chstr characters from cursor to end of line
@see mvwinchnstr(3x)
*/
static int
Wmvwinchnstr(lua_State *L)
{
WINDOW *w = checkwin(L, 1);
int y = checkint(L, 2);
int x = checkint(L, 3);
int n = checkint(L, 4);
chstr *cs = chstr_new(L, n);
if (mvwinchnstr(w, y, x, cs->str, n) == ERR)
return 0;
return 1;
}
/***
Fetch a string from cursor position up to rightmost window position.
@function winnstr
@int n
@treturn string string read from input buffer
@see winnstr(3x)
@see winchnstr
*/
static int
Wwinnstr(lua_State *L)
{
WINDOW *w = checkwin(L, 1);
int n = checkint(L, 2);
char buf[LUAL_BUFFERSIZE];
char *ptr = buf;
if (abs(n) >= LUAL_BUFFERSIZE)
ptr = lua_newuserdata(L, (size_t) abs(n) + 1);
n = winnstr(w, ptr, n);
if (n == ERR)
return 0;
lua_pushlstring(L, ptr, n);
return 1;
}
/***
Call @{move} then @{winnstr}.
@function mvwinnstr
@int y
@int x
@int n
@treturn string string read from input buffer
@see mvwinnstr(3x)
*/
static int
Wmvwinnstr(lua_State *L)
{
WINDOW *w = checkwin(L, 1);
int y = checkint(L, 2);
int x = checkint(L, 3);
int n = checkint(L, 4);
char buf[LUAL_BUFFERSIZE];
char *ptr = buf;
if (abs(n) >= LUAL_BUFFERSIZE)
ptr = lua_newuserdata(L, (size_t) abs(n) + 1);
n = mvwinnstr(w, y, x, ptr, n);
if (n == ERR)
return 0;
lua_pushlstring(L, ptr, n);
return 1;
}
/***
Insert an attributed character before the current cursor position.
@function winsch
@int ch
@treturn bool `true`, if successful
@see winsch(3x)
*/
static int
Wwinsch(lua_State *L)
{
WINDOW *w = checkwin(L, 1);
chtype ch = checkch(L, 2);
return pushokresult(winsch(w, ch));
}
/***
Call @{move} then @{winsch}.
@function mvwinsch
@int y
@int x
@int ch
@treturn bool `true`, if successful
@see mvwinsch(3x)
*/
static int
Wmvwinsch(lua_State *L)
{
WINDOW *w = checkwin(L, 1);
int y = checkint(L, 2);
int x = checkint(L, 3);
chtype ch = checkch(L, 4);
return pushokresult(mvwinsch(w, y, x, ch));
}
/***
Insert a string of characters before the current cursor position.
@function winsstr
@string str
@treturn bool `true`, if successful
@see winsstr(3x)
*/
static int
Wwinsstr(lua_State *L)
{
WINDOW *w = checkwin(L, 1);
const char *str = luaL_checkstring(L, 2);
return pushokresult(winsnstr(w, str, lua_strlen(L, 2)));
}
/***
Call @{move} then @{winsstr}.
@function mvwinsstr
@int y
@int x
@string str
@treturn bool `true`, if successful
@see mvwinsstr(3x)
*/
static int
Wmvwinsstr(lua_State *L)
{
WINDOW *w = checkwin(L, 1);
int y = checkint(L, 2);
int x = checkint(L, 3);
const char *str = luaL_checkstring(L, 4);
return pushokresult(mvwinsnstr(w, y, x, str, lua_strlen(L, 2)));
}
/***
Like @{winsstr}, but no more than *n* characters.
@function winsnstr
@string str
@int n
@treturn bool `true`, if successful
@see winsnstr(3x)
*/
static int
Wwinsnstr(lua_State *L)
{
WINDOW *w = checkwin(L, 1);
const char *str = luaL_checkstring(L, 2);
int n = checkint(L, 3);
return pushokresult(winsnstr(w, str, n));
}
/***
Call @{move} then @{winsnstr}.
@function mvwinsnstr
@int y
@int x
@string str
@int n
@treturn bool `true`, if successful
@see mvwinsnstr(3x)
*/
static int
Wmvwinsnstr(lua_State *L)
{
WINDOW *w = checkwin(L, 1);
int y = checkint(L, 2);
int x = checkint(L, 3);
const char *str = luaL_checkstring(L, 4);
int n = checkint(L, 5);
return pushokresult(mvwinsnstr(w, y, x, str, n));
}
/***
Return a new subpad window object.
@function subpad
@int nlines
@int ncols
@int begin_y
@int begin_x
@treturn window a new subpad window object
@see subpad(3x)
*/
static int
Wsubpad(lua_State *L)
{
WINDOW *orig = checkwin(L, 1);
int nlines = checkint(L, 2);
int ncols = checkint(L, 3);
int begin_y = checkint(L, 4);
int begin_x = checkint(L, 5);
lc_newwin(L, subpad(orig, nlines, ncols, begin_y, begin_x));
return 1;
}
/***
Equivalent to @{refresh} for use with pad windows.
@function prefresh
@int st top row from this pad window
@int sl left column from this pad window
@int dt top row of rectangle
@int dl left column of rectangle
@int db bottom row of rectangle
@int dr right column of rectangle
@treturn bool `true`, if successful
@see prefresh(3x)
*/
static int
Wprefresh(lua_State *L)
{
WINDOW *p = checkwin(L, 1);
int pminrow = checkint(L, 2);
int pmincol = checkint(L, 3);
int sminrow = checkint(L, 4);
int smincol = checkint(L, 5);
int smaxrow = checkint(L, 6);
int smaxcol = checkint(L, 7);
return pushokresult(prefresh(p, pminrow, pmincol,
sminrow, smincol, smaxrow, smaxcol));
}
/***
Equivalent to @{noutrefresh} for use with pad windows.
@function pnoutrefresh
@int st top row from this pad window
@int sl left column from this pad window
@int dt top row of rectangle
@int dl left column of rectangle
@int db bottom row of rectangle
@int dr right column of rectangle
@treturn bool `true`, if successful
@see pnoutrefresh(3x)
*/
static int
Wpnoutrefresh(lua_State *L)
{
WINDOW *p = checkwin(L, 1);
int pminrow = checkint(L, 2);
int pmincol = checkint(L, 3);
int sminrow = checkint(L, 4);
int smincol = checkint(L, 5);
int smaxrow = checkint(L, 6);
int smaxcol = checkint(L, 7);
return pushokresult(pnoutrefresh(p, pminrow, pmincol,
sminrow, smincol, smaxrow, smaxcol));
}
/***
An efficient equivalent to @{addch} followed by @{refresh}.
@function pechochar
@int ch
@treturn bool `true`, if successful
@see pechochar(3x)
*/
static int
Wpechochar(lua_State *L)
{
WINDOW *p = checkwin(L, 1);
chtype ch = checkch(L, 2);
return pushokresult(pechochar(p, ch));
}
/***
Turn off the given attributes for subsequent writes to the window.
@function attroff
@int attrs
@treturn bool `true`, if successful
@see wattroff(3x)
@see standend
*/
static int
Wattroff(lua_State *L)
{
WINDOW *w = checkwin(L, 1);
int attrs = checkint(L, 2);
return pushokresult(wattroff(w, attrs));
}
/***
Turn on the given attributes for subsequent writes to the window.
@function attron
@int attrs
@treturn bool `true`, if successful
@see wattron(3x)
*/
static int
Wattron(lua_State *L)
{
WINDOW *w = checkwin(L, 1);
int attrs = checkint(L, 2);
return pushokresult(wattron(w, attrs));
}
/***
Set the given attributes for subsequent writes to the window.
@function attrset
@int attrs
@treturn bool `true`, if successful
@see wattrset(3x)
*/
static int
Wattrset(lua_State *L)
{
WINDOW *w = checkwin(L, 1);
int attrs = checkint(L, 2);
return pushokresult(wattrset(w, attrs));
}
/***
Turn off all attributes for subsequent writes to the window.
@function standend
@treturn bool `true`, if successful
@see wstandend(3x)
*/
static int
Wstandend(lua_State *L)
{
return pushokresult(wstandend(checkwin(L, 1)));
}
/***
Set `A_STANDOUT` for subsequent writes to the window.
@function standout
@treturn bool `true`, if successful
@see wstandout(3x)
*/
static int
Wstandout(lua_State *L)
{
return pushokresult(wstandout(checkwin(L, 1)));
}
static const luaL_Reg curses_window_fns[] =
{
LCURSES_FUNC( W__tostring ),
LCURSES_FUNC( Waddch ),
LCURSES_FUNC( Waddchstr ),
LCURSES_FUNC( Waddstr ),
LCURSES_FUNC( Wattroff ),
LCURSES_FUNC( Wattron ),
LCURSES_FUNC( Wattrset ),
LCURSES_FUNC( Wborder ),
LCURSES_FUNC( Wbox ),
LCURSES_FUNC( Wclear ),
LCURSES_FUNC( Wclearok ),
LCURSES_FUNC( Wclone ),
LCURSES_FUNC( Wclose ),
LCURSES_FUNC( Wclrtobot ),
LCURSES_FUNC( Wclrtoeol ),
LCURSES_FUNC( Wcopywin ),
LCURSES_FUNC( Wcursyncup ),
LCURSES_FUNC( Wdelch ),
LCURSES_FUNC( Wdeleteln ),
LCURSES_FUNC( Wderive ),
LCURSES_FUNC( Wechoch ),
LCURSES_FUNC( Werase ),
LCURSES_FUNC( Wgetbegyx ),
LCURSES_FUNC( Wgetbkgd ),
LCURSES_FUNC( Wgetch ),
LCURSES_FUNC( Wgetmaxyx ),
LCURSES_FUNC( Wgetparyx ),
/* no 'getstr' because there's no way to hook standard Teliva hotkeys into it */
LCURSES_FUNC( Wgetyx ),
LCURSES_FUNC( Whline ),
LCURSES_FUNC( Widcok ),
LCURSES_FUNC( Widlok ),
LCURSES_FUNC( Wimmedok ),
LCURSES_FUNC( Winsertln ),
LCURSES_FUNC( Wintrflush ),
LCURSES_FUNC( Wis_linetouched ),
LCURSES_FUNC( Wis_wintouched ),
LCURSES_FUNC( Wkeypad ),
LCURSES_FUNC( Wleaveok ),
LCURSES_FUNC( Wmeta ),
LCURSES_FUNC( Wmove ),
LCURSES_FUNC( Wmove_derived ),
LCURSES_FUNC( Wmove_window ),
LCURSES_FUNC( Wmvaddch ),
LCURSES_FUNC( Wmvaddchstr ),
LCURSES_FUNC( Wmvaddstr ),
LCURSES_FUNC( Wmvdelch ),
LCURSES_FUNC( Wmvgetch ),
/* no 'mvgetstr' because there's no way to hook standard Teliva hotkeys into it */
LCURSES_FUNC( Wmvhline ),
LCURSES_FUNC( Wmvvline ),
LCURSES_FUNC( Wmvwinch ),
LCURSES_FUNC( Wmvwinchnstr ),
LCURSES_FUNC( Wmvwinnstr ),
LCURSES_FUNC( Wmvwinsch ),
LCURSES_FUNC( Wmvwinsnstr ),
LCURSES_FUNC( Wmvwinsstr ),
LCURSES_FUNC( Wnodelay ),
LCURSES_FUNC( Wnotimeout ),
LCURSES_FUNC( Wnoutrefresh ),
LCURSES_FUNC( Woverlay ),
LCURSES_FUNC( Woverwrite ),
LCURSES_FUNC( Wpechochar ),
LCURSES_FUNC( Wpnoutrefresh ),
LCURSES_FUNC( Wprefresh ),
LCURSES_FUNC( Wredrawln ),
LCURSES_FUNC( Wredrawwin ),
LCURSES_FUNC( Wrefresh ),
LCURSES_FUNC( Wresize ),
LCURSES_FUNC( Wscrl ),
LCURSES_FUNC( Wscrollok ),
LCURSES_FUNC( Wstandend ),
LCURSES_FUNC( Wstandout ),
LCURSES_FUNC( Wsub ),
LCURSES_FUNC( Wsubpad ),
LCURSES_FUNC( Wsyncdown ),
LCURSES_FUNC( Wsyncok ),
LCURSES_FUNC( Wsyncup ),
LCURSES_FUNC( Wtimeout ),
LCURSES_FUNC( Wtouch ),
LCURSES_FUNC( Wtouchline ),
LCURSES_FUNC( Wungetch ),
LCURSES_FUNC( Wvline ),
LCURSES_FUNC( Wwbkgd ),
LCURSES_FUNC( Wwbkgdset ),
LCURSES_FUNC( Wwinch ),
LCURSES_FUNC( Wwinchnstr ),
LCURSES_FUNC( Wwinnstr ),
LCURSES_FUNC( Wwinsch ),
LCURSES_FUNC( Wwinsdelln ),
LCURSES_FUNC( Wwinsnstr ),
LCURSES_FUNC( Wwinsstr ),
LCURSES_FUNC( Wwsetscrreg ),
{"__gc", Wclose }, /* rough safety net */
{NULL, NULL}
};
LUALIB_API int
luaopen_curses_window(lua_State *L)
{
int t, mt;
luaL_register(L, "curses.window", curses_window_fns);
t = lua_gettop(L);
luaL_newmetatable(L, WINDOWMETA);
mt = lua_gettop(L);
lua_pushvalue(L, mt);
lua_setfield(L, mt, "__index"); /* mt.__index = mt */
lua_pushliteral(L, "CursesWindow");
lua_setfield(L, mt, "_type"); /* mt._type = "Curses Window" */
/* for k,v in pairs(t) do mt[k]=v end */
for (lua_pushnil(L); lua_next(L, t) != 0;)
lua_setfield(L, mt, lua_tostring(L, -2));
lua_pop(L, 1); /* pop mt */
return 1;
}