From b618bfc7cf7eb5fa498a051a17832c2cda4cca9c Mon Sep 17 00:00:00 2001 From: "Kartik K. Agaram" Date: Sat, 20 Nov 2021 16:16:00 -0800 Subject: port changes from minimal to maximal version From lcurseslib.c to lcurses/ directory. --- src/lcurses/curses.c | 46 +---- src/lcurses/curses.lua | 49 +----- src/lcurses/window.c | 14 +- src/lcurseslib.c | 443 ------------------------------------------------- src/lua.c | 26 ++- 5 files changed, 47 insertions(+), 531 deletions(-) diff --git a/src/lcurses/curses.c b/src/lcurses/curses.c index c5f7c3e..303607a 100644 --- a/src/lcurses/curses.c +++ b/src/lcurses/curses.c @@ -111,19 +111,12 @@ Pnew_chstr(lua_State *L) #define CCR(n, v) \ lua_pushstring(L, n); \ lua_pushinteger(L, v); \ - lua_settable(L, lua_upvalueindex(1)) + lua_settable(L, -3); #define CC(s) CCR(#s, s) #define CF(i) CCR(LCURSES_STR(LCURSES_SPLICE(KEY_F, i)), KEY_F(i)) /* -** these values may be fixed only after initialization, so this is -** called from Pinitscr, after the curses driver is initialized -** -** curses table is kept at upvalue position 1, in case the global -** name is changed by the user or even in the registration phase by -** the developer -** ** some of these values are not constant so need to register ** them directly instead of using a table */ @@ -217,8 +210,8 @@ register_curses_constants(lua_State *L) ** proper cleanup) */ -static void -cleanup(void) +void +cleanup_curses(void) { if (!isendwin()) { @@ -229,31 +222,12 @@ cleanup(void) } -/*** -Initialise screen. -@function initscr -@treturn window main screen -@see initscr(3x) -*/ +extern void stack_dump(lua_State *L); static int -Pinitscr(lua_State *L) +init_stdscr(lua_State *L) { - WINDOW *w; - - /* initialize curses */ - w = initscr(); - - /* no longer used, so clean it up */ - lua_pushstring(L, RIPOFF_TABLE); - lua_pushnil(L); - lua_settable(L, LUA_REGISTRYINDEX); - - /* failed to initialize */ - if (w == NULL) - return 0; - /* return stdscr - main window */ - lc_newwin(L, w); + lc_newwin(L, stdscr); /* save main window on registry */ lua_pushstring(L, STDSCR_REGISTRY); @@ -261,10 +235,11 @@ Pinitscr(lua_State *L) 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); + atexit(cleanup_curses); return 1; } @@ -1546,10 +1521,7 @@ luaopen_curses_c(lua_State *L) luaL_register(L, "curses", curseslib); - lua_pushstring(L, "initscr"); - lua_pushvalue(L, -2); - lua_pushcclosure(L, Pinitscr, 1); - lua_settable(L, -3); + init_stdscr(L); return 1; } diff --git a/src/lcurses/curses.lua b/src/lcurses/curses.lua index bba9d12..216fb42 100644 --- a/src/lcurses/curses.lua +++ b/src/lcurses/curses.lua @@ -1,53 +1,20 @@ --- Lua bindings for curses local M = curses --- These Lua functions detect number of args, like Unified Funcs in Perl Curses --- see http://pjb.com.au/comp/lua/lcurses.html --- see http://search.cpan.org/perldoc?Curses - -function M.addch (...) - if #{...} == 3 then - return curses.stdscr():mvaddch(...) - else - return curses.stdscr():addch(...) - end -end - -function M.addstr(...) -- detect number of args, like Unified Funcs in Perl Curses - if #{...} == 3 then - return curses.stdscr():mvaddstr(...) - else - return curses.stdscr():addstr(...) - end -end +function M.addch (c) return curses.stdscr():addch(c) end +function M.mvaddch (y, x, c) return curses.stdscr():mvaddch(y, x, c) end +function M.addstr (s) return curses.stdscr():addstr(s) end +function M.mvaddstr (y, x, s) return curses.stdscr():mvaddstr(y, x, s) end function M.attrset (a) return curses.stdscr():attrset(a) end function M.clear () return curses.stdscr():clear() end function M.clrtobot () return curses.stdscr():clrtobot() end function M.clrtoeol () return curses.stdscr():clrtoeol() end -function M.getch (...) - local c - if #{...} == 2 then - c = curses.stdscr():mvgetch(...) - else - c = curses.stdscr():getch() - end - if c < 256 then - return string.char(c) - end - -- could kludge-test for utf8, e.g. c3 a9 20 c3 aa 20 c3 ab 20 e2 82 ac 0a - return c -end - -function M.getstr (...) - if #{...} > 1 then - return curses.stdscr():mvgetstr(...) - else - return curses.stdscr():getstr(...) - end -end -M.getnstr = M.getstr +function M.getch () return curses.stdscr():getch() end +function M.mvgetch (y, x) return curses.stdscr():getch(y, x) end +function M.getstr (s) return curses.stdscr():getstr(s) end +function M.mvgetstr (y, x, s) return curses.stdscr():mvgetstr(y, x, s) end function M.getyx () return curses.stdscr():getyx() end function M.keypad (b) return curses.stdscr():keypad(b) end diff --git a/src/lcurses/window.c b/src/lcurses/window.c index fd18570..9c243ea 100644 --- a/src/lcurses/window.c +++ b/src/lcurses/window.c @@ -36,8 +36,6 @@ @classmod curses.window */ -//? #include - #include "_helpers.c" #include "chstr.c" @@ -311,10 +309,13 @@ Refresh the window terminal display from the virtual screen. @see curses.doupdate @see noutrefresh */ +extern void draw_menu (lua_State *L); static int Wrefresh(lua_State *L) { - return pushokresult(wrefresh(checkwin(L, 1))); + int result = wrefresh(checkwin(L, 1)); + draw_menu(L); + return pushokresult(result); } @@ -548,6 +549,7 @@ 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; @@ -1302,6 +1304,7 @@ Read a character from the window input. @see curses.echo @see keypad */ +extern void switch_to_editor (lua_State *L, const char *message); static int Wgetch(lua_State *L) { @@ -1310,6 +1313,11 @@ Wgetch(lua_State *L) if (c == ERR) return 0; + if (c == 24) /* ctrl-x */ + exit(0); + if (c == 5) /* ctrl-e */ + switch_to_editor(L, ""); + /* handle other standard menu hotkeys here */ return pushintresult(c); } diff --git a/src/lcurseslib.c b/src/lcurseslib.c index 441a76c..b5173bb 100644 --- a/src/lcurseslib.c +++ b/src/lcurseslib.c @@ -1,21 +1,7 @@ #include -#include #include -#include #include "lua.h" -#include "llimits.h" - -#include "lauxlib.h" -#include "lualib.h" - -void cleanup_curses (void) { - if (!isendwin()) { - wclear(stdscr); - wrefresh(stdscr); - endwin(); - } -} int menu_column = 0; @@ -52,432 +38,3 @@ void draw_menu (lua_State *L) { lua_pop(L, 1); attroff(A_BOLD|A_REVERSE); } - - -static int Prefresh (lua_State *L) { - refresh(); - draw_menu(L); - return 1; -} - - -static int argtypeerror (lua_State *L, int narg, const char *expected) { - const char *got = luaL_typename(L, narg); - return luaL_argerror(L, narg, - lua_pushfstring(L, "%s expected, got %s", expected, got)); -} - - -static void checktype (lua_State *L, int narg, int t, const char *expected) { - if (lua_type(L, narg) != t) - argtypeerror(L, narg, expected); -} - - -static lua_Integer checkinteger (lua_State *L, int narg, const char *expected) { - lua_Integer d = lua_tointeger(L, narg); - if (d == 0 && !lua_isnumber(L, narg)) - argtypeerror(L, narg, expected); - return d; -} - - -static int Pstdscr (lua_State *L) { - lua_pushstring(L, "curses:stdscr"); - lua_rawget(L, LUA_REGISTRYINDEX); - return 1; -} - - -static int Pcolor_pairs (lua_State *L) { - lua_pushinteger(L, COLOR_PAIRS); - return 1; -} - - -static int Pinit_pair (lua_State *L) { - int pair = checkinteger(L, 1, "int"); - short f = checkinteger(L, 2, "int"); - short b = checkinteger(L, 3, "int"); - init_pair(pair, f, b); - return 1; -} - - -static int Pcolor_pair (lua_State *L) -{ - int n = checkinteger(L, 1, "int"); - lua_pushinteger(L, COLOR_PAIR(n)); - return 1; -} - - -extern void switch_to_editor (lua_State *L, const char *message); -static int Pgetch (lua_State *L) { - int c = wgetch(stdscr); - if (c == ERR) - return 0; - if (c == 24) /* ctrl-x */ - exit(0); - if (c == 5) /* ctrl-e */ - switch_to_editor(L, ""); - /* handle other standard menu hotkeys here */ - lua_pushinteger(L, c); - return 1; -} - - -static const struct luaL_Reg curseslib [] = { - {"color_pairs", Pcolor_pairs}, - {"color_pair", Pcolor_pair}, - {"getch", Pgetch}, - {"init_pair", Pinit_pair}, - {"refresh", Prefresh}, - {"stdscr", Pstdscr}, - {NULL, NULL} -}; - - -static void curses_newwin (lua_State *L, WINDOW *nw) { - if (nw) { - WINDOW **w = lua_newuserdata(L, sizeof(WINDOW*)); - luaL_getmetatable(L, "curses:window"); - 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, "curses:window"); - 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; -} - - -static chtype checkch (lua_State *L, int narg) { - if (lua_isnumber(L, narg)) - return cast(chtype, checkinteger(L, narg, "int")); - if (lua_isstring(L, narg)) - return *lua_tostring(L, narg); - - return argtypeerror(L, narg, "int or char"); -} - - -static int optint (lua_State *L, int narg, lua_Integer def) { - if (lua_isnoneornil(L, narg)) - return cast(int, def); - return cast(int, checkinteger(L, narg, "int or nil")); -} - - -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; -} - - -static int Waddstr (lua_State *L) { - WINDOW *w = checkwin(L, 1); - const char *str = luaL_checkstring(L, 2); - int n = optint(L, 3, -1); - lua_pushboolean(L, waddnstr(w, str, n)); - return 1; -} - - -static int Wattroff (lua_State *L) { - WINDOW *w = checkwin(L, 1); - int attrs = checkinteger(L, 2, "int"); - lua_pushboolean(L, wattroff(w, attrs)); - return 1; -} - - -static int Wattron (lua_State *L) { - WINDOW *w = checkwin(L, 1); - int attrs = checkinteger(L, 2, "int"); - lua_pushboolean(L, wattron(w, attrs)); - return 1; -} - - -static int Wclear (lua_State *L) { - lua_pushboolean(L, wclear(checkwin(L, 1))); - return 1; -} - - -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; -} - - -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; -} - - -static int Wmvaddch (lua_State *L) { - WINDOW *w = checkwin(L, 1); - int y = checkinteger(L, 2, "int"); - int x = checkinteger(L, 3, "int"); - chtype ch = checkch(L, 4); - mvwaddch(w, y, x, ch); - return 1; -} - - -static int Wmvaddstr (lua_State *L) { - WINDOW *w = checkwin(L, 1); - int y = checkinteger(L, 2, "int"); - int x = checkinteger(L, 3, "int"); - const char *str = luaL_checkstring(L, 4); - int n = optint(L, 5, -1); - mvwaddnstr(w, y, x, str, n); - return 1; -} - - -static int Wnodelay (lua_State *L) { - WINDOW *w = checkwin(L, 1); - checktype(L, 2, LUA_TBOOLEAN, "boolean or nil"); - int bf = (int)lua_toboolean(L, 2); - lua_pushboolean(L, nodelay(w, bf)); - return 1; -} - - -static const luaL_Reg curses_window_methods[] = -{ - {"__tostring", W__tostring}, - {"addstr", Waddstr}, - {"attroff", Wattroff}, - {"attron", Wattron}, - {"clear", Wclear}, - {"getmaxyx", Wgetmaxyx}, - {"getyx", Wgetyx}, - {"mvaddch", Wmvaddch}, - {"mvaddstr", Wmvaddstr}, - {"nodelay", Wnodelay}, - {NULL, NULL} -}; - - -static void register_curses_constant (lua_State *L, const char* name, int val) { - lua_pushstring(L, name); - lua_pushinteger(L, val); - lua_settable(L, -3); -} - - -static void register_curses_constants (lua_State *L) { -#define CC(s) register_curses_constant(L, #s, s) - /* 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); - CC(A_COLOR); - - /* 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); -#undef CC -} - - -LUALIB_API int luaopen_curses (lua_State *L) { - luaL_newmetatable(L, "curses:window"); - - /* metatable.__index = metatable */ - lua_pushstring(L, "__index"); - lua_pushvalue(L, -2); - lua_settable(L, -3); - - luaL_register(L, NULL, curses_window_methods); - - luaL_register(L, "curses", curseslib); - - /* save main window on registry */ - curses_newwin(L, stdscr); - lua_pushstring(L, "curses:stdscr"); - lua_pushvalue(L, -2); - lua_rawset(L, LUA_REGISTRYINDEX); - - lua_pushvalue(L, -2); - register_curses_constants(L); - - atexit(cleanup_curses); - return 1; -} - diff --git a/src/lua.c b/src/lua.c index 61836e6..ec8818b 100644 --- a/src/lua.c +++ b/src/lua.c @@ -249,30 +249,34 @@ static void dotty (lua_State *L) { void stack_dump (lua_State *L) { int i; int top = lua_gettop(L); + int y = 1; for (i = 1; i <= top; i++) { /* repeat for each level */ int t = lua_type(L, i); switch (t) { case LUA_TSTRING: /* strings */ - printf("`%s'", lua_tostring(L, i)); + mvprintw(y, 30, "`%s'", lua_tostring(L, i)); break; case LUA_TBOOLEAN: /* booleans */ - printf(lua_toboolean(L, i) ? "true" : "false"); + mvprintw(y, 30, lua_toboolean(L, i) ? "true" : "false"); break; case LUA_TNUMBER: /* numbers */ - printf("%g", lua_tonumber(L, i)); + mvprintw(y, 30, "%g", lua_tonumber(L, i)); break; default: /* other values */ - printf("%s", lua_typename(L, t)); + mvprintw(y, 30, "%s", lua_typename(L, t)); break; } - printf(" "); /* put a separator */ + y++; + mvprintw(y, 30, " "); /* put a separator */ + y++; } - printf("\n"); /* end the listing */ + mvprintw(y, 30, "\n"); /* end the listing */ + y++; } @@ -646,13 +650,21 @@ struct Smain { static int pmain (lua_State *L) { struct Smain *s = (struct Smain *)lua_touserdata(L, 1); char **argv = s->argv; + int status; int image; int has_i = 0, has_v = 0, has_e = 0; globalL = L; if (argv[0] && argv[0][0]) progname = argv[0]; lua_gc(L, LUA_GCSTOP, 0); /* stop collector during initialization */ luaL_openlibs(L); /* open libraries */ - dofile(L, "lcurses/curses.lua"); + status = luaL_loadfile(L, "lcurses/curses.lua") || docall(L, /*nargs*/0, /*don't clean up stack*/0); + if (status != 0) return report(L, status); + if (lua_isnil(L, -1)) { + endwin(); + printf("lcurses/curses.lua didn't return a module\n"); + exit(1); + } + lua_setglobal(L, "curses"); lua_gc(L, LUA_GCRESTART, 0); s->status = handle_luainit(L); if (s->status != 0) return 0; -- cgit 1.4.1-2-gfad0