161 lines
4.2 KiB
C
161 lines
4.2 KiB
C
/*
|
|
* lbtui.c
|
|
* A Lua library binding for btui, Bruce's Text User Interface library.
|
|
*/
|
|
|
|
#include "lua.h"
|
|
#include "lauxlib.h"
|
|
#include "btui.h"
|
|
|
|
// The C API changed from 5.1 to 5.2, so these shims help the code compile on >=5.2
|
|
#if LUA_VERSION_NUM >= 502
|
|
#define lua_objlen(L, i) lua_rawlen(L, i)
|
|
#define luaL_register(L, _, R) luaL_setfuncs(L, R, 0)
|
|
#endif
|
|
// Lua 5.3 introduced lua_isinteger, fall back to lua_isnumber
|
|
#if LUA_VERSION_NUM < 503
|
|
#define lua_isinteger(L, i) lua_isnumber(L, i)
|
|
#endif
|
|
|
|
const int BTUI_METATABLE;
|
|
|
|
static int Lbtui_enable(lua_State *L)
|
|
{
|
|
btui_t **bt = (btui_t**)lua_touserdata(L, 1);
|
|
if (bt == NULL) luaL_error(L, "Not a BTUI object");
|
|
*bt = btui_enable();
|
|
btui_move_cursor(*bt, 0, 0);
|
|
btui_flush(*bt);
|
|
return 0;
|
|
}
|
|
|
|
static int Lbtui_disable(lua_State *L)
|
|
{
|
|
btui_t **bt = (btui_t**)lua_touserdata(L, 1);
|
|
if (bt == NULL) luaL_error(L, "Not a BTUI object");
|
|
if (*bt == NULL) luaL_error(L, "BTUI object not initialized");
|
|
btui_disable(*bt);
|
|
return 0;
|
|
}
|
|
|
|
static int Lbtui_getkey(lua_State *L)
|
|
{
|
|
btui_t **bt = (btui_t**)lua_touserdata(L, 1);
|
|
if (bt == NULL) luaL_error(L, "Not a BTUI object");
|
|
if (*bt == NULL) luaL_error(L, "BTUI object not initialized");
|
|
int mouse_x = -1, mouse_y = -1;
|
|
int key = btui_getkey(*bt, &mouse_x, &mouse_y);
|
|
if (key == -1) return 0;
|
|
char buf[256] = {0};
|
|
btui_keyname(key, buf);
|
|
lua_pushstring(L, buf);
|
|
if (mouse_x != -1 || mouse_y != -1) {
|
|
lua_pushinteger(L, mouse_x);
|
|
lua_pushinteger(L, mouse_y);
|
|
return 3;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
static int Lbtui_print(lua_State *L)
|
|
{
|
|
btui_t **bt = (btui_t**)lua_touserdata(L, 1);
|
|
if (bt == NULL) luaL_error(L, "Not a BTUI object");
|
|
int n = lua_gettop(L);
|
|
for (int i = 2; i <= n; i++) {
|
|
btui_puts(*bt, luaL_tolstring(L, i, NULL));
|
|
lua_pop(L, 1);
|
|
}
|
|
btui_flush(*bt);
|
|
return 0;
|
|
}
|
|
|
|
static int Lbtui_clear(lua_State *L)
|
|
{
|
|
btui_t **bt = (btui_t**)lua_touserdata(L, 1);
|
|
if (bt == NULL) luaL_error(L, "Not a BTUI object");
|
|
btui_clear(*bt);
|
|
btui_flush(*bt);
|
|
return 0;
|
|
}
|
|
|
|
static int Lbtui_move(lua_State *L)
|
|
{
|
|
btui_t **bt = (btui_t**)lua_touserdata(L, 1);
|
|
if (bt == NULL) luaL_error(L, "Not a BTUI object");
|
|
if (lua_gettop(L) < 3) luaL_error(L, "Expected x and y values");
|
|
int isnum;
|
|
int x = lua_tointegerx(L, 2, &isnum);
|
|
if (!isnum) luaL_error(L, "Expected integer x value");
|
|
int y = lua_tointegerx(L, 3, &isnum);
|
|
if (!isnum) luaL_error(L, "Expected integer y value");
|
|
btui_move_cursor(*bt, x, y);
|
|
btui_flush(*bt);
|
|
return 0;
|
|
}
|
|
|
|
static int Lbtui_width(lua_State *L)
|
|
{
|
|
btui_t **bt = (btui_t**)lua_touserdata(L, 1);
|
|
if (bt == NULL) luaL_error(L, "Not a BTUI object");
|
|
lua_pushinteger(L, (*bt)->width);
|
|
return 1;
|
|
}
|
|
|
|
static int Lbtui_height(lua_State *L)
|
|
{
|
|
btui_t **bt = (btui_t**)lua_touserdata(L, 1);
|
|
if (bt == NULL) luaL_error(L, "Not a BTUI object");
|
|
lua_pushinteger(L, (*bt)->height);
|
|
return 1;
|
|
}
|
|
|
|
static int Lbtui_wrap(lua_State *L)
|
|
{
|
|
if (lua_gettop(L) < 1) luaL_error(L, "expected a callable object");
|
|
btui_t **bt = (btui_t**)lua_newuserdata(L, sizeof(btui_t*));
|
|
lua_pushlightuserdata(L, (void*)&BTUI_METATABLE);
|
|
lua_gettable(L, LUA_REGISTRYINDEX);
|
|
lua_setmetatable(L, -2);
|
|
*bt = btui_enable();
|
|
btui_move_cursor(*bt, 0, 0);
|
|
int status = lua_pcall(L, 1, 0, 0);
|
|
btui_disable(*bt);
|
|
if (status != LUA_OK)
|
|
lua_error(L);
|
|
return 0;
|
|
}
|
|
|
|
static int Lbtui_tostring(lua_State *L)
|
|
{
|
|
lua_pushliteral(L, "<BTUI>");
|
|
return 1;
|
|
}
|
|
|
|
static const luaL_Reg Rclass_metamethods[] =
|
|
{
|
|
{ "__tostring", Lbtui_tostring},
|
|
{ "enable", Lbtui_enable},
|
|
{ "disable", Lbtui_disable},
|
|
{ "getkey", Lbtui_getkey},
|
|
{ "print", Lbtui_print},
|
|
{ "clear", Lbtui_clear},
|
|
{ "move", Lbtui_move},
|
|
{ "width", Lbtui_width},
|
|
{ "height", Lbtui_height},
|
|
{ NULL, NULL}
|
|
};
|
|
|
|
LUALIB_API int luaopen_btui(lua_State *L)
|
|
{
|
|
lua_pushlightuserdata(L, (void*)&BTUI_METATABLE);
|
|
lua_createtable(L, 0, 16);
|
|
luaL_register(L, NULL, Rclass_metamethods);
|
|
lua_pushvalue(L, -1);
|
|
lua_setfield(L, -2, "__index");
|
|
lua_settable(L, LUA_REGISTRYINDEX);
|
|
|
|
lua_pushcfunction(L, Lbtui_wrap);
|
|
return 1;
|
|
}
|