From 52ce195dd00030b84cdc2e2d872438d5d8159102 Mon Sep 17 00:00:00 2001 From: jluehrs2 Date: Fri, 7 Sep 2007 17:52:38 -0500 Subject: working skeleton implementation of the library (no colors yet) --- src/curses.c | 311 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 296 insertions(+), 15 deletions(-) diff --git a/src/curses.c b/src/curses.c index ff90ef5..30ce292 100644 --- a/src/curses.c +++ b/src/curses.c @@ -1,5 +1,18 @@ #include #include +#include +#include +#include +#include + +#define REG_TABLE "luancurses" + +typedef struct _pos { + int x; + int y; +} pos; + +static int ncolors = 1, ncolor_pairs = 1; /* necessary because atexit() expects a function that returns void, and gcc * whines otherwise */ @@ -8,20 +21,47 @@ static void _endwin(void) endwin(); } -static int l_initialize(lua_State* L) +static void init_colors(lua_State* L) { - int ret; + lua_pushinteger(L, COLOR_BLACK); + lua_setfield(L, -2, "black"); + lua_pushinteger(L, COLOR_RED); + lua_setfield(L, -2, "red"); + lua_pushinteger(L, COLOR_GREEN); + lua_setfield(L, -2, "green"); + lua_pushinteger(L, COLOR_YELLOW); + lua_setfield(L, -2, "yellow"); + lua_pushinteger(L, COLOR_BLUE); + lua_setfield(L, -2, "blue"); + lua_pushinteger(L, COLOR_MAGENTA); + lua_setfield(L, -2, "magenta"); + lua_pushinteger(L, COLOR_CYAN); + lua_setfield(L, -2, "cyan"); + lua_pushinteger(L, COLOR_WHITE); + lua_setfield(L, -2, "white"); - /* XXX: do we want to do this? how important is cleaning up? */ - signal(SIGTERM, exit); - atexit(_endwin); - ret = initscr(); - if (has_colors()) { - start_color(); + ncolors = 8; +} + +static pos get_pos(lua_State* L) +{ + pos ret; + + getyx(stdscr, ret.y, ret.x); + + lua_getfield(L, -1, "x"); + if (lua_isnumber(L, -1)) { + ret.x = lua_tonumber(L, -1); } + lua_pop(L, 1); - lua_pushboolean(L, ret == OK); - return 1; + lua_getfield(L, -1, "y"); + if (lua_isnumber(L, -1)) { + ret.y = lua_tonumber(L, -1); + } + lua_pop(L, 1); + + return ret; } static int l_initscr(lua_State* L) @@ -30,15 +70,35 @@ static int l_initscr(lua_State* L) return 1; } +static int l_start_color(lua_State* L) +{ + if (has_colors()) { + lua_getfield(L, LUA_REGISTRYINDEX, REG_TABLE); + lua_newtable(L); + lua_setfield(L, -2, "color_pairs"); + lua_newtable(L); + init_colors(L); + lua_setfield(L, -2, "colors"); + lua_setfield(L, LUA_REGISTRYINDEX, REG_TABLE); + lua_pushboolean(L, start_color() == OK); + } + else { + lua_pushboolean(L, FALSE); + } + + return 1; +} + static int l_setup_term(lua_State* L) { int ret = 0; luaL_checktype(L, 1, LUA_TTABLE); + lua_pushnil(L); - while (lua_next(L, t) != 0) { + while (lua_next(L, 1) != 0) { if (lua_isstring(L, -2)) { - char* str; + const char* str; str = lua_tostring(L, -2); /* XXX: this certainly needs expansion */ @@ -52,7 +112,10 @@ static int l_setup_term(lua_State* L) ret += ((lua_toboolean(L, -1) ? echo() : noecho()) == OK); } else if (!strcmp(str, "keypad")) { - ret += ((keypad(stdscr, lua_toboolean(L, -1))) == OK); + ret += (keypad(stdscr, lua_toboolean(L, -1)) == OK); + } + else if (!strcmp(str, "scroll")) { + ret += (scrollok(stdscr, lua_toboolean(L, -1)) == OK); } else { luaL_error(L, "Unknown or unimplemented terminal mode %s", str); @@ -65,26 +128,244 @@ static int l_setup_term(lua_State* L) return 1; } +static int l_init_color(lua_State* L) +{ + /* test can_change_color here */ + return 0; +} + static int l_init_pair(lua_State* L) { + const char *name, *fg, *bg; + int name_val, fg_val, bg_val; + + /* check the arguments, and get them */ + name = luaL_checklstring(L, 1, NULL); + fg = luaL_optlstring(L, 2, "white", NULL); + bg = luaL_optlstring(L, 3, "black", NULL); + + lua_getfield(L, LUA_REGISTRYINDEX, REG_TABLE); + + /* figure out which pair value to use */ + lua_getfield(L, -1, "color_pairs"); + lua_getfield(L, -1, name); + if (lua_isnil(L, -1)) { + /* if it was nil, we want to set a new value in the color_pairs table, + * and we want to leave that C color_pair value on top of the stack + * for consistency */ + lua_pop(L, 1); + lua_pushinteger(L, ncolor_pairs++); + lua_pushvalue(L, -1); + lua_setfield(L, -3, name); + } + name_val = lua_tointeger(L, -1); + lua_pop(L, 2); + + /* figure out which foreground value to use */ + lua_getfield(L, -1, "colors"); + lua_getfield(L, -1, fg); + if (lua_isnil(L, -1)) { + return luaL_error(L, "init_pair: Trying to use a non-existant foreground color"); + } + fg_val = lua_tointeger(L, -1); + lua_pop(L, 1); + + /* and background value */ + lua_getfield(L, -1, bg); + if (lua_isnil(L, -1)) { + return luaL_error(L, "init_pair: Trying to use a non-existant background color"); + } + bg_val = lua_tointeger(L, -1); + lua_pop(L, 3); + + lua_pushboolean(L, (init_pair(name_val, fg_val, bg_val) == OK)); + return 1; } static int l_getch(lua_State* L) { + int c; + + if (lua_istable(L, 1)) { + pos p; + + p = get_pos(L); + c = mvgetch(p.y, p.x); + } + else { + c = getch(); + } + if (c == ERR) { + lua_pushboolean(L, 0); + return 1; + } + + switch (c) { + case KEY_LEFT: + lua_pushstring(L, "left"); + break; + case KEY_RIGHT: + lua_pushstring(L, "right"); + break; + case KEY_UP: + lua_pushstring(L, "up"); + break; + case KEY_DOWN: + lua_pushstring(L, "down"); + break; + case KEY_HOME: + lua_pushstring(L, "home"); + break; + case KEY_END: + lua_pushstring(L, "end"); + break; + case KEY_BACKSPACE: + lua_pushstring(L, "backspace"); + break; + case KEY_ENTER: + lua_pushstring(L, "enter"); + break; + case KEY_NPAGE: + lua_pushstring(L, "page down"); + break; + case KEY_PPAGE: + lua_pushstring(L, "page up"); + break; + default: + if (c >= KEY_F(1) && c <= KEY_F(64)) { + lua_pushfstring(L, "F%d", c - KEY_F0); + } + else { + char s[1]; + + s[0] = c; + lua_pushlstring(L, s, 1); + } + break; + } + + return 1; } static int l_move(lua_State* L) { + if (lua_istable(L, 1)) { + pos p; + + p = get_pos(L); + lua_pushboolean(L, (move(p.y, p.x) == OK)); + } + else { + int x, y; + + y = luaL_checkinteger(L, 1); + x = luaL_checkinteger(L, 2); + + lua_pushboolean(L, (move(y, x) == OK)); + } + + return 1; } -static int l_addch(lua_State* L) +static int l_addstr(lua_State* L) { + if (lua_istable(L, 1)) { + pos p; + size_t l; + const char* str; + + p = get_pos(L); + str = luaL_checklstring(L, 2, &l); + if (l == 1) { + mvaddch(p.y, p.x, *str); + } + else { + mvaddstr(p.y, p.x, str); + } + } + else { + size_t l; + const char* str; + + str = luaL_checklstring(L, 1, &l); + if (l == 1) { + addch(*str); + } + else { + addstr(str); + } + } + + return 1; } static int l_refresh(lua_State* L) { + lua_pushboolean(L, (refresh() == OK)); + return 1; } -int luaopen_ncurses(lua_State* L) +static int l_getmaxyx(lua_State* L) { + int x, y; + + getmaxyx(stdscr, y, x); + + lua_pushnumber(L, y); + lua_pushnumber(L, x); + return 2; +} + +static int l_getyx(lua_State* L) +{ + int x, y; + + getyx(stdscr, y, x); + + lua_pushnumber(L, y); + lua_pushnumber(L, x); + return 2; +} + +static int l_colors(lua_State* L) +{ + lua_pushinteger(L, COLORS); + return 1; +} + +static int l_color_pairs(lua_State* L) +{ + lua_pushinteger(L, COLOR_PAIRS); + return 1; +} + +const luaL_Reg reg[] = { + { "initscr", l_initscr }, + { "start_color", l_start_color }, + { "setup_term", l_setup_term }, + { "init_color", l_init_color }, + { "init_pair", l_init_pair }, + { "getch", l_getch }, + { "move", l_move }, + { "addstr", l_addstr }, + { "refresh", l_refresh }, + { "getmaxyx", l_getmaxyx }, + { "getyx", l_getyx }, + { "colors", l_colors }, + { "color_pairs", l_color_pairs }, + { NULL, NULL }, +}; + +extern int luaopen_curses(lua_State* L) +{ + /* XXX: do we want to do this? how important is cleaning up? */ + signal(SIGTERM, exit); + atexit(_endwin); + + lua_newtable(L); + lua_setfield(L, LUA_REGISTRYINDEX, REG_TABLE); + + luaL_register(L, "curses", reg); + + return 1; } -- cgit v1.2.3-54-g00ecf