about summary refs log tree commit diff stats
path: root/src/lcurses/chstr.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lcurses/chstr.c')
-rw-r--r--src/lcurses/chstr.c293
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*/