1 /////////////////////////////////////////////////////////////////////////////
2 // Name: wxlbind.cpp
3 // Purpose: wxLuaBinding
4 // Author: Ray Gilbert, John Labenski, J Winwood
5 // Created: 14/11/2001
6 // Copyright: (c) 2012 John Labenski
7 // Licence: wxWidgets licence
8 /////////////////////////////////////////////////////////////////////////////
9
10 #include <wx/wxprec.h>
11
12 #ifdef __BORLANDC__
13 #pragma hdrstop
14 #endif
15
16 #ifndef WX_PRECOMP
17 #include <wx/wx.h>
18 #endif
19
20 #include "wxlua/wxlbind.h"
21 #include "wxlua/wxlstate.h"
22
23 //#include "wxluadebug/include/wxldebug.h" // for debugging only
24
25
26 wxLuaArgType g_wxluaargtypeArray_None[1] = {0};
27
28 int wxluatype_TUNKNOWN = WXLUA_TUNKNOWN;
29 int wxluatype_TNONE = WXLUA_TNONE;
30 int wxluatype_TNIL = WXLUA_TNIL;
31 int wxluatype_TBOOLEAN = WXLUA_TBOOLEAN;
32 int wxluatype_TLIGHTUSERDATA = WXLUA_TLIGHTUSERDATA; // raw data
33 int wxluatype_TNUMBER = WXLUA_TNUMBER;
34 int wxluatype_TSTRING = WXLUA_TSTRING;
35 int wxluatype_TTABLE = WXLUA_TTABLE;
36 int wxluatype_TFUNCTION = WXLUA_TFUNCTION;
37 int wxluatype_TUSERDATA = WXLUA_TUSERDATA; // raw data
38 int wxluatype_TTHREAD = WXLUA_TTHREAD;
39 int wxluatype_TINTEGER = WXLUA_TINTEGER;
40 int wxluatype_TCFUNCTION = WXLUA_TCFUNCTION;
41 int wxluatype_TPOINTER = WXLUA_TPOINTER;
42 int wxluatype_TANY = WXLUA_TANY;
43
44 int wxluatype_NULL = WXLUATYPE_NULL;
45
46 wxLuaBindClass wxLuaBindClass_NULL =
47 { "NULL", NULL, 0, NULL, &wxluatype_NULL, NULL, NULL, NULL, NULL, NULL, 0, };
48
49 int* p_wxluatype_wxEvent = &wxluatype_TUNKNOWN;
50 int* p_wxluatype_wxWindow = &wxluatype_TUNKNOWN;
51 int* p_wxluatype_wxScrollEvent = &wxluatype_TUNKNOWN;
52 int* p_wxluatype_wxSpinEvent = &wxluatype_TUNKNOWN;
53 int* p_wxluatype_wxString = &wxluatype_TUNKNOWN;
54 int* p_wxluatype_wxArrayString = &wxluatype_TUNKNOWN;
55 int* p_wxluatype_wxSortedArrayString = &wxluatype_TUNKNOWN;
56 int* p_wxluatype_wxArrayInt = &wxluatype_TUNKNOWN;
57 int* p_wxluatype_wxArrayDouble = &wxluatype_TUNKNOWN;
58 int* p_wxluatype_wxMemoryBuffer = &wxluatype_TUNKNOWN;
59 int* p_wxluatype_wxPoint = &wxluatype_TUNKNOWN;
60 int* p_wxluatype_wxPoint2DDouble = &wxluatype_TUNKNOWN;
61
62 // ----------------------------------------------------------------------------
63 // wxlua_tableErrorHandler
64 // ----------------------------------------------------------------------------
65
66 /*
67 static int LUACALL wxlua_tableErrorHandler(lua_State *L)
68 {
69 wxlua_error(L, "Cannot modify read-only wxLua table");
70 return 0;
71 }
72 */
73
74 // ----------------------------------------------------------------------------
75 // Generic delete function for bindings
76 // ----------------------------------------------------------------------------
77
wxlua_userdata_delete(lua_State * L)78 int LUACALL wxlua_userdata_delete(lua_State *L)
79 {
80 // if removed from tracked mem list, remove the metatable so that __gc is not called on this object.
81 if (wxluaO_deletegcobject(L, 1, WXLUA_DELETE_OBJECT_ALL))
82 {
83 lua_pushnil(L);
84 lua_setmetatable(L, -2);
85 }
86 else
87 {
88 wxString msg;
89 msg.Printf(wxT("wxLua: Unable to call wxuserdata:delete() on object!"));
90
91 // leave this printf since we really want to know if this happens
92 wxPrintf(wxString(msg + wxT("\n")).c_str());
93 wxlua_argerrormsg(L, msg);
94 }
95
96 return 0;
97 }
98
99 // ----------------------------------------------------------------------------
100 // If the class defines a gc function, then call it.
101 // ----------------------------------------------------------------------------
102
wxlua_wxLuaBindClass__gc(lua_State * L)103 int LUACALL wxlua_wxLuaBindClass__gc(lua_State *L)
104 {
105 wxLuaBindClass *wxlClass = (wxLuaBindClass *)lua_touserdata(L, lua_upvalueindex(1));
106
107 if ((wxlClass != NULL) && wxlua_iswxuserdata(L, 1) && (wxluaT_type(L, 1) == *wxlClass->wxluatype))
108 {
109 // clean up the rest of this, this won't error if the key doesn't exist
110 wxluaO_deletegcobject(L, 1, WXLUA_DELETE_OBJECT_LAST);
111 }
112
113 return 0;
114 }
115
116 // ----------------------------------------------------------------------------
117 // Called by LUA to find the method that corresponds to a __index method name.
118 // ----------------------------------------------------------------------------
119
wxlua_wxLuaBindClass__index(lua_State * L)120 int LUACALL wxlua_wxLuaBindClass__index(lua_State *L)
121 {
122 // This function is called for the __index metatable of the wxLua userdata
123 // for class instances.
124
125 // Lua stack : 1 = userdata, 2 = key; userdata:key()
126 // You cannot seem to get the calling convention (. or :) or if it was
127 // called as a function() or a .member?
128
129 // See below, if _XXX is called then we set this flag so that
130 // the called function knows to call the base class instead of recalling
131 // the Lua function and recursing.
132 wxlua_setcallbaseclassfunction(L, false);
133
134 bool found = false;
135 int result = 0;
136 wxLuaBindClass *wxlClass = (wxLuaBindClass *)lua_touserdata(L, lua_upvalueindex(1));
137 wxCHECK_MSG(wxlClass, 0, wxT("Invalid wxLuaBindClass")); // fail hard
138
139 void *obj_ptr = wxlua_touserdata(L, 1, false);
140 const char *name = lua_tostring(L, 2); // name of the __index method called in Lua
141
142 if (!name)
143 {
144 // name is NULL if it's not a string
145 wxlua_error(L, wxString::Format(_("wxLua: Attempt to call a class method using '%s' on a '%s' wxLua type."),
146 wxlua_luaL_typename(L, 2).c_str(), lua2wx(wxlClass->name).c_str()).c_str());
147 }
148 else if (wxluaT_type(L, 1) == *wxlClass->wxluatype)
149 {
150 // check if we're to call the baseclass function or if it's a Lua derived function
151 bool callbase = (name[0] == '_');
152
153 if (callbase)
154 name++; // skip past "_"[FunctionName]
155 else
156 {
157 // if there's a derived method in Lua, push it onto the stack to be run
158 if (wxlua_hasderivedmethod(L, obj_ptr, name, true))
159 {
160 found = true;
161 result = 1; // the function for Lua to call is on the stack
162 }
163 }
164
165 // Search through the bindings for the function to call
166 if (!found)
167 {
168 wxLuaBindMethod* wxlMethod = wxLuaBinding::GetClassMethod(wxlClass, name, WXLUAMETHOD_METHOD|WXLUAMETHOD_GETPROP, true);
169
170 if ((wxlMethod != NULL) && (wxlMethod->wxluacfuncs != NULL))
171 {
172 if (WXLUA_HASBIT(wxlMethod->method_type, WXLUAMETHOD_GETPROP))
173 {
174 // The user wants to call the C++ function as a property
175 // which is treated as though it were a member variable.
176 // It shouldn't have been called as a function with ()
177 // and so we call the function here and leave the value on the stack.
178 found = true;
179 if (WXLUA_HASBIT(wxlMethod->method_type, WXLUAMETHOD_STATIC))
180 lua_pop(L, 2); // remove the userdata and func name
181 else
182 lua_pop(L, 1); // remove the name of the function
183
184 result = (*wxlMethod->wxluacfuncs[0].lua_cfunc)(L);
185 }
186 else
187 {
188 // The user has called a real C++ function and if it's
189 // overloaded we call wxlua_callOverloadedFunction() to
190 // find the correct one to call.
191 found = true;
192 result = 1;
193
194 lua_pushlightuserdata(L, wxlMethod);
195
196 if ((wxlMethod->wxluacfuncs_n > 1) || (wxlMethod->basemethod))
197 lua_pushcclosure(L, wxlua_callOverloadedFunction, 1);
198 else
199 lua_pushcclosure(L, wxlMethod->wxluacfuncs[0].lua_cfunc, 1);
200 }
201 }
202
203 // Maybe this is an undeclared property? Prepend 'Get' and try again.
204 if (!found)
205 {
206 int len = strlen(name);
207 wxCharBuffer buf(len + 4);
208 char* str = buf.data();
209 str[0] = 'G'; str[1] = 'e'; str[2] = 't';
210 memcpy(str+3, name, len+1); // include terminating NULL
211
212 wxlMethod = wxLuaBinding::GetClassMethod(wxlClass, str, WXLUAMETHOD_METHOD, true);
213
214 if ((wxlMethod != NULL) && WXLUA_HASBIT(wxlMethod->method_type, WXLUAMETHOD_METHOD))
215 //wxlMethod->funcs && (wxlMethod->funcs->minargs == 0) && // let it error out
216 //(wxlMethod->funcs->maxargs == 0))
217 {
218 found = true;
219 if (WXLUA_HASBIT(wxlMethod->method_type, WXLUAMETHOD_STATIC))
220 lua_pop(L, 2); // remove the userdata and func name
221 else
222 lua_pop(L, 1); // remove the name of the function
223
224 result = (*wxlMethod->wxluacfuncs[0].lua_cfunc)(L);
225 }
226 }
227
228 // This MUST be reset to false in the base class function
229 if (found && callbase) wxlua_setcallbaseclassfunction(L, true);
230 }
231 }
232
233 return result;
234 }
235
236 // ----------------------------------------------------------------------------
237 // Called by LUA to find the method that corresponds to a __newindex method name.
238 // ----------------------------------------------------------------------------
239
wxlua_wxLuaBindClass__newindex(lua_State * L)240 int LUACALL wxlua_wxLuaBindClass__newindex(lua_State *L)
241 {
242 wxLuaBindClass *wxlClass = (wxLuaBindClass *)lua_touserdata(L, lua_upvalueindex(1));
243 wxCHECK_MSG(wxlClass, 0, wxT("Invalid wxLuaBindClass")); // fail hard
244
245 // Lua Stack: 1 = userdata, 2 = key, 3 = value; userdata.key = value
246
247 const char *name = lua_tostring(L, 2);
248 bool found = false;
249
250 if (!name)
251 {
252 // name is NULL if it's not a string
253 wxlua_error(L, wxString::Format(_("wxLua: Attempt to call or add a class method using '%s' on a '%s' type."),
254 wxlua_luaL_typename(L, 2).c_str(), lua2wx(wxlClass->name).c_str()).c_str());
255 }
256 else if (wxluaT_type(L, 1) == *wxlClass->wxluatype)
257 {
258 // See if there is a WXLUAMETHOD_SETPROP in the wxLuaBindClass's wxLuaBindMethods
259 wxLuaBindMethod *wxlMethod = wxLuaBinding::GetClassMethod(wxlClass, name, WXLUAMETHOD_SETPROP, true);
260
261 if (wxlMethod != NULL)
262 {
263 found = true;
264 lua_remove(L, 2); // remove the function name
265 if (WXLUA_HASBIT(wxlMethod->method_type, WXLUAMETHOD_STATIC))
266 lua_remove(L, 1); // remove the userdata too, leaving the value
267
268 (*wxlMethod->wxluacfuncs[0].lua_cfunc)(L);
269 }
270 else
271 {
272 // Maybe this is an undeclared property? Prepend 'Set' and try again.
273 int len = strlen(name);
274 wxCharBuffer buf(len + 4);
275 char* str = buf.data();
276 str[0] = 'S'; str[1] = 'e'; str[2] = 't';
277 memcpy(str+3, name, len+1); // include terminating NULL
278
279 wxlMethod = wxLuaBinding::GetClassMethod(wxlClass, str, WXLUAMETHOD_METHOD, true);
280 if ((wxlMethod != NULL) && WXLUA_HASBIT(wxlMethod->method_type, WXLUAMETHOD_METHOD))
281 {
282 found = true;
283 lua_remove(L, 2); // remove the function name
284 if (WXLUA_HASBIT(wxlMethod->method_type, WXLUAMETHOD_STATIC))
285 lua_remove(L, 1); // remove the userdata too, leaving the value
286
287 (*wxlMethod->wxluacfuncs[0].lua_cfunc)(L);
288 }
289 }
290
291 // They want to add this to the class so store it in the derived method table
292 if (!found)
293 {
294 found = true;
295
296 void *obj_ptr = wxlua_touserdata(L, 1, false);
297 wxLuaObject* wxlObj = new wxLuaObject(L, 3);
298 wxlua_setderivedmethod(L, obj_ptr, name, wxlObj);
299 }
300 }
301
302 if (!found)
303 {
304 wxlua_error(L, wxString::Format(_("wxLua: Unable to call or add an unknown method '%s' on a '%s' type."),
305 lua2wx(name).c_str(), lua2wx(wxlClass ? wxlClass->name : "").c_str()).c_str());
306 }
307
308 return 0;
309 }
310
311 // ----------------------------------------------------------------------------
312 // wxlua_wxLuaBindClass__tostring
313 // ----------------------------------------------------------------------------
314
wxlua_wxLuaBindClass__tostring(lua_State * L)315 int LUACALL wxlua_wxLuaBindClass__tostring(lua_State *L)
316 {
317 // this should be identical to Lua's tostring for a userdata
318 wxString str = wxString::Format(wxT("userdata: %p"), lua_touserdata(L, 1));
319
320 int wxl_type = wxluaT_type(L, 1);
321 if (wxlua_iswxuserdatatype(wxl_type))
322 {
323 wxString name = wxluaT_typename(L, wxl_type);
324 if (!name.IsEmpty())
325 {
326 // GCC prints '(' for NULL %p for some reason.
327 void* p = wxlua_touserdata(L, 1, false);
328 if (p)
329 str += wxString::Format(wxT(" [%s(%p, %d)]"), name.c_str(), p, wxl_type);
330 else
331 str += wxString::Format(wxT(" [%s(0x0, %d)]"), name.c_str(), wxl_type);
332 }
333 }
334 else
335 str += wxT(" [??? Unknown wxLua class type!]"); // get people's attention
336
337 lua_pushstring(L, wx2lua(str));
338 return 1;
339 }
340
341 // ----------------------------------------------------------------------------
342 // The __call metatable function to allow the class tables to be called as functions
343 // ----------------------------------------------------------------------------
344
wxlua_wxLuaBindMethod_table__call(lua_State * L)345 int LUACALL wxlua_wxLuaBindMethod_table__call(lua_State *L)
346 {
347 lua_remove(L, 1); // remove the table
348
349 return wxlua_callOverloadedFunction(L);
350 }
351
wxlua_wxLuaBindMethod_table__index(lua_State * L)352 int LUACALL wxlua_wxLuaBindMethod_table__index(lua_State *L)
353 {
354 // Lua stack: 1 = table, 2 = key
355
356 wxLuaBindClass *wxlClass = (wxLuaBindClass *)lua_touserdata(L, lua_upvalueindex(1));
357 wxCHECK_MSG(wxlClass, 0, wxT("Invalid wxLuaBindClass")); // fail hard
358
359 int result = 0;
360
361 const char* name = lua_tostring(L, 2);
362 if (!name)
363 {
364 // name is NULL if it's not a string
365 wxlua_error(L, wxString::Format(_("wxLua: Attempt to call a static class method using '%s' on a '%s' type."),
366 wxlua_luaL_typename(L, 2).c_str(), lua2wx(wxlClass->name).c_str()).c_str());
367 return 0;
368 }
369
370 wxLuaBindMethod* wxlMethod = wxLuaBinding::GetClassMethod(wxlClass, name, WXLUAMETHOD_GETPROP, true);
371
372 if (wxlMethod && WXLUA_HASBIT(wxlMethod->method_type, WXLUAMETHOD_STATIC))
373 {
374 lua_pop(L, 2); // remove the table and the name of the function
375 result = (*wxlMethod->wxluacfuncs[0].lua_cfunc)(L);
376 }
377 else
378 {
379 lua_pushvalue(L, -1); // copy key
380 lua_rawget(L, -3); // get t[key] = value, pops key pushes value
381 result = 1; // ok if nil
382 }
383
384 return result;
385 }
386
wxlua_wxLuaBindMethod_table__newindex(lua_State * L)387 int LUACALL wxlua_wxLuaBindMethod_table__newindex(lua_State *L)
388 {
389 // 1 = table, 2 = key, 3 = value
390
391 wxLuaBindClass *wxlClass = (wxLuaBindClass *)lua_touserdata(L, lua_upvalueindex(1));
392 wxCHECK_MSG(wxlClass, 0, wxT("Invalid wxLuaBindClass"));
393
394 const char* name = lua_tostring(L, 2);
395 if (!name)
396 {
397 // name is NULL if it's not a string
398 wxlua_error(L, wxString::Format(_("wxLua: Attempt to call a static class method using '%s' on a '%s' type."),
399 wxlua_luaL_typename(L, 2).c_str(), lua2wx(wxlClass->name).c_str()).c_str());
400 return 0;
401 }
402
403 wxLuaBindMethod* wxlMethod = wxLuaBinding::GetClassMethod(wxlClass, name, WXLUAMETHOD_SETPROP, true);
404
405 if (wxlMethod && WXLUA_HASBIT(wxlMethod->method_type, WXLUAMETHOD_STATIC))
406 {
407 lua_remove(L, 2); // remove the key
408 lua_remove(L, 1); // remove the table
409 (*wxlMethod->wxluacfuncs[0].lua_cfunc)(L);
410 }
411 else
412 {
413 lua_pushvalue(L, -2); // copy key
414 lua_pushvalue(L, -2); // copy value
415 lua_rawset(L, -5); // set t[key] = value, pops key and value
416 }
417
418 return 0;
419 }
420
421 // ----------------------------------------------------------------------------
422 // Central function to call for overloaded functions
423 // ----------------------------------------------------------------------------
424
wxlua_callOverloadedFunction(lua_State * L)425 int LUACALL wxlua_callOverloadedFunction(lua_State* L)
426 {
427 wxLuaBindMethod* wxlMethod = (wxLuaBindMethod *)lua_touserdata(L, lua_upvalueindex(1)); // lightuserdata
428 wxCHECK_MSG(wxlMethod, 0, wxT("Invalid wxLuaBindMethod"));
429
430 if ((wxlMethod->wxluacfuncs_n > 1) || (wxlMethod->basemethod))
431 return wxlua_callOverloadedFunction(L, wxlMethod);
432 else
433 return (*wxlMethod->wxluacfuncs[0].lua_cfunc)(L);
434 }
435
wxlua_callOverloadedFunction(lua_State * L,struct wxLuaBindMethod * wxlMethod)436 int LUACALL wxlua_callOverloadedFunction(lua_State* L, struct wxLuaBindMethod* wxlMethod)
437 {
438 // get number of arguments called from Lua
439 int i, arg, arg_lua_count = lua_gettop(L);
440
441 // only look at the methods that could possibly work and traverse base classes
442 wxArrayPtrVoid cfuncArray;
443 wxLuaBindMethod* method = wxlMethod;
444 while (method)
445 {
446 wxLuaBindCFunc* wxlCFunc = method->wxluacfuncs;
447
448 for (i = 0; i < method->wxluacfuncs_n; ++i, ++wxlCFunc)
449 {
450 if ((arg_lua_count >= wxlCFunc->minargs) &&
451 (arg_lua_count <= wxlCFunc->maxargs))
452 {
453 cfuncArray.Add(wxlCFunc);
454 }
455 }
456
457 method = method->basemethod;
458 }
459
460 wxLuaBindCFunc* bestCFunc = NULL; // stores the last function that worked.
461 int invalid_lua_arg = 1; // arg that failed
462 int cfunc_count = cfuncArray.GetCount();
463
464 // Look at the available functions in parallel, per arg
465 for (arg = 0; (arg < arg_lua_count) && (cfunc_count != 0); ++arg)
466 {
467 int arg_lua = arg+1; // arg N on the Lua stack
468 int ltype = lua_type(L, arg_lua);
469
470 for (i = 0; i < cfunc_count; ++i)
471 {
472 wxLuaBindCFunc* wxlCFunc = (wxLuaBindCFunc*)cfuncArray[i];
473 bestCFunc = wxlCFunc;
474 invalid_lua_arg = arg_lua;
475
476 // does this method have any more arguments?
477 if (!wxlCFunc->argtypes[arg])
478 {
479 cfuncArray.RemoveAt(i);
480 cfunc_count--;
481 i--;
482 continue;
483 }
484
485 // get argument wxLua type
486 int wxl_type = (int)*(wxlCFunc->argtypes[arg]);
487
488 // Does the Lua type match the wxLua type
489 int is_ok = wxlua_iswxluatype(ltype, wxl_type, L);
490
491 // unknown/invalid standard wxLua type, check binding wxLua type
492 if ((is_ok == -1) || ((is_ok == 0) && (wxl_type == WXLUA_TSTRING)))
493 {
494 is_ok = (wxluaT_isuserdatatype(L, arg_lua, wxl_type) ||
495 (wxl_type == wxluatype_NULL)) ? 1 : 0;
496 }
497
498 // this arg is not a match, remove this function as a possibility
499 if (is_ok == 0)
500 {
501 cfuncArray.RemoveAt(i);
502 cfunc_count--;
503 i--;
504 continue;
505 }
506 }
507 }
508
509 // Note that the top function is the one that is highest in the
510 // derived functions from any baseclasses and should be the best choice.
511 // Example is wxBookCtrlBaseEvent::GetSelection() and wxCommandEvent::GetSelection()
512 if (cfunc_count > 0)
513 {
514 lua_CFunction lua_cfunc = ((wxLuaBindCFunc*)cfuncArray[0])->lua_cfunc;
515
516 // successfully found overloaded function to handle wxLua call
517 return (*lua_cfunc)(L);
518 }
519
520 // ----------------------------------------------------------------------
521 // Did not find a suitable function to call, post error
522
523 wxString fnCall = wxlua_getLuaArgsMsg(L, 1, arg_lua_count);
524
525 wxString fnOverloadList = wxString::Format(wxT("Function called: '%s'\n"), fnCall.c_str());
526 fnOverloadList += wxlua_getBindMethodArgsMsg(L, wxlMethod);
527
528 wxString errmsg;
529
530 if (cfunc_count > 1) // Note: we actually allow this.. for now
531 {
532 errmsg = wxT("wxLua: Function call is ambiguous.\nTry coercing values to proper types using tostring/number as appropriate.\n");
533 }
534
535 if (bestCFunc == NULL)
536 errmsg += wxT("wxLua: Function call has invalid arguments.");
537 else
538 {
539 // We have to count the methods that are displayed to find the one that failed
540 // since we've skipped the ones with wrong number of args.
541 method = wxlMethod;
542 int i_cfunc = 0;
543 bool found = false;
544 while (method && !found)
545 {
546 for (i = 0; i < method->wxluacfuncs_n; ++i)
547 {
548 i_cfunc++;
549 if (&method->wxluacfuncs[i] == bestCFunc)
550 {
551 found = true;
552 break;
553 }
554 }
555
556 method = method->basemethod;
557 }
558
559 errmsg += wxString::Format(wxT("wxLua: Function call has invalid argument %d on method %02d.\n"), invalid_lua_arg, i_cfunc);
560 }
561
562 errmsg += wxT("\n") + fnOverloadList;
563
564 wxlua_error(L, errmsg.c_str());
565
566 return 0;
567 }
568
wxlua_getLuaArgsMsg(lua_State * L,int start_stack_idx,int end_stack_idx)569 wxString wxlua_getLuaArgsMsg(lua_State* L, int start_stack_idx, int end_stack_idx)
570 {
571 lua_Debug ar = {0};
572
573 // NOTE: We'd like to be able to give some info, however if we are not
574 // running a Lua function the lua_Debug is empty and lua_getinfo() will panic.
575 if (lua_getstack(L, 0, &ar) == 0) // returns 0 when called on a level greater than stack depth
576 return wxT("?");
577
578 lua_getinfo(L, "n", &ar);
579 wxString funcName = lua2wx(ar.name);
580
581 wxString funcCall = funcName + wxT("(");
582
583 for (int arg = start_stack_idx; arg <= end_stack_idx; ++arg)
584 {
585 if (arg > start_stack_idx) funcCall += wxT(", ");
586
587 funcCall += wxluaT_gettypename(L, arg);
588 }
589 funcCall += wxT(")");
590
591 return funcCall;
592 }
593
wxlua_getBindMethodArgsMsg(lua_State * L,struct wxLuaBindMethod * wxlMethod)594 wxString wxlua_getBindMethodArgsMsg(lua_State* L, struct wxLuaBindMethod* wxlMethod)
595 {
596 wxCHECK_MSG(wxlMethod, wxEmptyString, wxT("Invalid method table"));
597
598 wxString overloadMethods;
599
600 int i_cfunc = 0; // count total number of overloads
601 wxLuaBindMethod* method = wxlMethod;
602
603 // traverse the methods down the baseclass methods if any
604 while (method)
605 {
606 wxLuaBindCFunc* wxluacfuncs = method->wxluacfuncs;
607 int i, arg, cfuncs_count = method->wxluacfuncs_n;
608
609 const wxLuaBindClass* wxlClass = wxLuaBinding::FindBindClass(method);
610 for (i = 0; i < cfuncs_count; ++i)
611 {
612 i_cfunc++;
613
614 wxString className;
615 if (wxlClass && !WXLUA_HASBIT(wxluacfuncs[i].method_type, WXLUAMETHOD_CONSTRUCTOR))
616 className = lua2wx(wxlClass->name) + wxT(".");
617
618 wxString funcStr = wxString::Format(wxT("%02d. %s%s("), i_cfunc, className.c_str(), lua2wx(method->name).c_str());
619
620 for (arg = 0; arg < wxluacfuncs[i].maxargs; ++arg)
621 {
622 // optional args?
623 if ((wxluacfuncs[i].minargs < wxluacfuncs[i].maxargs) && (arg == wxluacfuncs[i].minargs))
624 {
625 if (arg > 0) funcStr += wxT(" ");
626 funcStr += wxT("[");
627 }
628
629 if (arg > 0)
630 funcStr += wxT(", ");
631
632 int wxl_type = (int)*(wxluacfuncs[i].argtypes[arg]);
633 funcStr += wxluaT_typename(L, wxl_type);
634
635 if ((arg == 0) &&
636 !WXLUA_HASBIT(wxluacfuncs[i].method_type, WXLUAMETHOD_STATIC) &&
637 !WXLUA_HASBIT(wxluacfuncs[i].method_type, WXLUAMETHOD_CONSTRUCTOR) &&
638 !WXLUA_HASBIT(wxluacfuncs[i].method_type, WXLUAMETHOD_CFUNCTION))
639 funcStr += wxT("(self)");
640 }
641
642 // close optional args
643 if (wxluacfuncs[i].minargs < wxluacfuncs[i].maxargs)
644 funcStr += wxT("]");
645
646 funcStr += wxT(")");
647
648 if (WXLUA_HASBIT(wxluacfuncs[i].method_type, WXLUAMETHOD_STATIC))
649 funcStr += wxT(" - static");
650
651 if (overloadMethods.Length() > 0)
652 overloadMethods += wxT("\n") + funcStr;
653 else
654 overloadMethods += funcStr;
655 }
656
657 method = method->basemethod;
658 }
659
660 return overloadMethods;
661 }
662
663 // ----------------------------------------------------------------------------
664 // Functions to compare binding structs using qsort and bsearch
665 // ----------------------------------------------------------------------------
666
667 // Function to compare to wxLuaBindEvents by eventType
wxLuaBindEvent_CompareByEventTypeFn(const void * p1,const void * p2)668 int wxLuaBindEvent_CompareByEventTypeFn(const void *p1, const void *p2)
669 {
670 return (*((const wxLuaBindEvent*)p1)->eventType) - (*((const wxLuaBindEvent*)p2)->eventType);
671 }
672 // Function to compare to wxLuaBindNumber by name
wxLuaBindNumber_CompareByNameFn(const void * p1,const void * p2)673 int wxLuaBindNumber_CompareByNameFn(const void *p1, const void *p2)
674 {
675 return strcmp(((const wxLuaBindNumber*)p1)->name, ((const wxLuaBindNumber*)p2)->name);
676 }
677 // Function to compare to wxLuaBindStrings by name
wxLuaBindString_CompareByNameFn(const void * p1,const void * p2)678 int wxLuaBindString_CompareByNameFn(const void *p1, const void *p2)
679 {
680 return strcmp(((const wxLuaBindString*)p1)->name, ((const wxLuaBindString*)p2)->name);
681 }
682 // Function to compare to wxLuaBindObjects by name
wxLuaBindObject_CompareByNameFn(const void * p1,const void * p2)683 int wxLuaBindObject_CompareByNameFn(const void *p1, const void *p2)
684 {
685 return strcmp(((const wxLuaBindObject*)p1)->name, ((const wxLuaBindObject*)p2)->name);
686 }
687 // Function to compare to wxLuaBindMethods by name
wxLuaBindMethod_CompareByNameFnInit(const void * p1,const void * p2)688 int wxLuaBindMethod_CompareByNameFnInit(const void *p1, const void *p2)
689 {
690 int v = strcmp(((const wxLuaBindMethod*)p1)->name, ((const wxLuaBindMethod*)p2)->name);
691 if (v == 0)
692 {
693 int t1 = ((const wxLuaBindMethod*)p1)->method_type;
694 int t2 = ((const wxLuaBindMethod*)p2)->method_type;
695 v = t1 - t2;
696 }
697
698 wxCHECK_MSG(v != 0, 0, wxT("Duplicate wxLuaBindMethod names and method_types"));
699
700 return v;
701 }
702 // Function for wxLuaBinding::GetClassMethod()
wxLuaBindMethod_CompareByNameFnGet(const void * p1,const void * p2)703 int wxLuaBindMethod_CompareByNameFnGet(const void *p1, const void *p2)
704 {
705 int v = strcmp(((const wxLuaBindMethod*)p1)->name, ((const wxLuaBindMethod*)p2)->name);
706 if (v == 0)
707 {
708 int t1 = ((const wxLuaBindMethod*)p1)->method_type;
709 int t2 = ((const wxLuaBindMethod*)p2)->method_type;
710
711 if ((t1 & t2) != 0) return 0; // any matched bits will work
712
713 v = t1 - t2;
714 }
715
716 return v;
717 }
718 // Function to compare the wxLuaBindClasses by name
wxLuaBindClass_CompareByNameFn(const void * p1,const void * p2)719 int wxLuaBindClass_CompareByNameFn(const void *p1, const void *p2)
720 {
721 return strcmp(((const wxLuaBindClass*)p1)->name, ((const wxLuaBindClass*)p2)->name);
722 }
723 // Function to compare the wxLuaBindClasses by wxluatype
wxLuaBindClass_CompareBywxLuaTypeFn(const void * p1,const void * p2)724 int wxLuaBindClass_CompareBywxLuaTypeFn(const void *p1, const void *p2)
725 {
726 return (*((const wxLuaBindClass*)p1)->wxluatype) - (*((const wxLuaBindClass*)p2)->wxluatype);
727 }
728
729 // ----------------------------------------------------------------------------
730 // wxLuaBinding
731 // ----------------------------------------------------------------------------
732
733 IMPLEMENT_ABSTRACT_CLASS(wxLuaBinding, wxObject)
734
735 wxLuaBindingArray wxLuaBinding::sm_bindingArray;
736 int wxLuaBinding::sm_bindingArray_initialized = 0;
737 int wxLuaBinding::sm_wxluatype_max = WXLUA_T_MAX+1; // highest wxLua type initially
738
wxLuaBinding()739 wxLuaBinding::wxLuaBinding()
740 :m_classCount(0), m_classArray(NULL),
741 m_numberCount(0), m_numberArray(NULL),
742 m_stringCount(0), m_stringArray(NULL),
743 m_eventCount(0), m_eventArray(NULL),
744 m_objectCount(0), m_objectArray(NULL),
745 m_functionCount(0), m_functionArray(NULL),
746 m_first_wxluatype(WXLUA_TUNKNOWN),
747 m_last_wxluatype(WXLUA_TUNKNOWN)
748 {
749 }
750
InitBinding()751 void wxLuaBinding::InitBinding()
752 {
753 // Sort all the bindings by something useful for faster lookup later
754
755 if (m_classArray && (m_classCount > 0))
756 {
757 // initialize types only once, we don't need to resort them either
758 if (*m_classArray[0].wxluatype != WXLUA_TUNKNOWN)
759 return;
760
761 qsort(m_classArray, m_classCount, sizeof(wxLuaBindClass), wxLuaBindClass_CompareByNameFn);
762
763 wxLuaBindClass* wxlClass = m_classArray;
764 for (size_t i = 0; i < m_classCount; ++i, ++wxlClass)
765 {
766 *wxlClass->wxluatype = ++wxLuaBinding::sm_wxluatype_max;
767
768 // Also sort the member functions for each class
769 if (wxlClass->wxluamethods && (wxlClass->wxluamethods_n > 0))
770 qsort(wxlClass->wxluamethods, wxlClass->wxluamethods_n, sizeof(wxLuaBindMethod), wxLuaBindMethod_CompareByNameFnInit);
771 // And their enums
772 if (wxlClass->enums && (wxlClass->enums_n > 0))
773 qsort(wxlClass->enums, wxlClass->enums_n, sizeof(wxLuaBindNumber), wxLuaBindNumber_CompareByNameFn);
774 }
775
776 // these mark what types numbers are declared in this binding
777 m_first_wxluatype = *m_classArray[0].wxluatype;
778 m_last_wxluatype = *m_classArray[m_classCount-1].wxluatype;
779 }
780
781 if (m_numberArray && (m_numberCount > 0))
782 qsort(m_numberArray, m_numberCount, sizeof(wxLuaBindNumber), wxLuaBindNumber_CompareByNameFn);
783
784 if (m_stringArray && (m_stringCount > 0))
785 qsort(m_stringArray, m_stringCount, sizeof(wxLuaBindString), wxLuaBindString_CompareByNameFn);
786
787 // sort by event type for fastest lookup
788 if (m_eventArray && (m_eventCount > 0))
789 qsort(m_eventArray, m_eventCount, sizeof(wxLuaBindEvent), wxLuaBindEvent_CompareByEventTypeFn);
790
791 if (m_objectArray && (m_objectCount > 0))
792 qsort(m_objectArray, m_objectCount, sizeof(wxLuaBindObject), wxLuaBindObject_CompareByNameFn);
793 }
794
795 // static
RegisterBindings(const wxLuaState & wxlState)796 bool wxLuaBinding::RegisterBindings(const wxLuaState& wxlState)
797 {
798 wxCHECK_MSG(wxlState.Ok(), false, wxT("Invalid wxLuaState"));
799
800 lua_State *L = wxlState.GetLuaState();
801 size_t n, binding_count = sm_bindingArray.GetCount();
802
803 wxLuaBinding::InitAllBindings(); // only runs the first time through
804
805 for (n = 0; n < binding_count; ++n)
806 {
807 sm_bindingArray[n]->RegisterBinding(wxlState);
808 lua_pop(L, 1); // pop the Lua table the binding was installed into
809 }
810
811 return true;
812 }
813
RegisterBinding(const wxLuaState & wxlState)814 bool wxLuaBinding::RegisterBinding(const wxLuaState& wxlState)
815 {
816 wxCHECK_MSG(wxlState.Ok(), false, wxT("Invalid wxLuaState"));
817 lua_State *L = wxlState.GetLuaState();
818
819 // Let Lua create a new table for us and add it to these places.
820 // We use an empty luaL_Reg since we just want luaL_register to create the
821 // tables for us, but we want to install the elements ourselves since
822 // wxLua is too large to follow the luaL_register method without being
823 // wasteful of memory and slow down the initialization.
824 // LUA_REGISTRYINDEX["_LOADED"][m_nameSpace] = table
825 // LUA_GLOBALSINDEX[m_nameSpace] = table
826 // LUA_GLOBALSINDEX["package"]["loaded"][m_nameSpace] = table
827 static const luaL_Reg wxlualib[] = { {NULL, NULL} };
828
829 wxLuaState::luaL_Register(L, wx2lua(m_nameSpace), wxlualib);
830
831 // luaL_register should have given an error message about why it couldn't
832 // create the table for us
833 if (!lua_istable(L, -1))
834 {
835 lua_pop(L, 1); // pop the nil value
836 return false;
837 }
838
839 // Find a registered binding with the same namespace, if any,
840 // and share the table with that of the previously loaded binding
841 int luaTable_ref = -1;
842
843 lua_pushlightuserdata(L, &wxlua_lreg_wxluabindings_key); // push key
844 lua_rawget(L, LUA_REGISTRYINDEX); // pop key, push value (the bindings table)
845
846 lua_pushnil(L);
847 while (lua_next(L, -2) != 0)
848 {
849 // value = -1, key = -2, table = -3
850 wxLuaBinding* binding = (wxLuaBinding*)lua_touserdata(L, -2);
851
852 if (binding->GetLuaNamespace() == m_nameSpace)
853 {
854 luaTable_ref = (int)lua_tonumber(L, -1);
855 lua_pop(L, 2); // pop key and value
856 break;
857 }
858
859 lua_pop(L, 1); // pop value, lua_next will pop key at end
860 }
861
862 lua_pop(L, 1); // pop table
863
864
865 // first time adding this namespace table
866 if (luaTable_ref < 1)
867 {
868 // create a ref for the wxLua table we're filling
869 luaTable_ref = wxluaR_ref(L, -1, &wxlua_lreg_refs_key);
870 }
871
872 // Add us to the LUA_REGISTRYINDEX table of bindings
873 lua_pushlightuserdata(L, &wxlua_lreg_wxluabindings_key); // push key
874 lua_rawget(L, LUA_REGISTRYINDEX); // pop key, push value (the bindings table)
875
876 lua_pushlightuserdata(L, this); // push key
877 lua_pushnumber(L, luaTable_ref); // push value
878 lua_rawset(L, -3); // set t[key] = value; pop key and value
879 lua_pop(L, 1); // pop table
880
881 // register all our classes etc. in the wxLua table
882 DoRegisterBinding(wxlState);
883
884 return true;
885 }
886
DoRegisterBinding(const wxLuaState & wxlState) const887 void wxLuaBinding::DoRegisterBinding(const wxLuaState& wxlState) const
888 {
889 wxCHECK_RET(wxlState.Ok(), wxT("Invalid wxLuaState"));
890 lua_State *L = wxlState.GetLuaState();
891
892 size_t n;
893
894 // install the classes, functions and methods, creating new wxLua types
895 // if this is the first time we're registering them
896 const wxLuaBindClass *wxlClass = m_classArray;
897 for (n = 0; n < m_classCount; ++n, ++wxlClass)
898 {
899 InstallClassMetatable(L, wxlClass);
900 InstallClass(L, wxlClass);
901 }
902
903 // register the global C style functions
904 const wxLuaBindMethod* wxlMethod = m_functionArray;
905 for (n = 0; n < m_functionCount; ++n, ++wxlMethod)
906 {
907 lua_pushstring(L, wxlMethod->name);
908 lua_pushlightuserdata(L, (void*)wxlMethod);
909 lua_pushcclosure(L, wxlMethod->wxluacfuncs[0].lua_cfunc, 1);
910 lua_rawset(L, -3);
911 }
912
913 // install the numerical definitions
914 const wxLuaBindNumber* wxlNumber = m_numberArray;
915 for (n = 0; n < m_numberCount; ++n, ++wxlNumber)
916 {
917 lua_pushstring(L, wxlNumber->name);
918 lua_pushnumber(L, wxlNumber->value);
919 lua_rawset(L, -3);
920 }
921
922 // install the strings
923 const wxLuaBindString *wxlString = m_stringArray;
924 for (n = 0; n < m_stringCount; ++n, ++wxlString)
925 {
926 lua_pushstring(L, wxlString->name);
927 if (wxlString->wxchar_string != NULL)
928 lua_pushstring(L, wx2lua(wxlString->wxchar_string));
929 else
930 lua_pushstring(L, wxlString->c_string);
931 lua_rawset(L, -3);
932 }
933
934 // install the objects and pointers
935 const wxLuaBindObject *wxlObject = m_objectArray;
936 for (n = 0; n < m_objectCount; ++n, ++wxlObject)
937 {
938 lua_pushstring(L, wxlObject->name);
939
940 if (wxlObject->objPtr != 0)
941 wxluaT_pushuserdatatype(L, wxlObject->objPtr, *wxlObject->wxluatype, true);
942 else
943 wxluaT_pushuserdatatype(L, *wxlObject->pObjPtr, *wxlObject->wxluatype, true);
944
945 lua_rawset(L, -3);
946 }
947
948 // register the wxEvent types
949 const wxLuaBindEvent *wxlEvent = m_eventArray;
950 for (n = 0; n < m_eventCount; ++n, ++wxlEvent)
951 {
952 lua_pushstring(L, wxlEvent->name);
953 lua_pushnumber(L, *wxlEvent->eventType);
954 lua_rawset(L, -3);
955 }
956 }
957
958 /* static */
InstallClassMetatable(lua_State * L,const wxLuaBindClass * wxlClass)959 bool wxLuaBinding::InstallClassMetatable(lua_State* L, const wxLuaBindClass* wxlClass)
960 {
961 // Replace the metatable functions for the classes we push into Lua
962 static const luaL_Reg s_funcTable[] =
963 {
964 {"__gc", wxlua_wxLuaBindClass__gc },
965 {"__index", wxlua_wxLuaBindClass__index },
966 {"__newindex", wxlua_wxLuaBindClass__newindex },
967 {"__tostring", wxlua_wxLuaBindClass__tostring }
968 };
969 static const size_t s_funcCount = sizeof(s_funcTable)/sizeof(s_funcTable[0]);
970
971 // ------------------------------------------------------------------
972 // Add to the lookup table for "class name" to wxLuaBindClass struct
973 lua_pushlightuserdata(L, &wxlua_lreg_classes_key);
974 lua_rawget(L, LUA_REGISTRYINDEX); // pop key, push result (the classes table)
975 lua_pushstring(L, wxlClass->name); // push key
976 lua_pushlightuserdata(L, (void *)wxlClass); // push value
977 lua_rawset(L, -3); // set t[key] = value, pops key and value
978 lua_pop(L, 1); // pop wxlua_lreg_classes_key table
979
980 // ------------------------------------------------------------------
981 // Create a new metatable for this class with a numerical wxLua type index
982
983 int wxl_type = *wxlClass->wxluatype;
984
985 // we may be reregistering this binding, get the old metatable, we'll rewrite it
986 if (!wxluaT_getmetatable(L, wxl_type))
987 wxluaT_newmetatable(L, wxl_type); // create metatable, is on top of stack
988
989 // store a lookup in the class metatable to the wxLuaBindClass struct
990 lua_pushlightuserdata(L, &wxlua_metatable_wxluabindclass_key); // push key
991 lua_pushlightuserdata(L, (void *)wxlClass); // push value
992 lua_rawset(L, -3); // set t[key] = value, pops key and value
993
994 // set the functions for the class in the metatable
995 for (size_t i_func = 0; i_func < s_funcCount; ++i_func)
996 {
997 lua_pushstring(L, s_funcTable[i_func].name); // push method name
998 lua_pushlightuserdata(L, (void *)wxlClass); // push the userdata
999 lua_pushcclosure(L, s_funcTable[i_func].func, 1); // push func with wxlClass as upvalue
1000 lua_rawset(L, -3); // t["method_name"] = closure of func and upvalues
1001 }
1002
1003 lua_pop(L, 1); // pop metatable from wxluaT_newmetatable()
1004
1005 return true;
1006 }
1007
1008 /* static */
InstallClass(lua_State * L,const wxLuaBindClass * wxlClass)1009 bool wxLuaBinding::InstallClass(lua_State* L, const wxLuaBindClass* wxlClass)
1010 {
1011 // ------------------------------------------------------------------
1012 // Create and install the table for the class
1013
1014 lua_pushstring(L, wxlClass->name); // push key
1015 lua_newtable(L); // push value, the table we use as the class
1016
1017 // Install the member enums for the classname table
1018 for (int i_enum = 0; i_enum < wxlClass->enums_n; ++i_enum)
1019 {
1020 lua_pushstring(L, wxlClass->enums[i_enum].name);
1021 lua_pushnumber(L, wxlClass->enums[i_enum].value);
1022 lua_rawset(L, -3);
1023 }
1024
1025 int method_count = wxlClass->wxluamethods_n;
1026
1027 // Install the static functions for the classname table
1028 wxLuaBindMethod *wxlMethod = wxlClass->wxluamethods;
1029 for (int i_static_method = 0; i_static_method < method_count; ++i_static_method, ++wxlMethod)
1030 {
1031 // we will handle the WXLUAMETHOD_GET/SETPROP|WXLUAMETHOD_STATIC using __index and __newindex
1032 if (((wxlMethod->method_type & (WXLUAMETHOD_METHOD|WXLUAMETHOD_STATIC)) == (WXLUAMETHOD_METHOD|WXLUAMETHOD_STATIC)) &&
1033 (wxlMethod->wxluacfuncs_n > 0))
1034 {
1035 lua_pushstring(L, wxlMethod->name);
1036 lua_pushlightuserdata(L, wxlMethod);
1037 if (wxlMethod->wxluacfuncs_n > 1)
1038 lua_pushcclosure(L, wxlua_callOverloadedFunction, 1);
1039 else
1040 lua_pushcclosure(L, wxlMethod->wxluacfuncs[0].lua_cfunc, 1);
1041
1042 lua_rawset(L, -3);
1043 }
1044 }
1045
1046 // Create a metatable for the "class" table
1047 lua_newtable(L);
1048 lua_pushlstring(L, "__index", 7);
1049 lua_pushlightuserdata(L, (void*)wxlClass);
1050 lua_pushcclosure(L, wxlua_wxLuaBindMethod_table__index, 1);
1051 lua_rawset(L, -3);
1052
1053 lua_pushlstring(L, "__newindex", 10);
1054 lua_pushlightuserdata(L, (void*)wxlClass);
1055 lua_pushcclosure(L, wxlua_wxLuaBindMethod_table__newindex, 1);
1056 lua_rawset(L, -3);
1057
1058 //lua_pushstring(L, "__metatable");
1059 //lua_pushstring(L, "Metatable is not accessible");
1060 //lua_rawset(L, -3);
1061 lua_setmetatable(L, -2); // pops the metatable
1062
1063 // Finalize the class table since we may not have a constructor
1064 // or have multiple constructors.
1065 lua_rawset(L, -3); // set t[key] = value, pops key and value
1066
1067 // ------------------------------------------------------------------
1068 // Install public functions like constructors or global functions
1069 wxlMethod = wxlClass->wxluamethods;
1070 for (int i_method = 0; i_method < method_count; ++i_method, ++wxlMethod)
1071 {
1072 if (WXLUA_HASBIT(wxlMethod->method_type, WXLUAMETHOD_CONSTRUCTOR | WXLUAMETHOD_CFUNCTION) && wxlMethod->wxluacfuncs_n)
1073 {
1074 // push name of nested table and create the table or use existing
1075 // we do it this way since we can have multiple constructors (renamed)
1076 // that are of the same class and so they share the same wxLua type.
1077 lua_pushstring(L, wxlMethod->name);
1078
1079 if (strcmp(wxlMethod->name, wxlClass->name) != 0)
1080 lua_newtable(L);
1081 else
1082 lua_getfield(L, -2, wxlMethod->name);
1083
1084 // add the items to the table as t[first pushed] = second pushed
1085 lua_pushlstring(L, "new", 3);
1086 lua_pushlightuserdata(L, wxlMethod);
1087 lua_pushcclosure(L, wxlua_callOverloadedFunction, 1);
1088 lua_rawset(L, -3);
1089
1090 // Add __call to the metatable for this table
1091 bool has_meta = (lua_getmetatable(L, -1) != 0);
1092 if (!has_meta) lua_newtable(L);
1093
1094 lua_pushlstring(L, "__call", 6);
1095 lua_pushlightuserdata(L, wxlMethod);
1096 lua_pushcclosure(L, wxlua_wxLuaBindMethod_table__call, 1);
1097 lua_rawset(L, -3);
1098
1099 //lua_pushstring(L, "__metatable");
1100 //lua_pushstring(L, "Metatable is not accessible");
1101 //lua_rawset(L, -3);
1102
1103 if (!has_meta)
1104 lua_setmetatable(L, -2);
1105 else
1106 lua_pop(L, 1);
1107
1108 // add table to the binding table t[wxlMethod->name] = { this table }
1109 lua_rawset(L, -3); // set t[key] = value, pops key and value
1110 }
1111 }
1112
1113 return true;
1114 }
1115
1116 // ---------------------------------------------------------------------------
1117
GetBindEvent(wxEventType eventType_) const1118 const wxLuaBindEvent* wxLuaBinding::GetBindEvent(wxEventType eventType_) const
1119 {
1120 const wxEventType eventType = eventType_;
1121 wxLuaBindEvent eventItem = { "", &eventType, NULL };
1122
1123 const wxLuaBindEvent *pLuaEvent = (wxLuaBindEvent *)bsearch(&eventItem,
1124 m_eventArray,
1125 m_eventCount,
1126 sizeof(wxLuaBindEvent),
1127 wxLuaBindEvent_CompareByEventTypeFn);
1128 return pLuaEvent;
1129 }
1130
GetEventTypeName(wxEventType eventType) const1131 wxString wxLuaBinding::GetEventTypeName(wxEventType eventType) const
1132 {
1133 const wxLuaBindEvent* wxlEvent = GetBindEvent(eventType);
1134 return (wxlEvent != NULL) ? lua2wx(wxlEvent->name) : wxString();
1135 }
1136
GetBindClass(int wxluatype_) const1137 const wxLuaBindClass* wxLuaBinding::GetBindClass(int wxluatype_) const
1138 {
1139 int wxluatype = wxluatype_; // create a local var to get the address of
1140 wxLuaBindClass classItem = { 0, 0, 0, 0, &wxluatype, 0, 0, 0, 0 };
1141
1142 // this relies on LUA allocating the wxLua types in ascending order of definition
1143 // if LUA stops doing this, then the search may break. Note that we initially
1144 // sort the classes by name then allocate types in acending order.
1145 const wxLuaBindClass *wxlClass = (wxLuaBindClass *)bsearch(&classItem,
1146 m_classArray,
1147 m_classCount,
1148 sizeof(wxLuaBindClass),
1149 wxLuaBindClass_CompareBywxLuaTypeFn);
1150
1151 return wxlClass;
1152 }
1153
GetBindClass(const char * className) const1154 const wxLuaBindClass* wxLuaBinding::GetBindClass(const char* className) const
1155 {
1156 wxLuaBindClass classItem = { className, 0, 0, 0, 0, 0, 0, 0, 0 };
1157
1158 const wxLuaBindClass *wxlClass = (wxLuaBindClass *)bsearch(&classItem,
1159 m_classArray,
1160 m_classCount,
1161 sizeof(wxLuaBindClass),
1162 wxLuaBindClass_CompareByNameFn);
1163
1164 return wxlClass;
1165 }
1166
GetBindClass(const wxLuaBindMethod * wxlMethod_tofind) const1167 const wxLuaBindClass* wxLuaBinding::GetBindClass(const wxLuaBindMethod* wxlMethod_tofind) const
1168 {
1169 size_t c, m, methods_n;
1170 wxLuaBindClass* wxlClass = m_classArray;
1171 wxLuaBindMethod* wxlMethod = NULL;
1172
1173 for (c = 0; c < m_classCount; ++c, ++wxlClass)
1174 {
1175 wxlMethod = wxlClass->wxluamethods;
1176 methods_n = wxlClass->wxluamethods_n;
1177
1178 for (m = 0; m < methods_n; ++m, ++wxlMethod)
1179 {
1180 if (wxlMethod == wxlMethod_tofind)
1181 return wxlClass;
1182 }
1183 }
1184
1185 return NULL;
1186 }
1187
GetBindClass(const wxLuaBindCFunc * wxlCFunc_tofind) const1188 const wxLuaBindClass* wxLuaBinding::GetBindClass(const wxLuaBindCFunc* wxlCFunc_tofind) const
1189 {
1190 size_t c, m, f, methods_n, funcs_n;
1191 wxLuaBindClass* wxlClass = m_classArray;
1192 wxLuaBindMethod* wxlMethod = NULL;
1193 wxLuaBindCFunc* wxlCFunc = NULL;
1194
1195 for (c = 0; c < m_classCount; ++c, ++wxlClass)
1196 {
1197 wxlMethod = wxlClass->wxluamethods;
1198 methods_n = wxlClass->wxluamethods_n;
1199
1200 for (m = 0; m < methods_n; ++m, ++wxlMethod)
1201 {
1202 wxlCFunc = wxlMethod->wxluacfuncs;
1203 funcs_n = wxlMethod->wxluacfuncs_n;
1204
1205 for (f = 0; f < funcs_n; ++f, ++wxlCFunc)
1206 {
1207 if (wxlCFunc == wxlCFunc_tofind)
1208 return wxlClass;
1209 }
1210 }
1211 }
1212
1213 return NULL;
1214 }
1215
1216 // --------------------------------------------------------------------------
1217
1218 // static
GetLuaBinding(const wxString & bindingName)1219 wxLuaBinding* wxLuaBinding::GetLuaBinding(const wxString& bindingName)
1220 {
1221 size_t i, binding_count = sm_bindingArray.GetCount();
1222
1223 for (i = 0; i < binding_count; ++i)
1224 {
1225 if (sm_bindingArray[i]->GetBindingName() == bindingName)
1226 return sm_bindingArray[i];
1227 }
1228
1229 return NULL;
1230 }
1231
1232 // static
FindBindClass(const char * className)1233 const wxLuaBindClass* wxLuaBinding::FindBindClass(const char* className)
1234 {
1235 size_t i, binding_count = sm_bindingArray.GetCount();
1236
1237 for (i = 0; i < binding_count; ++i)
1238 {
1239 const wxLuaBindClass* wxlClass = sm_bindingArray[i]->GetBindClass(className);
1240
1241 if (wxlClass)
1242 return wxlClass;
1243 }
1244
1245 return NULL;
1246 }
1247
1248 // static
FindBindClass(int wxluatype)1249 const wxLuaBindClass* wxLuaBinding::FindBindClass(int wxluatype)
1250 {
1251 size_t i, binding_count = sm_bindingArray.GetCount();
1252
1253 for (i = 0; i < binding_count; ++i)
1254 {
1255 const wxLuaBindClass* wxlClass = sm_bindingArray[i]->GetBindClass(wxluatype);
1256
1257 if (wxlClass)
1258 return wxlClass;
1259 }
1260
1261 return NULL;
1262 }
1263
1264 // static
FindBindClass(const wxLuaBindMethod * wxlMethod)1265 const wxLuaBindClass* wxLuaBinding::FindBindClass(const wxLuaBindMethod* wxlMethod)
1266 {
1267 size_t i, binding_count = sm_bindingArray.GetCount();
1268
1269 for (i = 0; i < binding_count; ++i)
1270 {
1271 const wxLuaBindClass* wxlClass = sm_bindingArray[i]->GetBindClass(wxlMethod);
1272
1273 if (wxlClass)
1274 return wxlClass;
1275 }
1276
1277 return NULL;
1278 }
1279
1280 // static
FindBindClass(const wxLuaBindCFunc * wxlCFunc)1281 const wxLuaBindClass* wxLuaBinding::FindBindClass(const wxLuaBindCFunc* wxlCFunc)
1282 {
1283 size_t i, binding_count = sm_bindingArray.GetCount();
1284
1285 for (i = 0; i < binding_count; ++i)
1286 {
1287 const wxLuaBindClass* wxlClass = sm_bindingArray[i]->GetBindClass(wxlCFunc);
1288
1289 if (wxlClass)
1290 return wxlClass;
1291 }
1292
1293 return NULL;
1294 }
1295
1296 // static
FindBindEvent(wxEventType eventType)1297 const wxLuaBindEvent* wxLuaBinding::FindBindEvent(wxEventType eventType)
1298 {
1299 size_t i, binding_count = sm_bindingArray.GetCount();
1300
1301 for (i = 0; i < binding_count; ++i)
1302 {
1303 const wxLuaBindEvent* wxlEvent = sm_bindingArray[i]->GetBindEvent(eventType);
1304
1305 if (wxlEvent)
1306 return wxlEvent;
1307 }
1308
1309 return NULL;
1310 }
1311
1312 // static
FindMethodBinding(const wxLuaBindMethod * wxlMethod)1313 wxLuaBinding* wxLuaBinding::FindMethodBinding(const wxLuaBindMethod* wxlMethod)
1314 {
1315 size_t i, binding_count = sm_bindingArray.GetCount();
1316
1317 for (i = 0; i < binding_count; ++i)
1318 {
1319 size_t j, fn_count = sm_bindingArray[i]->GetFunctionCount();
1320 wxLuaBindMethod* m = sm_bindingArray[i]->GetFunctionArray();
1321
1322 for (j = 0; j < fn_count; ++j, ++m)
1323 {
1324 if (m == wxlMethod)
1325 return sm_bindingArray[i];
1326 }
1327 }
1328
1329 return NULL;
1330 }
1331
1332
1333 // --------------------------------------------------------------------------
1334
1335 // static
GetClassMethod(const wxLuaBindClass * wxlClass,const char * methodName,int method_type,bool search_baseclasses)1336 wxLuaBindMethod* wxLuaBinding::GetClassMethod(const wxLuaBindClass *wxlClass, const char *methodName, int method_type, bool search_baseclasses)
1337 {
1338 wxCHECK_MSG(wxlClass, NULL, wxT("Invalid wxLuaBindClass to find method from."));
1339
1340 wxLuaBindMethod methodItem = { methodName, method_type, 0, 0, 0 };
1341
1342 wxLuaBindMethod *wxlMethod = (wxLuaBindMethod *)bsearch(&methodItem,
1343 wxlClass->wxluamethods,
1344 wxlClass->wxluamethods_n,
1345 sizeof(wxLuaBindMethod),
1346 wxLuaBindMethod_CompareByNameFnGet);
1347
1348 if ((wxlMethod == NULL) && search_baseclasses && wxlClass->baseclassNames)
1349 {
1350 for (size_t i = 0; wxlClass->baseclassNames[i]; ++i)
1351 {
1352 // The class may not have been installed
1353 if (wxlClass->baseBindClasses[i])
1354 {
1355 wxlMethod = GetClassMethod(wxlClass->baseBindClasses[i], methodName, method_type, search_baseclasses);
1356 if (wxlMethod != NULL)
1357 return wxlMethod;
1358 }
1359 }
1360 }
1361
1362 return wxlMethod;
1363 }
1364
1365 // --------------------------------------------------------------------------
1366
1367 // static
InitAllBindings(bool force_update)1368 void wxLuaBinding::InitAllBindings(bool force_update)
1369 {
1370 size_t n, i, j, k, binding_count = sm_bindingArray.GetCount();
1371
1372 // update if a binding was added or removed
1373 if (((size_t)sm_bindingArray_initialized == binding_count) && !force_update)
1374 return;
1375
1376 // set the base class wxLuaBindClass* using the base class names of the parent wxLuaBindClass
1377 for (n = 0; n < binding_count; ++n)
1378 {
1379 wxLuaBindClass* wxlClass = sm_bindingArray[n]->GetClassArray();
1380 size_t class_count = sm_bindingArray[n]->GetClassCount();
1381
1382 for (i = 0; i < class_count; ++i, ++wxlClass)
1383 {
1384 if (wxlClass->baseclassNames) // does it have any base classes at all?
1385 {
1386 // find the base class using their names in the bindings
1387 for (j = 0; wxlClass->baseclassNames[j]; ++j)
1388 {
1389 wxLuaBindClass* wxlBaseClass = (wxLuaBindClass*)wxLuaBinding::FindBindClass(wxlClass->baseclassNames[j]);
1390 if (wxlBaseClass)
1391 wxlClass->baseBindClasses[j] = wxlBaseClass;
1392 }
1393 }
1394 }
1395 }
1396
1397 // Link together all of the class member functions with base class functions
1398 // with the same name so the overloads work for them too.
1399 for (n = 0; n < binding_count; ++n)
1400 {
1401 wxLuaBindClass* wxlClass = sm_bindingArray[n]->GetClassArray();
1402 size_t i, class_count = sm_bindingArray[n]->GetClassCount();
1403
1404 for (i = 0; i < class_count; ++i, ++wxlClass)
1405 {
1406 if (wxlClass->baseclassNames) // does it have any base classes at all?
1407 {
1408 wxLuaBindMethod *wxlMethod = wxlClass->wxluamethods;
1409 size_t method_count = wxlClass->wxluamethods_n;
1410
1411 for (j = 0; j < method_count; ++j, ++wxlMethod)
1412 {
1413 if (wxlClass->baseclassNames && !WXLUA_HASBIT(wxlMethod->method_type, WXLUAMETHOD_DELETE))
1414 {
1415 // Use the baseclassNames to check for terminating NULL
1416 for (k = 0; wxlClass->baseclassNames[k]; ++k)
1417 {
1418 // Note that these may be NULL if the lib/module containing them wasn't loaded
1419 wxLuaBindClass *baseClass = wxlClass->baseBindClasses[k];
1420 if (baseClass != NULL)
1421 {
1422 wxLuaBindMethod* baseMethod = wxLuaBinding::GetClassMethod(baseClass, wxlMethod->name, WXLUAMETHOD_MASK, true);
1423 if (baseMethod)
1424 {
1425 // don't link to base class delete functions
1426 if (!WXLUA_HASBIT(baseMethod->method_type, WXLUAMETHOD_DELETE))
1427 wxlMethod->basemethod = baseMethod;
1428 }
1429 }
1430 }
1431 }
1432 }
1433 }
1434 }
1435 }
1436
1437 sm_bindingArray_initialized = binding_count;
1438 }
1439