1 /*
2   fxasq_lua.c - Lua bindings for fxasq.cpp
3   Copyright (c) 2007-2012 Jeffrey Pohlmeyer <yetanothergeek@gmail.com>
4 
5   This program is free software; you can redistribute it and/or modify
6   it under the terms of the GNU General Public License as published by
7   the Free Software Foundation; either version 2 of the License, or
8   (at your option) any later version.
9 
10   This program is distributed in the hope that it will be useful,
11   but WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13   GNU General Public License for more details.
14 
15   You should have received a copy of the GNU General Public License along
16   with this program; if not, write to the Free Software Foundation, Inc.,
17   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 
19 */
20 
21 
22 #include <stdlib.h>
23 #include <string.h>
24 
25 #include <lua.h>
26 #include <lualib.h>
27 #include <lauxlib.h>
28 
29 #include "fxasq_c.h"
30 
31 #include "intl.h"
32 #include "fxasq_lua.h"
33 
34 #if LUA_VERSION_NUM<502
35 # define lua_rawlen lua_objlen
36 #endif
37 
38 #define DLG_MODULE_NAME "dialog"
39 #define MetaName "_fxasq_metatable"
40 
41 
42 static const char*DialogBoxType="DialogBox";
43 
44 typedef struct _DialogBox {
45   const char*id;
46   FxAsqDlg *dlg;
47 } DialogBox;
48 
49 
50 
todialog(lua_State * L,int argnum)51 static DialogBox* todialog(lua_State *L, int argnum)
52 {
53   DialogBox*rv=(DialogBox*)lua_touserdata(L,argnum);
54   return (rv && (DialogBoxType==rv->id))?rv:NULL;
55 }
56 
57 
58 
59 #define DLG_REQUIRE \
60   DialogBox*D=todialog(L,1); \
61   luaL_argcheck(L,D,1,_("expected DialogBox"))
62 
63 
64 
65 
asq_checkbox(lua_State * L)66 static int asq_checkbox(lua_State *L)
67 {
68   DLG_REQUIRE;
69   const char*label=luaL_checkstring(L,4);
70   luaL_argcheck(L,lua_isboolean(L,3),3,_("expected boolean"));
71   int value=lua_toboolean(L,3);
72   const char*key=luaL_checkstring(L,2);
73   fxasq_checkbox(D->dlg, key,value,label);
74   return 0;
75 }
76 
77 
78 
asq_hr(lua_State * L)79 static int asq_hr(lua_State *L)
80 {
81   DLG_REQUIRE;
82   fxasq_hr(D->dlg);
83   return 0;
84 }
85 
86 
87 
asq_text(lua_State * L)88 static int asq_text(lua_State *L)
89 {
90   DLG_REQUIRE;
91   const char*label=luaL_checkstring(L,4);
92   const char*value=lua_isnil(L,3)?NULL:luaL_checkstring(L,3);
93   const char*key=luaL_checkstring(L,2);
94   fxasq_text(D->dlg, key,value,label);
95   return 0;
96 }
97 
98 
99 
asq_password(lua_State * L)100 static int asq_password(lua_State *L)
101 {
102   DLG_REQUIRE;
103   const char*label=luaL_checkstring(L,4);
104   const char*value=lua_isnil(L,3)?NULL:luaL_checkstring(L,3);
105   const char*key=luaL_checkstring(L,2);
106   fxasq_password(D->dlg, key,value,label);
107   return 0;
108 }
109 
110 
111 
asq_file(lua_State * L)112 static int asq_file(lua_State *L)
113 {
114   DLG_REQUIRE;
115   const char*label=luaL_checkstring(L,4);
116   const char*value=lua_isnil(L,3)?NULL:luaL_checkstring(L,3);
117   const char*key=luaL_checkstring(L,2);
118   fxasq_file(D->dlg, key,value,label);
119   return 0;
120 }
121 
122 
123 
asq_color(lua_State * L)124 static int asq_color(lua_State *L)
125 {
126   DLG_REQUIRE;
127   const char*label=lua_isnil(L,4)?NULL:luaL_checkstring(L,4);
128   const char*value=lua_isnil(L,3)?NULL:luaL_checkstring(L,3);
129   const char*key=luaL_checkstring(L,2);
130   fxasq_color(D->dlg, key,value,label);
131   return 0;
132 }
133 
134 
135 
asq_font(lua_State * L)136 static int asq_font(lua_State *L)
137 {
138   DLG_REQUIRE;
139   const char*label=lua_isnil(L,4)?NULL:luaL_checkstring(L,4);
140   const char*value=lua_isnil(L,3)?NULL:luaL_checkstring(L,3);
141   const char*key=luaL_checkstring(L,2);
142   fxasq_font(D->dlg, key,value,label);
143   return 0;
144 }
145 
146 
147 
asq_textarea(lua_State * L)148 static int asq_textarea(lua_State *L)
149 {
150   DLG_REQUIRE;
151   const char*label=lua_isnil(L,4)?NULL:luaL_checkstring(L,4);
152   const char*value=lua_isnil(L,3)?NULL:luaL_checkstring(L,3);
153   const char*key=luaL_checkstring(L,2);
154   fxasq_textarea(D->dlg, key,value,label);
155   return 0;
156 }
157 
158 
159 
asq_group(lua_State * L)160 static int asq_group(lua_State *L)
161 {
162   DLG_REQUIRE;
163   const char*label=lua_isnil(L,4)?NULL:luaL_checkstring(L,4);
164   const char*value=lua_isnil(L,3)?NULL:luaL_checkstring(L,3);
165   const char*key=luaL_checkstring(L,2);
166   fxasq_group(D->dlg,key,value,label);
167   return 0;
168 }
169 
170 
171 
asq_select(lua_State * L)172 static int asq_select(lua_State *L)
173 {
174   DLG_REQUIRE;
175   const char*label=lua_isnil(L,4)?NULL:luaL_checkstring(L,4);
176   const char*value=lua_isnil(L,3)?NULL:luaL_checkstring(L,3);
177   const char*key=luaL_checkstring(L,2);
178   fxasq_select(D->dlg, key,value,label);
179   return 0;
180 }
181 
182 
183 
asq_radio(lua_State * L)184 static int asq_radio(lua_State *L)
185 {
186   DLG_REQUIRE;
187   const char*label=luaL_checkstring(L,4);
188   const char*value=luaL_checkstring(L,3);
189   const char*key=luaL_checkstring(L,2);
190   fxasq_radio(D->dlg, key,value,label);
191   return 0;
192 }
193 
194 
195 
asq_option(lua_State * L)196 static int asq_option(lua_State *L)
197 {
198   DLG_REQUIRE;
199   const char*label=luaL_checkstring(L,4);
200   const char*value=luaL_checkstring(L,3);
201   const char*key=luaL_checkstring(L,2);
202   fxasq_option(D->dlg,key,value,label);
203   return 0;
204 }
205 
206 
207 
asq_label(lua_State * L)208 static int asq_label(lua_State *L)
209 {
210   DLG_REQUIRE;
211   const char*text=luaL_checkstring(L,2);
212   fxasq_label(D->dlg,text);
213   return 0;
214 }
215 
216 
217 
asq_heading(lua_State * L)218 static int asq_heading(lua_State *L)
219 {
220   DLG_REQUIRE;
221   const char*text=luaL_checkstring(L,2);
222   fxasq_heading(D->dlg,text);
223   return 0;
224 }
225 
226 
227 
asq_new(lua_State * L)228 static int asq_new(lua_State *L) {
229   int argc=lua_gettop(L);
230   FxAsqStr title=NULL;
231   FxAsqStr *btns;
232   int i,n;
233   DialogBox*D;
234   if (argc>=1) {
235     title=luaL_checkstring(L,1);
236   }
237   if (argc>=2) {
238     luaL_argcheck(L,lua_istable(L,2),2,_("expected table"));
239   }
240   n=lua_rawlen(L,2);
241   for (i=1;i<=n; i++) {
242     lua_rawgeti(L,2,i);
243     char msg[64];
244     memset(msg,0,sizeof(msg));
245     snprintf(msg,sizeof(msg)-1, _("table element #%d is not a string"), i);
246     luaL_argcheck(L,lua_isstring(L, -1),2,msg);
247     lua_pop(L, 1);
248   }
249   btns=(const char**)calloc(sizeof(char*)*(n+1), 1);
250   for (i=1;i<=n; i++) {
251     lua_rawgeti(L,2,i);
252     btns[i-1]=lua_tostring(L, -1);
253     lua_pop(L, 1);
254   }
255   D=(DialogBox*)lua_newuserdata(L,sizeof(DialogBox));
256   luaL_getmetatable(L, MetaName);
257   lua_setmetatable(L, -2);
258   D->id=DialogBoxType;
259   D->dlg=fxasq_new(title,btns);
260   free(btns);
261   return 1;
262 }
263 
264 
265 
asq_run(lua_State * L)266 static int asq_run(lua_State *L)
267 {
268   int rv=-1;
269   FxAsqItem *results;
270   DLG_REQUIRE;
271   results=fxasq_run(D->dlg, &rv, L);
272   lua_pushnumber(L,(rv+1));
273   if (results) {
274     FxAsqItem*p;
275     lua_newtable(L);
276     for (p=results; p; p=p->next) {
277       lua_pushstring(L, p->key);
278       lua_pushstring(L, p->value);
279       lua_rawset(L,-3);
280     }
281     fxasq_free_results(results);
282     return 2;
283   }
284   return 1;
285 }
286 
287 
288 
asq_done(lua_State * L)289 static int asq_done(lua_State *L)
290 {
291   DialogBox*D;
292   if (lua_isnil(L, 1)) {
293     return 0;
294   }
295   D=(DialogBox*)lua_touserdata(L,1);
296   if (D->id!=DialogBoxType) {
297 
298     return 1;
299   }
300   fxasq_free(D->dlg);
301   return 1;
302 }
303 
304 
305 
306 
307 static const struct luaL_Reg asq_funcs[] = {
308   {"new",      asq_new},
309   {"run",      asq_run},
310   {"label",    asq_label},
311   {"text",     asq_text},
312   {"select",   asq_select},
313   {"option",   asq_option},
314   {"group",    asq_group},
315   {"radio",    asq_radio},
316   {"password", asq_password},
317   {"heading",  asq_heading},
318   {"checkbox", asq_checkbox},
319   {"hr",       asq_hr},
320   {"textarea", asq_textarea},
321   {"file",     asq_file},
322   {"color",    asq_color},
323   {"font",     asq_font},
324   {0,0}
325 };
326 
327 
328 
luaopen_dialog(lua_State * L)329 int luaopen_dialog(lua_State *L)
330 {
331   luaL_newmetatable(L, MetaName);
332   lua_pushstring(L, "__index");
333   lua_pushvalue(L, -2);
334   lua_settable(L, -3);
335 
336   lua_pushstring(L,"__gc");
337   lua_pushcfunction(L,asq_done);
338   lua_rawset(L,-3);
339 
340 #if LUA_VERSION_NUM < 502
341   luaL_Register(L, NULL, &asq_funcs[1]);
342   luaL_Register(L, DLG_MODULE_NAME, asq_funcs);
343 #else
344   luaL_setfuncs(L,asq_funcs,0);
345 #endif
346   return 1;
347 }
348