Merge remote branch 'master'
[adg-lua.git] / adg / adg.c
blob50b977e50e4b337d528f87e40e9bbfd51ebac3c3
1 /* adg-lua - lgob based Lua bindings for the ADG canvas
2 * Copyright (C) 2011 Nicola Fontana <ntd at entidi.it>
4 * adg-lua is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License as published
6 * by the Free Software Foundation, either version 3 of the License,
7 * or (at your option) any later version.
9 * adg-lua is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public License
15 * along with adg-lua. If not, see <http://www.gnu.org/licenses/>.
18 #include <lua.h>
19 #include <lauxlib.h>
20 #include <string.h>
22 #include <adg.h>
23 #include <glib-object.h>
24 #include <lgob/common/types.h>
27 static const struct luaL_reg _st__global[];
28 static const struct luaL_reg adg[] = {
29 { NULL, NULL }
33 static void
34 copy_interface(lua_State *L, const char *iface,
35 const char *target, const luaL_Reg *fnames)
37 lua_getfield(L, -1, iface);
38 lua_getfield(L, -2, target);
40 while (fnames->name) {
41 lua_getfield(L, -2, fnames->name);
42 lua_setfield(L, -2, fnames->name);
43 ++ fnames;
46 lua_pop(L, 2);
49 static void
50 object_new(lua_State* L, gpointer ptr, gboolean constructor)
52 /* Remove floating reference: we are in lua, not in C */
53 if (g_object_is_floating(ptr))
54 g_object_ref_sink(ptr);
56 lua_pushliteral(L, "lgobObjectNew");
57 lua_rawget(L, LUA_REGISTRYINDEX);
58 lua_pushlightuserdata(L, ptr);
59 lua_pushboolean(L, constructor);
60 lua_call(L, 2, 1);
63 static void
64 register_class(lua_State *L, const char *name,
65 const char *base, const luaL_Reg *reg)
67 lua_pushstring(L, name);
68 lua_newtable(L);
69 luaL_register(L, NULL, reg);
71 if (base) {
72 lua_newtable(L);
73 lua_pushliteral(L, "__index");
74 lua_pushstring(L, base);
75 lua_rawget(L, -6);
76 lua_rawset(L, -3);
77 lua_setmetatable(L, -2);
80 lua_rawset(L, -3);
83 static void
84 special_type_new(lua_State *L, const gchar *mt, gpointer ptr)
86 Object *object;
88 if (ptr == NULL) {
89 lua_pushnil(L);
90 return;
93 object = lua_newuserdata(L, sizeof(Object));
94 object->pointer = ptr;
95 object->need_unref = TRUE;
96 lua_getfield(L, LUA_REGISTRYINDEX, mt);
97 lua_setmetatable(L, -2);
100 static int
101 special_gc(lua_State *L)
103 Object *object = (Object *) lua_touserdata(L, 1);
105 if (object != NULL) {
106 g_free(object->pointer);
107 object->pointer = NULL;
110 return 0;
113 static gpointer
114 l_checkspecial(lua_State *L, int n)
116 Object *object = (Object *) lua_touserdata(L, n);
117 gpointer pointer = NULL;
119 if (object != NULL)
120 pointer = object->pointer;
122 if (pointer == NULL)
123 luaL_typerror(L, n, "special type");
125 return pointer;
130 * l_checkpairfield:
131 * @L: lua state
132 * @n: index in the stack of the AdgPair
134 * Given an AdgPair special object at index n and a key at index n+1,
135 * returns a pointer to the requested field on the provided instance.
136 * An exception is raised on errors or if the field name is invalid.
138 * Returns: a pointer to the field in the AdgPair instance.
140 static gdouble *
141 l_checkpairfield(lua_State *L, int n)
143 AdgPair *pair = (AdgPair *) l_checkspecial(L, n);
144 const gchar *key = luaL_checkstring(L, n + 1);
146 if (strcmp(key, "x") == 0) {
147 return & pair->x;
148 } else if (strcmp(key, "y") == 0) {
149 return & pair->y;
152 luaL_argerror(L, n + 1, "field not found");
153 return NULL;
156 static int
157 l_pair_index(lua_State *L)
159 gdouble *value = l_checkpairfield(L, 1);
160 lua_pushnumber(L, *value);
161 return 1;
164 static int
165 l_pair_newindex(lua_State *L)
167 gdouble *value = l_checkpairfield(L, 1);
168 *value = lua_tonumber(L, 3);
169 return 0;
172 static int
173 l_pair_tostring(lua_State *L)
175 AdgPair *pair = (AdgPair *) l_checkspecial(L, 1);
176 lua_pushfstring(L, "(%f, %f)", pair->x, pair->y);
177 return 1;
182 * l_checkmatrixfield:
183 * @L: lua state
184 * @n: index in the stack of the AdgMatrix
186 * Given an AdgMatrix special object at index n and a key at index n+1,
187 * returns a pointer to the requested field on the provided instance.
188 * An exception is raised on errors or if the field name is invalid.
190 * Returns: a pointer to the field in the AdgMatrix instance.
192 static gdouble *
193 l_checkmatrixfield(lua_State *L, int n)
195 AdgMatrix *matrix = (AdgMatrix *) l_checkspecial(L, n);
196 const gchar *key = luaL_checkstring(L, n + 1);
198 if (strcmp(key, "xx") == 0) {
199 return & matrix->xx;
200 } else if (strcmp(key, "yx") == 0) {
201 return & matrix->yx;
202 } else if (strcmp(key, "xy") == 0) {
203 return & matrix->xy;
204 } else if (strcmp(key, "yy") == 0) {
205 return & matrix->yy;
206 } else if (strcmp(key, "x0") == 0) {
207 return & matrix->x0;
208 } else if (strcmp(key, "y0") == 0) {
209 return & matrix->y0;
212 luaL_argerror(L, n + 1, "field not found");
213 return NULL;
216 static int
217 l_matrix_index(lua_State *L)
219 gdouble *value = l_checkmatrixfield(L, 1);
220 lua_pushnumber(L, *value);
221 return 1;
224 static int
225 l_matrix_newindex(lua_State *L)
227 gdouble *value = l_checkmatrixfield(L, 1);
228 *value = lua_tonumber(L, 3);
229 return 0;
232 static int
233 l_matrix_tostring(lua_State *L)
235 AdgMatrix *matrix = (AdgMatrix *) l_checkspecial(L, 1);
236 lua_pushfstring(L, "(%f, %f, %f, %f, %f, %f)",
237 matrix->xx, matrix->yx,
238 matrix->xy, matrix->yy,
239 matrix->x0, matrix->y0);
240 return 1;
244 static void
245 _wrap_adg_init(lua_State *L)
247 luaL_register(L, "adg", adg);
248 luaL_register(L, NULL, _st__global);
250 luaL_loadstring(L, "require('lgob.cpml')\n"
251 "require('lgob.gtk')\n"
252 "adg.Object = gobject.Object\n"
253 "adg.InitiallyUnowned = gobject.Object\n");
254 lua_call(L, 0, 0);
256 lua_getfield(L, LUA_REGISTRYINDEX, "lgobPrefix");
257 lua_pushliteral(L, "Adg");
258 lua_pushliteral(L, "adg");
259 lua_rawset(L, -3);
260 lua_pop(L, 1);
262 luaL_loadstring(L, "glib.handle_log('Adg')");
263 lua_call(L, 0, 0);
266 static void
267 _wrap_adg_ret(lua_State *L)
269 static const luaL_reg pair_metamethods[] = {
270 { "__index", l_pair_index },
271 { "__newindex", l_pair_newindex },
272 { "__tostring", l_pair_tostring },
273 { "__gc", special_gc },
274 { NULL, NULL }
276 static const luaL_reg matrix_metamethods[] = {
277 { "__index", l_matrix_index },
278 { "__newindex", l_matrix_newindex },
279 { "__tostring", l_matrix_tostring },
280 { "__gc", special_gc },
281 { NULL, NULL }
284 /* Register AdgPair meta methods */
285 luaL_getmetatable(L, "adgPairMT");
286 luaL_register(L, NULL, pair_metamethods);
287 lua_pop(L, 1);
289 /* Register AdgMatrix meta methods */
290 luaL_getmetatable(L, "adgMatrixMT");
291 luaL_register(L, NULL, matrix_metamethods);
292 lua_pop(L, 1);