teliva/src/lcurses/curses.c

1480 lines
32 KiB
C

/*
* 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.
*/
/***
Full-screen Text Terminal Manipulation.
Some of the C functions beginning with "no" do not exist in Lua. You should
use `curses.nl(false)` and `curses.nl(true)` instead of `nonl()` and `nl()`,
and likewise `curses.echo(false)` and `curses.echo(true)` instead of
`noecho()` and `echo()` .
In this Lua module the `stdscr:getch()` function always returns an integer.
In C, a single character is an integer, but in Lua (and Perl) a single
character is a short string. The Perl Curses function `getch()` returns a
char if it was a char, and a number if it was a constant; to get this
behaviour in Lua you have to convert explicitly, e.g.:
if c < 256 then c = string.char(c) end
Some Lua functions take a different set of parameters than their C
counterparts; for example, you should use `y, x = stdscr.getyx()` instead of
`getstr(str)` and `getyx(y, x)`, and likewise for `getbegyx` and `getmaxyx`
and `getparyx` and `pair_content`. The Perl Curses module now uses the
C-compatible parameters, so be aware of this difference when translating code
from Perl into Lua, as well as from C into Lua.
Many curses functions have variants starting with the prefixes `w-`, `mv-`,
and/or `wmv-`. These variants differ only in the explicit addition of a
window, or by the addition of two coordinates that are used to move the
cursor first. For example, in C `addch()` has three other variants:
`waddch()`, `mvaddch()` and `mvwaddch()`. The Lua equivalents,
respectively being `stdscr:addch()`, `somewindow:addch()`,
`stdscr:mvaddch()` and `somewindow:mvaddch()`, with the window argument
passed implicitly with Lua's `:` syntax sugar.
@module curses
*/
#include "_helpers.c"
#ifdef __linux__
#include "strlcpy.c"
#endif
#include "chstr.c"
#include "window.c"
static const char *STDSCR_REGISTRY = "curses:stdscr";
static const char *RIPOFF_TABLE = "curses:ripoffline";
/***
Create a new line drawing buffer instance.
@function new_chstr
@int len number of element to allocate
@treturn chstr a new char buffer object
@see curses.chstr
*/
static int
Pnew_chstr(lua_State *L)
{
int len = checkint(L, 1);
chstr* ncs = chstr_new(L, len); /* defined in curses/chstr.c */
memset(ncs->str, ' ', len*sizeof(chtype));
return 1;
}
#define CCR(n, v) \
lua_pushstring(L, n); \
lua_pushinteger(L, v); \
lua_settable(L, -3);
#define CC(s) CCR(#s, s)
#define CF(i) CCR(LCURSES_STR(LCURSES_SPLICE(KEY_F, i)), KEY_F(i))
/*
** 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);
#ifdef A_COLOR
CC(A_COLOR);
#endif
/* 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); /* ncurses extension: 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);
CF(1); CF(2); CF(3); CF(4); CF(5); CF(6); CF(7); CF(8);
CF(9); CF(10); CF(11); CF(12); CF(13); CF(14); CF(15); CF(16);
CF(17); CF(18); CF(19); CF(20); CF(21); CF(22); CF(23); CF(24);
CF(25); CF(26); CF(27); CF(28); CF(29); CF(30); CF(31); CF(32);
CF(33); CF(34); CF(35); CF(36); CF(37); CF(38); CF(39); CF(40);
CF(41); CF(42); CF(43); CF(44); CF(45); CF(46); CF(47); CF(48);
CF(49); CF(50); CF(51); CF(52); CF(53); CF(54); CF(55); CF(56);
CF(57); CF(58); CF(59); CF(60); CF(61); CF(62); CF(63);
}
/*
** make sure screen is restored (and cleared) at exit
** (for the situations where program is aborted without a
** proper cleanup)
*/
void
cleanup_curses(void)
{
if (!isendwin())
{
wclear(stdscr);
wrefresh(stdscr);
endwin();
}
}
extern void stack_dump(lua_State *L);
static int
init_stdscr(lua_State *L)
{
/* return stdscr - main window */
lc_newwin(L, stdscr);
/* 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 */
lua_pushvalue(L, -2);
register_curses_constants(L);
/* install cleanup handler to help in debugging and screen trashing */
atexit(cleanup_curses);
return 1;
}
/***
Clean up terminal prior to exiting or escaping curses.
@function endwin
@treturn bool `true`, if successful
@see endwin(3x)
*/
static int
Pendwin(lua_State *L)
{
return pushokresult(endwin());
}
/***
Has @{endwin} been called more recently than @{curses.window:refresh}?
@function isendwin
@treturn bool whether @{endwin} has been called
@see isendwin(3x)
*/
static int
Pisendwin(lua_State *L)
{
return pushboolresult(isendwin());
}
/***
Retern the main screen window.
@function stdscr
@treturn window main screen
@see initscr
@see stdscr(3x)
*/
static int
Pstdscr(lua_State *L)
{
lua_pushstring(L, STDSCR_REGISTRY);
lua_rawget(L, LUA_REGISTRYINDEX);
return 1;
}
/***
Number of columns in the main screen window.
@function cols
@treturn int number of columns in the main screen
@see lines
@see stdscr
@see COLS(3x)
*/
static int
Pcols(lua_State *L)
{
return pushintresult(COLS);
}
/***
Number of lines in the main screen window.
@function lines
@treturn int number of lines in the main screen
@see cols
@see stdscr
@see LINES(3x)
*/
static int
Plines(lua_State *L)
{
return pushintresult(LINES);
}
/***
Initialise color output facility.
@function start_color
@treturn bool `true`, if successful
@see can_change_color(3x)
@see has_colors
*/
static int
Pstart_color(lua_State *L)
{
return pushokresult(start_color());
}
/***
Does the terminal have color capability?
@function has_colors
@treturn bool `true`, if the terminal supports colors
@see can_change_color(3x)
@see start_color
@usage
if curses.has_colors () then
curses.start_color ()
end
*/
static int
Phas_colors(lua_State *L)
{
return pushboolresult(has_colors());
}
/***
Reserve `-1` to represent terminal default colors.
@function use_default_colors
@treturn bool `true`, if successful
@see use_default_colors(3x)
@fixme ncurses only?
*/
static int
Puse_default_colors(lua_State *L)
{
return pushokresult(use_default_colors());
}
/***
Set -1 foreground and background colors.
@function use_default_colors
@treturn bool `true`, if successful
@see use_default_colors(3x)
@fixme ncurses only?
*/
static int
Passume_default_colors(lua_State *L)
{
int fg = checkint(L, 1);
int bg = checkint(L, 2);
return pushokresult(assume_default_colors(fg, bg));
}
/***
Associate a color pair id with a specific foreground and background color.
@function init_pair
@int pair color pair id to act on
@int f foreground color to assign
@int b background color to assign
@treturn bool `true`, if successful
@see init_pair(3x)
@see pair_content
*/
static int
Pinit_pair(lua_State *L)
{
short pair = checkint(L, 1);
short f = checkint(L, 2);
short b = checkint(L, 3);
return pushokresult(init_pair(pair, f, b));
}
/***
Return the foreground and background colors associated with a color pair id.
@function pair_content
@int pair color pair id to act on
@treturn int foreground color of *pair*
@treturn int background color of *pair*
@see can_change_color(3x)
@see init_pair
*/
static int
Ppair_content(lua_State *L)
{
short pair = checkint(L, 1);
short f;
short b;
int ret = pair_content(pair, &f, &b);
if (ret == ERR)
return 0;
lua_pushinteger(L, f);
lua_pushinteger(L, b);
return 2;
}
/***
How many colors are available for this terminal?
@function colors
@treturn int total number of available colors
@see can_change_color(3x)
@see color_pairs
*/
static int
Pcolors(lua_State *L)
{
return pushintresult(COLORS);
}
/***
How may distinct color pairs are supported by this terminal?
@function color_pairs
@treturn int total number of available color pairs
@see can_change_color(3x)
@see colors
*/
static int
Pcolor_pairs(lua_State *L)
{
return pushintresult(COLOR_PAIRS);
}
/***
Return the attributes for the given color pair id.
@function color_pair
@int pair color pair id to act on
@treturn int attributes for color pair *pair*
@see can_change_color(3x)
*/
static int
Pcolor_pair(lua_State *L)
{
int n = checkint(L, 1);
return pushintresult(COLOR_PAIR(n));
}
/***
Fetch the output speed of the terminal.
@function baudrate
@treturn int output speed of the terminal in bits-per-second
@see baudrate(3x)
*/
static int
Pbaudrate(lua_State *L)
{
return pushintresult(baudrate());
}
/***
Fetch the terminal's current erase character.
@function erasechar
@treturn int current erase character
@see erasechar(3x)
*/
static int
Perasechar(lua_State *L)
{
return pushintresult(erasechar());
}
/***
Fetch the character insert and delete capability of the terminal.
@function has_ic
@treturn bool `true`, if the terminal has insert and delete character
operations
@see has_ic(3x)
*/
static int
Phas_ic(lua_State *L)
{
return pushboolresult(has_ic());
}
/***
Fetch the line insert and delete capability of the terminal.
@function has_il
@treturn bool `true`, if the terminal has insert and delete line operations
@see has_il(3x)
*/
static int
Phas_il(lua_State *L)
{
return pushboolresult(has_il());
}
/***
Fetch the terminal's current kill character.
@function killchar
@treturn int current line kill character
@see killchar(3x)
*/
static int
Pkillchar(lua_State *L)
{
return pushintresult(killchar());
}
/***
Bitwise OR of all (or selected) video attributes supported by the terminal.
@function termattrs
@int[opt] a terminal attribute bits
@treturn[1] bool `true`, if the terminal supports attribute *a*
@treturn[2] int bitarray of supported terminal attributes
@see termattrs(3x)
*/
static int
Ptermattrs(lua_State *L)
{
if (lua_gettop(L) > 0)
{
int a = checkint(L, 1);
return pushboolresult(termattrs() & a);
}
return pushintresult(termattrs());
}
/***
Fetch the name of the terminal.
@function termname
@treturn string terminal name
@see termname(3x)
*/
static int
Ptermname(lua_State *L)
{
return pushstringresult(termname());
}
/***
Fetch the verbose name of the terminal.
@function longname
@treturn string verbose description of the current terminal
@see longname(3x)
*/
static int
Plongname(lua_State *L)
{
return pushstringresult(longname());
}
/* 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 */
lc_newwin(rip_L, w); /* create window object */
lua_pushinteger(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;
}
/***
Reduce the available size of the main screen.
@function ripoffline
@bool top_line
@func callback
@treturn bool `true`, if successful
@see ripoffline(3x)
*/
static int
Pripoffline(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 */
return pushokresult(ripoffline(top_line ? 1 : -1, ripoffline_cb));
}
/***
Change the visibility of the cursor.
@function curs_set
@int vis one of `0` (invisible), `1` (visible) or `2` (very visible)
@treturn[1] int previous cursor state
@return[2] nil if *vis* is not supported
@see curs_set(3x)
*/
static int
Pcurs_set(lua_State *L)
{
int vis = checkint(L, 1);
int state = curs_set(vis);
if (state == ERR)
return 0;
return pushintresult(state);
}
/***
Sleep for a few milliseconds.
@function napms
@int ms time to wait in milliseconds
@treturn bool `true`, if successful
@see napms(3x)
@see delay_output
*/
static int
Pnapms(lua_State *L)
{
int ms = checkint(L, 1);
return pushokresult(napms(ms));
}
/***
Change the terminal size.
@function resizeterm
@int nlines number of lines
@int ncols number of columns
@treturn bool `true`, if successful
@raise unimplemented
@fixme ncurses only?
*/
static int
Presizeterm(lua_State *L)
{
int nlines = checkint(L, 1);
int ncols = checkint(L, 2);
return pushokresult(resizeterm (nlines, ncols));
}
/***
Send the terminal audible bell.
@function beep
@treturn bool `true`, if successful
@see beep(3x)
@see flash
*/
static int
Pbeep(lua_State *L)
{
return pushokresult(beep());
}
/***
Send the terminal visible bell.
@function flash
@treturn bool `true`, if successful
@see flash(3x)
@see beep
*/
static int
Pflash(lua_State *L)
{
return pushokresult(flash());
}
/***
Create a new window.
@function newwin
@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 window object
@see newwin(3x)
@see curses.window
*/
static int
Pnewwin(lua_State *L)
{
int nlines = checkint(L, 1);
int ncols = checkint(L, 2);
int begin_y = checkint(L, 3);
int begin_x = checkint(L, 4);
lc_newwin(L, newwin(nlines, ncols, begin_y, begin_x));
return 1;
}
/***
Refresh the visible terminal screen.
@function doupdate
@treturn bool `true`, if successful
@see doupdate(3x)
@see curses.window:refresh
*/
static int
Pdoupdate(lua_State *L)
{
return pushokresult(doupdate());
}
/***
Initialise the soft label keys area.
This must be called before @{initscr}.
@function slk_init
@int fmt
@treturn bool `true`, if successful
@see slk_init(3x)
*/
static int
Pslk_init(lua_State *L)
{
int fmt = checkint(L, 1);
return pushokresult(slk_init(fmt));
}
/***
Set the label for a soft label key.
@function slk_set
@int labnum
@string label
@int fmt
@treturn bool `true`, if successful
@see slk_set(3x)
*/
static int
Pslk_set(lua_State *L)
{
int labnum = checkint(L, 1);
const char* label = luaL_checkstring(L, 2);
int fmt = checkint(L, 3);
return pushokresult(slk_set(labnum, label, fmt));
}
/***
Refresh the soft label key area.
@function slk_refresh
@treturn bool `true`, if successful
@see slk_refresh(3x)
@see curses.window:refresh
*/
static int
Pslk_refresh(lua_State *L)
{
return pushokresult(slk_refresh());
}
/***
Copy the soft label key area backing screen to the virtual screen.
@function slk_noutrefresh
@treturn bool `true`, if successful
@see slk_noutrefresh(3x)
@see curses.window:refresh
*/
static int
Pslk_noutrefresh(lua_State *L)
{
return pushokresult(slk_noutrefresh());
}
/***
Fetch the label for a soft label key.
@function slk_label
@int labnum
@treturn string current label for *labnum*
@see slk_label(3x)
*/
static int
Pslk_label(lua_State *L)
{
int labnum = checkint(L, 1);
return pushstringresult(slk_label(labnum));
}
/***
Clears the soft labels from the screen.
@function slk_clear
@treturn bool `true`, if successful
@see slk_clear(3x)
@see slk_restore
*/
static int
Pslk_clear(lua_State *L)
{
return pushokresult(slk_clear());
}
/***
Restores the soft labels to the screen.
@function slk_restore
@treturn bool `true`, if successful
@see slk_restore(3x)
@see slk_clear
*/
static int
Pslk_restore(lua_State *L)
{
return pushokresult(slk_restore());
}
/***
Mark the soft label key area for refresh.
@function slk_touch
@treturn bool `true`, if successful
@see slk_touch(3x)
*/
static int
Pslk_touch(lua_State *L)
{
return pushokresult(slk_touch());
}
/***
Enable an attribute for soft labels.
@function slk_attron
@int attrs
@treturn bool `true`, if successful
@see slk_attron(3x)
*/
static int
Pslk_attron(lua_State *L)
{
chtype attrs = checkch(L, 1);
return pushokresult(slk_attron(attrs));
}
/***
Disable an attribute for soft labels.
@function slk_attroff
@int attrs
@treturn bool `true`, if successful
@see slk_attroff(3x)
*/
static int
Pslk_attroff(lua_State *L)
{
chtype attrs = checkch(L, 1);
return pushokresult(slk_attroff(attrs));
}
/***
Set the attributes for soft labels.
@function slk_attrset
@int attrs
@treturn bool `true`, if successful
@see slk_attrset(3x)
*/
static int
Pslk_attrset(lua_State *L)
{
chtype attrs = checkch(L, 1);
return pushokresult(slk_attrset(attrs));
}
/***
Put the terminal into cbreak mode.
@function cbreak
@bool[opt] on
@treturn bool `true`, if successful
@see cbreak(3x)
@see nocbreak(3x)
*/
static int
Pcbreak(lua_State *L)
{
if (lua_isnoneornil(L, 1) || lua_toboolean(L, 1))
return pushokresult(cbreak());
return pushokresult(nocbreak());
}
/***
Whether characters are echoed to the terminal as they are typed.
@function echo
@bool[opt] on
@treturn bool `true`, if successful
@see echo(3x)
@see noecho(3x)
*/
static int
Pecho(lua_State *L)
{
if (lua_isnoneornil(L, 1) || lua_toboolean(L, 1))
return pushokresult(echo());
return pushokresult(noecho());
}
/***
Put the terminal into raw mode.
@function raw
@bool[opt] on
@treturn bool `true`, if successful
@see noraw(3x)
@see raw(3x)
*/
static int
Praw(lua_State *L)
{
if (lua_isnoneornil(L, 1) || lua_toboolean(L, 1))
return pushokresult(raw());
return pushokresult(noraw());
}
/***
Put the terminal into halfdelay mode.
@function halfdelay
@int tenths delay in tenths of a second
@treturn bool `true`, if successful
@see halfdelay(3x)
*/
static int
Phalfdelay(lua_State *L)
{
int tenths = checkint(L, 1);
return pushokresult(halfdelay(tenths));
}
/***
Whether to translate a return key to newline on input.
@function nl
@bool[opt] on
@treturn bool `true`, if successful
@see nl(3x)
@see nonl(3x)
*/
static int
Pnl(lua_State *L)
{
if (lua_isnoneornil(L, 1) || lua_toboolean(L, 1))
return pushokresult(nl());
return pushokresult(nonl());
}
/***
Return a printable representation of a character, ignoring attributes.
@function unctrl
@int c character to act on
@treturn string printable representation of *c*
@see unctrl(3x)
@see keyname
*/
static int
Punctrl(lua_State *L)
{
chtype c = checkch(L, 1);
return pushstringresult(unctrl(c));
}
/***
Return a printable representation of a key.
@function keyname
@int c a key
@treturn string key name of *c*
@see keyname(3x)
@see unctrl
*/
static int
Pkeyname(lua_State *L)
{
int c = checkint(L, 1);
return pushstringresult(keyname(c));
}
/***
Insert padding characters to force a short delay.
@function delay_output
@int ms delay time in milliseconds
@treturn bool `true`, if successful
@see napms
@fixme ncurses only?
*/
static int
Pdelay_output(lua_State *L)
{
int ms = checkint(L, 1);
return pushokresult(delay_output(ms));
}
/***
Throw away any typeahead in the keyboard input buffer.
@function flushinp
@treturn bool `true`, if successful
@see flushinp(3x)
@see ungetch
*/
static int
Pflushinp(lua_State *L)
{
return pushboolresult(flushinp());
}
/***
Return a character to the keyboard input buffer.
@function ungetch
@int c
@treturn bool `true`, if successful
@see ungetch(3x)
@see flushinp
*/
static int
Pungetch(lua_State *L)
{
int c = checkint(L, 1);
return pushokresult(ungetch(c));
}
/***
Create a new pad.
@function newpad
@int nlines
@int ncols
@treturn bool `true`, if successful
@see newpad(3x)
*/
static int
Pnewpad(lua_State *L)
{
int nlines = checkint(L, 1);
int ncols = checkint(L, 2);
lc_newwin(L, newpad(nlines, ncols));
return 1;
}
static char ti_capname[32];
/***
Fetch terminfo boolean capability.
@function tigetflag
@string capname
@treturn bool content of terminal boolean capability
@see tigetflag(3x)
@see terminfo(5)
*/
static int
Ptigetflag (lua_State *L)
{
int r;
strlcpy (ti_capname, luaL_checkstring (L, 1), sizeof (ti_capname));
r = tigetflag (ti_capname);
if (-1 == r)
return luaL_error (L, "`%s' is not a boolean capability", ti_capname);
return pushboolresult (r);
}
/***
Fetch terminfo numeric capability.
@function tigetnum
@string capname
@treturn int content of terminal numeric capability
@see tigetnum(3x)
@see terminfo(5)
*/
static int
Ptigetnum (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_pushinteger(L, res);
return 1;
}
/***
Fetch terminfo string capability.
@function tigetstr
@string capname
@treturn string content of terminal string capability
@see tigetstr(3x)
@see terminfo(5)
*/
static int
Ptigetstr (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;
}
static const luaL_Reg curseslib[] =
{
LCURSES_FUNC( Pbaudrate ),
LCURSES_FUNC( Pbeep ),
LCURSES_FUNC( Pcbreak ),
LCURSES_FUNC( Pcolor_pair ),
LCURSES_FUNC( Pcolor_pairs ),
LCURSES_FUNC( Pcolors ),
LCURSES_FUNC( Pcols ),
LCURSES_FUNC( Pcurs_set ),
LCURSES_FUNC( Pdelay_output ),
LCURSES_FUNC( Pdoupdate ),
LCURSES_FUNC( Pecho ),
LCURSES_FUNC( Pendwin ),
LCURSES_FUNC( Perasechar ),
LCURSES_FUNC( Pflash ),
LCURSES_FUNC( Pflushinp ),
LCURSES_FUNC( Phalfdelay ),
LCURSES_FUNC( Phas_colors ),
LCURSES_FUNC( Phas_ic ),
LCURSES_FUNC( Phas_il ),
LCURSES_FUNC( Pinit_pair ),
LCURSES_FUNC( Pisendwin ),
LCURSES_FUNC( Pkeyname ),
LCURSES_FUNC( Pkillchar ),
LCURSES_FUNC( Plines ),
LCURSES_FUNC( Plongname ),
LCURSES_FUNC( Pnapms ),
LCURSES_FUNC( Pnew_chstr ),
LCURSES_FUNC( Pnewpad ),
LCURSES_FUNC( Pnewwin ),
LCURSES_FUNC( Pnl ),
LCURSES_FUNC( Ppair_content ),
LCURSES_FUNC( Praw ),
LCURSES_FUNC( Presizeterm ),
LCURSES_FUNC( Pripoffline ),
LCURSES_FUNC( Pslk_attroff ),
LCURSES_FUNC( Pslk_attron ),
LCURSES_FUNC( Pslk_attrset ),
LCURSES_FUNC( Pslk_clear ),
LCURSES_FUNC( Pslk_init ),
LCURSES_FUNC( Pslk_label ),
LCURSES_FUNC( Pslk_noutrefresh ),
LCURSES_FUNC( Pslk_refresh ),
LCURSES_FUNC( Pslk_restore ),
LCURSES_FUNC( Pslk_set ),
LCURSES_FUNC( Pslk_touch ),
LCURSES_FUNC( Pstart_color ),
LCURSES_FUNC( Pstdscr ),
LCURSES_FUNC( Ptermattrs ),
LCURSES_FUNC( Ptermname ),
LCURSES_FUNC( Ptigetflag ),
LCURSES_FUNC( Ptigetnum ),
LCURSES_FUNC( Ptigetstr ),
LCURSES_FUNC( Punctrl ),
LCURSES_FUNC( Pungetch ),
LCURSES_FUNC( Puse_default_colors),
LCURSES_FUNC( Passume_default_colors),
{NULL, NULL}
};
/***
Constants.
@section constants
*/
/***
Curses constants.
Any constants not available in the underlying system will be `nil` valued,
see @{curses.lua}. Many of the `KEY_` constants cannot be generated by
modern keyboards and are mostly for historical compatibility with ancient
terminal hardware keyboards.
Note that almost all of these constants remain undefined (`nil`) until
after @{curses.initscr} has returned successfully.
@table curses
@int ACS_BLOCK alternate character set solid block
@int ACS_BOARD alternate character set board of squares
@int ACS_BTEE alternate character set bottom-tee
@int ACS_BULLET alternate character set bullet
@int ACS_CKBOARD alternate character set stipple
@int ACS_DARROW alternate character set down arrow
@int ACS_DEGREE alternate character set degrees mark
@int ACS_DIAMOND alternate character set diamond
@int ACS_HLINE alternate character set horizontal line
@int ACS_LANTERN alternate character set lantern
@int ACS_LARROW alternate character set left arrow
@int ACS_LLCORNER alternate character set lower left corner
@int ACS_LRCORNER alternate character set lower right corner
@int ACS_LTEE alternate character set left tee
@int ACS_PLMINUS alternate character set plus/minus
@int ACS_PLUS alternate character set plus
@int ACS_RARROW alternate character set right arrow
@int ACS_RTEE alternate character set right tee
@int ACS_S1 alternate character set scan-line 1
@int ACS_S9 alternate character set scan-line 9
@int ACS_TTEE alternate character set top tee
@int ACS_UARROW alternate character set up arrow
@int ACS_ULCORNER alternate character set upper left corner
@int ACS_URCORNER alternate character set upper right corner
@int ACS_VLINE alternate character set vertical line
@int A_ALTCHARSET alternatate character set attribute
@int A_ATTRIBUTES attributed character attributes bitmask
@int A_BLINK blinking attribute
@int A_BOLD bold attribute
@int A_CHARTEXT attributed character text bitmask
@int A_COLOR attributed character color-pair bitmask
@int A_DIM half-bright attribute
@int A_INVIS invisible attribute
@int A_NORMAL normal attribute (all attributes off)
@int A_PROTECT protected attribute
@int A_REVERSE reverse video attribute
@int A_STANDOUT standout attribute
@int A_UNDERLINE underline attribute
@int COLOR_BLACK black color attribute
@int COLOR_BLUE blue color attribute
@int COLOR_CYAN cyan color attribute
@int COLOR_GREEN green color attribute
@int COLOR_MAGENTA magenta color attribute
@int COLOR_RED red color attribute
@int COLOR_WHITE white color attribute
@int COLOR_YELLOW yellow color attribute
@int KEY_A1 upper-left of keypad key
@int KEY_A3 upper-right of keypad key
@int KEY_B2 center of keypad key
@int KEY_BACKSPACE backspace key
@int KEY_BEG beginning key
@int KEY_BREAK break key
@int KEY_BTAB backtab key
@int KEY_C1 bottom-left of keypad key
@int KEY_C3 bottom-right of keypad key
@int KEY_CANCEL cancel key
@int KEY_CATAB clear all tabs key
@int KEY_CLEAR clear screen key
@int KEY_CLOSE close key
@int KEY_COMMAND command key
@int KEY_COPY copy key
@int KEY_CREATE create key
@int KEY_CTAB clear tab key
@int KEY_DC delete character key
@int KEY_DL delete line key
@int KEY_DOWN down arrow key
@int KEY_EIC exit insert char mode key
@int KEY_END end key
@int KEY_ENTER enter key
@int KEY_EOL clear to end of line key
@int KEY_EOS clear to end of screen key
@int KEY_EXIT exit key
@int KEY_F0 f0 key
@int KEY_F1 f1 key
@int KEY_F2 f2 key
@int KEY_F3 f3 key
@int KEY_F4 f4 key
@int KEY_F5 f5 key
@int KEY_F6 f6 key
@int KEY_F7 f7 key
@int KEY_F8 f8 key
@int KEY_F9 f9 key
@int KEY_F10 f10 key
@int KEY_F11 f11 key
@int KEY_F12 f12 key
@int KEY_F13 f13 key
@int KEY_F14 f14 key
@int KEY_F15 f15 key
@int KEY_F16 f16 key
@int KEY_F17 f17 key
@int KEY_F18 f18 key
@int KEY_F19 f19 key
@int KEY_F20 f20 key
@int KEY_F21 f21 key
@int KEY_F22 f22 key
@int KEY_F23 f23 key
@int KEY_F24 f24 key
@int KEY_F25 f25 key
@int KEY_F26 f26 key
@int KEY_F27 f27 key
@int KEY_F28 f28 key
@int KEY_F29 f29 key
@int KEY_F30 f30 key
@int KEY_F31 f31 key
@int KEY_F32 f32 key
@int KEY_F33 f33 key
@int KEY_F34 f34 key
@int KEY_F35 f35 key
@int KEY_F36 f36 key
@int KEY_F37 f37 key
@int KEY_F38 f38 key
@int KEY_F39 f39 key
@int KEY_F40 f40 key
@int KEY_F41 f41 key
@int KEY_F42 f42 key
@int KEY_F43 f43 key
@int KEY_F44 f44 key
@int KEY_F45 f45 key
@int KEY_F46 f46 key
@int KEY_F47 f47 key
@int KEY_F48 f48 key
@int KEY_F49 f49 key
@int KEY_F50 f50 key
@int KEY_F51 f51 key
@int KEY_F52 f52 key
@int KEY_F53 f53 key
@int KEY_F54 f54 key
@int KEY_F55 f55 key
@int KEY_F56 f56 key
@int KEY_F57 f57 key
@int KEY_F58 f58 key
@int KEY_F59 f59 key
@int KEY_F60 f60 key
@int KEY_F61 f61 key
@int KEY_F62 f62 key
@int KEY_F63 f63 key
@int KEY_FIND find key
@int KEY_HELP help key
@int KEY_HOME home key
@int KEY_IC enter insert char mode key
@int KEY_IL insert line key
@int KEY_LEFT cursor left key
@int KEY_LL home down or bottom key
@int KEY_MARK mark key
@int KEY_MESSAGE message key
@int KEY_MOUSE mouse event available virtual key
@int KEY_MOVE move key
@int KEY_NEXT next object key
@int KEY_NPAGE next page key
@int KEY_OPEN open key
@int KEY_OPTIONS options key
@int KEY_PPAGE previous page key
@int KEY_PREVIOUS prewious object key
@int KEY_PRINT print key
@int KEY_REDO redo key
@int KEY_REFERENCE reference key
@int KEY_REFRESH refresh key
@int KEY_REPLACE replace key
@int KEY_RESET hard reset key
@int KEY_RESIZE resize event virtual key
@int KEY_RESTART restart key
@int KEY_RESUME resume key
@int KEY_RIGHT cursor right key
@int KEY_SAVE save key
@int KEY_SBEG shift beginning key
@int KEY_SCANCEL shift cancel key
@int KEY_SCOMMAND shift command key
@int KEY_SCOPY shift copy key
@int KEY_SCREATE shift create key
@int KEY_SDC shift delete character key
@int KEY_SDL shift delete line key
@int KEY_SELECT select key
@int KEY_SEND send key
@int KEY_SEOL shift clear to end of line key
@int KEY_SEXIT shift exit key
@int KEY_SF scroll one line forward key
@int KEY_SFIND shift find key
@int KEY_SHELP shift help key
@int KEY_SHOME shift home key
@int KEY_SIC shift enter insert mode key
@int KEY_SLEFT shift cursor left key
@int KEY_SMESSAGE shift message key
@int KEY_SMOVE shift move key
@int KEY_SNEXT shift next object key
@int KEY_SOPTIONS shift options key
@int KEY_SPREVIOUS shift previous object key
@int KEY_SPRINT shift print key
@int KEY_SR scroll one line backward key
@int KEY_SREDO shift redo key
@int KEY_SREPLACE shift replace key
@int KEY_SRESET soft reset key
@int KEY_SRIGHT shift cursor right key
@int KEY_SRSUME shift resume key
@int KEY_SSAVE shift save key
@int KEY_SSUSPEND shift suspend key
@int KEY_STAB shift tab key
@int KEY_SUNDO shift undo key
@int KEY_SUSPEND suspend key
@int KEY_UNDO undo key
@int KEY_UP cursor up key
@usage
-- Print curses constants supported on this host.
for name, value in pairs (require "curses") do
if type (value) == "number" then
print (name, value)
end
end
*/
LUALIB_API int
luaopen_curses(lua_State *L)
{
luaopen_curses_window(L);
luaopen_curses_chstr(L);
luaL_register(L, "curses", curseslib);
init_stdscr(L);
return 1;
}