1 /////////////////////////////////////////////////////////////////////////////
2 // Name: wxlstate.cpp
3 // Purpose: wxLuaState, a wxWidgets interface to Lua
4 // Author: Ray Gilbert, John Labenski, J Winwood (Reuben Thomas for bitlib at bottom)
5 // Created: 14/11/2001
6 // Copyright: (c) 2012 John Labenski, 2001-2002 Lomtick Software. All rights reserved.
7 // Licence: wxWidgets licence
8 /////////////////////////////////////////////////////////////////////////////
9
10 // For compilers that support precompilation, includes "wx/wx.h"
11 #include <wx/wxprec.h>
12
13 #ifdef __BORLANDC__
14 #pragma hdrstop
15 #endif
16
17 // for all others, include the necessary headers
18 #ifndef WX_PRECOMP
19 #include <wx/wx.h>
20 #endif
21
22 #include "wxlua/wxllua.h"
23 #include "wxlua/wxlstate.h"
24 #include "wxlua/wxlbind.h"
25 #include "wxlua/wxlcallb.h"
26
27 //#include "wxluadebug/include/wxldebug.h" // for debugging only
28
29 const char* wxlua_lreg_regtable_key = "wxlua_lreg_regtable_key : wxLua LUA_REGISTRYINDEX tables";
30
31 const char* wxlua_lreg_wxluastate_key = "wxlua_lreg_wxluastate_key : wxLuaState";
32 const char* wxlua_lreg_wxluastatedata_key = "wxlua_lreg_wxluastatedata_key : wxLuaStateData";
33
34 const char* wxlua_lreg_wxluabindings_key = "wxlua_lreg_wxluabindings_key : wxLuaBindings installed";
35 const char* wxlua_lreg_classes_key = "wxlua_lreg_classes_key : wxLuaBindClass structs installed";
36 const char* wxlua_lreg_types_key = "wxlua_lreg_types_key : wxLua metatable class types";
37
38 const char* wxlua_lreg_weakobjects_key = "wxlua_lreg_weakobjects_key : wxLua objects pushed";
39 const char* wxlua_lreg_gcobjects_key = "wxlua_lreg_gcobjects_key : wxLua gc objects to delete";
40 const char* wxlua_lreg_derivedmethods_key = "wxlua_lreg_derivedmethods_key : wxLua derived class methods";
41 const char* wxlua_lreg_evtcallbacks_key = "wxlua_lreg_evtcallbacks_key : wxLuaEventCallbacks";
42 const char* wxlua_lreg_windestroycallbacks_key = "wxlua_lreg_windestroycallbacks_key : wxLuaWinDestoyCallbacks";
43 const char* wxlua_lreg_topwindows_key = "wxlua_lreg_topwindows_key : wxLua top level wxWindows";
44 const char* wxlua_lreg_wxeventtype_key = "wxlua_lreg_wxeventtype_key : wxLua wxEventType";
45 const char* wxlua_lreg_callbaseclassfunc_key = "wxlua_lreg_callbaseclassfunc_key : wxLua CallBaseClassFunc";
46
47 const char* wxlua_lreg_refs_key = "wxlua_lreg_refs_key : wxLua Lua object refs";
48 const char* wxlua_lreg_debug_refs_key = "wxlua_lreg_debug_refs_key : wxLuaDebugData refs";
49
50 const char* wxlua_metatable_type_key = "wxlua_metatable_type_key : wxLua metatable class type";
51 const char* wxlua_metatable_wxluabindclass_key = "wxlua_metatable_wxluabindclass_key : wxLua metatable wxLuaBindClass";
52
53 // ----------------------------------------------------------------------------
54
wxlua_lreg_createtable(lua_State * L,void * lightuserdata_reg_key,int narr,int nrec)55 void wxlua_lreg_createtable(lua_State* L, void* lightuserdata_reg_key, int narr, int nrec)
56 {
57 // clear the old ref to the table, even though it's weak kv
58 // it doesn't get cleared until the gc runs
59 lua_pushlightuserdata(L, &wxlua_lreg_regtable_key); // push key
60 lua_rawget(L, LUA_REGISTRYINDEX); // get table
61 lua_pushlightuserdata(L, lightuserdata_reg_key); // push key
62 lua_rawget(L, LUA_REGISTRYINDEX); // get table or nil
63 if (lua_istable(L, -1))
64 {
65 lua_pushnil(L); // push value
66 lua_rawset(L, -3); // clear t[key] = nil
67 lua_pop(L, 1); // pop wxlua_lreg_regtable_key table
68 }
69 else
70 lua_pop(L, 2); // pop nil and wxlua_lreg_regtable_key table
71
72 // Add new LUA_REGISTRYINDEX[&wxlua_lreg_regtable_key][lightuserdata_reg_key table] = lightuserdata_reg_key
73 lua_pushlightuserdata(L, lightuserdata_reg_key); // push key
74 lua_createtable(L, narr, nrec); // push value
75 lua_pushlightuserdata(L, &wxlua_lreg_regtable_key); // push key
76 lua_rawget(L, LUA_REGISTRYINDEX); // get wxlua_lreg_regtable_key table
77 lua_pushvalue(L, -2); // push key (copy of the new table)
78 lua_pushvalue(L, -4); // push value (copy of lightuserdata key)
79 lua_rawset(L, -3); // set t[key] = value; pops key and value
80 lua_pop(L, 1); // pop wxlua_lreg_regtable_key table
81 lua_rawset(L, LUA_REGISTRYINDEX); // set the value
82 }
83
84 // ----------------------------------------------------------------------------
85 // Lua helper functions
86 // ----------------------------------------------------------------------------
87
wxlua_LUA_ERR_msg(int LUA_ERRx)88 wxString wxlua_LUA_ERR_msg(int LUA_ERRx)
89 {
90 switch (LUA_ERRx)
91 {
92 case 0 : return wxEmptyString;
93 case LUA_YIELD : return wxT("Lua: Thread is suspended");
94 case LUA_ERRRUN : return wxT("Lua: Error while running chunk");
95 case LUA_ERRSYNTAX : return wxT("Lua: Syntax error during pre-compilation");
96 case LUA_ERRMEM : return wxT("Lua: Memory allocation error");
97 case LUA_ERRERR : return wxT("Lua: Generic error or an error occurred while running the error handler");
98 case LUA_ERRFILE : return wxT("Lua: Error occurred while opening file");
99 }
100
101 return wxT("Lua: Unknown LUA_ERRx error value");
102 }
103
wxlua_errorinfo(lua_State * L,int status,int top,wxString * errorMsg_,int * line_num_)104 bool wxlua_errorinfo(lua_State* L, int status, int top, wxString* errorMsg_, int* line_num_)
105 {
106 if (status == 0)
107 return false;
108
109 int newtop = lua_gettop(L);
110
111 wxString errorMsg = wxlua_LUA_ERR_msg(status);
112
113 switch(status)
114 {
115 case LUA_ERRMEM:
116 case LUA_ERRERR:
117 {
118 if (newtop > top)
119 errorMsg += wxT("\n");
120 break;
121 }
122 case LUA_ERRRUN:
123 case LUA_ERRFILE:
124 case LUA_ERRSYNTAX:
125 default:
126 {
127 if (newtop > top)
128 errorMsg += wxT("\n") + lua2wx(lua_tostring(L, -1));
129 break;
130 }
131 }
132
133 errorMsg += wxT("\n");
134
135 // Why can't I fill a lua_Debug here? Try to get the line number
136 // by parsing the error message that looks like this, 3 is linenumber
137 // [string "a = 1("]:3: unexpected symbol near `<eof>'
138 wxString lineStr = errorMsg;
139 long line_num = -1;
140 while(!lineStr.IsEmpty())
141 {
142 // search through the str to find ']:LONG:' pattern
143 lineStr = lineStr.AfterFirst(wxT(']'));
144 if ((lineStr.Length() > 0) && (lineStr.GetChar(0) == wxT(':')))
145 {
146 lineStr = lineStr.AfterFirst(wxT(':'));
147 if (lineStr.IsEmpty() || lineStr.BeforeFirst(wxT(':')).ToLong(&line_num))
148 break;
149 }
150 }
151
152 lua_settop(L, top); // pops the message if any
153
154 if (errorMsg_) *errorMsg_ = errorMsg;
155 if (line_num_) *line_num_ = (int)line_num;
156
157 return true;
158 }
159
wxlua_error(lua_State * L,const char * errorMsg)160 void LUACALL wxlua_error(lua_State *L, const char *errorMsg)
161 {
162 // Use luaL_error(L, s) and not "lua_pushstring(L, s); lua_error(L)" since
163 // luaL_error() provides the file and line number too.
164 luaL_error(L, "%s", errorMsg);
165 }
166
wxlua_argerror(lua_State * L,int stack_idx,const wxString & expectedType)167 void LUACALL wxlua_argerror(lua_State *L, int stack_idx, const wxString& expectedType)
168 {
169 wxString argType = wxlua_luaL_typename(L, stack_idx);
170
171 wxString msg(wxString::Format(_("wxLua: Expected %s for parameter %d, but got a '%s'."),
172 expectedType.c_str(), stack_idx, argType.c_str()));
173
174 wxlua_argerrormsg(L, msg);
175 }
176
wxlua_argerrormsg(lua_State * L,const wxString & msg_)177 void LUACALL wxlua_argerrormsg(lua_State *L, const wxString& msg_)
178 {
179 wxString funcArgs(wxT("\n"));
180 wxString argMsg = wxlua_getLuaArgsMsg(L, 1, lua_gettop(L));
181
182 wxLuaBindMethod* wxlMethod = (wxLuaBindMethod *)lua_touserdata(L, lua_upvalueindex(1)); // lightuserdata
183 if (wxlMethod != NULL)
184 {
185 // Guarantee that this is a wxLuaBindMethod of ours so we don't crash.
186 // Since we're going to error out we don't have to be quick about it.
187
188 // check if this method is part of a class
189 const wxLuaBindClass* wxlClass = wxLuaBinding::FindBindClass(wxlMethod);
190
191 // if not, check if it's a global C style function
192 wxLuaBinding* binding = NULL;
193 if (wxlClass == NULL)
194 binding = wxLuaBinding::FindMethodBinding(wxlMethod);
195
196 if ((wxlClass != NULL) || (binding != NULL))
197 funcArgs += wxlua_getBindMethodArgsMsg(L, wxlMethod);
198 }
199
200 wxString msg;
201 msg.Printf(wxT("%s\nFunction called: '%s'%s"), msg_.c_str(), argMsg.c_str(), funcArgs.c_str());
202 wxlua_error(L, msg.c_str());
203 }
204
wxlua_touserdata(lua_State * L,int stack_idx,bool null_ptr)205 void* LUACALL wxlua_touserdata(lua_State *L, int stack_idx, bool null_ptr /*= false*/)
206 {
207 if (lua_islightuserdata(L, stack_idx) != 0)
208 {
209 // can't NULL the ptr, just return the lightuserdata as is
210 return lua_touserdata(L, stack_idx);
211 }
212
213 void *pdata = NULL;
214 void **ptr = (void **)lua_touserdata(L, stack_idx);
215
216 if (ptr != NULL)
217 {
218 pdata = *ptr; // get the pointer the userdata holds
219 if (null_ptr) // NULL ptr so Lua won't try to gc it
220 *ptr = NULL;
221 }
222
223 return pdata;
224 }
225
226 // ----------------------------------------------------------------------------
227 // wxluaR_XXX - functions operate on tables in Lua's LUA_REGISTRYINDEX
228 // ----------------------------------------------------------------------------
229
230 #define ABS_LUA_STKIDX(n, added_items) ((n) > 0 ? (n) : (n)-(added_items))
231
232 // Note about luaL_ref() and luaL_unref().
233 // ref creates integer numbers from 1 to ...
234 // unref uses t[0] to hold the last unused reference and when you call unref
235 // again the next unused ref points back to the first and t[0] points to the
236 // last unrefed key.
237 // eg. create 5 refs, get refs 1,2,3,4,5, then call unref on 3 then 4 then
238 // call ref 3 times and the new references will be 4, 3, 6
239
wxluaR_ref(lua_State * L,int stack_idx,void * lightuserdata_reg_key)240 int wxluaR_ref(lua_State* L, int stack_idx, void* lightuserdata_reg_key)
241 {
242 // nothing on stack to insert and don't bother inserting nil
243 if (lua_isnoneornil(L, stack_idx))
244 return LUA_REFNIL;
245
246 lua_pushlightuserdata(L, lightuserdata_reg_key); // push key
247 lua_rawget(L, LUA_REGISTRYINDEX); // pop key, push value (table)
248
249 lua_pushvalue(L, ABS_LUA_STKIDX(stack_idx,1)); // push value to store
250
251 int ref_idx = luaL_ref(L, -2); // t[ref_idx] = value; pops value
252
253 // We also store t[value] = table_idx for this table for faster lookup
254 if (lightuserdata_reg_key == &wxlua_lreg_debug_refs_key)
255 {
256 lua_pushvalue(L, ABS_LUA_STKIDX(stack_idx,1)); // push key
257 lua_pushnumber(L, ref_idx); // push value
258 lua_rawset(L, -3); // set t[key] = value; pops key and value
259 }
260
261 lua_pop(L, 1); // pop table
262
263 return ref_idx;
264 }
265
wxluaR_unref(lua_State * L,int ref_idx,void * lightuserdata_reg_key)266 bool wxluaR_unref(lua_State* L, int ref_idx, void* lightuserdata_reg_key)
267 {
268 if (ref_idx == LUA_REFNIL) // nothing to remove
269 return false;
270
271 lua_pushlightuserdata(L, lightuserdata_reg_key); // push key
272 lua_rawget(L, LUA_REGISTRYINDEX); // pop key, push value (table)
273
274 // Also remove the t[value] = table_idx for this table
275 if (lightuserdata_reg_key == &wxlua_lreg_debug_refs_key)
276 {
277 lua_pushnumber(L, ref_idx); // push key
278 lua_rawget(L, -2); // get t[key] = value; pop key, push value;
279
280 lua_pushnil(L);
281 lua_rawset(L, -3); // t[value] = nil; pops key and value
282 }
283
284 luaL_unref(L, -1, ref_idx); // remove key and value in refs table
285 // note: this key will be used for the next wxluaR_ref()
286
287 lua_pop(L, 1); // pop table
288
289 return true;
290 }
291
wxluaR_getref(lua_State * L,int ref_idx,void * lightuserdata_reg_key)292 bool LUACALL wxluaR_getref(lua_State *L, int ref_idx, void* lightuserdata_reg_key)
293 {
294 if (ref_idx == LUA_REFNIL) // nothing to get
295 return false;
296
297 lua_pushlightuserdata(L, lightuserdata_reg_key); // push key
298 lua_rawget(L, LUA_REGISTRYINDEX); // pop key, push value (table)
299
300 lua_rawgeti(L, -1, ref_idx); // get t[ref_idx] = value; push value
301
302 if (lua_isnil(L, -1)) // not a valid table key
303 {
304 lua_pop(L, 2); // pop nil and table
305 return false;
306 }
307
308 lua_remove(L, -2); // remove table, leaving value on top
309
310 return true; // return if table has a valid value and it's on the stack
311 }
312
wxluaR_isrefed(lua_State * L,int stack_idx,void * lightuserdata_reg_key)313 int LUACALL wxluaR_isrefed(lua_State* L, int stack_idx, void* lightuserdata_reg_key)
314 {
315 int ref_idx = LUA_NOREF;
316
317 lua_pushlightuserdata(L, lightuserdata_reg_key); // push key
318 lua_rawget(L, LUA_REGISTRYINDEX); // pop key, push value (table)
319
320 if (lightuserdata_reg_key == &wxlua_lreg_debug_refs_key)
321 {
322 // For this table we've pushed the value for a faster lookup
323 lua_pushvalue(L, ABS_LUA_STKIDX(stack_idx,1)); // push key (the value)
324 lua_rawget(L, -2); // get t[key] = value; pop key push value
325 ref_idx = (int)lua_tonumber(L, -1);
326
327 if ((ref_idx == 0) && !lua_isnumber(L, -1)) // if !isnumber it returns 0 (faster)
328 ref_idx = LUA_NOREF;
329
330 lua_pop(L, 2); // pop object we pushed and the ref table
331 }
332 else
333 {
334 // otherwise search through all the values
335 lua_pushnil(L);
336 while (lua_next(L, -2) != 0)
337 {
338 // value = -1, key = -2, table = -3, object = stack_idx before 3 added items
339 if (lua_equal(L, -1, ABS_LUA_STKIDX(stack_idx,3)))
340 {
341 ref_idx = (int)lua_tonumber(L, -2);
342 lua_pop(L, 2); // pop key, value
343 break;
344 }
345 else
346 lua_pop(L, 1); // pop value, lua_next will pop key at end
347 }
348
349 lua_pop(L, 1); // pop ref table
350 }
351
352 return ref_idx;
353 }
354
355 // ----------------------------------------------------------------------------
356 // wxluaO_XXX - functions operate on the "Objects"
357 // ----------------------------------------------------------------------------
358
wxluaO_addgcobject(lua_State * L,void * obj_ptr,int wxl_type)359 bool LUACALL wxluaO_addgcobject(lua_State *L, void *obj_ptr, int wxl_type)
360 {
361 lua_pushlightuserdata(L, &wxlua_lreg_gcobjects_key); // push key
362 lua_rawget(L, LUA_REGISTRYINDEX); // pop key, push value (table)
363
364 // Check if it's already tracked since that means the weak udata table isn't working right
365 lua_pushlightuserdata(L, obj_ptr); // push key
366 lua_rawget(L, -2); // get t[key] = value, pops key
367
368 if (!lua_isnil(L, -1))
369 {
370 lua_pop(L, 2); // pop table and value
371 wxCHECK_MSG(false, false, wxT("Tracking an object twice in wxluaO_addgcobject: ") + wxluaT_typename(L, wxl_type));
372 return false;
373 }
374
375 lua_pop(L, 1); // pop nil
376
377 // Then add it
378 lua_pushlightuserdata(L, obj_ptr); // push key
379 lua_pushnumber(L, wxl_type); // push value
380 lua_rawset(L, -3); // set t[key] = value, pops key and value
381
382 lua_pop(L, 1); // pop table
383
384 return true;
385 }
386
wxluaO_deletegcobject(lua_State * L,int stack_idx,int flags)387 bool LUACALL wxluaO_deletegcobject(lua_State *L, int stack_idx, int flags)
388 {
389 void* udata = lua_touserdata(L, stack_idx);
390 void* obj_ptr = wxlua_touserdata(L, stack_idx, true); // clear lua userdata's ptr
391
392 if (obj_ptr == NULL) return false; // can happen
393
394 bool delete_all = WXLUA_HASBIT(flags, WXLUA_DELETE_OBJECT_ALL);
395
396 wxLuaBindClass *wxlClass = NULL;
397
398 if (lua_getmetatable(L, stack_idx))
399 {
400 lua_pushlightuserdata(L, &wxlua_metatable_wxluabindclass_key); // push key
401 lua_rawget(L, -2); // get t[key] = value; pop key push value
402 wxlClass = (wxLuaBindClass *)lua_touserdata(L, -1);
403 lua_pop(L, 2); // pop metatable and lightuserdata value
404 }
405
406 // Remove the weak ref to it, will optionally clear all the metatables
407 // for an userdata created for this object to make them unusable.
408 int udata_count = wxluaO_untrackweakobject(L, delete_all ? NULL : udata, obj_ptr);
409
410 if (delete_all || (udata_count < 1))
411 {
412 // remove any derived methods attached to this object
413 wxlua_removederivedmethods(L, obj_ptr);
414
415 // check if we are really supposed to delete it
416 lua_pushlightuserdata(L, &wxlua_lreg_gcobjects_key); // push key
417 lua_rawget(L, LUA_REGISTRYINDEX); // pop key, push value (table)
418
419 lua_pushlightuserdata(L, obj_ptr); // push key
420 lua_rawget(L, -2); // get t[key] = value, pops key
421
422 if (wxlClass && lua_isnumber(L, -1)) // the wxLua type for it
423 {
424 lua_pop(L, 1); // pop number value
425
426 lua_pushlightuserdata(L, obj_ptr); // push key
427 lua_pushnil(L); // push value
428 lua_rawset(L, -3); // set t[key] = value, pops key and value
429
430 lua_pop(L, 1); // pop delobj table
431
432 // delete the object using the function stored in the wxLuaBindClass
433 if (obj_ptr)
434 wxlClass->delete_fn(&obj_ptr);
435 else
436 return false;
437
438 return true;
439 }
440 else
441 {
442 // no error message since we're called from wxlua_wxLuaBindClass__gc
443 // automatically for all our objects and this table stores which ones to delete
444 // so we don't want to have to check first and then call this.
445 lua_pop(L, 2); // pop nil and delobj
446 }
447 }
448
449 return false;
450 }
451
wxluaO_undeletegcobject(lua_State * L,void * obj_ptr)452 bool LUACALL wxluaO_undeletegcobject(lua_State *L, void *obj_ptr)
453 {
454 if (obj_ptr == NULL) return false;
455
456 lua_pushlightuserdata(L, &wxlua_lreg_gcobjects_key); // push key
457 lua_rawget(L, LUA_REGISTRYINDEX); // pop key, push value (table)
458
459 lua_pushlightuserdata(L, obj_ptr); // push key
460 lua_rawget(L, -2); // get t[key] = value, pops key
461
462 if (lua_isnumber(L, -1)) // is the wxLua type of the object
463 {
464 lua_pop(L, 1); // pop number
465
466 lua_pushlightuserdata(L, obj_ptr); // push key
467 lua_pushnil(L); // push value
468 lua_rawset(L, -3); // set t[key] = value, pops key and value
469
470 lua_pop(L, 1); // pop delobj table
471 return true;
472 }
473 else
474 lua_pop(L, 2); // pop nil and gcobject table
475
476 return false;
477 }
478
wxluaO_isgcobject(lua_State * L,void * obj_ptr)479 bool LUACALL wxluaO_isgcobject(lua_State *L, void *obj_ptr)
480 {
481 lua_pushlightuserdata(L, &wxlua_lreg_gcobjects_key); // push key
482 lua_rawget(L, LUA_REGISTRYINDEX); // pop key, push value (table)
483
484 lua_pushlightuserdata(L, obj_ptr); // push key
485 lua_rawget(L, -2); // get t[key] = value, pops key
486
487 bool found = (0 != lua_isnumber(L, -1));
488 lua_pop(L, 2); // pop udata and table
489
490 return found;
491 }
492
wxluaO_getgcobjectinfo(lua_State * L)493 wxArrayString LUACALL wxluaO_getgcobjectinfo(lua_State *L)
494 {
495 wxArrayString arrStr;
496
497 lua_pushlightuserdata(L, &wxlua_lreg_gcobjects_key); // push key
498 lua_rawget(L, LUA_REGISTRYINDEX); // pop key, push value (table)
499
500 lua_pushnil(L);
501 while (lua_next(L, -2) != 0)
502 {
503 // value = -1, key = -2, table = -3
504 wxString name(wxT("wxObject?"));
505
506 int wxl_type = (int)lua_tonumber(L, -1);
507 name = wxluaT_typename(L, wxl_type);
508
509 arrStr.Add(wxString::Format(wxT("%s(%p)"), name.c_str(), lua_touserdata(L, -2)));
510
511 lua_pop(L, 1); // pop value, lua_next will pop key at end
512 }
513
514 lua_pop(L, 1); // pop table
515
516 arrStr.Sort();
517 return arrStr;
518 }
519
wxluaO_trackweakobject(lua_State * L,int udata_stack_idx,void * obj_ptr,int wxl_type)520 void LUACALL wxluaO_trackweakobject(lua_State *L, int udata_stack_idx, void *obj_ptr, int wxl_type)
521 {
522 lua_pushlightuserdata(L, &wxlua_lreg_weakobjects_key); // push key
523 lua_rawget(L, LUA_REGISTRYINDEX); // pop key, push value (the obj table)
524
525 lua_pushlightuserdata(L, obj_ptr); // push key
526 lua_rawget(L, -2);
527
528 if (lua_isnil(L, -1)) // not tracked yet, create new table to store items
529 {
530 lua_pop(L, 1); // pop nil
531
532 lua_pushlightuserdata(L, obj_ptr);
533 lua_newtable(L);
534 lua_newtable(L); // metatable
535 lua_pushlstring(L, "__mode", 6);
536 lua_pushlstring(L, "v", 1);
537 lua_rawset(L, -3); // set mode of main table
538 lua_setmetatable(L, -2); // via the metatable
539 lua_rawset(L, -3);
540
541 lua_pushlightuserdata(L, obj_ptr); // get the table back
542 lua_rawget(L, -2);
543 }
544 else
545 {
546 // check for dupes since that's what we're trying to avoid
547 lua_pushnumber(L, wxl_type);
548 lua_rawget(L, -2);
549 // this must never happen
550 if (!lua_isnil(L, -1))
551 {
552 wxFAIL_MSG(wxT("Trying to push userdata for object with same wxLua type twice"));
553 }
554 lua_pop(L, 1); // pop nil
555 }
556
557 lua_pushnumber(L, wxl_type);
558 lua_pushvalue(L, ABS_LUA_STKIDX(udata_stack_idx, 3)); // push the Lua userdata as the value (note: weak valued table)
559 lua_rawset(L, -3); // t[key] = value; pops key and value
560 lua_pop(L, 2); // pop weakobj table and obj_ptr table
561 }
562
wxluaO_untrackweakobject(lua_State * L,void * udata,void * obj_ptr)563 int LUACALL wxluaO_untrackweakobject(lua_State *L, void* udata, void *obj_ptr)
564 {
565 lua_pushlightuserdata(L, &wxlua_lreg_weakobjects_key); // push key
566 lua_rawget(L, LUA_REGISTRYINDEX); // pop key, push value (the object table)
567
568 lua_pushlightuserdata(L, (void*)obj_ptr); // push key
569 lua_rawget(L, -2); // get t[key] = value; pop key push value
570
571 int count = 0;
572
573 if (lua_istable(L, -1))
574 {
575 // clear the metatables for the userdata
576 lua_pushnil(L);
577 while (lua_next(L, -2) != 0)
578 {
579 // value = -1, key = -2, table = -3
580 void *u = lua_touserdata(L, -1);
581
582 if ((udata == NULL) || (udata == u))
583 {
584 lua_pushnil(L);
585 lua_setmetatable(L, -2); // remove value's metatable
586 }
587
588 if (udata == u)
589 {
590 lua_pop(L, 1); // pop value
591
592 lua_pushvalue(L, -1); // copy key for next iteration
593 lua_pushnil(L);
594 lua_rawset(L, -4); // set t[key] = nil to remove it
595 }
596 else
597 {
598 ++count; // only count ones that still exist
599 lua_pop(L, 1); // pop value, leave key for next iteration
600 }
601 }
602
603 lua_pop(L, 1); // pop obj_ptr table
604
605 // If we've cleared everything then remove the table
606 if ((udata == NULL) || (count == 0))
607 {
608 count = 0; // removed them all
609 lua_pushlightuserdata(L, (void*)obj_ptr); // push key
610 lua_pushnil(L); // push value
611 lua_rawset(L, -3); // set t[key] = nil; pops key and value
612 }
613
614 lua_pop(L, 1); // pop objects table
615 }
616 else
617 lua_pop(L, 2); // pop nil and weakobj table
618
619 return count;
620 }
621
wxluaO_istrackedweakobject(lua_State * L,void * obj_ptr,int wxl_type,bool push_on_stack)622 bool LUACALL wxluaO_istrackedweakobject(lua_State *L, void *obj_ptr, int wxl_type, bool push_on_stack)
623 {
624 lua_pushlightuserdata(L, &wxlua_lreg_weakobjects_key); // push key
625 lua_rawget(L, LUA_REGISTRYINDEX); // pop key, push value (the obj table)
626
627 lua_pushlightuserdata(L, obj_ptr); // push key
628 lua_rawget(L, -2); // get t[key] value; pop key push value
629
630 if (lua_istable(L, -1))
631 {
632 lua_pushnumber(L, wxl_type); // push key
633 lua_rawget(L, -2); // get t[key] = value; pops key
634
635 // check if they've dynamic casted the object or if it was casted in C++
636 if (wxl_type == wxluaT_type(L, -1))
637 {
638 if (push_on_stack)
639 {
640 lua_remove(L, -3); // remove the obj table, leave value on the stack
641 lua_remove(L, -2); // remove table of userdata, leave value on the stack
642 }
643 else
644 lua_pop(L, 3);
645
646 return true;
647 }
648 else
649 lua_pop(L, 1); // pop the userdata that is not the right type
650 }
651
652 lua_pop(L, 2); // pop the weakobj table and the nil.
653 return false;
654 }
655
wxluaO_gettrackedweakobjectinfo(lua_State * L)656 wxArrayString LUACALL wxluaO_gettrackedweakobjectinfo(lua_State *L)
657 {
658 wxArrayString arrStr;
659
660 lua_pushlightuserdata(L, &wxlua_lreg_weakobjects_key); // push key
661 lua_rawget(L, LUA_REGISTRYINDEX); // pop key, push value (table)
662
663 lua_pushnil(L);
664 while (lua_next(L, -2) != 0)
665 {
666 // value = -1, key = -2, table = -3
667 void* obj_ptr = lua_touserdata(L, -2); // actually lightuserdata
668
669 wxString name;
670
671 // iterate the table of userdata
672 lua_pushnil(L);
673 while (lua_next(L, -2) != 0)
674 {
675 // value = -1, key = -2, table = -3
676 int wxl_type = (int)lua_tonumber(L, -2);
677 if (!name.IsEmpty()) name += wxT(", ");
678 name += wxString::Format(wxT("%s(%p, type=%d)"), wxluaT_typename(L, wxl_type).c_str(), lua_touserdata(L, -1), wxl_type);
679 lua_pop(L, 1); // pop value, lua_next will pop key at end
680 }
681
682 arrStr.Add(wxString::Format(wxT("%p = %s"), obj_ptr, name.c_str()));
683
684 lua_pop(L, 1); // pop value, lua_next will pop key at end
685 }
686
687 lua_pop(L, 1); // pop table
688
689 arrStr.Sort();
690 return arrStr;
691 }
692
693 // ----------------------------------------------------------------------------
694 // wxluaW_XXX - functions operate on tracked wxWindows
695 // ----------------------------------------------------------------------------
696
wxluaW_addtrackedwindow(lua_State * L,wxObject * wxobj)697 void LUACALL wxluaW_addtrackedwindow(lua_State *L, wxObject* wxobj)
698 {
699 if (!wxobj) return; // allow NULL w/o error
700
701 // don't track these "windows" since they're supposed to be attached
702 // and their parents are not properly set so we can't tell if
703 // their parents are tracked.
704 if (wxDynamicCast(wxobj, wxMenuBar) != NULL) return;
705 if (wxDynamicCast(wxobj, wxToolBar) != NULL) return;
706
707 wxWindow* win = wxDynamicCast(wxobj, wxWindow);
708
709 // only need to track parent window, it deletes children for us
710 if (win && !wxluaW_istrackedwindow(L, win, true))
711 {
712 lua_pushlightuserdata(L, &wxlua_lreg_topwindows_key); // push key
713 lua_rawget(L, LUA_REGISTRYINDEX); // pop key, push value (table)
714
715 lua_pushlightuserdata(L, win); // push key
716 lua_pushnumber(L, 1); // push value
717 lua_rawset(L, -3); // set t[key] = value, pops key and value
718
719 lua_pop(L, 1); // pop topwindows table
720 }
721 }
722
wxluaW_removetrackedwindow(lua_State * L,wxWindow * win)723 void LUACALL wxluaW_removetrackedwindow(lua_State *L, wxWindow* win)
724 {
725 lua_pushlightuserdata(L, &wxlua_lreg_topwindows_key); // push key
726 lua_rawget(L, LUA_REGISTRYINDEX); // pop key, push value (table)
727
728 lua_pushlightuserdata(L, win); // push key
729 lua_pushnil(L); // push value
730 lua_rawset(L, -3); // set t[key] = value, pops key and value
731
732 lua_pop(L, 1); // pop topwindows table
733 }
734
wxluaW_istrackedwindow(lua_State * L,wxWindow * win,bool check_parents)735 bool LUACALL wxluaW_istrackedwindow(lua_State *L, wxWindow* win, bool check_parents)
736 {
737 lua_pushlightuserdata(L, &wxlua_lreg_topwindows_key); // push key
738 lua_rawget(L, LUA_REGISTRYINDEX); // pop key, push value (table)
739
740 wxWindow* parent = win;
741
742 while (parent)
743 {
744 lua_pushlightuserdata(L, parent); // push key
745 lua_rawget(L, -2); // pop key, push value
746
747 if (lua_isnumber(L, -1))
748 {
749 lua_pop(L, 2); // pop topwindows table and value
750 return true;
751 }
752
753 parent = check_parents ? parent->GetParent() : NULL;
754 lua_pop(L, 1); // pop value (nil)
755 }
756
757 lua_pop(L, 1); // pop topwindows table
758
759 return false;
760 }
761
wxluaW_gettrackedwindowinfo(lua_State * L)762 wxArrayString LUACALL wxluaW_gettrackedwindowinfo(lua_State *L)
763 {
764 wxArrayString arrStr;
765
766 lua_pushlightuserdata(L, &wxlua_lreg_topwindows_key); // push key
767 lua_rawget(L, LUA_REGISTRYINDEX); // pop key, push value (table)
768
769 lua_pushnil(L);
770 while (lua_next(L, -2) != 0)
771 {
772 // value = -1, key = -2, table = -3
773 wxWindow* win = (wxWindow*)lua_touserdata(L, -2);
774 wxCHECK_MSG(win, arrStr, wxT("Invalid wxWindow"));
775
776 wxString name(win->GetClassInfo()->GetClassName());
777 arrStr.Add(wxString::Format(wxT("%s(%p id=%d)"), name.c_str(), win, win->GetId()));
778
779 lua_pop(L, 1); // pop value, lua_next will pop key at end
780 }
781
782 lua_pop(L, 1); // pop table
783
784 arrStr.Sort();
785 return arrStr;
786 }
787
788 // ----------------------------------------------------------------------------
789 // wxluaT_XXX - functions operate on the wxLua types
790 // ----------------------------------------------------------------------------
791
wxluaT_newmetatable(lua_State * L,int wxl_type)792 int wxluaT_newmetatable(lua_State* L, int wxl_type)
793 {
794 lua_newtable(L); // create a table for our new type
795 lua_pushlightuserdata(L, &wxlua_metatable_type_key); // push key
796 lua_pushnumber(L, wxl_type); // push value
797 lua_rawset(L, -3); // set t[key] = value; pop key and value
798
799 lua_pushlightuserdata(L, &wxlua_lreg_types_key); // push key
800 lua_rawget(L, LUA_REGISTRYINDEX); // pop key, push value (table)
801
802 // make sure that the Lua table array is contiguous
803 int len = (int)lua_objlen(L, -1); // get the length of the table
804 while (++len < wxl_type)
805 {
806 lua_pushnumber(L, 0);
807 lua_rawseti(L, -2, len);
808 }
809
810 // It is not allowed to reregister this type
811 lua_rawgeti(L, -1, wxl_type);
812 int t = lua_type(L, -1);
813 wxCHECK_MSG((t == LUA_TNUMBER) || (t == LUA_TNIL), WXLUA_TUNKNOWN, wxT("Attempting to reregister wxLua type"));
814 lua_pop(L, 1);
815
816 // Add the metatable to the wxlua_lreg_types_key table
817 lua_pushvalue(L, -2); // copy the metatable
818 lua_rawseti(L, -2, wxl_type); // add it, pops table
819 lua_pop(L, 1); // pop wxlua_lreg_types_key table
820
821 return wxl_type; // leave the table on the stack
822 }
823
wxluaT_getmetatable(lua_State * L,int wxl_type)824 bool LUACALL wxluaT_getmetatable(lua_State* L, int wxl_type)
825 {
826 if (wxluaR_getref(L, wxl_type, &wxlua_lreg_types_key)) // get the metatable
827 {
828 if (lua_type(L, -1) == LUA_TTABLE)
829 return true;
830
831 lua_pop(L, 1); // pop nil or 0 placeholder
832 }
833
834 return false;
835 }
836
wxluaT_setmetatable(lua_State * L,int wxl_type)837 bool LUACALL wxluaT_setmetatable(lua_State *L, int wxl_type)
838 {
839 if (wxluaT_getmetatable(L, wxl_type)) // get the metatable
840 {
841 // set it as the metatable of the object at the top of the stack
842 if (lua_setmetatable(L, -2)) // pops table
843 return true;
844 else
845 {
846 lua_pop(L, 1); // pop table
847 wxlua_error(L, "wxLua: Unable to set metatable in wxluaT_setmetatable.");
848 }
849 }
850 else
851 wxlua_error(L, "wxLua: Unable to get metatable in wxluaT_setmetatable.");
852
853 return false;
854 }
855
wxluaT_type(lua_State * L,int stack_idx)856 int LUACALL wxluaT_type(lua_State *L, int stack_idx)
857 {
858 int wxl_type = WXLUA_TUNKNOWN;
859 int ltype = lua_type(L, stack_idx);
860
861 if ((ltype == LUA_TUSERDATA) && lua_getmetatable(L, stack_idx)) // see wxluaT_newmetatable()
862 {
863 lua_pushlightuserdata(L, &wxlua_metatable_type_key); // push key
864 lua_rawget(L, -2); // get t[key] = value; pop key push value
865 wxl_type = (int)lua_tonumber(L, -1); // if !isnumber it returns 0 (check below is faster)
866
867 // if it's not a number (it's probably nil) then it's someone else's userdata
868 if ((wxl_type == 0) && !lua_isnumber(L, -1))
869 wxl_type = WXLUA_TUSERDATA;
870
871 lua_pop(L, 2); // pop metatable and wxl_type number
872 }
873 else
874 wxl_type = wxlua_luatowxluatype(ltype);
875
876 return wxl_type;
877 }
878
wxluaT_typename(lua_State * L,int wxl_type)879 wxString LUACALL wxluaT_typename(lua_State* L, int wxl_type)
880 {
881 // try to use wxString's ref counting and return this existing copy
882 static wxString s[14] = {
883 wxT("unknown"),
884 wxT("none"),
885 wxT("nil"),
886 wxT("boolean"),
887 wxT("lightuserdata"),
888 wxT("number"),
889 wxT("string"),
890 wxT("table"),
891 wxT("function"),
892 wxT("userdata"),
893 wxT("thread"),
894 wxT("integer"),
895 wxT("cfunction"),
896 wxT("pointer")
897 };
898
899 // Check for real type or this is a predefined WXLUA_TXXX type
900 if ((L == NULL) || (WXLUAT_IS_LUAT(wxl_type)))
901 {
902 switch (wxl_type)
903 {
904 case WXLUA_TUNKNOWN : return s[0];
905 case WXLUA_TNONE : return s[1];
906 case WXLUA_TNIL : return s[2];
907 case WXLUA_TBOOLEAN : return s[3];
908 case WXLUA_TLIGHTUSERDATA : return s[4];
909 case WXLUA_TNUMBER : return s[5];
910 case WXLUA_TSTRING : return s[6];
911 case WXLUA_TTABLE : return s[7];
912 case WXLUA_TFUNCTION : return s[8];
913 case WXLUA_TUSERDATA : return s[9];
914 case WXLUA_TTHREAD : return s[10];
915
916 case WXLUA_TINTEGER : return s[11];
917 case WXLUA_TCFUNCTION : return s[12];
918 case WXLUA_TPOINTER : return s[13];
919 }
920 }
921 else
922 {
923 const wxLuaBindClass* wxlClass = wxluaT_getclass(L, wxl_type);
924 if (wxlClass)
925 return lua2wx(wxlClass->name);
926 }
927
928 return wxT("Unknown wxLua Type?");
929 }
930
wxluaT_gettypename(lua_State * L,int stack_idx)931 wxString LUACALL wxluaT_gettypename(lua_State* L, int stack_idx)
932 {
933 return wxluaT_typename(L, wxluaT_type(L, stack_idx));
934 }
935
wxlua_luaL_typename(lua_State * L,int stack_idx)936 wxString LUACALL wxlua_luaL_typename(lua_State* L, int stack_idx)
937 {
938 // lua_typename(L, lua_type(L, stack_idx))
939 return lua2wx(luaL_typename(L, stack_idx));
940 }
941
wxluaT_gettype(lua_State * L,const char * class_name)942 int LUACALL wxluaT_gettype(lua_State* L, const char* class_name)
943 {
944 const wxLuaBindClass* wxlClass = wxluaT_getclass(L, class_name);
945 if (wxlClass)
946 return *wxlClass->wxluatype;
947
948 return WXLUA_TUNKNOWN;
949 }
950
wxluaT_getclass(lua_State * L,int wxl_type)951 const wxLuaBindClass* LUACALL wxluaT_getclass(lua_State* L, int wxl_type)
952 {
953 // note: wxluaT_getmetatable() doesn't leave anything on the stack on failure
954 if (wxluaT_getmetatable(L, wxl_type))
955 {
956 // t[wxluatype] = { [bindclass_key] = lightuserdata wxLuaBindClass... (or nil if not a wxLua class type)
957 lua_pushlightuserdata(L, &wxlua_metatable_wxluabindclass_key);
958 lua_rawget(L, -2);
959 const wxLuaBindClass* wxlClass = (wxLuaBindClass *)lua_touserdata(L, -1); // actually lightuserdata
960
961 lua_pop(L, 2); // pop type table and lightuserdata (or nil if none)
962
963 return wxlClass;
964 }
965
966 return NULL;
967 }
968
wxluaT_getclass(lua_State * L,const char * class_name)969 const wxLuaBindClass* LUACALL wxluaT_getclass(lua_State* L, const char* class_name)
970 {
971 lua_pushlightuserdata(L, &wxlua_lreg_classes_key); // push key
972 lua_rawget(L, LUA_REGISTRYINDEX); // pop key, push value (table)
973
974 lua_pushstring(L, class_name); // push key
975 lua_rawget(L, -2); // get t["class_name"] = &wxLuaBindClass; pop key push value
976 const wxLuaBindClass* wxlClass = (wxLuaBindClass *)lua_touserdata(L, -1); // actually lightuserdata
977
978 lua_pop(L, 2); // pop table and lightuserdata (or nil if none)
979
980 return wxlClass; // may be NULL
981 }
982
wxluaT_isuserdatatype(lua_State * L,int stack_idx,int wxl_type)983 bool wxluaT_isuserdatatype(lua_State* L, int stack_idx, int wxl_type)
984 {
985 int stack_type = wxluaT_type(L, stack_idx);
986
987 if (wxlua_iswxuserdatatype(stack_type) &&
988 ((wxluatype_NULL == stack_type) || // FIXME, how to check when NULL is valid or not?
989 ((wxl_type == WXLUA_TSTRING) &&
990 ((wxluaT_isderivedtype(L, stack_type, *p_wxluatype_wxString) >= 0) ||
991 (wxluaT_isderivedtype(L, stack_type, *p_wxluatype_wxMemoryBuffer) >= 0))) ||
992 (wxluaT_isderivedtype(L, stack_type, wxl_type) >= 0)))
993 return true;
994
995 return false;
996 }
997
998 // Note about multiple inheritance in wxLua :
999 // See wxLuaBindClass::baseclass_vtable_offsets
1000 //
1001 // class A { int x; }; class B { int y; }; class AB : public A, public B { int z; };
1002 // AB ab; void *v_ab_a = (A*)&ab; void *v_ab_b = (B*)&ab;
1003 // long int dummy = 0;
1004 // long int AB_diff = ((long int)(B*)(AB*)&dummy) - ((long int)(A*)(AB*)&dummy);
1005 // wxPrintf(wxT("AB*=%p, A*=%p, B*=%p, B*-A*=%d\n"), &ab, v_ab_a, v_ab_b, AB_diff);
1006 // prints: "AB*=0x614dfc, A*=0x614dfc, B*=0x614e00, B*-A*=4"
1007 //
1008 // In order to call B's functions from a void* pointer to an AB object :
1009 // 1) Ideally, we cast to an AB object and the compiler will appropriately lookup
1010 // and handle calls to B's functions.
1011 // 2) Cast to an AB object then to a B object where the compiler has already
1012 // shifted the pointer and calls to B's functions are made directly.
1013 // 3) Explicitly shift the void* pointer to the AB object to where the vtable for
1014 // B is. We now have an object that only knows about B and what B was derived from.
1015 // I'm sure this is frowned upon by C++ enthusiasts.
1016 //
1017 // Ways of doing 1 and 2 in wxLua with C++ constraints, wxLua does #3 above.
1018 //
1019 // 1) wxLua would duplicate all the the binding functions for second
1020 // and higher base classes and therefore each binding function will cast the
1021 // void* we get from Lua to exactly the object type that it is. This is best,
1022 // but it adds bloat.
1023 // 2) Come up with a clever way using overloaded functions, templates,
1024 // or some sort of variant class to convert the void* pointer from Lua to
1025 // type of object that it really is (we know by the wxLuaType integer)
1026 // and then the binding function will cast it whatever base class it may be.
1027 // The problem is that we really need to overload this casting function by
1028 // return type, the function takes void* and returns ClassXYZ*, but this
1029 // is not allowed in C++.
1030 // 3) Store an array of the offsets in each classes' wxLuaBindClass struct
1031 // to the second or higher base classes and automatically add this offset in
1032 // wxluaT_getuserdatatype(). The offsets are calculated at compile time
1033 // using the AB_diff method above.
1034 //
1035 // Various ways to cast a void* pointer to the second base class :
1036 // void* v_ab = &ab; // compilier doesn't know what v_ab is anymore
1037 // AB* ab = (AB*)v_ab; // ok since we cast right back to original type
1038 // A* a = (A*)v_ab; // ok in GCC & MSVC since we are casting to 1st base class
1039 // B* b = (B*)v_ab; // segfault! since B*'s vtable is +4 bytes as shown above
1040 // B* b1 = (B*)(AB*)v_ab; // ok since compiler converts to AB* and knows that B* is shifted
1041 // B* b2 = (B*)((long int)v_ab + AB_diff); // ok since we've shifted to B
1042
1043
1044 // forward declaration
1045 static int wxluaT_isderivedtype_recurser(const wxLuaBindClass *wxlClass, int base_wxl_type, int levels, int* baseclass_n);
1046
wxluaT_getuserdatatype(lua_State * L,int stack_idx,int wxl_type)1047 void* LUACALL wxluaT_getuserdatatype(lua_State* L, int stack_idx, int wxl_type)
1048 {
1049 int stack_type = wxluaT_type(L, stack_idx);
1050
1051 if (wxluatype_NULL == stack_type)
1052 return NULL;
1053
1054 // Note: we directly use the recurser function since we may need the wxLuaBindClass
1055 //int level = wxluaT_isderivedtype(L, stack_type, wxl_type);
1056
1057 int baseclass_n = 0;
1058 const wxLuaBindClass* wxlClass = wxluaT_getclass(L, stack_type);
1059 int level = wxluaT_isderivedtype_recurser(wxlClass, wxl_type, 0, &baseclass_n);
1060
1061 if ((level >= 0) && (baseclass_n == 0))
1062 {
1063 // We can directly cast the void* pointer to the baseclass if baseclass_n == 0
1064 return wxlua_touserdata(L, stack_idx, false);
1065 }
1066 else if (level > 0)
1067 {
1068 // The class on the stack is derived from a second or higher base class
1069 // and therefore the pointer to the base class is not the same as the
1070 // pointer to the class object on the stack. We need to shift the
1071 // pointer by the number of bytes in wxLuaBindClass::baseclass_vtable_offsets
1072 // so that when it is casted to the base class we don't segfault.
1073 // Using 'long long' for 32 and 64 bit and compatibility with older compilers that don't have uintptr_t.
1074 unsigned long long o = (unsigned long long)wxlua_touserdata(L, stack_idx, false);
1075
1076 if (wxlClass->baseclass_wxluatypes)
1077 {
1078 int i = 0;
1079 while (wxlClass->baseclass_wxluatypes[i]) // NULL terminated, the baseclass_vtable_offsets is not
1080 {
1081 if (*(wxlClass->baseclass_wxluatypes[i]) == wxl_type)
1082 {
1083 o += wxlClass->baseclass_vtable_offsets[i];
1084 break;
1085 }
1086 i++;
1087 }
1088 }
1089
1090 return (void*)o;
1091 }
1092
1093
1094
1095 wxlua_argerror(L, stack_idx, wxT("a '") + wxluaT_typename(L, wxl_type) + wxT("'"));
1096
1097 return NULL;
1098 }
1099
wxluaT_pushuserdatatype(lua_State * L,const void * obj_ptr,int wxl_type,bool track,bool allow_NULL)1100 bool LUACALL wxluaT_pushuserdatatype(lua_State* L, const void *obj_ptr, int wxl_type, bool track, bool allow_NULL)
1101 {
1102 // FIXME allow_NULL is a hack for the NULL userdata type.
1103
1104 if (allow_NULL || (obj_ptr != NULL))
1105 {
1106 // First check to see if we've already pushed this object into Lua.
1107 // This avoids the problem of the gc deleting a returned pointer to a permanent object.
1108 // Test code is this:
1109 // il = wx.wxImageList(16,16); ... noteBook:SetImageList(il); ... local il2 = noteBook:GetImageList()
1110 // When il2 gets gc it will delete il even though il may still be valid and used by the notebook.
1111
1112 if (wxluaO_istrackedweakobject(L, (void*)obj_ptr, wxl_type, true))
1113 return true;
1114
1115 // if the object we are referencing is derived from wxWindow
1116 if (obj_ptr && (wxluaT_isderivedtype(L, wxl_type, *p_wxluatype_wxWindow) >= 0))
1117 {
1118 wxWindow* win = wxDynamicCast(obj_ptr, wxWindow); // double check that it's a wxWindow
1119 if (win != NULL)
1120 {
1121 // check to make sure that we're not trying to attach another destroy callback
1122 lua_pushlightuserdata(L, &wxlua_lreg_windestroycallbacks_key); // push key
1123 lua_rawget(L, LUA_REGISTRYINDEX); // pop key, push value (table)
1124
1125 lua_pushlightuserdata(L, win); // push key
1126 lua_rawget(L, -2); // get t[key] = value; pops key
1127
1128 if (!lua_islightuserdata(L, -1))
1129 {
1130 // Connect the wxWindow to wxEVT_DESTROY callback so if Lua has
1131 // a copy(s) of it we can clear the metatable when we get the
1132 // event so we don't segfault if we try to access it by accident.
1133 wxLuaState wxlState(L);
1134 wxCHECK_MSG(wxlState.Ok(), false, wxT("Invalid wxLuaState"));
1135 wxLuaWinDestroyCallback *pCallback =
1136 new wxLuaWinDestroyCallback(wxlState, win);
1137
1138 if (pCallback == NULL)
1139 wxlua_error(L, "wxLua: Out of memory creating wxLuaWinDestroyCallback.");
1140 // assert should have been given in constructor so delete it
1141 // since it's not attached as a callback user data
1142 if (!pCallback->Ok())
1143 delete pCallback;
1144 }
1145
1146 lua_pop(L, 2); // pop windestroy table and value
1147 }
1148 }
1149
1150 // Wrap the void* pointer in a newuserdata
1151 const void **ptr = (const void **)lua_newuserdata(L, sizeof(void *));
1152 if (ptr != NULL)
1153 {
1154 *ptr = obj_ptr;
1155 // try to get the object's references table and set the metatable to the object
1156 if (wxluaT_getmetatable(L, wxl_type))
1157 {
1158 // pop the table and set it as the metatable for the newuserdata
1159 lua_setmetatable(L, -2);
1160
1161 if (track)
1162 wxluaO_trackweakobject(L, -1, (void*)obj_ptr, wxl_type);
1163
1164 return true; // leave value on the stack
1165 }
1166 else
1167 wxlua_error(L, "wxLua: Unable to get metatable in wxluaT_pushuserdatatype.");
1168 }
1169 else
1170 wxlua_error(L, "wxLua: Out of memory");
1171 }
1172 else
1173 {
1174 lua_pushnil(L);
1175 return true;
1176 }
1177
1178 return false;
1179 }
1180
1181 // ----------------------------------------------------------------------------
1182 // Functions to get info about the wxLua types
1183 // ----------------------------------------------------------------------------
1184
wxluaT_isderivedtype_recurser(const wxLuaBindClass * wxlClass,int base_wxl_type,int levels,int * baseclass_n)1185 static int wxluaT_isderivedtype_recurser(const wxLuaBindClass *wxlClass, int base_wxl_type, int levels, int* baseclass_n)
1186 {
1187 if (wxlClass != NULL)
1188 {
1189 // check that input isn't what we want first since this func is used in a couple places
1190 if (*wxlClass->wxluatype == base_wxl_type)
1191 return levels;
1192 else if (wxlClass->baseclassNames != NULL) // check baseclass by baseclass
1193 {
1194 for (size_t i = 0; wxlClass->baseclassNames[i]; ++i)
1195 {
1196 // Note: base class may be NULL if lib/module containing it is not loaded
1197 wxLuaBindClass* baseClass = wxlClass->baseBindClasses[i];
1198
1199 if (baseClass != NULL)
1200 {
1201 if (*baseClass->wxluatype == base_wxl_type)
1202 {
1203 if (baseclass_n) *baseclass_n = wxMax(*baseclass_n, (int)i);
1204 return levels+1;
1205 }
1206 else
1207 {
1208 // create a new baseclass_n since we may be going down the wrong path
1209 // and we do not want to change the original.
1210 int baseclass_n_tmp = wxMax(baseclass_n ? *baseclass_n : 0, (int)i);
1211 int ret = wxluaT_isderivedtype_recurser(baseClass, base_wxl_type, levels+1, &baseclass_n_tmp);
1212 if (ret > -1)
1213 {
1214 // now set the baseclass_n var to the tmp one
1215 if (baseclass_n) *baseclass_n = wxMax(baseclass_n_tmp, (int)i);
1216 return ret;
1217 }
1218 }
1219 }
1220 }
1221 }
1222 }
1223
1224 return -1; // wxluatype is not derived from base_wxluatype
1225 }
1226
wxluaT_isderivedtype(lua_State * L,int wxl_type,int base_wxl_type,int * baseclass_n)1227 int LUACALL wxluaT_isderivedtype(lua_State* L, int wxl_type, int base_wxl_type, int* baseclass_n)
1228 {
1229 // couldn't possibly be derived from each other
1230 if (!wxlua_iswxuserdatatype(wxl_type) || !wxlua_iswxuserdatatype(base_wxl_type))
1231 return -1;
1232
1233 // These two types are the same, yes recurser also checks, but this is faster
1234 if (wxl_type == base_wxl_type)
1235 return 0;
1236
1237 const wxLuaBindClass *wxlClass = wxluaT_getclass(L, wxl_type);
1238
1239 if (baseclass_n != NULL) *baseclass_n = 0;
1240
1241 return wxluaT_isderivedtype_recurser(wxlClass, base_wxl_type, 0, baseclass_n);
1242 }
1243
wxluaT_isderivedclass(const wxLuaBindClass * wxlClass,const wxLuaBindClass * base_wxlClass,int * baseclass_n)1244 int LUACALL wxluaT_isderivedclass(const wxLuaBindClass* wxlClass, const wxLuaBindClass* base_wxlClass, int* baseclass_n)
1245 {
1246 // Ok if either is NULL to allow blindly calling this
1247 if ((wxlClass == NULL) || (base_wxlClass == NULL))
1248 return -1;
1249
1250 // These two types are the same
1251 if (wxlClass->wxluatype == base_wxlClass->wxluatype) // comparing pointers
1252 return 0;
1253
1254 if (baseclass_n != NULL) *baseclass_n = 0;
1255
1256 return wxluaT_isderivedtype_recurser(wxlClass, *base_wxlClass->wxluatype, 1, baseclass_n);
1257 }
1258
wxlua_iswxluatype(int luatype,int wxl_type,lua_State * L)1259 int LUACALL wxlua_iswxluatype(int luatype, int wxl_type, lua_State* L /* = NULL */)
1260 {
1261 int ret = -1; // unknown wxlua arg type
1262
1263 switch (wxl_type)
1264 {
1265 case WXLUA_TNONE :
1266 ret = (luatype == LUA_TNONE) ? 1 : 0;
1267 break;
1268 case WXLUA_TNIL :
1269 ret = (luatype == LUA_TNIL) ? 1 : 0;
1270 break;
1271 case WXLUA_TBOOLEAN :
1272 // LUA_TNIL: nil == false
1273 // LUA_TNUMBER: 0 == false as in C
1274 ret = ((luatype == LUA_TBOOLEAN) || (luatype == LUA_TNUMBER) || (luatype == LUA_TNIL)) ? 1 : 0;
1275 break;
1276 case WXLUA_TLIGHTUSERDATA:
1277 ret = (luatype == LUA_TLIGHTUSERDATA) ? 1 : 0;
1278 break;
1279 case WXLUA_TNUMBER :
1280 // LUA_TNIL: evaluates to 0, too easy to have a typo
1281 // LUA_TSTRING: will be 0 unless really a number "2"
1282 // LUA_TBOOLEAN: can't do (bool_val or 1)
1283 ret = ((luatype == LUA_TNUMBER) || (luatype == LUA_TBOOLEAN)) ? 1 : 0;
1284 break;
1285 case WXLUA_TSTRING :
1286 // LUA_TNIL: too easy to have a variable typo, use (str or "")
1287 // LUA_TNUMBER: can convert easily, always works, but breaks overload bindings
1288 ret = (luatype == LUA_TSTRING) ? 1 : 0;
1289 break;
1290 case WXLUA_TTABLE :
1291 ret = (luatype == LUA_TTABLE) ? 1 : 0;
1292 break;
1293 case WXLUA_TFUNCTION :
1294 ret = (luatype == LUA_TFUNCTION) ? 1 : 0;
1295 break;
1296 case WXLUA_TUSERDATA :
1297 ret = (luatype == LUA_TUSERDATA) ? 1 : 0;
1298 break;
1299 case WXLUA_TTHREAD :
1300 ret = (luatype == LUA_TTHREAD) ? 1 : 0;
1301 break;
1302 case WXLUA_TINTEGER :
1303 // LUA_TNIL: evaluates to 0 so wx.ENUM_typo = 0
1304 ret = (luatype == LUA_TNUMBER) ? 1 : 0;
1305 break;
1306 case WXLUA_TCFUNCTION :
1307 ret = (luatype == LUA_TFUNCTION) ? 1 : 0;
1308 break;
1309 case WXLUA_TPOINTER :
1310 ret = (luatype == LUA_TLIGHTUSERDATA) || (luatype == LUA_TUSERDATA) ||
1311 (luatype == LUA_TFUNCTION) || (luatype == LUA_TTABLE) ||
1312 (luatype == LUA_TTHREAD) ? 1 : 0;
1313 break;
1314 case WXLUA_TANY :
1315 ret = 1; // any type is acceptable
1316 break;
1317 }
1318
1319 // if we don't know the type (it's not predefined)
1320 if ((ret < 0) && L &&(luatype == LUA_TTABLE))
1321 {
1322 const wxLuaBindClass* wxlClass = wxluaT_getclass(L, wxl_type);
1323
1324 if (wxluaT_isderivedclass(wxlClass, wxluaT_getclass(L, "wxArrayString")) >= 0)
1325 ret = 1;
1326 else if (wxluaT_isderivedclass(wxlClass, wxluaT_getclass(L, "wxSortedArrayString")) >= 0)
1327 ret = 1;
1328 else if (wxluaT_isderivedclass(wxlClass, wxluaT_getclass(L, "wxArrayInt")) >= 0)
1329 ret = 1;
1330 else if (wxluaT_isderivedclass(wxlClass, wxluaT_getclass(L, "wxArrayDouble")) >= 0)
1331 ret = 1;
1332 }
1333
1334 return ret;
1335 }
1336
wxlua_luatowxluatype(int luatype)1337 int wxlua_luatowxluatype(int luatype)
1338 {
1339 //int wxltype = LUAT_TO_WXLUAT(luatype);
1340 //if (!WXLUAT_IS_LUAT(wxltype))
1341 // return WXLUA_TUNKNOWN;
1342 //return wxltype;
1343
1344 switch (luatype)
1345 {
1346 case LUA_TNONE : return WXLUA_TNONE;
1347 case LUA_TNIL : return WXLUA_TNIL;
1348 case LUA_TBOOLEAN : return WXLUA_TBOOLEAN;
1349 case LUA_TLIGHTUSERDATA : return WXLUA_TLIGHTUSERDATA;
1350 case LUA_TNUMBER : return WXLUA_TNUMBER;
1351 case LUA_TSTRING : return WXLUA_TSTRING;
1352 case LUA_TTABLE : return WXLUA_TTABLE;
1353 case LUA_TFUNCTION : return WXLUA_TFUNCTION;
1354 case LUA_TUSERDATA : return WXLUA_TUSERDATA;
1355 case LUA_TTHREAD : return WXLUA_TTHREAD;
1356 //case LUA_T??? : return WXLUA_TINTEGER;
1357 //case LUA_T??? : return WXLUA_TCFUNCTION;
1358 //case LUA_T??? : return WXLUA_TPOINTER;
1359 }
1360
1361 return WXLUA_TUNKNOWN;
1362 }
1363
wxlua_wxluatoluatype(int wxlarg)1364 int wxlua_wxluatoluatype(int wxlarg)
1365 {
1366 switch (wxlarg)
1367 {
1368 case WXLUA_TNONE : return LUA_TNONE;
1369 case WXLUA_TNIL : return LUA_TNIL;
1370 case WXLUA_TBOOLEAN : return LUA_TBOOLEAN;
1371 case WXLUA_TLIGHTUSERDATA : return LUA_TLIGHTUSERDATA;
1372 case WXLUA_TNUMBER : return LUA_TNUMBER;
1373 case WXLUA_TSTRING : return LUA_TSTRING;
1374 case WXLUA_TTABLE : return LUA_TTABLE;
1375 case WXLUA_TFUNCTION : return LUA_TFUNCTION;
1376 case WXLUA_TUSERDATA : return LUA_TUSERDATA;
1377 case WXLUA_TTHREAD : return LUA_TTHREAD;
1378 case WXLUA_TINTEGER : return LUA_TNUMBER;
1379 case WXLUA_TCFUNCTION : return LUA_TFUNCTION;
1380 //case WXLUA_TPOINTER : return LUA_T???; multiple types
1381 }
1382
1383 return -1;
1384 }
1385
wxlua_iswxstringtype(lua_State * L,int stack_idx)1386 bool wxlua_iswxstringtype(lua_State* L, int stack_idx)
1387 {
1388 // NOTE: If we ever allow numbers to be coerced to strings we must
1389 // change how we handle lua_tostring() calls since it will change a number
1390 // to a string on the stack. This could break people's code.
1391 if (wxlua_iswxluatype(lua_type(L, stack_idx), WXLUA_TSTRING) == 1)
1392 return true;
1393 else if (wxlua_iswxuserdata(L, stack_idx))
1394 {
1395 int wxl_type = wxluaT_type(L, stack_idx);
1396 return (wxluaT_isderivedtype(L, wxl_type, *p_wxluatype_wxString) >= 0);
1397 }
1398
1399 return false;
1400 }
1401
wxlua_getstringtypelen(lua_State * L,int stack_idx,size_t * len)1402 const char* LUACALL wxlua_getstringtypelen(lua_State *L, int stack_idx, size_t *len)
1403 {
1404 if (wxlua_isstringtype(L, stack_idx))
1405 return lua_tolstring(L, stack_idx, len);
1406 else if (wxlua_iswxuserdata(L, stack_idx))
1407 {
1408 int stack_type = wxluaT_type(L, stack_idx);
1409
1410 if (wxluaT_isderivedtype(L, stack_type, *p_wxluatype_wxString) >= 0)
1411 {
1412 wxString* wxstr = (wxString*)wxlua_touserdata(L, stack_idx, false);
1413 wxCHECK_MSG(wxstr, NULL, wxT("Invalid userdata wxString"));
1414 const char *retp = (const char *)wx2lua(*wxstr);
1415 if (len != NULL)
1416 *len = strlen(retp);
1417 return retp;
1418 }
1419 else if (wxluaT_isderivedtype(L, stack_type, *p_wxluatype_wxMemoryBuffer) >= 0)
1420 {
1421 wxMemoryBuffer * wxmem = (wxMemoryBuffer *)wxluaT_getuserdatatype(L, stack_idx, *p_wxluatype_wxMemoryBuffer);
1422 const char *datap = (const char *)wxmem->GetData();
1423 if (len != NULL)
1424 *len = wxmem->GetDataLen();
1425 return datap;
1426 }
1427 }
1428
1429 wxlua_argerror(L, stack_idx, wxT("a 'string' or 'wxString'"));
1430
1431 return NULL;
1432 }
1433
wxlua_getstringtype(lua_State * L,int stack_idx)1434 const char* LUACALL wxlua_getstringtype(lua_State *L, int stack_idx)
1435 {
1436 return wxlua_getstringtypelen(L, stack_idx, NULL);
1437 }
1438
wxlua_getwxStringtype(lua_State * L,int stack_idx)1439 wxString LUACALL wxlua_getwxStringtype(lua_State *L, int stack_idx)
1440 {
1441 if (wxlua_isstringtype(L, stack_idx))
1442 return lua2wx(lua_tostring(L, stack_idx));
1443 else if (wxlua_iswxuserdata(L, stack_idx))
1444 {
1445 int stack_type = wxluaT_type(L, stack_idx);
1446
1447 if (wxluaT_isderivedtype(L, stack_type, *p_wxluatype_wxString) >= 0)
1448 {
1449 wxString* wxstr = (wxString*)wxlua_touserdata(L, stack_idx, false);
1450 wxCHECK_MSG(wxstr, wxEmptyString, wxT("Invalid userdata wxString"));
1451 return *wxstr;
1452 }
1453 }
1454
1455 wxlua_argerror(L, stack_idx, wxT("a 'string' or 'wxString'"));
1456
1457 return wxEmptyString;
1458 }
1459
wxlua_getbooleantype(lua_State * L,int stack_idx)1460 bool LUACALL wxlua_getbooleantype(lua_State *L, int stack_idx)
1461 {
1462 int l_type = lua_type(L, stack_idx);
1463
1464 if (!wxlua_iswxluatype(l_type, WXLUA_TBOOLEAN))
1465 wxlua_argerror(L, stack_idx, wxT("a 'boolean'"));
1466
1467 int num = 0;
1468 // we also allow 0 = false and !0 = true (Lua thinks 0 == true, i.e. !nil)
1469 if (l_type == LUA_TNUMBER)
1470 num = (int)lua_tonumber(L, stack_idx);
1471 else
1472 num = (int)lua_toboolean(L, stack_idx);
1473
1474 return (num != 0);
1475 }
wxlua_getenumtype(lua_State * L,int stack_idx)1476 long LUACALL wxlua_getenumtype(lua_State *L, int stack_idx)
1477 {
1478 int l_type = lua_type(L, stack_idx);
1479
1480 if (!wxlua_iswxluatype(l_type, WXLUA_TINTEGER))
1481 wxlua_argerror(L, stack_idx, wxT("an 'integer enum'"));
1482
1483 // we don't allow bool or round, enums must strictly be integers
1484 double value = lua_tonumber(L, stack_idx);
1485 long long_value = (long)value;
1486
1487 if (value != long_value)
1488 wxlua_argerror(L, stack_idx, wxT("an 'integer enum'"));
1489
1490 return long_value;
1491 }
wxlua_getintegertype(lua_State * L,int stack_idx)1492 long LUACALL wxlua_getintegertype(lua_State *L, int stack_idx)
1493 {
1494 int l_type = lua_type(L, stack_idx);
1495
1496 if (!wxlua_iswxluatype(l_type, WXLUA_TINTEGER))
1497 wxlua_argerror(L, stack_idx, wxT("an 'integer'"));
1498
1499 double value = 0;
1500 // we also allow bool = 1/0 which Lua evaluates to nil in lua_tonumber
1501 if (l_type == LUA_TBOOLEAN)
1502 value = lua_toboolean(L, stack_idx) ? 1 : 0;
1503 else
1504 value = lua_tonumber(L, stack_idx);
1505
1506 long long_value = (long)value;
1507
1508 if (value != long_value)
1509 wxlua_argerror(L, stack_idx, wxT("an 'integer'"));
1510
1511 return long_value;
1512 }
wxlua_getuintegertype(lua_State * L,int stack_idx)1513 unsigned long LUACALL wxlua_getuintegertype(lua_State *L, int stack_idx)
1514 {
1515 int l_type = lua_type(L, stack_idx);
1516
1517 if (!wxlua_iswxluatype(l_type, WXLUA_TINTEGER))
1518 wxlua_argerror(L, stack_idx, wxT("an 'unsigned integer'"));
1519
1520 double value = 0;
1521 // we also allow bool = 1/0 which Lua evaluates to nil in lua_tonumber
1522 if (l_type == LUA_TBOOLEAN)
1523 value = lua_toboolean(L, stack_idx) ? 1 : 0;
1524 else
1525 value = lua_tonumber(L, stack_idx);
1526
1527 unsigned long ulong_value = (unsigned long)value;
1528
1529 if ((value != ulong_value) || (value < 0))
1530 wxlua_argerror(L, stack_idx, wxT("an 'unsigned integer'"));
1531
1532 return ulong_value;
1533 }
wxlua_getnumbertype(lua_State * L,int stack_idx)1534 double LUACALL wxlua_getnumbertype(lua_State *L, int stack_idx)
1535 {
1536 int l_type = lua_type(L, stack_idx);
1537
1538 if (!wxlua_iswxluatype(l_type, WXLUA_TNUMBER))
1539 wxlua_argerror(L, stack_idx, wxT("a 'number'"));
1540
1541 double value = 0;
1542 // we also allow bool = 1/0 which Lua evaluates to nil in lua_tonumber
1543 if (l_type == LUA_TBOOLEAN)
1544 value = lua_toboolean(L, stack_idx) ? 1 : 0;
1545 else
1546 value = lua_tonumber(L, stack_idx);
1547
1548 return value;
1549 }
1550
wxlua_getpointertype(lua_State * L,int stack_idx)1551 void* LUACALL wxlua_getpointertype(lua_State* L, int stack_idx)
1552 {
1553 int l_type = lua_type(L, stack_idx);
1554
1555 if (!wxlua_iswxluatype(l_type, WXLUA_TPOINTER))
1556 wxlua_argerror(L, stack_idx, wxT("a 'pointer'"));
1557
1558 void* value = (void *)lua_topointer(L, stack_idx);
1559
1560 return value;
1561 }
1562
wxlua_getchararray(lua_State * L,int stack_idx,int & count)1563 const char** LUACALL wxlua_getchararray(lua_State *L, int stack_idx, int &count)
1564 {
1565 const char **arrChar = NULL;
1566 count = 0;
1567
1568 if (lua_istable(L, stack_idx))
1569 {
1570 int table_len = lua_objlen(L, stack_idx);
1571 if (table_len > 0)
1572 arrChar = new const char *[table_len];
1573
1574 if (arrChar != NULL)
1575 {
1576 for (int n = 0; n < table_len; ++n)
1577 {
1578 lua_rawgeti(L, stack_idx, n+1); // Lua array starts at 1
1579 const char *s = wxlua_getstringtype(L, -1);
1580 arrChar[n] = s; // share Lua string
1581 lua_pop(L, 1);
1582 }
1583 }
1584
1585 count = table_len;
1586 }
1587 else
1588 wxlua_argerror(L, stack_idx, wxT("a 'table' array of strings"));
1589
1590 return arrChar;
1591 }
1592
wxlua_getwxStringarray(lua_State * L,int stack_idx,int & count)1593 wxString* LUACALL wxlua_getwxStringarray(lua_State* L, int stack_idx, int& count)
1594 {
1595 wxString *strArray = NULL;
1596 count = 0; // zero it in case we do a long jmp
1597 wxLuaSmartwxArrayString arr(wxlua_getwxArrayString(L, stack_idx));
1598
1599 count = (int)((wxArrayString&)arr).GetCount();
1600 strArray = new wxString[count];
1601 for (int n = 0; n < count; ++n)
1602 strArray[n] = ((wxArrayString&)arr)[n];
1603
1604 return strArray;
1605 }
1606
wxlua_getintarray(lua_State * L,int stack_idx,int & count)1607 int* LUACALL wxlua_getintarray(lua_State* L, int stack_idx, int& count)
1608 {
1609 int *intArray = NULL;
1610 count = 0; // zero it in case we do a long jmp
1611 wxLuaSmartwxArrayInt arr(wxlua_getwxArrayInt(L, stack_idx));
1612
1613 count = (int)((wxArrayInt&)arr).GetCount();
1614 intArray = new int[count];
1615 for (int n = 0; n < count; ++n)
1616 intArray[n] = ((wxArrayInt&)arr)[n];
1617
1618 return intArray;
1619 }
1620
wxlua_getwxArrayString(lua_State * L,int stack_idx)1621 wxLuaSmartwxArrayString LUACALL wxlua_getwxArrayString(lua_State* L, int stack_idx)
1622 {
1623 wxLuaSmartwxArrayString arr(NULL, true); // will added to or replaced
1624 int count = -1; // used to check for failure
1625
1626 if (lua_istable(L, stack_idx))
1627 {
1628 count = 0;
1629
1630 while (1)
1631 {
1632 lua_rawgeti(L, stack_idx, count+1);
1633
1634 if (wxlua_iswxstringtype(L, -1))
1635 {
1636 ((wxArrayString&)arr).Add(wxlua_getwxStringtype(L, -1));
1637 ++count;
1638
1639 lua_pop(L, 1);
1640 }
1641 else if (lua_isnil(L, -1))
1642 {
1643 lua_pop(L, 1);
1644 break;
1645 }
1646 else
1647 {
1648 wxlua_argerror(L, stack_idx, wxT("a 'wxArrayString' or table array of strings"));
1649 return arr;
1650 }
1651 }
1652 }
1653 else if (wxlua_iswxuserdata(L, stack_idx))
1654 {
1655 int arrstr_wxltype = wxluaT_gettype(L, "wxArrayString");
1656
1657 if (wxluaT_isuserdatatype(L, stack_idx, arrstr_wxltype))
1658 {
1659 wxArrayString *arrStr = (wxArrayString *)wxluaT_getuserdatatype(L, stack_idx, arrstr_wxltype);
1660 if (arrStr)
1661 {
1662 arr = wxLuaSmartwxArrayString(arrStr, false); // replace
1663 count = arrStr->GetCount();
1664 }
1665 }
1666 }
1667
1668 if (count < 0)
1669 wxlua_argerror(L, stack_idx, wxT("a 'wxArrayString' or table array of strings"));
1670
1671 return arr;
1672 }
1673
wxlua_getwxSortedArrayString(lua_State * L,int stack_idx)1674 wxLuaSmartwxSortedArrayString LUACALL wxlua_getwxSortedArrayString(lua_State* L, int stack_idx)
1675 {
1676 wxLuaSmartwxSortedArrayString arr(NULL, true); // will be replaced
1677 int count = -1; // used to check for failure
1678
1679 if (lua_istable(L, stack_idx))
1680 {
1681 wxLuaSmartwxArrayString a = wxlua_getwxArrayString(L, stack_idx);
1682 arr = wxLuaSmartwxSortedArrayString(new wxSortedArrayString(a), true);
1683 count = 0;
1684 }
1685 else if (wxlua_iswxuserdata(L, stack_idx))
1686 {
1687 int arrstr_wxltype = wxluaT_gettype(L, "wxArrayString");
1688
1689 if (wxluaT_isuserdatatype(L, stack_idx, arrstr_wxltype))
1690 {
1691 wxSortedArrayString *arrStr = (wxSortedArrayString *)wxluaT_getuserdatatype(L, stack_idx, arrstr_wxltype);
1692 if (arrStr)
1693 {
1694 arr = wxLuaSmartwxSortedArrayString(arrStr, false); // replace
1695 count = arrStr->GetCount();
1696 }
1697 }
1698 }
1699
1700 if (count < 0)
1701 wxlua_argerror(L, stack_idx, wxT("a 'wxArrayString' or table array of strings"));
1702
1703 return arr;
1704 }
1705
wxlua_getwxArrayInt(lua_State * L,int stack_idx)1706 wxLuaSmartwxArrayInt LUACALL wxlua_getwxArrayInt(lua_State* L, int stack_idx)
1707 {
1708 wxLuaSmartwxArrayInt arr(NULL, true); // will be replaced
1709 int count = -1; // used to check for failure
1710
1711 if (lua_istable(L, stack_idx))
1712 {
1713 count = 0;
1714
1715 while(1)
1716 {
1717 lua_rawgeti(L, stack_idx, count+1);
1718
1719 if (wxlua_isnumbertype(L, -1))
1720 {
1721 ((wxArrayInt&)arr).Add((int)lua_tonumber(L, -1));
1722 ++count;
1723
1724 lua_pop(L, 1);
1725 }
1726 else if (lua_isnil(L, -1))
1727 {
1728 lua_pop(L, 1);
1729 break;
1730 }
1731 else
1732 {
1733 wxlua_argerror(L, stack_idx, wxT("a 'wxArrayInt' or a table array of integers"));
1734 return arr;
1735 }
1736 }
1737 }
1738 else if (wxlua_iswxuserdata(L, stack_idx))
1739 {
1740 int arrint_wxltype = wxluaT_gettype(L, "wxArrayInt");
1741
1742 if (wxluaT_isuserdatatype(L, stack_idx, arrint_wxltype))
1743 {
1744 wxArrayInt *arrInt = (wxArrayInt *)wxluaT_getuserdatatype(L, stack_idx, arrint_wxltype);
1745 if (arrInt)
1746 {
1747 arr = wxLuaSmartwxArrayInt(arrInt, false); // replace
1748 count = arrInt->GetCount();
1749 }
1750 }
1751 }
1752
1753 if (count < 0)
1754 wxlua_argerror(L, stack_idx, wxT("a 'wxArrayInt' or a table array of integers"));
1755
1756 return arr;
1757 }
1758
wxlua_getwxArrayDouble(lua_State * L,int stack_idx)1759 wxLuaSmartwxArrayDouble LUACALL wxlua_getwxArrayDouble(lua_State* L, int stack_idx)
1760 {
1761 wxLuaSmartwxArrayDouble arr(NULL, true); // will be replaced
1762 int count = -1; // used to check for failure
1763
1764 if (lua_istable(L, stack_idx))
1765 {
1766 count = 0;
1767
1768 while(1)
1769 {
1770 lua_rawgeti(L, stack_idx, count+1);
1771
1772 if (wxlua_isnumbertype(L, -1))
1773 {
1774 ((wxArrayDouble&)arr).Add(lua_tonumber(L, -1));
1775 ++count;
1776
1777 lua_pop(L, 1);
1778 }
1779 else if (lua_isnil(L, -1))
1780 {
1781 lua_pop(L, 1);
1782 break;
1783 }
1784 else
1785 {
1786 wxlua_argerror(L, stack_idx, wxT("a 'wxArrayDouble' or a table array of integers"));
1787 return arr;
1788 }
1789 }
1790 }
1791 else if (wxlua_iswxuserdata(L, stack_idx))
1792 {
1793 int arrdouble_wxltype = wxluaT_gettype(L, "wxArrayDouble");
1794
1795 if (wxluaT_isuserdatatype(L, stack_idx, arrdouble_wxltype))
1796 {
1797 wxArrayDouble *arrDouble = (wxArrayDouble *)wxluaT_getuserdatatype(L, stack_idx, arrdouble_wxltype);
1798 if (arrDouble)
1799 {
1800 arr = wxLuaSmartwxArrayDouble(arrDouble, false); // replace
1801 count = arrDouble->GetCount();
1802 }
1803 }
1804 }
1805
1806 if (count < 0)
1807 wxlua_argerror(L, stack_idx, wxT("a 'wxArrayDouble' or a table array of numbers"));
1808
1809 return arr;
1810 }
1811
wxlua_getwxPointArray(lua_State * L,int stack_idx)1812 wxLuaSharedPtr<std::vector<wxPoint> > LUACALL wxlua_getwxPointArray(lua_State* L, int stack_idx)
1813 {
1814 wxLuaSharedPtr<std::vector<wxPoint> > pointArray(new std::vector<wxPoint>);
1815 int count = -1; // used to check for failure
1816 int is_xy_table = -1; // is it a table with x,y fields or a number array {1,2}
1817
1818 if (lua_istable(L, stack_idx))
1819 {
1820 count = lua_objlen(L, stack_idx); /* get size of table */
1821
1822 double x, y;
1823 for (int i = 1; i <= count; ++i)
1824 {
1825 lua_rawgeti(L, stack_idx, i); /* get next point as {x,y} */
1826 int t = wxluaT_type(L, -1);
1827 if (t == WXLUA_TTABLE)
1828 {
1829 // First time, check how it was formatted
1830 if (is_xy_table == -1)
1831 {
1832 lua_rawgeti(L, -1, 1);
1833 is_xy_table = (lua_isnumber(L, -1) == 0) ? 1 : 0;
1834 lua_pop(L, 1);
1835 }
1836
1837 if (is_xy_table == 1)
1838 {
1839 lua_pushstring(L, "x");
1840 lua_rawget(L, -2);
1841 if (!lua_isnumber(L, -1))
1842 wxlua_argerror(L, stack_idx, wxT("a 'number' for x-coordinate of a wxPoint array, valid tables are {{1,2},...}, {{x=1,y=2},...}, or {wx.wxPoint(1,2),,...}."));
1843 x = lua_tonumber(L, -1);
1844 lua_pop(L, 1);
1845
1846 lua_pushstring(L, "y");
1847 lua_rawget(L, -2);
1848 if (!lua_isnumber(L, -1))
1849 wxlua_argerror(L, stack_idx, wxT("a 'number' for y-coordinate of a wxPoint array, valid tables are {{1,2},...}, {{x=1,y=2},...}, or {wx.wxPoint(1,2),,...}."));
1850 y = lua_tonumber(L, -1);
1851 lua_pop(L, 1);
1852 }
1853 else
1854 {
1855 lua_rawgeti(L, -1, 1);
1856 if (!lua_isnumber(L, -1))
1857 wxlua_argerror(L, stack_idx, wxT("a 'number' for [1] index (x-coordinate) of a wxPoint array, valid tables {{1,2},...}, {{x=1,y=2},...}, or {wx.wxPoint(1,2),,...}."));
1858 x = lua_tonumber(L, -1);
1859 lua_pop(L, 1);
1860
1861 lua_rawgeti(L, -1, 2);
1862 if (!lua_isnumber(L, -1))
1863 wxlua_argerror(L, stack_idx, wxT("a 'number' for [2] index (y-coordinate) of a wxPoint array, valid tables {{1,2},...}, {{x=1,y=2},...}, or {wx.wxPoint(1,2),,...}."));
1864 y = lua_tonumber(L,-1);
1865 lua_pop(L, 1);
1866 }
1867
1868 pointArray->push_back(wxPoint((int)x, (int)y));
1869 }
1870 else if (t == *p_wxluatype_wxPoint)
1871 {
1872 const wxPoint* point = (const wxPoint *)wxluaT_getuserdatatype(L, -1, *p_wxluatype_wxPoint);
1873 pointArray->push_back(*point);
1874 }
1875 else
1876 {
1877 wxlua_argerror(L, stack_idx, wxT("a Lua table of 'wxPoints', valid tables {{1,2},...}, {{x=1,y=2},...}, or {wx.wxPoint(1,2),,...}."));
1878 return pointArray;
1879 }
1880
1881 lua_pop(L, 1);
1882 }
1883 }
1884 /*
1885
1886 // Binding the wxPointList is a problem since we have to worry about
1887 // wxList::DeleteContents() and who calls it, it'll be accident waiting to happen.
1888
1889 else if (wxlua_iswxuserdata(L, stack_idx))
1890 {
1891 int pointlist_wxltype = wxluaT_gettype(L, "wxPointList");
1892
1893 if (wxluaT_isuserdatatype(L, stack_idx, pointlist_wxltype))
1894 {
1895 wxPointList *ptList = (wxPointList *)wxluaT_getuserdatatype(L, stack_idx, pointlist_wxltype);
1896 if (ptList)
1897 {
1898 //pointArray.reset(ptList);
1899 //pointArray.SetDelete(false);
1900 count = ptList->GetCount();
1901 }
1902 }
1903 }
1904 */
1905
1906 if (count < 0)
1907 wxlua_argerror(L, stack_idx, wxT("a Lua table of 'wxPoints', valid tables {{1,2},...}, {{x=1,y=2},...}, or {wx.wxPoint(1,2),,...}."));
1908
1909 return pointArray;
1910 }
1911
wxlua_getwxPoint2DDoubleArray(lua_State * L,int stack_idx)1912 wxLuaSharedPtr<std::vector<wxPoint2DDouble> > LUACALL wxlua_getwxPoint2DDoubleArray(lua_State* L, int stack_idx)
1913 {
1914 wxLuaSharedPtr<std::vector<wxPoint2DDouble> > pointArray(new std::vector<wxPoint2DDouble>);
1915 int count = -1; // used to check for failure
1916 int is_xy_table = -1; // is it a table with x,y fields or a number array {1,2}
1917
1918 if (lua_istable(L, stack_idx))
1919 {
1920 count = lua_objlen(L, stack_idx); /* get size of table */
1921
1922 double x, y;
1923 for (int i = 1; i <= count; ++i)
1924 {
1925 lua_rawgeti(L, stack_idx, i); /* get next point as {x,y} */
1926 int t = wxluaT_type(L, -1);
1927 if (t == WXLUA_TTABLE)
1928 {
1929 // First time, check how it was formatted
1930 if (is_xy_table == -1)
1931 {
1932 lua_rawgeti(L, -1, 1);
1933 is_xy_table = (lua_isnumber(L, -1) == 0) ? 1 : 0;
1934 lua_pop(L, 1);
1935 }
1936
1937 if (is_xy_table == 1)
1938 {
1939 lua_pushstring(L, "x");
1940 lua_rawget(L, -2);
1941 if (!lua_isnumber(L, -1))
1942 wxlua_argerror(L, stack_idx, wxT("a 'number' for x-coordinate of a wxPoint2DDouble array, valid tables are {{1,2},...}, {{x=1,y=2},...}, or {wx.wxPoint2DDouble(1,2),,...}."));
1943 x = lua_tonumber(L, -1);
1944 lua_pop(L, 1);
1945
1946 lua_pushstring(L, "y");
1947 lua_rawget(L, -2);
1948 if (!lua_isnumber(L, -1))
1949 wxlua_argerror(L, stack_idx, wxT("a 'number' for y-coordinate of a wxPoint2DDouble array, valid tables are {{1,2},...}, {{x=1,y=2},...}, or {wx.wxPoint2DDouble(1,2),,...}."));
1950 y = lua_tonumber(L, -1);
1951 lua_pop(L, 1);
1952 }
1953 else
1954 {
1955 lua_rawgeti(L, -1, 1);
1956 if (!lua_isnumber(L, -1))
1957 wxlua_argerror(L, stack_idx, wxT("a 'number' for [1] index (x-coordinate) of a wxPoint2DDouble array, valid tables {{1,2},...}, {{x=1,y=2},...}, or {wx.wxPoint2DDouble(1,2),,...}."));
1958 x = lua_tonumber(L, -1);
1959 lua_pop(L, 1);
1960
1961 lua_rawgeti(L, -1, 2);
1962 if (!lua_isnumber(L, -1))
1963 wxlua_argerror(L, stack_idx, wxT("a 'number' for [2] index (y-coordinate) of a wxPoint2DDouble array, valid tables {{1,2},...}, {{x=1,y=2},...}, or {wx.wxPoint2DDouble(1,2),,...}."));
1964 y = lua_tonumber(L,-1);
1965 lua_pop(L, 1);
1966 }
1967
1968 pointArray->push_back(wxPoint2DDouble(x, y));
1969 }
1970 else if (t == *p_wxluatype_wxPoint2DDouble)
1971 {
1972 const wxPoint* point = (const wxPoint *)wxluaT_getuserdatatype(L, -1, *p_wxluatype_wxPoint);
1973 pointArray->push_back(*point);
1974 }
1975 else
1976 {
1977 wxlua_argerror(L, stack_idx, wxT("a Lua table of 'wxPoint2DDoubles', valid tables {{1,2},...}, {{x=1,y=2},...}, or {wx.wxPoint2DDouble(1,2),,...}."));
1978 return pointArray;
1979 }
1980
1981 lua_pop(L, 1);
1982 }
1983 }
1984 if (count < 0)
1985 wxlua_argerror(L, stack_idx, wxT("a Lua table of 'wxPoint2DDoubles', valid tables {{1,2},...}, {{x=1,y=2},...}, or {wx.wxPoint2DDouble(1,2),,...}."));
1986
1987 return pointArray;
1988 }
1989
wxlua_pushwxArrayStringtable(lua_State * L,const wxArrayString & strArray)1990 int LUACALL wxlua_pushwxArrayStringtable(lua_State *L, const wxArrayString &strArray)
1991 {
1992 size_t idx, count = strArray.GetCount();
1993 lua_createtable(L, count, 0);
1994
1995 for (idx = 0; idx < count; ++idx)
1996 {
1997 wxlua_pushwxString(L, strArray[idx]);
1998 lua_rawseti(L, -2, idx + 1);
1999 }
2000 return idx;
2001 }
2002
wxlua_pushwxArrayInttable(lua_State * L,const wxArrayInt & intArray)2003 int LUACALL wxlua_pushwxArrayInttable(lua_State *L, const wxArrayInt &intArray)
2004 {
2005 size_t idx, count = intArray.GetCount();
2006 lua_createtable(L, count, 0);
2007
2008 for (idx = 0; idx < count; ++idx)
2009 {
2010 #if LUA_VERSION_NUM >= 503
2011 lua_pushinteger(L, intArray[idx]);
2012 #else
2013 lua_pushnumber(L, intArray[idx]);
2014 #endif
2015 lua_rawseti(L, -2, idx + 1);
2016 }
2017 return idx;
2018 }
2019
wxlua_pushwxArrayDoubletable(lua_State * L,const wxArrayDouble & doubleArray)2020 int LUACALL wxlua_pushwxArrayDoubletable(lua_State *L, const wxArrayDouble &doubleArray)
2021 {
2022 size_t idx, count = doubleArray.GetCount();
2023 lua_createtable(L, count, 0);
2024
2025 for (idx = 0; idx < count; ++idx)
2026 {
2027 lua_pushnumber(L, doubleArray[idx]);
2028 lua_rawseti(L, -2, idx + 1);
2029 }
2030 return idx;
2031 }
2032
wxlua_pushwxString(lua_State * L,const wxString & str)2033 void LUACALL wxlua_pushwxString(lua_State* L, const wxString& str)
2034 {
2035 lua_pushstring(L, wx2lua(str));
2036 }
2037
wxlua_concatwxArrayString(const wxArrayString & arr,const wxString & sep)2038 wxString wxlua_concatwxArrayString(const wxArrayString& arr, const wxString& sep)
2039 {
2040 wxString s;
2041 size_t n, count = arr.GetCount();
2042 for (n = 0; n < count; ++n)
2043 {
2044 s += arr[n];
2045 if (n < count - 1) s += sep;
2046 }
2047
2048 return s;
2049 }
2050
wxlua_pushargs(lua_State * L,wxChar ** argv,int argc,int start_n)2051 int wxlua_pushargs(lua_State* L, wxChar **argv, int argc, int start_n)
2052 {
2053 if (argc == 0) return 0;
2054
2055 int i = 0;
2056 int narg = argc - (start_n + 1); // number of arguments to the script
2057 luaL_checkstack(L, narg + 3, "too many arguments to script");
2058 for (i = start_n+1; i < argc; i++)
2059 lua_pushstring(L, wx2lua(argv[i]));
2060
2061 lua_createtable(L, narg, start_n + 1);
2062
2063 for (i = 0; i < argc; i++)
2064 {
2065 lua_pushstring(L, wx2lua(argv[i]));
2066 lua_rawseti(L, -2, i - start_n);
2067 }
2068
2069 lua_setglobal(L, "arg");
2070
2071 return narg;
2072 }
2073
2074 //----------------------------------------------------------------------------
2075 // Derived class member functions for classes in wxLua
2076 //----------------------------------------------------------------------------
2077
wxlua_setderivedmethod(lua_State * L,void * obj_ptr,const char * method_name,wxLuaObject * wxlObj)2078 bool LUACALL wxlua_setderivedmethod(lua_State* L, void *obj_ptr, const char *method_name, wxLuaObject* wxlObj)
2079 {
2080 lua_pushlightuserdata(L, &wxlua_lreg_derivedmethods_key); // push key
2081 lua_rawget( L, LUA_REGISTRYINDEX ); // pop key, push value (table)
2082
2083 lua_pushlightuserdata(L, (void *)obj_ptr); // push key
2084 lua_rawget(L, -2); // get t[key] = value, pop key push value
2085
2086 if (!lua_istable(L, -1))
2087 {
2088 lua_pop(L, 1); // pop nil value
2089
2090 // add new table for this object
2091 lua_pushlightuserdata(L, (void *)obj_ptr); // push key
2092 lua_newtable(L); // push value
2093 lua_rawset(L, -3); // set t[key] = value; pops key and value
2094
2095 // put the new table back on the top of the stack
2096 lua_pushlightuserdata(L, (void *)obj_ptr);
2097 lua_rawget(L, -2);
2098 }
2099 else
2100 {
2101 // see if there already is a method
2102 lua_pushstring( L, method_name );
2103 lua_rawget(L, -2);
2104
2105 if (lua_islightuserdata(L, -1))
2106 {
2107 // already have a method, delete it before replacing it
2108 wxLuaObject* o = (wxLuaObject*)lua_touserdata( L, -1 );
2109 o->RemoveReference(L);
2110 delete o;
2111 }
2112
2113 lua_pop(L, 1); // pop the deleted old object, or nil
2114 }
2115
2116 lua_pushstring( L, method_name ); // push key
2117 lua_pushlightuserdata(L, (void*)wxlObj); // push value
2118 lua_rawset(L, -3); // set t[key] = value; pops key and value
2119
2120 lua_pop(L, 2); // pop the object and overridden function table
2121
2122 return true;
2123 }
wxlua_hasderivedmethod(lua_State * L,const void * obj_ptr,const char * method_name,bool push_method)2124 bool LUACALL wxlua_hasderivedmethod(lua_State* L, const void *obj_ptr, const char *method_name, bool push_method)
2125 {
2126 bool found = false;
2127 wxLuaObject* wxlObj = NULL;
2128
2129 lua_pushlightuserdata(L, &wxlua_lreg_derivedmethods_key);
2130 lua_rawget( L, LUA_REGISTRYINDEX ); // pop key, push table
2131
2132 lua_pushlightuserdata(L, (void *)obj_ptr);
2133 lua_rawget(L, -2); // pop key, push table or nil
2134
2135 if (lua_istable(L, -1))
2136 {
2137 // see if there is a method with the same name
2138 lua_pushstring( L, method_name );
2139 lua_rawget(L, -2);
2140
2141 if (lua_islightuserdata(L, -1))
2142 wxlObj = (wxLuaObject*)lua_touserdata( L, -1 );
2143
2144 lua_pop(L, 1); // pop the method object or nil
2145 }
2146
2147 lua_pop(L, 2); // pop registry table and object table or nil
2148
2149 if (wxlObj != NULL)
2150 {
2151 // if we've got the object, put it on top of the stack
2152 if (push_method && wxlObj->GetObject(L))
2153 found = true;
2154 else if (!push_method)
2155 found = true;
2156 }
2157
2158 return found;
2159 }
wxlua_removederivedmethods(lua_State * L,void * obj_ptr)2160 bool LUACALL wxlua_removederivedmethods(lua_State* L, void *obj_ptr)
2161 {
2162 bool found = false;
2163
2164 lua_pushlightuserdata(L, &wxlua_lreg_derivedmethods_key);
2165 lua_rawget( L, LUA_REGISTRYINDEX ); // pop key, push table
2166
2167 lua_pushlightuserdata(L, (void *)obj_ptr);
2168 lua_rawget(L, -2); // pop key, push table or nil
2169
2170 if (lua_istable(L, -1))
2171 {
2172 found = true;
2173
2174 // delete all of the derived methods we've pushed
2175 lua_pushnil(L);
2176 while (lua_next(L, -2) != 0)
2177 {
2178 // value at -1, key at -2, table at -3
2179 if (lua_islightuserdata(L, -1))
2180 {
2181 wxLuaObject* o = (wxLuaObject*)lua_touserdata(L, -1);
2182 o->RemoveReference(L);
2183 delete o;
2184 }
2185
2186 lua_pop(L, 1); // remove value; keep key for next iteration
2187 }
2188
2189 lua_pop(L, 1); // pop the obj table
2190
2191 lua_pushlightuserdata(L, (void *)obj_ptr); // push key
2192 lua_pushnil(L); // push value, to remove it
2193 lua_rawset(L, -3); // set t[key] = value; pop key and value
2194
2195 lua_pop(L, 1); // pop the derived table
2196 }
2197 else
2198 lua_pop(L, 2); // pop the derived table and nil for the obj table
2199
2200 return found;
2201 }
2202
2203 //----------------------------------------------------------------------------
2204 // Other functions for wxLua's keys in the
2205 //----------------------------------------------------------------------------
2206
wxlua_getcallbaseclassfunction(lua_State * L)2207 bool LUACALL wxlua_getcallbaseclassfunction(lua_State* L)
2208 {
2209 lua_pushlightuserdata(L, &wxlua_lreg_callbaseclassfunc_key);
2210 lua_rawget( L, LUA_REGISTRYINDEX ); // pop key, push bool
2211
2212 bool call_base = (0 != lua_toboolean(L, -1)); // nil == 0 too
2213 lua_pop(L, 1); // pop bool
2214
2215 return call_base;
2216 }
2217
wxlua_setcallbaseclassfunction(lua_State * L,bool call_base)2218 void LUACALL wxlua_setcallbaseclassfunction(lua_State* L, bool call_base)
2219 {
2220 lua_pushlightuserdata(L, &wxlua_lreg_callbaseclassfunc_key);
2221 lua_pushboolean(L, call_base);
2222 lua_rawset( L, LUA_REGISTRYINDEX ); // pop key and bool
2223 }
2224
wxlua_getwxeventtype(lua_State * L)2225 wxEventType LUACALL wxlua_getwxeventtype(lua_State* L)
2226 {
2227 lua_pushlightuserdata(L, &wxlua_lreg_wxeventtype_key);
2228 lua_rawget( L, LUA_REGISTRYINDEX ); // pop key, push bool
2229
2230 wxEventType evt_type = (wxEventType)lua_tonumber(L, -1);
2231 lua_pop(L, 1); // pop number
2232
2233 return evt_type;
2234 }
2235
wxlua_setwxeventtype(lua_State * L,wxEventType evt_type)2236 void LUACALL wxlua_setwxeventtype(lua_State* L, wxEventType evt_type)
2237 {
2238 lua_pushlightuserdata(L, &wxlua_lreg_wxeventtype_key);
2239 lua_pushnumber(L, evt_type);
2240 lua_rawset( L, LUA_REGISTRYINDEX ); // pop key and number
2241 }
2242
wxlua_getwxluastatedata(lua_State * L)2243 wxLuaStateData* LUACALL wxlua_getwxluastatedata(lua_State* L)
2244 {
2245 lua_pushlightuserdata(L, &wxlua_lreg_wxluastatedata_key);
2246 lua_rawget( L, LUA_REGISTRYINDEX ); // pop key, push bool
2247
2248 wxLuaStateData* data = (wxLuaStateData*)lua_touserdata(L, -1);
2249 lua_pop(L, 1); // pop udata
2250
2251 return data;
2252 }
2253