diff options
Diffstat (limited to 'src/lcurses/chstr.c')
-rw-r--r-- | src/lcurses/chstr.c | 293 |
1 files changed, 293 insertions, 0 deletions
diff --git a/src/lcurses/chstr.c b/src/lcurses/chstr.c new file mode 100644 index 0000000..2688155 --- /dev/null +++ b/src/lcurses/chstr.c @@ -0,0 +1,293 @@ +/* + * Curses binding for Lua 5.1, 5.2 & 5.3. + * + * (c) Gary V. Vaughan <gary@vaughan.pe> 2013-2017 + * (c) Reuben Thomas <rrt@sc3d.org> 2009-2012 + * (c) Tiago Dionizio <tiago.dionizio AT gmail.com> 2004-2007 + * + * 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. + */ +/*** +Curses attributed string buffers. + +An array of characters, plus associated curses attributes and +colors at each position. + +Although marginally useful alone, the constants used to set colors +and attributes in `chstr` buffers are not defined until **after** +`curses.initscr ()` has been called. + +@classmod curses.chstr +*/ + +#ifndef LCURSES_CHSTR_C +#define LCURSES_CHSTR_C 1 + +#include "_helpers.c" + + +static const char *CHSTRMETA = "curses:chstr"; + + +typedef struct +{ + unsigned int len; + chtype str[1]; +} chstr; +#define CHSTR_SIZE(len) (sizeof(chstr) + len * sizeof(chtype)) + + +/* create new chstr object and leave it in the lua stack */ +static chstr * +chstr_new(lua_State *L, int len) +{ + chstr *cs; + + if (len < 1) + return luaL_error(L, "invalid chstr length"), NULL; + + cs = lua_newuserdata(L, CHSTR_SIZE(len)); + luaL_getmetatable(L, CHSTRMETA); + lua_setmetatable(L, -2); + cs->len = len; + return cs; +} + + +/* get chstr from lua (convert if needed) */ +static chstr * +checkchstr(lua_State *L, int narg) +{ + chstr *cs = (chstr*)luaL_checkudata(L, narg, CHSTRMETA); + if (cs) + return cs; + + luaL_argerror(L, narg, "bad curses chstr"); + + /*NOTREACHED*/ + return NULL; +} + + +/*** +Change the contents of the chstr. +@function set_str +@int o offset to start of change +@string s characters to insert into *cs* at *o* +@int[opt=A_NORMAL] attr attributes for changed elements +@int[opt=1] rep repeat count +@usage + cs = curses.chstr (10) + cs:set_str(0, "0123456789", curses.A_BOLD) +*/ +static int +Cset_str(lua_State *L) +{ + chstr *cs = checkchstr(L, 1); + int offset = checkint(L, 2); + const char *str = luaL_checkstring(L, 3); + int len = lua_strlen(L, 3); + int attr = optint(L, 4, A_NORMAL); + int rep = optint(L, 5, 1); + int i; + + if (offset < 0) + return 0; + + while (rep-- > 0 && offset <= (int)cs->len) + { + if (offset + len - 1 > (int)cs->len) + len = cs->len - offset + 1; + + for (i = 0; i < len; ++i) + cs->str[offset + i] = str[i] | attr; + offset += len; + } + + return 0; +} + + +/*** +Set a character in the buffer. +*ch* can be a one-character string, or an integer from `string.byte` +@function set_ch +@int o offset to start of change +@param int|string ch character to insert +@int[opt=A_NORMAL] attr attributes for changed elements +@int[opt=1] rep repeat count +@usage + -- Write a bold 'A' followed by normal 'a' chars to a new buffer + size = 10 + cs = curses.chstr (size) + cs:set_ch(0, 'A', curses.A_BOLD) + cs:set_ch(1, 'a', curses.A_NORMAL, size - 1) +*/ +static int +Cset_ch(lua_State *L) +{ + chstr* cs = checkchstr(L, 1); + int offset = checkint(L, 2); + chtype ch = checkch(L, 3); + int attr = optint(L, 4, A_NORMAL); + int rep = optint(L, 5, 1); + + while (rep-- > 0) + { + if (offset < 0 || offset >= (int) cs->len) + return 0; + + cs->str[offset] = ch | attr; + + ++offset; + } + return 0; +} + + +/*** +Get information from the chstr. +@function get +@int o offset from start of *cs* +@treturn int character at offset *o* in *cs* +@treturn int bitwise-OR of attributes at offset *o* in *cs* +@treturn int colorpair at offset *o* in *cs* +@usage + cs = curses.chstr (10) + cs:set_ch(0, 'A', curses.A_BOLD, 10) + --> 65 2097152 0 + print (cs:get (9)) +*/ +static int +Cget(lua_State *L) +{ + chstr* cs = checkchstr(L, 1); + int offset = checkint(L, 2); + chtype ch; + + if (offset < 0 || offset >= (int) cs->len) + return 0; + + ch = cs->str[offset]; + + lua_pushinteger(L, ch & A_CHARTEXT); + lua_pushinteger(L, ch & A_ATTRIBUTES); + lua_pushinteger(L, ch & A_COLOR); + return 3; +} + + +/*** +Retrieve chstr length. +@function len +@tparam chstr cs buffer to act on +@treturn int length of *cs* +@usage + cs = curses.chstr (123) + --> 123 + print (cs:len ()) +*/ +static int +Clen(lua_State *L) +{ + chstr *cs = checkchstr(L, 1); + return pushintresult(cs->len); +} + + +/*** +Duplicate chstr. +@function dup +@treturn chstr duplicate of *cs* +@usage + dup = cs:dup () +*/ +static int +Cdup(lua_State *L) +{ + chstr *cs = checkchstr(L, 1); + chstr *ncs = chstr_new(L, cs->len); + + memcpy(ncs->str, cs->str, CHSTR_SIZE(cs->len)); + return 1; +} + + +/*** +Initialise a new chstr. +@function __call +@int len buffer length +@treturn chstr a new chstr filled with spaces +@usage + cs = curses.chstr (10) +*/ +static int +C__call(lua_State *L) +{ + int len = checkint(L, 2); + chstr* ncs = chstr_new(L, len); + memset(ncs->str, ' ', len * sizeof(chtype)); + return 1; +} + + +static const luaL_Reg curses_chstr_fns[] = +{ + LCURSES_FUNC( Clen ), + LCURSES_FUNC( Cset_ch ), + LCURSES_FUNC( Cset_str ), + LCURSES_FUNC( Cget ), + LCURSES_FUNC( Cdup ), + { NULL, NULL } +}; + + + +LUALIB_API int +luaopen_curses_chstr(lua_State *L) +{ + int t, mt; + + luaL_register(L, "curses.chstr", curses_chstr_fns); + t = lua_gettop(L); + + lua_createtable(L, 0, 1); /* u = {} */ + lua_pushcfunction(L, C__call); + lua_setfield(L, -2, "__call"); /* u.__call = C__call */ + lua_setmetatable(L, -2); /* setmetatable (t, u) */ + + luaL_newmetatable(L, CHSTRMETA); + mt = lua_gettop(L); + + lua_pushvalue(L, mt); + lua_setfield(L, -2, "__index"); /* mt.__index = mt */ + lua_pushliteral(L, "CursesChstr"); + lua_setfield(L, -2, "_type"); /* mt._type = "CursesChstr" */ + + /* for k,v in pairs(t) do mt[k]=v end */ + for (lua_pushnil(L); lua_next(L, t) != 0;) + lua_setfield(L, mt, lua_tostring(L, -2)); + + lua_pop(L, 1); /* pop mt */ + + return 1; +} + +#endif /*!LCURSES_CHSTR_C*/ |