diff options
-rw-r--r-- | include/proto.h | 3 | ||||
-rw-r--r-- | mbbsd/bbslua.c | 126 | ||||
-rw-r--r-- | mbbsd/io.c | 48 |
3 files changed, 172 insertions, 5 deletions
diff --git a/include/proto.h b/include/proto.h index a5371e25..e796f81d 100644 --- a/include/proto.h +++ b/include/proto.h @@ -333,6 +333,8 @@ void set_converting_type(int which); int getdata(int line, int col, const char *prompt, char *buf, int len, int echo); int igetch(void); int wait_input(float f, int flDoRefresh); +int peek_input(float f, int c); +void drop_input(void); int getdata_str(int line, int col, const char *prompt, char *buf, int len, int echo, const char *defaultstr); int getdata_buf(int line, int col, const char *prompt, char *buf, int len, int echo); void add_io(int fd, int timeout); @@ -340,6 +342,7 @@ void oflush(void); int oldgetdata(int line, int col, const char *prompt, char *buf, int len, int echo); void output(const char *s, int len); int num_in_buf(void); +int input_isfull(); int ochar(int c); /* kaede */ diff --git a/mbbsd/bbslua.c b/mbbsd/bbslua.c index 082bc257..2a94ecd9 100644 --- a/mbbsd/bbslua.c +++ b/mbbsd/bbslua.c @@ -8,7 +8,8 @@ // TODO: // 1. add quick key/val conversion // 2. add key values (UP/DOWN/...) -// 3. remove i/o libraries +// 3. remove i/o libraries [done] +// 4. add system break key (Ctrl-C?) ////////////////////////////////////////////////////////////////////////// #include "bbs.h" @@ -26,6 +27,11 @@ #define BLAPI_PROTO int ////////////////////////////////////////////////////////////////////////// +// GLOBAL VARIABLES +////////////////////////////////////////////////////////////////////////// +static int abortBBSLua = 0; + +////////////////////////////////////////////////////////////////////////// // BBSLUA API IMPLEMENTATION ////////////////////////////////////////////////////////////////////////// @@ -101,14 +107,53 @@ bl_addstr(lua_State* L) return 0; } +void +bl_k2s(lua_State* L, int v) +{ + if (v <= 0) + lua_pushnil(L); + else if (v == KEY_TAB) + lua_pushstring(L, "TAB"); + else if (v == '\b' || v == 0x7F) + lua_pushstring(L, "BS"); + else if (v == '\n') + lua_pushstring(L, "ENTER"); + else if (v < ' ') + lua_pushfstring(L, "^%c", v-1+'A'); + else if (v < 0x100) + lua_pushfstring(L, "%c", v); + else if (v >= KEY_F1 && v <= KEY_F12) + lua_pushfstring(L, "F%d", v - KEY_F1 +1); + else switch(v) + { + case KEY_UP: lua_pushstring(L, "UP"); break; + case KEY_DOWN: lua_pushstring(L, "DOWN"); break; + case KEY_RIGHT: lua_pushstring(L, "RIGHT"); break; + case KEY_LEFT: lua_pushstring(L, "LEFT"); break; + case KEY_HOME: lua_pushstring(L, "HOME"); break; + case KEY_END: lua_pushstring(L, "END"); break; + case KEY_INS: lua_pushstring(L, "INS"); break; + case KEY_DEL: lua_pushstring(L, "DEL"); break; + case KEY_PGUP: lua_pushstring(L, "PGUP"); break; + case KEY_PGDN: lua_pushstring(L, "PGDN"); break; + default: lua_pushnil(L); break; + } +} + BLAPI_PROTO bl_igetch(lua_State* L) { int c = igetch(); - lua_pushinteger(L, c); + if (c == Ctrl('C')) + { + abortBBSLua = 1; + return lua_yield(L, 0); + } + bl_k2s(L, c); return 1; } + BLAPI_PROTO bl_getdata(lua_State* L) { @@ -127,6 +172,7 @@ bl_getdata(lua_State* L) if (len >= sizeof(buf)) len = sizeof(buf)-1; + // TODO process Ctrl-C here getyx(&y, &x); len = getdata(y, x, NULL, buf, len, echo); if (len) @@ -143,6 +189,11 @@ bl_vmsg(lua_State* L) s = lua_tostring(L, 1); n = vmsg(s); + if (n == Ctrl('C')) + { + abortBBSLua = 1; + return lua_yield(L, 0); + } lua_pushinteger(L, n); return 1; } @@ -161,6 +212,26 @@ bl_stand_title(lua_State* L) return 0; } +BLAPI_PROTO +bl_ansi_color(lua_State *L) +{ + char buf[PATHLEN] = ESC_STR "["; + char *p = buf + strlen(buf); + int i = 1; + int n = lua_gettop(L); + if (n >= 10) n = 10; + for (i = 1; i <= n; i++) + { + if (i > 1) *p++ = ';'; + sprintf(p, "%d", (int)lua_tointeger(L, i)); + p += strlen(p); + } + *p++ = 'm'; + *p = 0; + lua_pushstring(L, buf); + return 1; +} + ////////////////////////////////////////////////////////////////////////// // BBSLUA LIBRARY ////////////////////////////////////////////////////////////////////////// @@ -186,6 +257,8 @@ static const struct luaL_reg lib_bbslua [] = { { "vmsg", bl_vmsg }, { "pause", bl_vmsg }, { "stand_title",bl_stand_title }, + /* ANSI helpers */ + { "ANSI_COLOR", bl_ansi_color }, { NULL, NULL}, }; @@ -213,25 +286,68 @@ LUALIB_API void myluaL_openlibs (lua_State *L) { } } +static void +bbsluaRegConst(lua_State *L, const char *globName) +{ + lua_getglobal(L, globName); + + lua_pushstring(L, "ESC"); lua_pushstring(L, ESC_STR); + lua_settable(L, -3); + + lua_pushstring(L, "ANSI_RESET"); lua_pushstring(L, ANSI_RESET); + lua_settable(L, -3); + +} + +static void +bbsluaHook(lua_State *L, lua_Debug* ar) +{ + // vmsg("bbslua HOOK!"); + if (ar->event == LUA_HOOKCOUNT) + lua_yield(L, 0); +} int bbslua(const char *fpath) { int r = 0; lua_State *L = lua_open(); + + abortBBSLua = 0; myluaL_openlibs(L); - luaL_openlib(L, "bbs", lib_bbslua, 0); + luaL_openlib(L, "bbs", lib_bbslua, 0); + bbsluaRegConst(L, "bbs"); grayout(0, b_lines, GRAYOUT_DARK); move(b_lines, 0); clrtoeol(); outs("Loading BBS-Lua " BBSLUA_VERSION_STR " ..."); refresh(); - r = luaL_dofile(L, fpath); + if ((r = luaL_loadfile(L, fpath)) == 0) + { + // ready for running + lua_sethook(L, bbsluaHook, LUA_MASKCOUNT, 100 ); + + while (!abortBBSLua && lua_resume(L, 0) == LUA_YIELD) + { + if (input_isfull()) + drop_input(); + + refresh(); + + // check if input key is system break key. + if (peek_input(0.1, Ctrl('C'))) + { + drop_input(); + abortBBSLua = 1; + break; + } + } + } lua_close(L); grayout(0, b_lines, GRAYOUT_DARK); move(b_lines, 0); clrtoeol(); - vmsgf("BBS-Lua: %s", r ? "FAILED" : "OK"); + vmsgf("BBS-Lua: %s", abortBBSLua ? "USER ABORT" : r ? "FAILED" : "OK"); clear(); return 0; @@ -168,6 +168,12 @@ num_in_buf(void) return ibufsize - icurrchar; } +int +input_isfull(void) +{ + return ibufsize >= IBUFSIZE; +} + /* * dogetch() is not reentrant-safe. SIGUSR[12] might happen at any time, and * dogetch() might be called again, and then ibufsize/icurrchar/inbuf might @@ -236,6 +242,17 @@ dogetch(void) if(len > 0) len = input_wrapper(inbuf, len); #endif +#ifdef DBG_OUTRPT + // if (0) + { + static char xbuf[128]; + sprintf(xbuf, ESC_STR "[s" ESC_STR "[2;1H [%ld] " + ESC_STR "[u", len); + write(1, xbuf, strlen(xbuf)); + fsync(1); + } +#endif // DBG_OUTRPT + } while (len <= 0); ibufsize = len; @@ -669,6 +686,37 @@ wait_input(float f, int flDoRefresh) return 1; } +void +drop_input(void) +{ + icurrchar = ibufsize = 0; +} + +int +peek_input(float f, int c) +{ + int i = 0; + assert (c > 0 && c < ' '); // only ^x keys are safe to be detected. + // other keys may fall into escape sequence. + + if (wait_input(f, 0) && (IBUFSIZE > ibufsize)) + { + int len = tty_read(inbuf + ibufsize, IBUFSIZE - ibufsize); +#ifdef CONVERT + if(len > 0) + len = input_wrapper(inbuf+ibufsize, len); +#endif + if (len > 0) + ibufsize += len; + } + for (i = icurrchar; i < ibufsize; i++) + { + if (inbuf[i] == c) + return 1; + } + return 0; +} + #ifdef DBCSAWARE |