rewrite curses
This commit is contained in:
@@ -187,7 +187,7 @@
|
|||||||
same "printed page" as the copyright notice for easier
|
same "printed page" as the copyright notice for easier
|
||||||
identification within third-party archives.
|
identification within third-party archives.
|
||||||
|
|
||||||
Copyright 2016-2018 TBOOX Open Source Group
|
Copyright 2016-present TBOOX Open Source Group
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
11
NOTICE.md
11
NOTICE.md
@@ -1,5 +1,5 @@
|
|||||||
A cross-platform terminal ui library based on Lua
|
A cross-platform terminal ui library based on Lua
|
||||||
Copyright 2015-2018 The TBOOX Open Source Group
|
Copyright 2015-present The TBOOX Open Source Group
|
||||||
|
|
||||||
This product includes software developed by The TBOOX Open Source Group (https://tboox.org/).
|
This product includes software developed by The TBOOX Open Source Group (https://tboox.org/).
|
||||||
|
|
||||||
@@ -13,12 +13,3 @@ which can be obtained at:
|
|||||||
* HOMEPAGE:
|
* HOMEPAGE:
|
||||||
* http://pdcurses.org/
|
* http://pdcurses.org/
|
||||||
|
|
||||||
This product depends on 'lcurses/cui', Lua Console User Interface,
|
|
||||||
which can be obtained at:
|
|
||||||
|
|
||||||
* LICENSE:
|
|
||||||
* core/src/lcurses/LICENSE (MIT License)
|
|
||||||
* HOMEPAGE:
|
|
||||||
* http://lua-cui.sourceforge.net/
|
|
||||||
|
|
||||||
|
|
||||||
|
@@ -24,7 +24,7 @@ build = {
|
|||||||
type = "builtin",
|
type = "builtin",
|
||||||
modules = {
|
modules = {
|
||||||
["ltui"] = {
|
["ltui"] = {
|
||||||
sources = "src/core/lcurses/lcurses.c",
|
sources = "src/core/curses/curses.c",
|
||||||
libraries = {"curses"}
|
libraries = {"curses"}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
865
src/core/curses/curses.c
Normal file
865
src/core/curses/curses.c
Normal file
@@ -0,0 +1,865 @@
|
|||||||
|
/*!A cross-platform terminal ui library based on Lua
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2016-present, TBOOX Open Source Group.
|
||||||
|
*
|
||||||
|
* @author ruki
|
||||||
|
* @file curses.c
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* //////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
* includes
|
||||||
|
*/
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#ifndef LUAJIT
|
||||||
|
# define LUA_COMPAT_5_1
|
||||||
|
# define LUA_COMPAT_5_3
|
||||||
|
# define LUA_COMPAT_ALL
|
||||||
|
#endif
|
||||||
|
#include "luaconf.h"
|
||||||
|
#undef LUA_API
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
# define LUA_API extern "C"
|
||||||
|
#else
|
||||||
|
# define LUA_API extern
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef LUAJIT
|
||||||
|
# include "luajit.h"
|
||||||
|
#else
|
||||||
|
# include "lua.h"
|
||||||
|
#endif
|
||||||
|
#include "lualib.h"
|
||||||
|
#include "lauxlib.h"
|
||||||
|
|
||||||
|
#include <curses.h>
|
||||||
|
|
||||||
|
#if defined(NCURSES_VERSION)
|
||||||
|
# include <locale.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* //////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
* macros
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define LT_CURSES_STDSCR "curses.stdscr"
|
||||||
|
#define LT_CURSES_WINDOW "curses.window"
|
||||||
|
#define LT_CURSES_OK(v) (((v) == ERR) ? 0 : 1)
|
||||||
|
|
||||||
|
// define functions
|
||||||
|
#define LT_CURSES_NUMBER(n) \
|
||||||
|
static int lt_curses_ ## n(lua_State* lua) \
|
||||||
|
{ \
|
||||||
|
lua_pushnumber(lua, n()); \
|
||||||
|
return 1; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define LT_CURSES_NUMBER2(n, v) \
|
||||||
|
static int lt_curses_ ## n(lua_State* lua) \
|
||||||
|
{ \
|
||||||
|
lua_pushnumber(lua, v); \
|
||||||
|
return 1; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define LT_CURSES_BOOL(n) \
|
||||||
|
static int lt_curses_ ## n(lua_State* lua) \
|
||||||
|
{ \
|
||||||
|
lua_pushboolean(lua, n()); \
|
||||||
|
return 1; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define LT_CURSES_BOOLOK(n) \
|
||||||
|
static int lt_curses_ ## n(lua_State* lua) \
|
||||||
|
{ \
|
||||||
|
lua_pushboolean(lua, LT_CURSES_OK(n())); \
|
||||||
|
return 1; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define LT_CURSES_WINDOW_BOOLOK(n) \
|
||||||
|
static int lt_curses_window_ ## n(lua_State* lua) \
|
||||||
|
{ \
|
||||||
|
WINDOW* w = lt_curses_window_check(lua, 1); \
|
||||||
|
lua_pushboolean(lua, LT_CURSES_OK(n(w))); \
|
||||||
|
return 1; \
|
||||||
|
}
|
||||||
|
|
||||||
|
// define constants
|
||||||
|
#define LT_CURSES_CONST_(n, v) \
|
||||||
|
lua_pushstring(lua, n); \
|
||||||
|
lua_pushnumber(lua, v); \
|
||||||
|
lua_settable(lua, lua_upvalueindex(1));
|
||||||
|
|
||||||
|
#define LT_CURSES_CONST(s) LT_CURSES_CONST_(#s, s)
|
||||||
|
#define LT_CURSES_CONST2(s, v) LT_CURSES_CONST_(#s, v)
|
||||||
|
|
||||||
|
// export
|
||||||
|
#if defined(_WIN32)
|
||||||
|
# define __export __declspec(dllexport)
|
||||||
|
#elif defined(__GNUC__) && ((__GNUC__ >= 4) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3))
|
||||||
|
# define __export __attribute__((visibility("default")))
|
||||||
|
#else
|
||||||
|
# define __export
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* //////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
* globals
|
||||||
|
*/
|
||||||
|
|
||||||
|
// map key for pdcurses, keeping the keys consistent with ncurses
|
||||||
|
static int g_mapkey = 0;
|
||||||
|
|
||||||
|
/* //////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
* private implementation
|
||||||
|
*/
|
||||||
|
static chtype lt_curses_checkch(lua_State* lua, int index)
|
||||||
|
{
|
||||||
|
if (lua_type(lua, index) == LUA_TNUMBER)
|
||||||
|
return (chtype)luaL_checknumber(lua, index);
|
||||||
|
if (lua_type(lua, index) == LUA_TSTRING)
|
||||||
|
return *lua_tostring(lua, index);
|
||||||
|
#ifdef LUAJIT
|
||||||
|
luaL_typerror(lua, index, "chtype");
|
||||||
|
#endif
|
||||||
|
return (chtype)0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get character and map key
|
||||||
|
static int lt_curses_window_getch_impl(WINDOW* w)
|
||||||
|
{
|
||||||
|
#ifdef PDCURSES
|
||||||
|
static int has_key = 0;
|
||||||
|
static int temp_key = 0;
|
||||||
|
|
||||||
|
int key;
|
||||||
|
if (g_mapkey && has_key)
|
||||||
|
{
|
||||||
|
has_key = 0;
|
||||||
|
return temp_key;
|
||||||
|
}
|
||||||
|
|
||||||
|
key = wgetch(w);
|
||||||
|
if (key == ERR || !g_mapkey) return key;
|
||||||
|
if (key >= ALT_A && key <= ALT_Z)
|
||||||
|
{
|
||||||
|
has_key = 1;
|
||||||
|
temp_key = key - ALT_A + 'A';
|
||||||
|
}
|
||||||
|
else if (key >= ALT_0 && key <= ALT_9)
|
||||||
|
{
|
||||||
|
has_key = 1;
|
||||||
|
temp_key = key - ALT_0 + '0';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch (key)
|
||||||
|
{
|
||||||
|
case ALT_DEL: temp_key = KEY_DC; break;
|
||||||
|
case ALT_INS: temp_key = KEY_IC; break;
|
||||||
|
case ALT_HOME: temp_key = KEY_HOME; break;
|
||||||
|
case ALT_END: temp_key = KEY_END; break;
|
||||||
|
case ALT_PGUP: temp_key = KEY_PPAGE; break;
|
||||||
|
case ALT_PGDN: temp_key = KEY_NPAGE; break;
|
||||||
|
case ALT_UP: temp_key = KEY_UP; break;
|
||||||
|
case ALT_DOWN: temp_key = KEY_DOWN; break;
|
||||||
|
case ALT_RIGHT: temp_key = KEY_RIGHT; break;
|
||||||
|
case ALT_LEFT: temp_key = KEY_LEFT; break;
|
||||||
|
case ALT_BKSP: temp_key = KEY_BACKSPACE; break;
|
||||||
|
default: return key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
has_key = 1;
|
||||||
|
return 27;
|
||||||
|
#else
|
||||||
|
return wgetch(w);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// new a window object
|
||||||
|
static void lt_curses_window_new(lua_State* lua, WINDOW* nw)
|
||||||
|
{
|
||||||
|
if (nw)
|
||||||
|
{
|
||||||
|
WINDOW** w = (WINDOW**)lua_newuserdata(lua, sizeof(WINDOW*));
|
||||||
|
luaL_getmetatable(lua, LT_CURSES_WINDOW);
|
||||||
|
lua_setmetatable(lua, -2);
|
||||||
|
*w = nw;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lua_pushliteral(lua, "failed to create window");
|
||||||
|
lua_error(lua);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// get window
|
||||||
|
static WINDOW** lt_curses_window_get(lua_State* lua, int index)
|
||||||
|
{
|
||||||
|
WINDOW** w = (WINDOW**)luaL_checkudata(lua, index, LT_CURSES_WINDOW);
|
||||||
|
if (w == NULL) luaL_argerror(lua, index, "bad curses window");
|
||||||
|
return w;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get and check window
|
||||||
|
static WINDOW* lt_curses_window_check(lua_State* lua, int index)
|
||||||
|
{
|
||||||
|
WINDOW** w = lt_curses_window_get(lua, index);
|
||||||
|
if (*w == NULL) luaL_argerror(lua, index, "attempt to use closed curses window");
|
||||||
|
return *w;
|
||||||
|
}
|
||||||
|
|
||||||
|
// tostring(window)
|
||||||
|
static int lt_curses_window_tostring(lua_State* lua)
|
||||||
|
{
|
||||||
|
WINDOW** w = lt_curses_window_get(lua, 1);
|
||||||
|
char const* s = NULL;
|
||||||
|
if (*w) s = (char const*)lua_touserdata(lua, 1);
|
||||||
|
lua_pushfstring(lua, "curses window (%s)", s? s : "closed");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// window:move(y, x)
|
||||||
|
static int lt_curses_window_move(lua_State* lua)
|
||||||
|
{
|
||||||
|
WINDOW* w = lt_curses_window_check(lua, 1);
|
||||||
|
int y = luaL_checkint(lua, 2);
|
||||||
|
int x = luaL_checkint(lua, 3);
|
||||||
|
lua_pushboolean(lua, LT_CURSES_OK(wmove(w, y, x)));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// window:getyx(y, x)
|
||||||
|
static int lt_curses_window_getyx(lua_State* lua)
|
||||||
|
{
|
||||||
|
WINDOW* w = lt_curses_window_check(lua, 1);
|
||||||
|
int y, x;
|
||||||
|
getyx(w, y, x);
|
||||||
|
lua_pushnumber(lua, y);
|
||||||
|
lua_pushnumber(lua, x);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// window:getmaxyx(y, x)
|
||||||
|
static int lt_curses_window_getmaxyx(lua_State* lua)
|
||||||
|
{
|
||||||
|
WINDOW* w = lt_curses_window_check(lua, 1);
|
||||||
|
int y, x;
|
||||||
|
getmaxyx(w, y, x);
|
||||||
|
lua_pushnumber(lua, y);
|
||||||
|
lua_pushnumber(lua, x);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// window:delwin()
|
||||||
|
static int lt_curses_window_delwin(lua_State* lua)
|
||||||
|
{
|
||||||
|
WINDOW** w = lt_curses_window_get(lua, 1);
|
||||||
|
if (*w && *w != stdscr)
|
||||||
|
{
|
||||||
|
delwin(*w);
|
||||||
|
*w = NULL;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// window:addch(ch)
|
||||||
|
static int lt_curses_window_addch(lua_State* lua)
|
||||||
|
{
|
||||||
|
WINDOW* w = lt_curses_window_check(lua, 1);
|
||||||
|
chtype ch = lt_curses_checkch(lua, 2);
|
||||||
|
lua_pushboolean(lua, LT_CURSES_OK(waddch(w, ch)));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// window:addnstr(str)
|
||||||
|
static int lt_curses_window_addnstr(lua_State* lua)
|
||||||
|
{
|
||||||
|
WINDOW* w = lt_curses_window_check(lua, 1);
|
||||||
|
const char* str = luaL_checkstring(lua, 2);
|
||||||
|
int n = luaL_optint(lua, 3, -1);
|
||||||
|
if (n < 0) n = (int)lua_strlen(lua, 2);
|
||||||
|
lua_pushboolean(lua, LT_CURSES_OK(waddnstr(w, str, n)));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// window:keypad(true)
|
||||||
|
static int lt_curses_window_keypad(lua_State* lua)
|
||||||
|
{
|
||||||
|
WINDOW* w = lt_curses_window_check(lua, 1);
|
||||||
|
int enabled = lua_isnoneornil(lua, 2) ? 1 : lua_toboolean(lua, 2);
|
||||||
|
if (enabled)
|
||||||
|
{
|
||||||
|
// on WIN32 ALT keys need to be mapped, so to make sure you get the wanted keys,
|
||||||
|
// only makes sense when using keypad(true) and echo(false)
|
||||||
|
g_mapkey = 1;
|
||||||
|
}
|
||||||
|
lua_pushboolean(lua, LT_CURSES_OK(keypad(w, enabled)));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// window:meta(true)
|
||||||
|
static int lt_curses_window_meta(lua_State* lua)
|
||||||
|
{
|
||||||
|
WINDOW* w = lt_curses_window_check(lua, 1);
|
||||||
|
int enabled = lua_toboolean(lua, 2);
|
||||||
|
lua_pushboolean(lua, LT_CURSES_OK(meta(w, enabled)));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// window:nodelay(true)
|
||||||
|
static int lt_curses_window_nodelay(lua_State* lua)
|
||||||
|
{
|
||||||
|
WINDOW* w = lt_curses_window_check(lua, 1);
|
||||||
|
int enabled = lua_toboolean(lua, 2);
|
||||||
|
lua_pushboolean(lua, LT_CURSES_OK(nodelay(w, enabled)));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// window:leaveok(true)
|
||||||
|
static int lt_curses_window_leaveok(lua_State* lua)
|
||||||
|
{
|
||||||
|
WINDOW* w = lt_curses_window_check(lua, 1);
|
||||||
|
int enabled = lua_toboolean(lua, 2);
|
||||||
|
lua_pushboolean(lua, LT_CURSES_OK(leaveok(w, enabled)));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// window:getch()
|
||||||
|
static int lt_curses_window_getch(lua_State* lua)
|
||||||
|
{
|
||||||
|
WINDOW* w = lt_curses_window_check(lua, 1);
|
||||||
|
int c = lt_curses_window_getch_impl(w);
|
||||||
|
if (c == ERR) return 0;
|
||||||
|
lua_pushnumber(lua, c);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// window:attroff(attrs)
|
||||||
|
static int lt_curses_window_attroff(lua_State* lua)
|
||||||
|
{
|
||||||
|
WINDOW* w = lt_curses_window_check(lua, 1);
|
||||||
|
int attrs = luaL_checkint(lua, 2);
|
||||||
|
lua_pushboolean(lua, LT_CURSES_OK(wattroff(w, attrs)));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// window:attron(attrs)
|
||||||
|
static int lt_curses_window_attron(lua_State* lua)
|
||||||
|
{
|
||||||
|
WINDOW* w = lt_curses_window_check(lua, 1);
|
||||||
|
int attrs = luaL_checkint(lua, 2);
|
||||||
|
lua_pushboolean(lua, LT_CURSES_OK(wattron(w, attrs)));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// window:attrset(attrs)
|
||||||
|
static int lt_curses_window_attrset(lua_State* lua)
|
||||||
|
{
|
||||||
|
WINDOW* w = lt_curses_window_check(lua, 1);
|
||||||
|
int attrs = luaL_checkint(lua, 2);
|
||||||
|
lua_pushboolean(lua, LT_CURSES_OK(wattrset(w, attrs)));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// window:copywin(...)
|
||||||
|
static int lt_curses_window_copywin(lua_State* lua)
|
||||||
|
{
|
||||||
|
WINDOW* srcwin = lt_curses_window_check(lua, 1);
|
||||||
|
WINDOW* dstwin = lt_curses_window_check(lua, 2);
|
||||||
|
int sminrow = luaL_checkint(lua, 3);
|
||||||
|
int smincol = luaL_checkint(lua, 4);
|
||||||
|
int dminrow = luaL_checkint(lua, 5);
|
||||||
|
int dmincol = luaL_checkint(lua, 6);
|
||||||
|
int dmaxrow = luaL_checkint(lua, 7);
|
||||||
|
int dmaxcol = luaL_checkint(lua, 8);
|
||||||
|
int overlay = lua_toboolean(lua, 9);
|
||||||
|
lua_pushboolean(lua, LT_CURSES_OK(copywin(srcwin, dstwin, sminrow,
|
||||||
|
smincol, dminrow, dmincol, dmaxrow, dmaxcol, overlay)));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// clean window after exiting program
|
||||||
|
static void lt_curses_cleanup()
|
||||||
|
{
|
||||||
|
if (!isendwin())
|
||||||
|
{
|
||||||
|
wclear(stdscr);
|
||||||
|
wrefresh(stdscr);
|
||||||
|
endwin();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// register constants
|
||||||
|
static void lt_curses_register_constants(lua_State* lua)
|
||||||
|
{
|
||||||
|
// colors
|
||||||
|
LT_CURSES_CONST(COLOR_BLACK)
|
||||||
|
LT_CURSES_CONST(COLOR_RED)
|
||||||
|
LT_CURSES_CONST(COLOR_GREEN)
|
||||||
|
LT_CURSES_CONST(COLOR_YELLOW)
|
||||||
|
LT_CURSES_CONST(COLOR_BLUE)
|
||||||
|
LT_CURSES_CONST(COLOR_MAGENTA)
|
||||||
|
LT_CURSES_CONST(COLOR_CYAN)
|
||||||
|
LT_CURSES_CONST(COLOR_WHITE)
|
||||||
|
|
||||||
|
// alternate character set
|
||||||
|
LT_CURSES_CONST(ACS_BLOCK)
|
||||||
|
LT_CURSES_CONST(ACS_BOARD)
|
||||||
|
LT_CURSES_CONST(ACS_BTEE)
|
||||||
|
LT_CURSES_CONST(ACS_TTEE)
|
||||||
|
LT_CURSES_CONST(ACS_LTEE)
|
||||||
|
LT_CURSES_CONST(ACS_RTEE)
|
||||||
|
LT_CURSES_CONST(ACS_LLCORNER)
|
||||||
|
LT_CURSES_CONST(ACS_LRCORNER)
|
||||||
|
LT_CURSES_CONST(ACS_URCORNER)
|
||||||
|
LT_CURSES_CONST(ACS_ULCORNER)
|
||||||
|
LT_CURSES_CONST(ACS_LARROW)
|
||||||
|
LT_CURSES_CONST(ACS_RARROW)
|
||||||
|
LT_CURSES_CONST(ACS_UARROW)
|
||||||
|
LT_CURSES_CONST(ACS_DARROW)
|
||||||
|
LT_CURSES_CONST(ACS_HLINE)
|
||||||
|
LT_CURSES_CONST(ACS_VLINE)
|
||||||
|
LT_CURSES_CONST(ACS_BULLET)
|
||||||
|
LT_CURSES_CONST(ACS_CKBOARD)
|
||||||
|
LT_CURSES_CONST(ACS_LANTERN)
|
||||||
|
LT_CURSES_CONST(ACS_DEGREE)
|
||||||
|
LT_CURSES_CONST(ACS_DIAMOND)
|
||||||
|
LT_CURSES_CONST(ACS_PLMINUS)
|
||||||
|
LT_CURSES_CONST(ACS_PLUS)
|
||||||
|
LT_CURSES_CONST(ACS_S1)
|
||||||
|
LT_CURSES_CONST(ACS_S9)
|
||||||
|
|
||||||
|
// attributes
|
||||||
|
LT_CURSES_CONST(A_NORMAL)
|
||||||
|
LT_CURSES_CONST(A_STANDOUT)
|
||||||
|
LT_CURSES_CONST(A_UNDERLINE)
|
||||||
|
LT_CURSES_CONST(A_REVERSE)
|
||||||
|
LT_CURSES_CONST(A_BLINK)
|
||||||
|
LT_CURSES_CONST(A_DIM)
|
||||||
|
LT_CURSES_CONST(A_BOLD)
|
||||||
|
LT_CURSES_CONST(A_PROTECT)
|
||||||
|
LT_CURSES_CONST(A_INVIS)
|
||||||
|
LT_CURSES_CONST(A_ALTCHARSET)
|
||||||
|
LT_CURSES_CONST(A_CHARTEXT)
|
||||||
|
|
||||||
|
// key functions
|
||||||
|
LT_CURSES_CONST(KEY_BREAK)
|
||||||
|
LT_CURSES_CONST(KEY_DOWN)
|
||||||
|
LT_CURSES_CONST(KEY_UP)
|
||||||
|
LT_CURSES_CONST(KEY_LEFT)
|
||||||
|
LT_CURSES_CONST(KEY_RIGHT)
|
||||||
|
LT_CURSES_CONST(KEY_HOME)
|
||||||
|
LT_CURSES_CONST(KEY_BACKSPACE)
|
||||||
|
|
||||||
|
LT_CURSES_CONST(KEY_DL)
|
||||||
|
LT_CURSES_CONST(KEY_IL)
|
||||||
|
LT_CURSES_CONST(KEY_DC)
|
||||||
|
LT_CURSES_CONST(KEY_IC)
|
||||||
|
LT_CURSES_CONST(KEY_EIC)
|
||||||
|
LT_CURSES_CONST(KEY_CLEAR)
|
||||||
|
LT_CURSES_CONST(KEY_EOS)
|
||||||
|
LT_CURSES_CONST(KEY_EOL)
|
||||||
|
LT_CURSES_CONST(KEY_SF)
|
||||||
|
LT_CURSES_CONST(KEY_SR)
|
||||||
|
LT_CURSES_CONST(KEY_NPAGE)
|
||||||
|
LT_CURSES_CONST(KEY_PPAGE)
|
||||||
|
LT_CURSES_CONST(KEY_STAB)
|
||||||
|
LT_CURSES_CONST(KEY_CTAB)
|
||||||
|
LT_CURSES_CONST(KEY_CATAB)
|
||||||
|
LT_CURSES_CONST(KEY_ENTER)
|
||||||
|
LT_CURSES_CONST(KEY_SRESET)
|
||||||
|
LT_CURSES_CONST(KEY_RESET)
|
||||||
|
LT_CURSES_CONST(KEY_PRINT)
|
||||||
|
LT_CURSES_CONST(KEY_LL)
|
||||||
|
LT_CURSES_CONST(KEY_A1)
|
||||||
|
LT_CURSES_CONST(KEY_A3)
|
||||||
|
LT_CURSES_CONST(KEY_B2)
|
||||||
|
LT_CURSES_CONST(KEY_C1)
|
||||||
|
LT_CURSES_CONST(KEY_C3)
|
||||||
|
LT_CURSES_CONST(KEY_BTAB)
|
||||||
|
LT_CURSES_CONST(KEY_BEG)
|
||||||
|
LT_CURSES_CONST(KEY_CANCEL)
|
||||||
|
LT_CURSES_CONST(KEY_CLOSE)
|
||||||
|
LT_CURSES_CONST(KEY_COMMAND)
|
||||||
|
LT_CURSES_CONST(KEY_COPY)
|
||||||
|
LT_CURSES_CONST(KEY_CREATE)
|
||||||
|
LT_CURSES_CONST(KEY_END)
|
||||||
|
LT_CURSES_CONST(KEY_EXIT)
|
||||||
|
LT_CURSES_CONST(KEY_FIND)
|
||||||
|
LT_CURSES_CONST(KEY_HELP)
|
||||||
|
LT_CURSES_CONST(KEY_MARK)
|
||||||
|
LT_CURSES_CONST(KEY_MESSAGE)
|
||||||
|
#ifdef PDCURSES
|
||||||
|
// https://github.com/xmake-io/xmake/issues/1610#issuecomment-971149885
|
||||||
|
LT_CURSES_CONST(KEY_C2)
|
||||||
|
LT_CURSES_CONST(KEY_A2)
|
||||||
|
LT_CURSES_CONST(KEY_B1)
|
||||||
|
LT_CURSES_CONST(KEY_B3)
|
||||||
|
#endif
|
||||||
|
#if !defined(XCURSES)
|
||||||
|
# ifndef NOMOUSE
|
||||||
|
LT_CURSES_CONST(KEY_MOUSE)
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
LT_CURSES_CONST(KEY_MOVE)
|
||||||
|
LT_CURSES_CONST(KEY_NEXT)
|
||||||
|
LT_CURSES_CONST(KEY_OPEN)
|
||||||
|
LT_CURSES_CONST(KEY_OPTIONS)
|
||||||
|
LT_CURSES_CONST(KEY_PREVIOUS)
|
||||||
|
LT_CURSES_CONST(KEY_REDO)
|
||||||
|
LT_CURSES_CONST(KEY_REFERENCE)
|
||||||
|
LT_CURSES_CONST(KEY_REFRESH)
|
||||||
|
LT_CURSES_CONST(KEY_REPLACE)
|
||||||
|
LT_CURSES_CONST(KEY_RESIZE)
|
||||||
|
LT_CURSES_CONST(KEY_RESTART)
|
||||||
|
LT_CURSES_CONST(KEY_RESUME)
|
||||||
|
LT_CURSES_CONST(KEY_SAVE)
|
||||||
|
LT_CURSES_CONST(KEY_SBEG)
|
||||||
|
LT_CURSES_CONST(KEY_SCANCEL)
|
||||||
|
LT_CURSES_CONST(KEY_SCOMMAND)
|
||||||
|
LT_CURSES_CONST(KEY_SCOPY)
|
||||||
|
LT_CURSES_CONST(KEY_SCREATE)
|
||||||
|
LT_CURSES_CONST(KEY_SDC)
|
||||||
|
LT_CURSES_CONST(KEY_SDL)
|
||||||
|
LT_CURSES_CONST(KEY_SELECT)
|
||||||
|
LT_CURSES_CONST(KEY_SEND)
|
||||||
|
LT_CURSES_CONST(KEY_SEOL)
|
||||||
|
LT_CURSES_CONST(KEY_SEXIT)
|
||||||
|
LT_CURSES_CONST(KEY_SFIND)
|
||||||
|
LT_CURSES_CONST(KEY_SHELP)
|
||||||
|
LT_CURSES_CONST(KEY_SHOME)
|
||||||
|
LT_CURSES_CONST(KEY_SIC)
|
||||||
|
LT_CURSES_CONST(KEY_SLEFT)
|
||||||
|
LT_CURSES_CONST(KEY_SMESSAGE)
|
||||||
|
LT_CURSES_CONST(KEY_SMOVE)
|
||||||
|
LT_CURSES_CONST(KEY_SNEXT)
|
||||||
|
LT_CURSES_CONST(KEY_SOPTIONS)
|
||||||
|
LT_CURSES_CONST(KEY_SPREVIOUS)
|
||||||
|
LT_CURSES_CONST(KEY_SPRINT)
|
||||||
|
LT_CURSES_CONST(KEY_SREDO)
|
||||||
|
LT_CURSES_CONST(KEY_SREPLACE)
|
||||||
|
LT_CURSES_CONST(KEY_SRIGHT)
|
||||||
|
LT_CURSES_CONST(KEY_SRSUME)
|
||||||
|
LT_CURSES_CONST(KEY_SSAVE)
|
||||||
|
LT_CURSES_CONST(KEY_SSUSPEND)
|
||||||
|
LT_CURSES_CONST(KEY_SUNDO)
|
||||||
|
LT_CURSES_CONST(KEY_SUSPEND)
|
||||||
|
LT_CURSES_CONST(KEY_UNDO)
|
||||||
|
|
||||||
|
// KEY_Fx 0 <= x <= 63
|
||||||
|
LT_CURSES_CONST(KEY_F0)
|
||||||
|
LT_CURSES_CONST2(KEY_F1, KEY_F(1))
|
||||||
|
LT_CURSES_CONST2(KEY_F2, KEY_F(2))
|
||||||
|
LT_CURSES_CONST2(KEY_F3, KEY_F(3))
|
||||||
|
LT_CURSES_CONST2(KEY_F4, KEY_F(4))
|
||||||
|
LT_CURSES_CONST2(KEY_F5, KEY_F(5))
|
||||||
|
LT_CURSES_CONST2(KEY_F6, KEY_F(6))
|
||||||
|
LT_CURSES_CONST2(KEY_F7, KEY_F(7))
|
||||||
|
LT_CURSES_CONST2(KEY_F8, KEY_F(8))
|
||||||
|
LT_CURSES_CONST2(KEY_F9, KEY_F(9))
|
||||||
|
LT_CURSES_CONST2(KEY_F10, KEY_F(10))
|
||||||
|
LT_CURSES_CONST2(KEY_F11, KEY_F(11))
|
||||||
|
LT_CURSES_CONST2(KEY_F12, KEY_F(12))
|
||||||
|
|
||||||
|
#if !defined(XCURSES)
|
||||||
|
# ifndef NOMOUSE
|
||||||
|
// mouse constants
|
||||||
|
LT_CURSES_CONST(BUTTON1_RELEASED)
|
||||||
|
LT_CURSES_CONST(BUTTON1_PRESSED)
|
||||||
|
LT_CURSES_CONST(BUTTON1_CLICKED)
|
||||||
|
LT_CURSES_CONST(BUTTON1_DOUBLE_CLICKED)
|
||||||
|
LT_CURSES_CONST(BUTTON1_TRIPLE_CLICKED)
|
||||||
|
LT_CURSES_CONST(BUTTON2_RELEASED)
|
||||||
|
LT_CURSES_CONST(BUTTON2_PRESSED)
|
||||||
|
LT_CURSES_CONST(BUTTON2_CLICKED)
|
||||||
|
LT_CURSES_CONST(BUTTON2_DOUBLE_CLICKED)
|
||||||
|
LT_CURSES_CONST(BUTTON2_TRIPLE_CLICKED)
|
||||||
|
LT_CURSES_CONST(BUTTON3_RELEASED)
|
||||||
|
LT_CURSES_CONST(BUTTON3_PRESSED)
|
||||||
|
LT_CURSES_CONST(BUTTON3_CLICKED)
|
||||||
|
LT_CURSES_CONST(BUTTON3_DOUBLE_CLICKED)
|
||||||
|
LT_CURSES_CONST(BUTTON3_TRIPLE_CLICKED)
|
||||||
|
LT_CURSES_CONST(BUTTON4_RELEASED)
|
||||||
|
LT_CURSES_CONST(BUTTON4_PRESSED)
|
||||||
|
LT_CURSES_CONST(BUTTON4_CLICKED)
|
||||||
|
LT_CURSES_CONST(BUTTON4_DOUBLE_CLICKED)
|
||||||
|
LT_CURSES_CONST(BUTTON4_TRIPLE_CLICKED)
|
||||||
|
LT_CURSES_CONST(BUTTON_CTRL)
|
||||||
|
LT_CURSES_CONST(BUTTON_SHIFT)
|
||||||
|
LT_CURSES_CONST(BUTTON_ALT)
|
||||||
|
LT_CURSES_CONST(REPORT_MOUSE_POSITION)
|
||||||
|
LT_CURSES_CONST(ALL_MOUSE_EVENTS)
|
||||||
|
# if NCURSES_MOUSE_VERSION > 1
|
||||||
|
LT_CURSES_CONST(BUTTON5_RELEASED)
|
||||||
|
LT_CURSES_CONST(BUTTON5_PRESSED)
|
||||||
|
LT_CURSES_CONST(BUTTON5_CLICKED)
|
||||||
|
LT_CURSES_CONST(BUTTON5_DOUBLE_CLICKED)
|
||||||
|
LT_CURSES_CONST(BUTTON5_TRIPLE_CLICKED)
|
||||||
|
# else
|
||||||
|
LT_CURSES_CONST(BUTTON1_RESERVED_EVENT)
|
||||||
|
LT_CURSES_CONST(BUTTON2_RESERVED_EVENT)
|
||||||
|
LT_CURSES_CONST(BUTTON3_RESERVED_EVENT)
|
||||||
|
LT_CURSES_CONST(BUTTON4_RESERVED_EVENT)
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// init curses
|
||||||
|
static int lt_curses_initscr(lua_State* lua)
|
||||||
|
{
|
||||||
|
WINDOW* w = initscr();
|
||||||
|
if (!w) return 0;
|
||||||
|
lt_curses_window_new(lua, w);
|
||||||
|
|
||||||
|
#if defined(NCURSES_VERSION)
|
||||||
|
ESCDELAY = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
lua_pushstring(lua, LT_CURSES_STDSCR);
|
||||||
|
lua_pushvalue(lua, -2);
|
||||||
|
lua_rawset(lua, LUA_REGISTRYINDEX);
|
||||||
|
|
||||||
|
lt_curses_register_constants(lua);
|
||||||
|
|
||||||
|
#ifndef PDCURSES
|
||||||
|
atexit(lt_curses_cleanup);
|
||||||
|
#endif
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int lt_curses_endwin(lua_State* lua)
|
||||||
|
{
|
||||||
|
endwin();
|
||||||
|
#ifdef XCURSES
|
||||||
|
XCursesExit();
|
||||||
|
exit(0);
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int lt_curses_stdscr(lua_State* lua)
|
||||||
|
{
|
||||||
|
lua_pushstring(lua, LT_CURSES_STDSCR);
|
||||||
|
lua_rawget(lua, LUA_REGISTRYINDEX);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !defined(XCURSES) && !defined(NOMOUSE)
|
||||||
|
static int lt_curses_getmouse(lua_State* lua)
|
||||||
|
{
|
||||||
|
MEVENT e;
|
||||||
|
if (getmouse(&e) == OK)
|
||||||
|
{
|
||||||
|
lua_pushinteger(lua, e.bstate);
|
||||||
|
lua_pushinteger(lua, e.x);
|
||||||
|
lua_pushinteger(lua, e.y);
|
||||||
|
lua_pushinteger(lua, e.z);
|
||||||
|
lua_pushinteger(lua, e.id);
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
lua_pushnil(lua);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int lt_curses_mousemask(lua_State* lua)
|
||||||
|
{
|
||||||
|
mmask_t m = luaL_checkint(lua, 1);
|
||||||
|
mmask_t om;
|
||||||
|
m = mousemask(m, &om);
|
||||||
|
lua_pushinteger(lua, m);
|
||||||
|
lua_pushinteger(lua, om);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static int lt_curses_init_pair(lua_State* lua)
|
||||||
|
{
|
||||||
|
short pair = luaL_checkint(lua, 1);
|
||||||
|
short f = luaL_checkint(lua, 2);
|
||||||
|
short b = luaL_checkint(lua, 3);
|
||||||
|
|
||||||
|
lua_pushboolean(lua, LT_CURSES_OK(init_pair(pair, f, b)));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int lt_curses_COLOR_PAIR(lua_State* lua)
|
||||||
|
{
|
||||||
|
int n = luaL_checkint(lua, 1);
|
||||||
|
lua_pushnumber(lua, COLOR_PAIR(n));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int lt_curses_curs_set(lua_State* lua)
|
||||||
|
{
|
||||||
|
int vis = luaL_checkint(lua, 1);
|
||||||
|
int state = curs_set(vis);
|
||||||
|
if (state == ERR)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
lua_pushnumber(lua, state);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int lt_curses_napms(lua_State* lua)
|
||||||
|
{
|
||||||
|
int ms = luaL_checkint(lua, 1);
|
||||||
|
lua_pushboolean(lua, LT_CURSES_OK(napms(ms)));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int lt_curses_cbreak(lua_State* lua)
|
||||||
|
{
|
||||||
|
if (lua_isnoneornil(lua, 1) || lua_toboolean(lua, 1))
|
||||||
|
lua_pushboolean(lua, LT_CURSES_OK(cbreak()));
|
||||||
|
else
|
||||||
|
lua_pushboolean(lua, LT_CURSES_OK(nocbreak()));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int lt_curses_echo(lua_State* lua)
|
||||||
|
{
|
||||||
|
if (lua_isnoneornil(lua, 1) || lua_toboolean(lua, 1))
|
||||||
|
lua_pushboolean(lua, LT_CURSES_OK(echo()));
|
||||||
|
else
|
||||||
|
lua_pushboolean(lua, LT_CURSES_OK(noecho()));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int lt_curses_nl(lua_State* lua)
|
||||||
|
{
|
||||||
|
if (lua_isnoneornil(lua, 1) || lua_toboolean(lua, 1))
|
||||||
|
lua_pushboolean(lua, LT_CURSES_OK(nl()));
|
||||||
|
else
|
||||||
|
lua_pushboolean(lua, LT_CURSES_OK(nonl()));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int lt_curses_newpad(lua_State* lua)
|
||||||
|
{
|
||||||
|
int nlines = luaL_checkint(lua, 1);
|
||||||
|
int ncols = luaL_checkint(lua, 2);
|
||||||
|
lt_curses_window_new(lua, newpad(nlines, ncols));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
LT_CURSES_NUMBER2(COLS, COLS)
|
||||||
|
LT_CURSES_NUMBER2(LINES, LINES)
|
||||||
|
LT_CURSES_BOOL(isendwin)
|
||||||
|
LT_CURSES_BOOLOK(start_color)
|
||||||
|
LT_CURSES_BOOL(has_colors)
|
||||||
|
LT_CURSES_BOOLOK(doupdate)
|
||||||
|
LT_CURSES_WINDOW_BOOLOK(wclear)
|
||||||
|
LT_CURSES_WINDOW_BOOLOK(wnoutrefresh)
|
||||||
|
|
||||||
|
/* //////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
* globals
|
||||||
|
*/
|
||||||
|
|
||||||
|
static const luaL_Reg g_window_functions[] =
|
||||||
|
{
|
||||||
|
{ "close", lt_curses_window_delwin },
|
||||||
|
{ "keypad", lt_curses_window_keypad },
|
||||||
|
{ "meta", lt_curses_window_meta },
|
||||||
|
{ "nodelay", lt_curses_window_nodelay },
|
||||||
|
{ "leaveok", lt_curses_window_leaveok },
|
||||||
|
{ "move", lt_curses_window_move },
|
||||||
|
{ "clear", lt_curses_window_wclear },
|
||||||
|
{ "noutrefresh",lt_curses_window_wnoutrefresh },
|
||||||
|
{ "attroff", lt_curses_window_attroff },
|
||||||
|
{ "attron", lt_curses_window_attron },
|
||||||
|
{ "attrset", lt_curses_window_attrset },
|
||||||
|
{ "getch", lt_curses_window_getch },
|
||||||
|
{ "getyx", lt_curses_window_getyx },
|
||||||
|
{ "getmaxyx", lt_curses_window_getmaxyx },
|
||||||
|
{ "addch", lt_curses_window_addch },
|
||||||
|
{ "addstr", lt_curses_window_addnstr },
|
||||||
|
{ "copy", lt_curses_window_copywin },
|
||||||
|
{"__gc", lt_curses_window_delwin },
|
||||||
|
{"__tostring", lt_curses_window_tostring },
|
||||||
|
{NULL, NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
static const luaL_Reg g_curses_functions[] =
|
||||||
|
{
|
||||||
|
{ "done", lt_curses_endwin },
|
||||||
|
{ "isdone", lt_curses_isendwin },
|
||||||
|
{ "main_window", lt_curses_stdscr },
|
||||||
|
{ "columns", lt_curses_COLS },
|
||||||
|
{ "lines", lt_curses_LINES },
|
||||||
|
{ "start_color", lt_curses_start_color },
|
||||||
|
{ "has_colors", lt_curses_has_colors },
|
||||||
|
{ "init_pair", lt_curses_init_pair },
|
||||||
|
{ "color_pair", lt_curses_COLOR_PAIR },
|
||||||
|
{ "napms", lt_curses_napms },
|
||||||
|
{ "cursor_set", lt_curses_curs_set },
|
||||||
|
{ "new_pad", lt_curses_newpad },
|
||||||
|
{ "doupdate", lt_curses_doupdate },
|
||||||
|
{ "cbreak", lt_curses_cbreak },
|
||||||
|
{ "echo", lt_curses_echo },
|
||||||
|
{ "nl", lt_curses_nl },
|
||||||
|
#if !defined(XCURSES)
|
||||||
|
#ifndef NOMOUSE
|
||||||
|
{ "mousemask", lt_curses_mousemask },
|
||||||
|
{ "getmouse", lt_curses_getmouse },
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
{NULL, NULL}
|
||||||
|
};
|
||||||
|
|
||||||
|
/* //////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
* implementations
|
||||||
|
*/
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
__export int luaopen_ltui_lcurses(lua_State* lua)
|
||||||
|
{
|
||||||
|
// create new metatable for window objects
|
||||||
|
luaL_newmetatable(lua, LT_CURSES_WINDOW);
|
||||||
|
lua_pushliteral(lua, "__index");
|
||||||
|
lua_pushvalue(lua, -2); /* push metatable */
|
||||||
|
lua_rawset(lua, -3); /* metatable.__index = metatable */
|
||||||
|
luaL_setfuncs(lua, g_window_functions, 0);
|
||||||
|
lua_pop(lua, 1); /* remove metatable from stack */
|
||||||
|
|
||||||
|
// create global table with curses methods/variables/constants
|
||||||
|
lua_newtable(lua);
|
||||||
|
luaL_setfuncs(lua, g_curses_functions, 0);
|
||||||
|
|
||||||
|
// add curses.init()
|
||||||
|
lua_pushstring(lua, "init");
|
||||||
|
lua_pushvalue(lua, -2);
|
||||||
|
lua_pushcclosure(lua, lt_curses_initscr, 1);
|
||||||
|
lua_settable(lua, -3);
|
||||||
|
|
||||||
|
/* Since version 5.4, the ncurses library decides how to interpret non-ASCII data using the nl_langinfo function.
|
||||||
|
* That means that you have to call setlocale() in the application and encode Unicode strings using one of the system’s available encodings.
|
||||||
|
*
|
||||||
|
* And we need link libncursesw.so for drawing vline, hline characters
|
||||||
|
*/
|
||||||
|
#if defined(NCURSES_VERSION)
|
||||||
|
setlocale(LC_ALL, "");
|
||||||
|
#endif
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
3
src/core/curses/xmake.lua
Normal file
3
src/core/curses/xmake.lua
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
target("ltui")
|
||||||
|
add_files("curses.c", {languages = "c99", cflags = "-Wno-expansion-to-defined"})
|
||||||
|
|
@@ -1,20 +0,0 @@
|
|||||||
Author: Tiago Dionizio <tiago.dionizio (AT) gmail.com>
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
a copy of this software and associated documentation files (the
|
|
||||||
"Software"), to deal in the Software without restriction, including
|
|
||||||
without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be
|
|
||||||
included in all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
||||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
||||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
||||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
||||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
||||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
File diff suppressed because it is too large
Load Diff
@@ -1,358 +0,0 @@
|
|||||||
/************************************************************************
|
|
||||||
* Author : Tiago Dionizio (tngd@mega.ist.utl.pt) *
|
|
||||||
* Library : lcurses - Lua 5 interface to the curses library *
|
|
||||||
* *
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining *
|
|
||||||
* a copy of this software and associated documentation files (the *
|
|
||||||
* "Software"), to deal in the Software without restriction, including *
|
|
||||||
* without limitation the rights to use, copy, modify, merge, publish, *
|
|
||||||
* distribute, sublicense, and/or sell copies of the Software, and to *
|
|
||||||
* permit persons to whom the Software is furnished to do so, subject to *
|
|
||||||
* the following conditions: *
|
|
||||||
* *
|
|
||||||
* The above copyright notice and this permission notice shall be *
|
|
||||||
* included in all copies or substantial portions of the Software. *
|
|
||||||
* *
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, *
|
|
||||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
|
|
||||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*
|
|
||||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY *
|
|
||||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, *
|
|
||||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE *
|
|
||||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
|
||||||
************************************************************************/
|
|
||||||
|
|
||||||
/************************************************************************
|
|
||||||
$Id: lpanel.c 17 2007-06-21 15:30:45Z tngd $
|
|
||||||
Changes:
|
|
||||||
|
|
||||||
************************************************************************/
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "lua.h"
|
|
||||||
#include "lauxlib.h"
|
|
||||||
|
|
||||||
#include <panel.h>
|
|
||||||
|
|
||||||
/*
|
|
||||||
** =======================================================
|
|
||||||
** defines
|
|
||||||
** =======================================================
|
|
||||||
*/
|
|
||||||
#define PANELMETA "curses:panel"
|
|
||||||
#define UPINDEX LUA_ENVIRONINDEX
|
|
||||||
|
|
||||||
/* ======================================================= */
|
|
||||||
|
|
||||||
#define LCP_BOOLOK(n) \
|
|
||||||
static int lcp_ ## n(lua_State *L) \
|
|
||||||
{ \
|
|
||||||
PANEL *p = lcp_check(L, 1); \
|
|
||||||
lua_pushboolean(L, B(n(p))); \
|
|
||||||
return 1; \
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** =======================================================
|
|
||||||
** privates
|
|
||||||
** =======================================================
|
|
||||||
*/
|
|
||||||
static void lcp_new(lua_State *L, PANEL *np)
|
|
||||||
{
|
|
||||||
if (np)
|
|
||||||
{
|
|
||||||
PANEL **p = lua_newuserdata(L, sizeof(PANEL*));
|
|
||||||
luaL_getmetatable(L, PANELMETA);
|
|
||||||
lua_setmetatable(L, -2);
|
|
||||||
*p = np;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
lua_pushliteral(L, "failed to create panel");
|
|
||||||
lua_error(L);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static PANEL *lcp_check(lua_State *L, int index)
|
|
||||||
{
|
|
||||||
PANEL **p = (PANEL**)luaL_checkudata(L, 1, PANELMETA);
|
|
||||||
if (p == NULL) luaL_argerror(L, index, "bad curses panel");
|
|
||||||
if (*p == NULL) luaL_argerror(L, index, "attempt to use closed curses panel");
|
|
||||||
return *p;
|
|
||||||
}
|
|
||||||
|
|
||||||
static PANEL **lcp_get(lua_State *L, int index)
|
|
||||||
{
|
|
||||||
PANEL **p = (PANEL**)luaL_checkudata(L, 1, PANELMETA);
|
|
||||||
if (p == NULL) luaL_argerror(L, index, "bad curses panel");
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int lcp_tostring(lua_State *L)
|
|
||||||
{
|
|
||||||
PANEL **p = lcp_get(L, 1);
|
|
||||||
char buff[34];
|
|
||||||
if (*p == NULL)
|
|
||||||
strcpy(buff, "closed");
|
|
||||||
else
|
|
||||||
sprintf(buff, "%p", lua_touserdata(L, 1));
|
|
||||||
lua_pushfstring(L, "curses panel (%s)", buff);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** =======================================================
|
|
||||||
** panel
|
|
||||||
** =======================================================
|
|
||||||
*/
|
|
||||||
|
|
||||||
static int lc_new_panel(lua_State *L)
|
|
||||||
{
|
|
||||||
WINDOW *w = lcw_check(L, 1);
|
|
||||||
lcp_new(L, new_panel(w));
|
|
||||||
|
|
||||||
/* save window userdata for future use if needed */
|
|
||||||
lua_pushlightuserdata(L, w);
|
|
||||||
lua_pushvalue(L, 1);
|
|
||||||
lua_rawset(L, UPINDEX);
|
|
||||||
|
|
||||||
/* save panel userdata for future use if needed */
|
|
||||||
lua_pushlightuserdata(L, *(PANEL**)lua_touserdata(L, 2));
|
|
||||||
lua_pushvalue(L, -2);
|
|
||||||
lua_rawset(L, UPINDEX);
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int lcp_del_panel(lua_State *L)
|
|
||||||
{
|
|
||||||
PANEL **p = lcp_get(L, 1);
|
|
||||||
if (*p != NULL)
|
|
||||||
{
|
|
||||||
/* remove information associated with panel */
|
|
||||||
|
|
||||||
/* remove panel userdata entry */
|
|
||||||
lua_pushlightuserdata(L, *p);
|
|
||||||
lua_pushnil(L);
|
|
||||||
lua_rawset(L, UPINDEX);
|
|
||||||
|
|
||||||
/* remove associated window */
|
|
||||||
lua_pushlightuserdata(L, panel_window(*p));
|
|
||||||
lua_pushnil(L);
|
|
||||||
lua_rawset(L, UPINDEX);
|
|
||||||
|
|
||||||
/* remove panel user data entry */
|
|
||||||
lua_pushvalue(L, 1);
|
|
||||||
lua_pushnil(L);
|
|
||||||
lua_rawset(L, UPINDEX);
|
|
||||||
|
|
||||||
del_panel(*p);
|
|
||||||
*p = NULL;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
LCP_BOOLOK(bottom_panel)
|
|
||||||
LCP_BOOLOK(top_panel)
|
|
||||||
|
|
||||||
static int lcp_show_panel(lua_State *L)
|
|
||||||
{
|
|
||||||
PANEL *p = lcp_check(L, 1);
|
|
||||||
|
|
||||||
if (lua_isnoneornil(L, 2) || lua_toboolean(L, 2))
|
|
||||||
lua_pushboolean(L, B(show_panel(p)));
|
|
||||||
else
|
|
||||||
lua_pushboolean(L, B(hide_panel(p)));
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*LCP_BOOLOK(show_panel)*/
|
|
||||||
LCP_BOOLOK(hide_panel)
|
|
||||||
LCP_BOOLOK(panel_hidden)
|
|
||||||
|
|
||||||
static int lc_update_panels(lua_State *L)
|
|
||||||
{
|
|
||||||
update_panels();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int lcp_panel_window(lua_State *L)
|
|
||||||
{
|
|
||||||
PANEL *p = lcp_check(L, 1);
|
|
||||||
WINDOW *w = panel_window(p);
|
|
||||||
|
|
||||||
/* get window userdata */
|
|
||||||
lua_pushlightuserdata(L, w);
|
|
||||||
lua_rawget(L, UPINDEX);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int lcp_replace_panel(lua_State *L)
|
|
||||||
{
|
|
||||||
PANEL *p = lcp_check(L, 1);
|
|
||||||
WINDOW *w = lcw_check(L, 2);
|
|
||||||
WINDOW *oldw = panel_window(p);
|
|
||||||
|
|
||||||
if (replace_panel(p, w) == ERR)
|
|
||||||
{
|
|
||||||
lua_pushboolean(L, 0);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* remove entry of old window */
|
|
||||||
lua_pushlightuserdata(L, oldw);
|
|
||||||
lua_pushnil(L);
|
|
||||||
lua_rawset(L, UPINDEX);
|
|
||||||
|
|
||||||
/* and save new window */
|
|
||||||
lua_pushlightuserdata(L, oldw);
|
|
||||||
lua_pushvalue(L, 2);
|
|
||||||
lua_rawset(L, UPINDEX);
|
|
||||||
|
|
||||||
lua_pushboolean(L, 1);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int lcp_move_panel(lua_State *L)
|
|
||||||
{
|
|
||||||
PANEL *p = lcp_check(L, 1);
|
|
||||||
int starty = luaL_checkint(L, 2);
|
|
||||||
int startx = luaL_checkint(L, 3);
|
|
||||||
|
|
||||||
lua_pushboolean(L, B(move_panel(p, starty, startx)));
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int lc_bottom_panel(lua_State *L)
|
|
||||||
{
|
|
||||||
PANEL *ap = panel_above(NULL);
|
|
||||||
|
|
||||||
/* get associated userdata variable */
|
|
||||||
lua_pushlightuserdata(L, ap);
|
|
||||||
lua_rawget(L, UPINDEX);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int lcp_panel_above(lua_State *L)
|
|
||||||
{
|
|
||||||
PANEL *p = lcp_check(L, 1);
|
|
||||||
PANEL *ap = panel_above(p);
|
|
||||||
|
|
||||||
/* get associated userdata variable */
|
|
||||||
lua_pushlightuserdata(L, ap);
|
|
||||||
lua_rawget(L, UPINDEX);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int lc_top_panel(lua_State *L)
|
|
||||||
{
|
|
||||||
PANEL *bp = panel_below(NULL);
|
|
||||||
|
|
||||||
/* get associated userdata variable */
|
|
||||||
lua_pushlightuserdata(L, bp);
|
|
||||||
lua_rawget(L, UPINDEX);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int lcp_panel_below(lua_State *L)
|
|
||||||
{
|
|
||||||
PANEL *p = lcp_check(L, 1);
|
|
||||||
PANEL *bp = panel_below(p);
|
|
||||||
|
|
||||||
/* get associated userdata variable */
|
|
||||||
lua_pushlightuserdata(L, bp);
|
|
||||||
lua_rawget(L, UPINDEX);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int lcp_set_panel_userptr(lua_State *L)
|
|
||||||
{
|
|
||||||
lcp_check(L, 1);
|
|
||||||
/* instead of checkinf if we have a user data value,
|
|
||||||
** force it's existance without any side effects */
|
|
||||||
lua_settop(L, 2);
|
|
||||||
lua_rawset(L, UPINDEX);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int lcp_panel_userptr(lua_State *L)
|
|
||||||
{
|
|
||||||
lcp_check(L, 1);
|
|
||||||
lua_pushvalue(L, 1);
|
|
||||||
lua_rawget(L, UPINDEX);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ======================================================= */
|
|
||||||
#define EPF(name) { #name, lcp_ ## name },
|
|
||||||
static const luaL_reg panellib[] =
|
|
||||||
{
|
|
||||||
/* panel */
|
|
||||||
{ "close", lcp_del_panel },
|
|
||||||
|
|
||||||
{ "make_bottom", lcp_bottom_panel },
|
|
||||||
{ "make_top", lcp_top_panel },
|
|
||||||
{ "show", lcp_show_panel },
|
|
||||||
{ "hide", lcp_hide_panel },
|
|
||||||
{ "hidden", lcp_panel_hidden },
|
|
||||||
|
|
||||||
{ "window", lcp_panel_window },
|
|
||||||
{ "replace", lcp_replace_panel },
|
|
||||||
{ "move", lcp_move_panel },
|
|
||||||
|
|
||||||
{ "above", lcp_panel_above },
|
|
||||||
{ "below", lcp_panel_below },
|
|
||||||
|
|
||||||
{ "set_userdata", lcp_set_panel_userptr },
|
|
||||||
{ "userdata", lcp_panel_userptr },
|
|
||||||
|
|
||||||
/* misc */
|
|
||||||
{"__gc", lcp_del_panel}, /* rough safety net */
|
|
||||||
{"__tostring", lcp_tostring},
|
|
||||||
{NULL, NULL}
|
|
||||||
};
|
|
||||||
|
|
||||||
#define ECF(name) { #name, lc_ ## name },
|
|
||||||
static const luaL_reg cursespanellib[] =
|
|
||||||
{
|
|
||||||
/* panel */
|
|
||||||
ECF(new_panel)
|
|
||||||
ECF(update_panels)
|
|
||||||
ECF(bottom_panel)
|
|
||||||
ECF(top_panel)
|
|
||||||
|
|
||||||
/* terminator */
|
|
||||||
{NULL, NULL}
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
** TODO: add upvalue table with lightuserdata keys and weak keyed
|
|
||||||
** values containing WINDOWS and PANELS used in above functions
|
|
||||||
*/
|
|
||||||
int PANEL_EP (lua_State *L)
|
|
||||||
{
|
|
||||||
/* metatable with used panels and associated windows */
|
|
||||||
lua_newtable(L);
|
|
||||||
|
|
||||||
/*
|
|
||||||
** create new metatable for window objects
|
|
||||||
*/
|
|
||||||
luaL_newmetatable(L, PANELMETA);
|
|
||||||
lua_pushliteral(L, "__index");
|
|
||||||
lua_pushvalue(L, -2); /* push metatable */
|
|
||||||
lua_rawset(L, -3); /* metatable.__index = metatable */
|
|
||||||
|
|
||||||
lua_pushvalue(L, -2); /* upvalue table */
|
|
||||||
luaL_openlib(L, NULL, panellib, 1);
|
|
||||||
|
|
||||||
lua_pop(L, 1); /* remove metatable from stack */
|
|
||||||
|
|
||||||
/*
|
|
||||||
** create global table with curses methods/variables/constants
|
|
||||||
*/
|
|
||||||
luaL_openlib(L, NULL, cursespanellib, 1);
|
|
||||||
return 1;
|
|
||||||
}
|
|
@@ -1,5 +0,0 @@
|
|||||||
target("ltui")
|
|
||||||
|
|
||||||
-- add source files
|
|
||||||
add_files("lcurses.c", {languages = "c99", cflags = "-Wno-expansion-to-defined"})
|
|
||||||
|
|
@@ -51,14 +51,6 @@ function program:init(name, argv)
|
|||||||
curses.mousemask(curses.ALL_MOUSE_EVENTS)
|
curses.mousemask(curses.ALL_MOUSE_EVENTS)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- to filter characters being output to the screen
|
|
||||||
-- this will filter all characters where a chtype or chstr is used
|
|
||||||
curses.map_output(true)
|
|
||||||
|
|
||||||
-- on WIN32 ALT keys need to be mapped, so to make sure you get the wanted keys,
|
|
||||||
-- only makes sense when using keypad(true) and echo(false)
|
|
||||||
curses.map_keyboard(true)
|
|
||||||
|
|
||||||
-- init colors
|
-- init colors
|
||||||
if (curses.has_colors()) then
|
if (curses.has_colors()) then
|
||||||
curses.start_color()
|
curses.start_color()
|
||||||
|
Reference in New Issue
Block a user