wxlbind.cpp

Go to the documentation of this file.
00001 /////////////////////////////////////////////////////////////////////////////
00002 // Name:          wxlbind.cpp
00003 // Purpose:       wxLuaBinding
00004 // Author:        Ray Gilbert, John Labenski, J Winwood
00005 // Created:       14/11/2001
00006 // Copyright:
00007 // Licence:       wxWidgets licence
00008 /////////////////////////////////////////////////////////////////////////////
00009 
00010 #include "wx/wxprec.h"
00011 
00012 #ifdef __BORLANDC__
00013     #pragma hdrstop
00014 #endif
00015 
00016 #ifndef WX_PRECOMP
00017     #include "wx/wx.h"
00018 #endif
00019 
00020 #include "wxlua/include/wxlbind.h"
00021 #include "wxlua/include/wxlstate.h"
00022 
00023 //#include "wxluadebug/include/wxldebug.h" // for debugging only
00024 
00025 const wxLuaSmartwxArrayString wxLuaNullSmartwxArrayString(NULL, true);
00026 
00027 
00028 #include "wx/listimpl.cpp"
00029 WX_DEFINE_LIST(wxLuaBindingList);
00030 
00031 wxLuaArgType g_wxluaargtypeArray_None[1] = {0};
00032 wxLuaBindNumber g_wxluanumberArray_None[1] = {{0, 0}};
00033 
00034 int wxluatype_TNONE          = WXLUA_TNONE;
00035 int wxluatype_TNIL           = WXLUA_TNIL;
00036 int wxluatype_TBOOLEAN       = WXLUA_TBOOLEAN;
00037 int wxluatype_TLIGHTUSERDATA = WXLUA_TLIGHTUSERDATA; // raw data
00038 int wxluatype_TNUMBER        = WXLUA_TNUMBER;
00039 int wxluatype_TSTRING        = WXLUA_TSTRING;
00040 int wxluatype_TTABLE         = WXLUA_TTABLE;
00041 int wxluatype_TFUNCTION      = WXLUA_TFUNCTION;
00042 int wxluatype_TUSERDATA      = WXLUA_TUSERDATA;      // raw data
00043 int wxluatype_TTHREAD        = WXLUA_TTHREAD;
00044 int wxluatype_TINTEGER       = WXLUA_TINTEGER;
00045 int wxluatype_TCFUNCTION     = WXLUA_TCFUNCTION;
00046 
00047 int wxluatype_NULL           = WXLUATYPE_NULL;
00048 
00049 wxLuaBindClass wxLuaBindClass_NULL =
00050     { "NULL", NULL, 0, NULL, &wxluatype_NULL, NULL, NULL, g_wxluanumberArray_None, 0, };
00051 
00052 static int wxluatype_dummy           = WXLUA_TUNKNOWN;
00053 int* p_wxluatype_wxEvent             = &wxluatype_dummy;
00054 int* p_wxluatype_wxWindow            = &wxluatype_dummy;
00055 int* p_wxluatype_wxString            = &wxluatype_dummy;
00056 int* p_wxluatype_wxArrayString       = &wxluatype_dummy;
00057 int* p_wxluatype_wxSortedArrayString = &wxluatype_dummy;
00058 int* p_wxluatype_wxArrayInt          = &wxluatype_dummy;
00059 
00060 //-----------------------------------------------------------------------------
00061 // wxLuaObject
00062 //-----------------------------------------------------------------------------
00063 IMPLEMENT_ABSTRACT_CLASS(wxLuaObject, wxObject)
00064 
00065 wxLuaObject::wxLuaObject(const wxLuaState& wxlState, int stack_idx)
00066             : m_wxlState(new wxLuaState(wxlState)),
00067               m_alloc_flag(wxLUAOBJECT_NONE),
00068               m_int(0) // GCC only wants one initializer
00069 
00070 {
00071     // set up the reference to the item on the stack
00072     m_reference = m_wxlState->wxluaR_Ref(stack_idx, &wxlua_lreg_refs_key);
00073 }
00074 
00075 wxLuaObject::~wxLuaObject()
00076 {
00077     if (m_alloc_flag == wxLUAOBJECT_STRING)
00078         delete m_string;
00079     else if (m_alloc_flag == wxLUAOBJECT_ARRAYINT)
00080         delete m_arrayInt;
00081 
00082     // If a refererence exists, remove it, but don't bother if Lua is being closed
00083     if ((m_reference != LUA_NOREF) && m_wxlState->Ok() && !m_wxlState->IsClosing())
00084         m_wxlState->wxluaR_Unref(m_reference, &wxlua_lreg_refs_key);
00085 
00086     delete m_wxlState;
00087 }
00088 
00089 wxLuaState wxLuaObject::GetwxLuaState() const
00090 {
00091     return (m_wxlState != NULL) ? *m_wxlState : wxNullLuaState;
00092 }
00093 
00094 bool wxLuaObject::GetObject()
00095 {
00096     wxCHECK_MSG(m_wxlState->Ok(), false, wxT("Invalid wxLuaState"));
00097     lua_State* L = m_wxlState->GetLuaState();
00098 
00099     if (m_alloc_flag == wxLUAOBJECT_BOOL)
00100     {
00101         lua_pushboolean(L, m_bool);
00102         return true;
00103     }
00104     else if (m_alloc_flag == wxLUAOBJECT_INT)
00105     {
00106         lua_pushnumber(L, m_int);
00107         return true;
00108     }
00109     else if (m_alloc_flag == wxLUAOBJECT_STRING)
00110     {
00111         lua_pushstring(L, wx2lua(*m_string));
00112         return true;
00113     }
00114     else if (m_alloc_flag == wxLUAOBJECT_ARRAYINT)
00115     {
00116         wxlua_pushwxArrayInttable(L, *m_arrayInt);
00117         return true;
00118     }
00119     else if (wxluaR_getref(L, m_reference, &wxlua_lreg_refs_key))
00120         return true;
00121 
00122     return false; // nothing on the stack
00123 }
00124 
00125 void wxLuaObject::SetObject(int stack_idx)
00126 {
00127     wxCHECK_RET(m_wxlState->Ok(), wxT("Invalid wxLuaState"));
00128 
00129     if (m_reference != LUA_NOREF) // FIXME should this error out?
00130         m_wxlState->wxluaR_Unref(m_reference, &wxlua_lreg_refs_key);
00131 
00132     m_reference = m_wxlState->wxluaR_Ref(stack_idx, &wxlua_lreg_refs_key);
00133 }
00134 
00135 bool *wxLuaObject::GetBoolPtr()
00136 {
00137     wxCHECK_MSG(m_wxlState->Ok(), 0, wxT("Invalid wxLuaState"));
00138     wxCHECK_MSG(m_alloc_flag == wxLUAOBJECT_NONE, 0, wxT("wxLuaObject already initialized in wxLuaObject::GetBoolPtr"));
00139 
00140     if ((m_reference != LUA_NOREF) && GetObject())
00141     {
00142         m_bool = (m_wxlState->lua_ToBoolean(-1) != 0);
00143         m_alloc_flag = wxLUAOBJECT_BOOL;
00144         m_wxlState->lua_Pop(1);
00145     }
00146     return &m_bool;
00147 }
00148 
00149 int *wxLuaObject::GetIntPtr()
00150 {
00151     wxCHECK_MSG(m_wxlState->Ok(), false, wxT("Invalid wxLuaState"));
00152     wxCHECK_MSG(m_alloc_flag == wxLUAOBJECT_NONE, 0, wxT("wxLuaObject already initialized in wxLuaObject::GetIntPtr"));
00153 
00154     if ((m_reference != LUA_NOREF) && GetObject())
00155     {
00156         m_int = (int)m_wxlState->lua_ToNumber(-1);
00157         m_alloc_flag = wxLUAOBJECT_INT;
00158         m_wxlState->lua_Pop(1);
00159     }
00160     return &m_int;
00161 }
00162 
00163 wxString *wxLuaObject::GetStringPtr()
00164 {
00165     wxCHECK_MSG(m_wxlState->Ok(), false, wxT("Invalid wxLuaState"));
00166     wxCHECK_MSG(m_alloc_flag == wxLUAOBJECT_NONE, 0, wxT("wxLuaObject already initialized in wxLuaObject::GetStringPtr"));
00167 
00168     m_string = new wxString(); // create valid string for return
00169 
00170     if ((m_reference != LUA_NOREF) && GetObject())
00171     {
00172         *m_string = m_wxlState->lua_TowxString(-1);
00173         m_alloc_flag = wxLUAOBJECT_STRING;
00174         m_wxlState->lua_Pop(1);
00175     }
00176 
00177     return m_string;
00178 }
00179 
00180 wxArrayInt *wxLuaObject::GetArrayPtr()
00181 {
00182     wxCHECK_MSG(m_wxlState->Ok(), false, wxT("Invalid wxLuaState"));
00183     wxCHECK_MSG(m_alloc_flag == wxLUAOBJECT_NONE, 0, wxT("wxLuaObject already initialized in wxLuaObject::GetArrayPtr"));
00184 
00185     m_arrayInt = new wxArrayInt(); // create valid array for return
00186 
00187     if ((m_reference != LUA_NOREF) && GetObject())
00188     {
00189         *m_arrayInt = (wxArrayInt&)m_wxlState->GetwxArrayInt(-1); // coerce wxLuaSmartwxArrayInt
00190         m_alloc_flag = wxLUAOBJECT_ARRAYINT;
00191         m_wxlState->lua_Pop(1);
00192     }
00193     return m_arrayInt;
00194 }
00195 
00196 // ----------------------------------------------------------------------------
00197 // wxLuaSmartwxArrayString
00198 // ----------------------------------------------------------------------------
00199 
00200 class wxLuaSmartwxArrayStringRefData : public wxObjectRefData
00201 {
00202 public:
00203     wxLuaSmartwxArrayStringRefData(wxArrayString* arr, int del) : m_arr(arr), m_delete(del)
00204     {
00205         if (!m_arr) { m_arr = new wxArrayString; m_delete = true; } // always exists
00206     }
00207 
00208     virtual ~wxLuaSmartwxArrayStringRefData() { if (m_delete) delete m_arr; }
00209 
00210     wxArrayString *m_arr;
00211     bool           m_delete;
00212 };
00213 
00214 wxLuaSmartwxArrayString::wxLuaSmartwxArrayString(wxArrayString *arr, bool del)
00215 {
00216     m_refData = new wxLuaSmartwxArrayStringRefData(arr, del);
00217 }
00218 wxArrayString* wxLuaSmartwxArrayString::GetArray() const
00219 {
00220     return ((wxLuaSmartwxArrayStringRefData*)m_refData)->m_arr;
00221 }
00222 
00223 // ----------------------------------------------------------------------------
00224 // wxLuaSmartwxSortedArrayString
00225 // ----------------------------------------------------------------------------
00226 
00227 class wxLuaSmartwxSortedArrayStringRefData : public wxObjectRefData
00228 {
00229 public:
00230     wxLuaSmartwxSortedArrayStringRefData(wxSortedArrayString* arr, int del) : m_arr(arr), m_delete(del)
00231     {
00232         if (!m_arr) { m_arr = new wxSortedArrayString; m_delete = true; } // always exists
00233     }
00234 
00235     virtual ~wxLuaSmartwxSortedArrayStringRefData() { if (m_delete) delete m_arr; }
00236 
00237     wxSortedArrayString *m_arr;
00238     bool                 m_delete;
00239 };
00240 
00241 wxLuaSmartwxSortedArrayString::wxLuaSmartwxSortedArrayString(wxSortedArrayString *arr, bool del)
00242 {
00243     m_refData = new wxLuaSmartwxSortedArrayStringRefData(arr, del);
00244 }
00245 wxSortedArrayString* wxLuaSmartwxSortedArrayString::GetArray() const
00246 {
00247     return ((wxLuaSmartwxSortedArrayStringRefData*)m_refData)->m_arr;
00248 }
00249 
00250 // ----------------------------------------------------------------------------
00251 // wxLuaSmartwxArrayInt
00252 // ----------------------------------------------------------------------------
00253 
00254 class wxLuaSmartwxArrayIntRefData : public wxObjectRefData
00255 {
00256 public:
00257     wxLuaSmartwxArrayIntRefData(wxArrayInt* arr, int del) : m_arr(arr), m_delete(del)
00258     {
00259         if (!m_arr) { m_arr = new wxArrayInt; m_delete = true; } // always exists
00260     }
00261 
00262     virtual ~wxLuaSmartwxArrayIntRefData() { if (m_delete) delete m_arr; }
00263 
00264     wxArrayInt *m_arr;
00265     bool        m_delete;
00266 };
00267 
00268 wxLuaSmartwxArrayInt::wxLuaSmartwxArrayInt(wxArrayInt *arr, bool del)
00269 {
00270     m_refData = new wxLuaSmartwxArrayIntRefData(arr, del);
00271 }
00272 
00273 wxArrayInt* wxLuaSmartwxArrayInt::GetArray() const
00274 {
00275     return ((wxLuaSmartwxArrayIntRefData*)m_refData)->m_arr;
00276 }
00277 
00278 // ----------------------------------------------------------------------------
00279 // wxlua_tableErrorHandler
00280 // ----------------------------------------------------------------------------
00281 
00282 static int LUACALL wxlua_tableErrorHandler(lua_State *L)
00283 {
00284     wxlua_error(L, "Cannot modify read-only wxLua table");
00285     return 0;
00286 }
00287 
00288 // ----------------------------------------------------------------------------
00289 // Generic delete function for bindings
00290 // ----------------------------------------------------------------------------
00291 
00292 int LUACALL wxlua_userdata_delete(lua_State *L)
00293 {
00294     void* udata   = lua_touserdata(L, 1);
00295     void* obj_ptr = wxlua_touserdata(L, 1, false);
00296 
00297     // if removed from tracked mem list, remove the metatable so that __gc is not called on this object.
00298     if ((obj_ptr != NULL) && wxluaO_deletegcobject(L, udata, obj_ptr, WXLUA_DELETE_OBJECT_ALL))
00299     {
00300         lua_pushnil(L);
00301         lua_setmetatable(L, -2);
00302     }
00303     else
00304     {
00305         wxString msg;
00306         msg.Printf(wxT("wxLua: Unable to call wxuserdata:delete() on object %p, someone else owns it."), obj_ptr);
00307 
00308         // leave this printf since we really want to know if this happens
00309         wxPrintf(wxString(msg + wxT("\n")).c_str());
00310         wxlua_argerrormsg(L, msg);
00311     }
00312 
00313     return 0;
00314 }
00315 
00316 // ----------------------------------------------------------------------------
00317 // If the class defines a gc function, then call it.
00318 // ----------------------------------------------------------------------------
00319 
00320 int LUACALL wxlua_wxLuaBindClass__gc(lua_State *L)
00321 {
00322     wxLuaBindClass *wxlClass = (wxLuaBindClass *)lua_touserdata(L, lua_upvalueindex(1));
00323 
00324     if ((wxlClass != NULL) && wxlua_iswxuserdata(L, 1) && (wxluaT_type(L, 1) == *wxlClass->wxluatype))
00325     {
00326         void* udata   = lua_touserdata(L, 1);
00327         void* obj_ptr = wxlua_touserdata(L, 1, true); // clear lua userdata's ptr
00328 
00329         // clean up the rest of this, this won't error if the key doesn't exist
00330         wxluaO_deletegcobject(L, udata, obj_ptr, WXLUA_DELETE_OBJECT_LAST);
00331     }
00332 
00333     return 0;
00334 }
00335 
00336 // ----------------------------------------------------------------------------
00337 // Called by LUA to find the method that corresponds to a __index method name.
00338 // ----------------------------------------------------------------------------
00339 
00340 int LUACALL wxlua_wxLuaBindClass__index(lua_State *L)
00341 {
00342     // This function is called for the __index metable of the wxLua userdata
00343     // for class instances.
00344 
00345     // Lua stack : 1 = userdata, 2 = key; userdata:key()
00346     // You cannot seem to get the calling convention (. or :) or if it was
00347     // called as a function() or a .member?
00348 
00349     // See below, if _XXX is called then we set this flag so that
00350     //  the called function knows to call the base class instead of recalling
00351     //  the Lua function and recursing.
00352     wxlua_setcallbaseclassfunction(L, false);
00353 
00354     bool found    = false;
00355     int  result   = 0;
00356     wxLuaBindClass *wxlClass = (wxLuaBindClass *)lua_touserdata(L, lua_upvalueindex(1));
00357     wxCHECK_MSG(wxlClass, 0, wxT("Invalid wxLuaBindClass")); // fail hard
00358 
00359     void *obj_ptr = wxlua_touserdata(L, 1, false);
00360     const char *name = lua_tostring(L, 2); // name of the __index method called in Lua
00361 
00362     if (!name)
00363     {
00364         // name is NULL if it's not a string
00365         wxlua_error(L, wxString::Format(_("wxLua: Attempt to call a class method using '%s' on a '%s' wxLua type."),
00366             wxlua_luaL_typename(L, 2).c_str(), lua2wx(wxlClass->name).c_str()));
00367     }
00368     else if (wxluaT_type(L, 1) == *wxlClass->wxluatype)
00369     {
00370         // check if we're to call the baseclass function or if it's a Lua derived function
00371         bool callbase = (name[0] == '_');
00372 
00373         if (callbase)
00374             name++; // skip past "_"[FunctionName]
00375         else
00376         {
00377             // if there's a derived method, push it onto the stack to be run
00378             if (wxlua_hasderivedmethod(L, obj_ptr, name, true))
00379             {
00380                 found = true;
00381                 result = 1; // the function for Lua to call is on the stack
00382             }
00383         }
00384 
00385         // Search through the bindings for the function to call
00386         if (!found)
00387         {
00388             wxLuaBindMethod* wxlMethod = wxLuaBinding::GetClassMethod(wxlClass, name, WXLUAMETHOD_METHOD|WXLUAMETHOD_GETPROP, true);
00389 
00390             if (wxlMethod != NULL)
00391             {
00392                 if (WXLUA_HASBIT(wxlMethod->method_type, WXLUAMETHOD_GETPROP))
00393                 {
00394                     found = true;
00395                     if (WXLUA_HASBIT(wxlMethod->method_type, WXLUAMETHOD_STATIC))
00396                         lua_pop(L, 2); // remove the userdata and func name
00397                     else
00398                         lua_pop(L, 1); // remove the name of the function
00399 
00400                     result = (*wxlMethod->wxluacfuncs[0].lua_cfunc)(L);
00401                 }
00402                 else
00403                 {
00404                     found = true;
00405                     result = 1;
00406 
00407                     lua_pushlightuserdata(L, wxlMethod);
00408 
00409                     if ((wxlMethod->wxluacfuncs_n > 1) || (wxlMethod->basemethod))
00410                         lua_pushcclosure(L, wxlua_callOverloadedFunction, 1);
00411                     else
00412                         lua_pushcclosure(L, wxlMethod->wxluacfuncs[0].lua_cfunc, 1);
00413                 }
00414             }
00415 
00416             // Maybe this is an undeclared property? Prepend 'Get' and try again.
00417             if (!found)
00418             {
00419                 int len = strlen(name);
00420                 wxCharBuffer buf(len + 4);
00421                 char* str = buf.data();
00422                 str[0] = 'G'; str[1] = 'e'; str[2] = 't';
00423                 memcpy(str+3, name, len+1); // include terminating NULL
00424 
00425                 wxlMethod = wxLuaBinding::GetClassMethod(wxlClass, str, WXLUAMETHOD_METHOD, true);
00426 
00427                 if ((wxlMethod != NULL) && WXLUA_HASBIT(wxlMethod->method_type, WXLUAMETHOD_METHOD))
00428                     //wxlMethod->funcs && (wxlMethod->funcs->minargs == 0) && // let it error out
00429                     //(wxlMethod->funcs->maxargs == 0))
00430                 {
00431                     found = true;
00432                     if (WXLUA_HASBIT(wxlMethod->method_type, WXLUAMETHOD_STATIC))
00433                         lua_pop(L, 2); // remove the userdata and func name
00434                     else
00435                         lua_pop(L, 1); // remove the name of the function
00436 
00437                     result = (*wxlMethod->wxluacfuncs[0].lua_cfunc)(L);
00438                 }
00439             }
00440 
00441             // This MUST be reset to false in the base class function
00442             if (found && callbase) wxlua_setcallbaseclassfunction(L, true);
00443         }
00444     }
00445 
00446     if (!found)
00447     {
00448         wxlua_error(L, wxString::Format(_("wxLua: Unable to call an unknown method '%s' on a '%s' type."),
00449             lua2wx(name).c_str(), lua2wx(wxlClass ? wxlClass->name : "").c_str()));
00450     }
00451 
00452     return result;
00453 }
00454 
00455 // ----------------------------------------------------------------------------
00456 // Called by LUA to find the method that corresponds to a __newindex method name.
00457 // ----------------------------------------------------------------------------
00458 
00459 int LUACALL wxlua_wxLuaBindClass__newindex(lua_State *L)
00460 {
00461     wxLuaBindClass *wxlClass = (wxLuaBindClass *)lua_touserdata(L, lua_upvalueindex(1));
00462     wxCHECK_MSG(wxlClass, 0, wxT("Invalid wxLuaBindClass")); // fail hard
00463 
00464     // Lua Stack: 1 = userdata, 2 = key, 3 = value; userdata.key = value
00465 
00466     const char *name = lua_tostring(L, 2);
00467     bool found = false;
00468 
00469     if (!name)
00470     {
00471         // name is NULL if it's not a string
00472         wxlua_error(L, wxString::Format(_("wxLua: Attempt to call or add a class method using '%s' on a '%s' type."),
00473             wxlua_luaL_typename(L, 2).c_str(), lua2wx(wxlClass->name).c_str()));
00474     }
00475     else if (wxluaT_type(L, 1) == *wxlClass->wxluatype)
00476     {
00477         // See if there is a WXLUAMETHOD_SETPROP in the wxLuaBindClass's wxLuaBindMethods
00478         wxLuaBindMethod *wxlMethod = wxLuaBinding::GetClassMethod(wxlClass, name, WXLUAMETHOD_SETPROP, true);
00479 
00480         if (wxlMethod != NULL)
00481         {
00482             found = true;
00483             lua_remove(L, 2); // remove the function name
00484             if (WXLUA_HASBIT(wxlMethod->method_type, WXLUAMETHOD_STATIC))
00485                 lua_remove(L, 1); // remove the userdata too, leaving the value
00486 
00487             (*wxlMethod->wxluacfuncs[0].lua_cfunc)(L);
00488         }
00489 
00490         // Maybe this is an undeclared property? Prepend 'Set' and try again.
00491         if (!found)
00492         {
00493             int len = strlen(name);
00494             wxCharBuffer buf(len + 4);
00495             char* str = buf.data();
00496             str[0] = 'S'; str[1] = 'e'; str[2] = 't';
00497             memcpy(str+3, name, len+1); // include terminating NULL
00498 
00499             wxlMethod = wxLuaBinding::GetClassMethod(wxlClass, str, WXLUAMETHOD_METHOD, true);
00500             if ((wxlMethod != NULL) && WXLUA_HASBIT(wxlMethod->method_type, WXLUAMETHOD_METHOD))
00501             {
00502                 found = true;
00503                 lua_remove(L, 2); // remove the function name
00504                 if (WXLUA_HASBIT(wxlMethod->method_type, WXLUAMETHOD_STATIC))
00505                     lua_remove(L, 1); // remove the userdata too, leaving the value
00506 
00507                 (*wxlMethod->wxluacfuncs[0].lua_cfunc)(L);
00508             }
00509         }
00510 
00511         // They want to add this to the class so store it in the derived method table
00512         if (!found)
00513         {
00514             found = true;
00515             wxLuaState wxlState(L);
00516             wxCHECK_MSG(wxlState.Ok(), 0, wxT("Invalid wxLuaState"));
00517 
00518             void *obj_ptr = wxlua_touserdata(L, 1, false);
00519             wxLuaObject* wxlObj = new wxLuaObject(wxlState, 3);
00520             wxlua_setderivedmethod(L, obj_ptr, name, wxlObj);
00521         }
00522     }
00523 
00524     if (!found)
00525     {
00526         wxlua_error(L, wxString::Format(_("wxLua: Unable to call or add an unknown method '%s' on a '%s' type."),
00527             lua2wx(name).c_str(), lua2wx(wxlClass ? wxlClass->name : "").c_str()));
00528     }
00529 
00530     return 0;
00531 }
00532 
00533 // ----------------------------------------------------------------------------
00534 // wxlua_wxLuaBindClass__tostring
00535 // ----------------------------------------------------------------------------
00536 
00537 int LUACALL wxlua_wxLuaBindClass__tostring(lua_State *L)
00538 {
00539     // this should be identical to Lua's tostring for a userdata
00540     wxString str = wxString::Format(wxT("userdata: %p"), lua_touserdata(L, 1));
00541 
00542     int wxl_type = wxluaT_type(L, 1);
00543     if (wxlua_iswxuserdatatype(wxl_type))
00544     {
00545         wxString name = wxluaT_typename(L, wxl_type);
00546         if (!name.IsEmpty())
00547         {
00548             // GCC prints '(' for NULL %p for some reason.
00549             void* p = wxlua_touserdata(L, 1, false);
00550             if (p)
00551                 str += wxString::Format(wxT(" [%s(%p, %d)]"), name.c_str(), p, wxl_type);
00552             else
00553                 str += wxString::Format(wxT(" [%s(0x0, %d)]"), name.c_str(), wxl_type);
00554         }
00555     }
00556     else
00557         str += wxT(" [??? Unknown wxLua class type!]"); // get people's attention
00558 
00559     lua_pushstring(L, wx2lua(str));
00560     return 1;
00561 }
00562 
00563 // ----------------------------------------------------------------------------
00564 // The __call metatable function to allow the class tables to be called as functions
00565 // ----------------------------------------------------------------------------
00566 
00567 int LUACALL wxlua_wxLuaBindMethod_table__call(lua_State *L)
00568 {
00569     lua_remove(L, 1); // remove the table
00570 
00571     return wxlua_callOverloadedFunction(L);
00572 }
00573 
00574 int LUACALL wxlua_wxLuaBindMethod_table__index(lua_State *L)
00575 {
00576     // Lua stack: 1 = table, 2 = key
00577 
00578     wxLuaBindClass *wxlClass = (wxLuaBindClass *)lua_touserdata(L, lua_upvalueindex(1));
00579     wxCHECK_MSG(wxlClass, 0, wxT("Invalid wxLuaBindClass")); // fail hard
00580 
00581     int result = 0;
00582 
00583     const char* name = lua_tostring(L, 2);
00584     if (!name)
00585     {
00586         // name is NULL if it's not a string
00587         wxlua_error(L, wxString::Format(_("wxLua: Attempt to call a static class method using '%s' on a '%s' type."),
00588             wxlua_luaL_typename(L, 2).c_str(), lua2wx(wxlClass->name).c_str()));
00589         return 0;
00590     }
00591 
00592     wxLuaBindMethod* wxlMethod = wxLuaBinding::GetClassMethod(wxlClass, name, WXLUAMETHOD_GETPROP, true);
00593 
00594     if (wxlMethod && WXLUA_HASBIT(wxlMethod->method_type, WXLUAMETHOD_STATIC))
00595     {
00596         lua_pop(L, 2); // remove the table and the name of the function
00597         result = (*wxlMethod->wxluacfuncs[0].lua_cfunc)(L);
00598     }
00599     else
00600     {
00601         lua_pushvalue(L, -1);  // copy key
00602         lua_rawget(L, -3);     // get t[key] = value, pops key pushes value
00603         result = 1;            // ok if nil
00604     }
00605 
00606     return result;
00607 }
00608 
00609 int LUACALL wxlua_wxLuaBindMethod_table__newindex(lua_State *L)
00610 {
00611     // 1 = table, 2 = key, 3 = value
00612 
00613     wxLuaBindClass *wxlClass = (wxLuaBindClass *)lua_touserdata(L, lua_upvalueindex(1));
00614     wxCHECK_MSG(wxlClass, 0, wxT("Invalid wxLuaBindClass"));
00615 
00616     const char* name = lua_tostring(L, 2);
00617     if (!name)
00618     {
00619         // name is NULL if it's not a string
00620         wxlua_error(L, wxString::Format(_("wxLua: Attempt to call a static class method using '%s' on a '%s' type."),
00621             wxlua_luaL_typename(L, 2).c_str(), lua2wx(wxlClass->name).c_str()));
00622         return 0;
00623     }
00624 
00625     wxLuaBindMethod* wxlMethod = wxLuaBinding::GetClassMethod(wxlClass, name, WXLUAMETHOD_SETPROP, true);
00626 
00627     if (wxlMethod && WXLUA_HASBIT(wxlMethod->method_type, WXLUAMETHOD_STATIC))
00628     {
00629         lua_remove(L, 2); // remove the key
00630         lua_remove(L, 1); // remove the table
00631         (*wxlMethod->wxluacfuncs[0].lua_cfunc)(L);
00632     }
00633     else
00634     {
00635         lua_pushvalue(L, -2); // copy key
00636         lua_pushvalue(L, -2); // copy value
00637         lua_rawset(L, -5);    // set t[key] = value, pops key and value
00638     }
00639 
00640     return 0;
00641 }
00642 
00643 // ----------------------------------------------------------------------------
00644 // Central function to call for overloaded functions
00645 // ----------------------------------------------------------------------------
00646 
00647 int LUACALL wxlua_callOverloadedFunction(lua_State* L)
00648 {
00649     wxLuaBindMethod* wxlMethod = (wxLuaBindMethod *)lua_touserdata(L, lua_upvalueindex(1)); // lightuserdata
00650     wxCHECK_MSG(wxlMethod, 0, wxT("Invalid wxLuaBindMethod"));
00651 
00652     if ((wxlMethod->wxluacfuncs_n > 1) || (wxlMethod->basemethod))
00653         return wxlua_callOverloadedFunction(L, wxlMethod);
00654     else
00655         return (*wxlMethod->wxluacfuncs[0].lua_cfunc)(L);
00656 }
00657 
00658 int LUACALL wxlua_callOverloadedFunction(lua_State* L, struct wxLuaBindMethod* wxlMethod)
00659 {
00660     // get number of arguments called from Lua
00661     int i, arg, arg_lua_count = lua_gettop(L);
00662 
00663     // only look at the methods that could possibly work and traverse base classes
00664     wxArrayPtrVoid cfuncArray;
00665     wxLuaBindMethod* method = wxlMethod;
00666     while (method)
00667     {
00668         wxLuaBindCFunc* wxlCFunc = method->wxluacfuncs;
00669 
00670         for (i = 0; i < method->wxluacfuncs_n; ++i, ++wxlCFunc)
00671         {
00672             if ((arg_lua_count >= wxlCFunc->minargs) &&
00673                 (arg_lua_count <= wxlCFunc->maxargs))
00674             {
00675                 cfuncArray.Add(wxlCFunc);
00676             }
00677         }
00678 
00679         method = method->basemethod;
00680     }
00681 
00682     wxLuaBindCFunc* bestCFunc = NULL; // stores the last function that worked.
00683     int invalid_lua_arg = 1; // arg that failed
00684     int cfunc_count = cfuncArray.GetCount();
00685 
00686     // Look at the available functions in parallel, per arg
00687     for (arg = 0; (arg < arg_lua_count) && (cfunc_count != 0); ++arg)
00688     {
00689         int arg_lua = arg+1; // arg N on the Lua stack
00690         int ltype = lua_type(L, arg_lua);
00691 
00692         for (i = 0; i < cfunc_count; ++i)
00693         {
00694             wxLuaBindCFunc* wxlCFunc = (wxLuaBindCFunc*)cfuncArray[i];
00695             bestCFunc = wxlCFunc;
00696             invalid_lua_arg = arg_lua;
00697 
00698             // does this method have any more arguments?
00699             if (!wxlCFunc->argtypes[arg])
00700             {
00701                 cfuncArray.RemoveAt(i);
00702                 cfunc_count--;
00703                 i--;
00704                 continue;
00705             }
00706 
00707             // get argument wxLua type
00708             int wxl_type = (int)*(wxlCFunc->argtypes[arg]);
00709 
00710             // Does the Lua type match the wxLua type
00711             int is_ok = wxlua_iswxluatype(ltype, wxl_type, L);
00712 
00713             // unknown/invalid standard wxLua type, check binding wxLua type
00714             if ((is_ok == -1) || ((is_ok == 0) && (wxl_type == WXLUA_TSTRING)))
00715             {
00716                 is_ok = (wxluaT_isuserdatatype(L, arg_lua, wxl_type) ||
00717                         (wxl_type == wxluatype_NULL)) ? 1 : 0;
00718             }
00719 
00720             // this arg is not a match, remove this function as a possibility
00721             if (is_ok == 0)
00722             {
00723                 cfuncArray.RemoveAt(i);
00724                 cfunc_count--;
00725                 i--;
00726                 continue;
00727             }
00728         }
00729     }
00730 
00731     // Note that the top function is the one that is highest in the
00732     // derived functions from any baseclasses and should be the best choice.
00733     // Example is wxBookCtrlBaseEvent::GetSelection() and wxCommandEvent::GetSelection()
00734     if (cfunc_count > 0)
00735     {
00736         lua_CFunction lua_cfunc = ((wxLuaBindCFunc*)cfuncArray[0])->lua_cfunc;
00737 
00738         // successfully found overloaded function to handle wxLua call
00739         return (*lua_cfunc)(L);
00740     }
00741 
00742     // ----------------------------------------------------------------------
00743     // Did not find a suitable function to call, post error
00744 
00745     wxString fnCall = wxlua_getLuaArgsMsg(L, 1, arg_lua_count);
00746 
00747     wxString fnOverloadList = wxString::Format(wxT("Function called: '%s'\n"), fnCall.c_str());
00748     fnOverloadList += wxlua_getBindMethodArgsMsg(L, wxlMethod);
00749 
00750     wxString errmsg;
00751 
00752     if (cfunc_count > 1) // Note: we actually allow this.. for now
00753     {
00754         errmsg = wxT("wxLua: Function call is ambiguous.\nTry coercing values to proper types using tostring/number as appropriate.\n");
00755     }
00756 
00757     if (bestCFunc == NULL)
00758         errmsg += wxT("wxLua: Function call has invalid arguments.");
00759     else
00760     {
00761         // We have to count the methods that are displayed to find the one that failed
00762         // since we've skipped the ones with wrong number of args.
00763         method = wxlMethod;
00764         int i_cfunc = 0;
00765         bool found = false;
00766         while (method && !found)
00767         {
00768             for (i = 0; i < method->wxluacfuncs_n; ++i)
00769             {
00770                 i_cfunc++;
00771                 if (&method->wxluacfuncs[i] == bestCFunc)
00772                 {
00773                     found = true;
00774                     break;
00775                 }
00776             }
00777 
00778             method = method->basemethod;
00779         }
00780 
00781         errmsg += wxString::Format(wxT("wxLua: Function call has invalid argument %d on method %02d.\n"), invalid_lua_arg, i_cfunc);
00782     }
00783 
00784     errmsg += wxT("\n") + fnOverloadList;
00785 
00786     wxlua_error(L, errmsg);
00787 
00788     return 0;
00789 }
00790 
00791 wxString wxlua_getLuaArgsMsg(lua_State* L, int start_stack_idx, int end_stack_idx)
00792 {
00793     lua_Debug ar = {0};
00794 
00795     // NOTE: We'd like to be able to give some info, however if we are not
00796     // running a Lua function the lua_Debug is empty and lua_getinfo() will panic.
00797     if (lua_getstack(L, 0, &ar) == 0) // returns 0 when called on a level greater than stack depth
00798         return wxT("?");
00799 
00800     lua_getinfo(L, "n", &ar);
00801     wxString funcName = lua2wx(ar.name);
00802 
00803     wxString funcCall = funcName + wxT("(");
00804 
00805     for (int arg = start_stack_idx; arg <= end_stack_idx; ++arg)
00806     {
00807         if (arg > start_stack_idx) funcCall += wxT(", ");
00808 
00809         funcCall += wxluaT_gettypename(L, arg);
00810     }
00811     funcCall += wxT(")");
00812 
00813     return funcCall;
00814 }
00815 
00816 wxString wxlua_getBindMethodArgsMsg(lua_State* L, struct wxLuaBindMethod* wxlMethod)
00817 {
00818     wxCHECK_MSG(wxlMethod, wxEmptyString, wxT("Invalid method table"));
00819 
00820     wxString overloadMethods;
00821 
00822     int i_cfunc = 0; // count total number of overloads
00823     wxLuaBindMethod* method = wxlMethod;
00824 
00825     // traverse the methods down the baseclass methods if any
00826     while (method)
00827     {
00828         wxLuaBindCFunc* wxluacfuncs = method->wxluacfuncs;
00829         int i, arg, cfuncs_count = method->wxluacfuncs_n;
00830         wxString className;
00831 
00832         const wxLuaBindClass* wxlClass = wxLuaBinding::FindBindClass(method);
00833         if (wxlClass)
00834             className = lua2wx(wxlClass->name) + wxT("::");
00835 
00836         for (i = 0; i < cfuncs_count; ++i)
00837         {
00838             i_cfunc++;
00839 
00840             wxString funcStr = wxString::Format(wxT("%02d. %s%s("), i_cfunc, className.c_str(), lua2wx(method->name).c_str());
00841 
00842             for (arg = 0; arg < wxluacfuncs[i].maxargs; ++arg)
00843             {
00844                 // optional args?
00845                 if ((wxluacfuncs[i].minargs < wxluacfuncs[i].maxargs) && (arg+1 == wxluacfuncs[i].minargs))
00846                 {
00847                     if (arg > 0) funcStr += wxT(" ");
00848                     funcStr += wxT("[");
00849                 }
00850 
00851                 if (arg > 0)
00852                     funcStr += wxT(", ");
00853 
00854                 int wxl_type = (int)*(wxluacfuncs[i].argtypes[arg]);
00855                 funcStr += wxluaT_typename(L, wxl_type);
00856 
00857                 if ((arg == 0) &&
00858                     !WXLUA_HASBIT(wxluacfuncs[i].method_type, WXLUAMETHOD_STATIC) &&
00859                     !WXLUA_HASBIT(wxluacfuncs[i].method_type, WXLUAMETHOD_CONSTRUCTOR) &&
00860                     !WXLUA_HASBIT(wxluacfuncs[i].method_type, WXLUAMETHOD_CFUNCTION))
00861                     funcStr += wxT("(self)");
00862             }
00863 
00864             // close optional args
00865             if (wxluacfuncs[i].minargs < wxluacfuncs[i].maxargs)
00866                 funcStr += wxT("]");
00867 
00868             funcStr += wxT(")");
00869 
00870             if (WXLUA_HASBIT(wxluacfuncs[i].method_type, WXLUAMETHOD_STATIC))
00871                 funcStr += wxT(" - static");
00872 
00873             if (overloadMethods.Length() > 0)
00874                 overloadMethods += wxT("\n") + funcStr;
00875             else
00876                 overloadMethods += funcStr;
00877         }
00878 
00879         method = method->basemethod;
00880     }
00881 
00882     return overloadMethods;
00883 }
00884 
00885 // ----------------------------------------------------------------------------
00886 // Functions to compare binding structs using qsort and bsearch
00887 // ----------------------------------------------------------------------------
00888 
00889 // Function to compare to wxLuaBindEvents by eventType
00890 int wxLuaBindEventArrayCompareFn(const void *p1, const void *p2)
00891 {
00892     return (*((const wxLuaBindEvent*)p1)->eventType) - (*((const wxLuaBindEvent*)p2)->eventType);
00893 }
00894 // Function to compare to wxLuaBindNumber by name
00895 int wxLuaBindNumberArrayCompareFn(const void *p1, const void *p2)
00896 {
00897     return strcmp(((const wxLuaBindNumber*)p1)->name, ((const wxLuaBindNumber*)p2)->name);
00898 }
00899 // Function to compare to wxLuaBindStrings by name
00900 int wxLuaBindStringArrayCompareFn(const void *p1, const void *p2)
00901 {
00902     return strcmp(((const wxLuaBindString*)p1)->name, ((const wxLuaBindString*)p2)->name);
00903 }
00904 // Function to compare to wxLuaBindObjects by name
00905 int wxLuaBindObjectArrayCompareFn(const void *p1, const void *p2)
00906 {
00907     return strcmp(((const wxLuaBindObject*)p1)->name, ((const wxLuaBindObject*)p2)->name);
00908 }
00909 // Function to compare to wxLuaBindMethods by name
00910 int wxLuaBindMethodArrayCompareFnInit(const void *p1, const void *p2)
00911 {
00912     int v = strcmp(((const wxLuaBindMethod*)p1)->name, ((const wxLuaBindMethod*)p2)->name);
00913     if (v == 0)
00914     {
00915         int t1 = WXLUAMETHOD_SORT_MASK & ((const wxLuaBindMethod*)p1)->method_type;
00916         int t2 = WXLUAMETHOD_SORT_MASK & ((const wxLuaBindMethod*)p2)->method_type;
00917         v = t1 - t2;
00918     }
00919 
00920     wxCHECK_MSG(v != 0, 0, wxT("Duplicate wxLuaBindMethod names and method_types"));
00921 
00922     return v;
00923 }
00924 // Function for wxLuaBinding::GetClassMethod()
00925 int wxLuaBindMethodArrayCompareFnGet(const void *p1, const void *p2)
00926 {
00927     int v = strcmp(((const wxLuaBindMethod*)p1)->name, ((const wxLuaBindMethod*)p2)->name);
00928     if (v == 0)
00929     {
00930         int t1 = WXLUAMETHOD_SEARCH_MASK & ((const wxLuaBindMethod*)p1)->method_type;
00931         int t2 = WXLUAMETHOD_SEARCH_MASK & ((const wxLuaBindMethod*)p2)->method_type;
00932 
00933         if ((t1 & t2) != 0) return 0; // any matched bits will work
00934 
00935         v = t1 - t2;
00936     }
00937 
00938     return v;
00939 }
00940 // Function to compare the wxLuaBindClasses by name
00941 int wxLuaBindClassArrayCompareFn(const void *p1, const void *p2)
00942 {
00943     return strcmp(((const wxLuaBindClass*)p1)->name, ((const wxLuaBindClass*)p2)->name);
00944 }
00945 // Function to compare the wxLuaBindClasses by wxluatype
00946 int wxLuaBindClassArrayCompareBywxLuaType(const void *p1, const void *p2)
00947 {
00948     return (*((const wxLuaBindClass*)p1)->wxluatype) - (*((const wxLuaBindClass*)p2)->wxluatype);
00949 }
00950 
00951 // ----------------------------------------------------------------------------
00952 // wxLuaBinding
00953 // ----------------------------------------------------------------------------
00954 
00955 IMPLEMENT_ABSTRACT_CLASS(wxLuaBinding, wxObject)
00956 
00957 wxLuaBindingList wxLuaBinding::sm_bindingList;
00958 bool wxLuaBinding::sm_bindingList_initialized = false;
00959 int wxLuaBinding::sm_wxluatype_max = WXLUA_T_MAX+1; // highest wxLua type initially
00960 
00961 wxLuaBinding::wxLuaBinding()
00962              :m_classCount(0),    m_classArray(NULL),
00963               m_numberCount(0),   m_numberArray(NULL),
00964               m_stringCount(0),   m_stringArray(NULL),
00965               m_eventCount(0),    m_eventArray(NULL),
00966               m_objectCount(0),   m_objectArray(NULL),
00967               m_functionCount(0), m_functionArray(NULL),
00968               m_first_wxluatype(WXLUA_TUNKNOWN),
00969               m_last_wxluatype(WXLUA_TUNKNOWN)
00970 {
00971 }
00972 
00973 void wxLuaBinding::InitBinding()
00974 {
00975     // Sort all the bindings by something useful for faster lookup later
00976 
00977     if (m_classArray && (m_classCount > 0))
00978     {
00979         // initialize types only once, we don't need to resort them either
00980         if (*m_classArray[0].wxluatype != WXLUA_TUNKNOWN)
00981             return;
00982 
00983         qsort(m_classArray, m_classCount, sizeof(wxLuaBindClass), wxLuaBindClassArrayCompareFn);
00984 
00985         wxLuaBindClass* wxlClass = m_classArray;
00986         for (size_t i = 0; i < m_classCount; ++i, ++wxlClass)
00987         {
00988             *wxlClass->wxluatype = ++wxLuaBinding::sm_wxluatype_max;
00989 
00990             // Also sort the member functions for each class
00991             if (wxlClass->wxluamethods && (wxlClass->wxluamethods_n > 0))
00992                 qsort(wxlClass->wxluamethods, wxlClass->wxluamethods_n, sizeof(wxLuaBindMethod), wxLuaBindMethodArrayCompareFnInit);
00993             // And their enums
00994             if (wxlClass->enums && (wxlClass->enums_n > 0))
00995                 qsort(wxlClass->enums, wxlClass->enums_n, sizeof(wxLuaBindNumber), wxLuaBindNumberArrayCompareFn);
00996         }
00997 
00998         // these mark what types numbers are declared in this binding
00999         m_first_wxluatype = *m_classArray[0].wxluatype;
01000         m_last_wxluatype  = *m_classArray[m_classCount-1].wxluatype;
01001     }
01002 
01003     if (m_numberArray && (m_numberCount > 0))
01004         qsort(m_numberArray, m_numberCount, sizeof(wxLuaBindNumber), wxLuaBindNumberArrayCompareFn);
01005 
01006     if (m_stringArray && (m_stringCount > 0))
01007         qsort(m_stringArray, m_stringCount, sizeof(wxLuaBindString), wxLuaBindStringArrayCompareFn);
01008 
01009     // sort by event type for fastest lookup
01010     if (m_eventArray && (m_eventCount > 0))
01011         qsort(m_eventArray, m_eventCount, sizeof(wxLuaBindEvent), wxLuaBindEventArrayCompareFn);
01012 
01013     if (m_objectArray && (m_objectCount > 0))
01014         qsort(m_objectArray, m_objectCount, sizeof(wxLuaBindObject), wxLuaBindObjectArrayCompareFn);
01015 }
01016 
01017 bool wxLuaBinding::RegisterBinding(const wxLuaState& wxlState)
01018 {
01019     wxCHECK_MSG(wxlState.Ok(), false, wxT("Invalid wxLuaState"));
01020     lua_State *L = wxlState.GetLuaState();
01021 
01022     // Let Lua create a new table for us and add it to these places.
01023     // We use an empty luaL_Reg since we just want luaI_openlib to create the
01024     // tables for us, but we want to install the elements ourselves since
01025     // wxLua is too large to follow the luaI_openlib method without being
01026     // wasteful of memory and slow down the initialization.
01027     //    LUA_REGISTRYINDEX["_LOADED"][m_nameSpace] = table
01028     //    LUA_GLOBALSINDEX[m_nameSpace] = table
01029     //    LUA_GLOBALSINDEX["package"]["loaded"][m_nameSpace] = table
01030     static const luaL_Reg wxlualib[] = { {NULL, NULL} };
01031     luaI_openlib(L, wx2lua(m_nameSpace), wxlualib, 0);
01032 
01033     // luaI_openlib should have given error message about why it couldn't
01034     // create the table for us
01035     if (!lua_istable(L, -1))
01036     {
01037         lua_pop(L, 1); // pop the nil value
01038         return false;
01039     }
01040 
01041     // Find a registered binding with the same namespace, if any,
01042     // and share the table with that of the previously loaded binding
01043     int luaTable_ref = -1;
01044 
01045     lua_pushlightuserdata(L, &wxlua_lreg_wxluabindings_key); // push key
01046     lua_rawget(L, LUA_REGISTRYINDEX);   // pop key, push value (the bindings table)
01047 
01048     lua_pushnil(L);
01049     while (lua_next(L, -2) != 0)
01050     {
01051         // value = -1, key = -2, table = -3
01052         wxLuaBinding* binding = (wxLuaBinding*)lua_touserdata(L, -2);
01053 
01054         if (binding->GetLuaNamespace() == m_nameSpace)
01055         {
01056             luaTable_ref = (int)lua_tonumber(L, -1);
01057             lua_pop(L, 2); // pop key and value
01058             break;
01059         }
01060 
01061         lua_pop(L, 1); // pop value, lua_next will pop key at end
01062     }
01063 
01064     lua_pop(L, 1); // pop table
01065 
01066 
01067     // first time adding this namespace table
01068     if (luaTable_ref < 1)
01069     {
01070         // create a ref for the wxLua table we're filling
01071         luaTable_ref = wxluaR_ref(L, -1, &wxlua_lreg_refs_key);
01072     }
01073 
01074     // Add us to the LUA_REGISTRYINDEX table of bindings
01075     lua_pushlightuserdata(L, &wxlua_lreg_wxluabindings_key); // push key
01076     lua_rawget(L, LUA_REGISTRYINDEX); // pop key, push value (the bindings table)
01077 
01078     lua_pushlightuserdata(L, this);  // push key
01079     lua_pushnumber(L, luaTable_ref); // push value
01080     lua_rawset(L, -3);               // set t[key] = value; pop key and value
01081     lua_pop(L, 1);                   // pop table
01082 
01083     // register all our classes etc. in the wxLua table
01084     DoRegisterBinding(wxlState);
01085 
01086     return true;
01087 }
01088 
01089 void wxLuaBinding::DoRegisterBinding(const wxLuaState& wxlState) const
01090 {
01091     wxCHECK_RET(wxlState.Ok(), wxT("Invalid wxLuaState"));
01092     lua_State *L = wxlState.GetLuaState();
01093 
01094     size_t n;
01095 
01096     // install the classes, functions and methods, creating new wxLua types
01097     // if this is the first time we're registering them
01098     const wxLuaBindClass *wxlClass = m_classArray;
01099     for (n = 0; n < m_classCount; ++n, ++wxlClass)
01100     {
01101         InstallClassMetatable(L, wxlClass);
01102         InstallClass(L, wxlClass);
01103     }
01104 
01105     // register the global C style functions
01106     const wxLuaBindMethod* wxlMethod = m_functionArray;
01107     for (n = 0; n < m_functionCount; ++n, ++wxlMethod)
01108     {
01109         lua_pushstring(L, wxlMethod->name);
01110         lua_pushlightuserdata(L, (void*)wxlMethod);
01111         lua_pushcclosure(L, wxlMethod->wxluacfuncs[0].lua_cfunc, 1);
01112         lua_rawset(L, -3);
01113     }
01114 
01115     // install the numerical definitions
01116     const wxLuaBindNumber* wxlNumber = m_numberArray;
01117     for (n = 0; n < m_numberCount; ++n, ++wxlNumber)
01118     {
01119         lua_pushstring(L, wxlNumber->name);
01120         lua_pushnumber(L, wxlNumber->value);
01121         lua_rawset(L, -3);
01122     }
01123 
01124     // install the strings
01125     const wxLuaBindString *wxlString = m_stringArray;
01126     for (n = 0; n < m_stringCount; ++n, ++wxlString)
01127     {
01128         lua_pushstring(L, wxlString->name);
01129         lua_pushstring(L, wx2lua(wxlString->value));
01130         lua_rawset(L, -3);
01131     }
01132 
01133     // install the objects and pointers
01134     const wxLuaBindObject *wxlObject = m_objectArray;
01135     for (n = 0; n < m_objectCount; ++n, ++wxlObject)
01136     {
01137         lua_pushstring(L, wxlObject->name);
01138 
01139         if (wxlObject->objPtr != 0)
01140             wxluaT_pushuserdatatype(L, wxlObject->objPtr, *wxlObject->wxluatype, true);
01141         else
01142             wxluaT_pushuserdatatype(L, *wxlObject->pObjPtr, *wxlObject->wxluatype, true);
01143 
01144         lua_rawset(L, -3);
01145     }
01146 
01147     // register the wxEvent types
01148     const wxLuaBindEvent *wxlEvent = m_eventArray;
01149     for (n = 0; n < m_eventCount; ++n, ++wxlEvent)
01150     {
01151         lua_pushstring(L, wxlEvent->name);
01152         lua_pushnumber(L, *wxlEvent->eventType);
01153         lua_rawset(L, -3);
01154     }
01155 }
01156 
01157 /* static */
01158 bool wxLuaBinding::InstallClassMetatable(lua_State* L, const wxLuaBindClass* wxlClass)
01159 {
01160     // Replace the metatable functions for the classes we push into Lua
01161     static const luaL_reg s_funcTable[] =
01162     {
01163         {"__gc",       wxlua_wxLuaBindClass__gc },
01164         {"__index",    wxlua_wxLuaBindClass__index },
01165         {"__newindex", wxlua_wxLuaBindClass__newindex },
01166         {"__tostring", wxlua_wxLuaBindClass__tostring }
01167     };
01168     static const size_t s_funcCount = sizeof(s_funcTable)/sizeof(s_funcTable[0]);
01169 
01170     // ------------------------------------------------------------------
01171     // Add to the lookup table for "class name" to wxLuaBindClass struct
01172     lua_pushlightuserdata(L, &wxlua_lreg_classes_key);
01173     lua_rawget(L, LUA_REGISTRYINDEX);           // pop key, push result (the classes table)
01174     lua_pushstring(L, wxlClass->name);          // push key
01175     lua_pushlightuserdata(L, (void *)wxlClass); // push value
01176     lua_rawset(L, -3);                          // set t[key] = value, pops key and value
01177     lua_pop(L, 1);                              // pop wxlua_lreg_classes_key table
01178 
01179     // ------------------------------------------------------------------
01180     // Create a new metatable for this class with a numerical wxLua type index
01181 
01182     int wxl_type = *wxlClass->wxluatype;
01183 
01184     // we may be reregistering this binding, get the old metatable, we'll rewrite it
01185     if (!wxluaT_getmetatable(L, wxl_type))
01186         wxluaT_newmetatable(L, wxl_type); // create metatable, is on top of stack
01187 
01188     // store a lookup in the class metatable to the wxLuaBindClass struct
01189     lua_pushlightuserdata(L, &wxlua_metatable_wxluabindclass_key); // push key
01190     lua_pushlightuserdata(L, (void *)wxlClass);                    // push value
01191     lua_rawset(L, -3); // set t[key] = value, pops key and value
01192 
01193     // set the functions for the class in the metatable
01194     for (size_t i_func = 0; i_func < s_funcCount; ++i_func)
01195     {
01196         lua_pushstring(L, s_funcTable[i_func].name);      // push method name
01197         lua_pushlightuserdata(L, (void *)wxlClass);       // push the userdata
01198         lua_pushcclosure(L, s_funcTable[i_func].func, 1); // push func with wxlClass as upvalue
01199         lua_rawset(L, -3);  // t["method_name"] = closure of func and upvalues
01200     }
01201 
01202     lua_pop(L, 1); // pop metatable from wxluaT_newmetatable()
01203 
01204     return true;
01205 }
01206 
01207 /* static */
01208 bool wxLuaBinding::InstallClass(lua_State* L, const wxLuaBindClass* wxlClass)
01209 {
01210     // ------------------------------------------------------------------
01211     // Create and install the table for the class
01212 
01213     lua_pushstring(L, wxlClass->name); // push key
01214     lua_newtable(L);                   // push value, the table we use as the class
01215 
01216     // Install the member enums for the classname table
01217     for (int i_enum = 0; i_enum < wxlClass->enums_n; ++i_enum)
01218     {
01219         lua_pushstring(L, wxlClass->enums[i_enum].name);
01220         lua_pushnumber(L, wxlClass->enums[i_enum].value);
01221         lua_rawset(L, -3);
01222     }
01223 
01224     int method_count = wxlClass->wxluamethods_n;
01225 
01226     // Install the static functions for the classname table
01227     wxLuaBindMethod *wxlMethod = wxlClass->wxluamethods;
01228     for (int i_static_method = 0; i_static_method < method_count; ++i_static_method, ++wxlMethod)
01229     {
01230         // we will handle the WXLUAMETHOD_GET/SETPROP|WXLUAMETHOD_STATIC using __index and __newindex
01231         if (((wxlMethod->method_type & (WXLUAMETHOD_METHOD|WXLUAMETHOD_STATIC)) == (WXLUAMETHOD_METHOD|WXLUAMETHOD_STATIC)) &&
01232             (wxlMethod->wxluacfuncs_n > 0))
01233         {
01234             lua_pushstring(L, wxlMethod->name);
01235             lua_pushlightuserdata(L, wxlMethod);
01236             if (wxlMethod->wxluacfuncs_n > 1)
01237                 lua_pushcclosure(L, wxlua_callOverloadedFunction, 1);
01238             else
01239                 lua_pushcclosure(L, wxlMethod->wxluacfuncs[0].lua_cfunc, 1);
01240 
01241             lua_rawset(L, -3);
01242         }
01243     }
01244 
01245     // Create a metatable for the "class" table
01246     lua_newtable(L);
01247         lua_pushlstring(L, "__index", 7);
01248         lua_pushlightuserdata(L, (void*)wxlClass);
01249         lua_pushcclosure(L, wxlua_wxLuaBindMethod_table__index, 1);
01250         lua_rawset(L, -3);
01251 
01252         lua_pushlstring(L, "__newindex", 10);
01253         lua_pushlightuserdata(L, (void*)wxlClass);
01254         lua_pushcclosure(L, wxlua_wxLuaBindMethod_table__newindex, 1);
01255         lua_rawset(L, -3);
01256 
01257         //lua_pushstring(L, "__metatable");
01258         //lua_pushstring(L, "Metatable is not accessible");
01259         //lua_rawset(L, -3);
01260     lua_setmetatable(L, -2); // pops the metatable
01261 
01262     // Finalize the class table since we may not have a constructor
01263     // or have multiple constructors.
01264     lua_rawset(L, -3); // set t[key] = value, pops key and value
01265 
01266     // ------------------------------------------------------------------
01267     // Install public functions like constructors or global functions
01268     wxlMethod = wxlClass->wxluamethods;
01269     for (int i_method = 0; i_method < method_count; ++i_method, ++wxlMethod)
01270     {
01271         if (WXLUA_HASBIT(wxlMethod->method_type, WXLUAMETHOD_CONSTRUCTOR | WXLUAMETHOD_CFUNCTION) && wxlMethod->wxluacfuncs_n)
01272         {
01273             // push name of nested table and create the table or use existing
01274             // we do it this way since we can have multiple constructors (renamed)
01275             // that are of the same class and so they share the same wxLua type.
01276             lua_pushstring(L, wxlMethod->name);
01277 
01278             if (strcmp(wxlMethod->name, wxlClass->name) != 0)
01279                 lua_newtable(L);
01280             else
01281                 lua_getfield(L, -2, wxlMethod->name);
01282 
01283                 // add the items to the table as t[first pushed] = second pushed
01284                 lua_pushlstring(L, "new", 3);
01285                 lua_pushlightuserdata(L, wxlMethod);
01286                 lua_pushcclosure(L, wxlua_callOverloadedFunction, 1);
01287                 lua_rawset(L, -3);
01288 
01289                 // Add __call to the metatable for this table
01290                 bool has_meta = (lua_getmetatable(L, -1) != 0);
01291                 if (!has_meta) lua_newtable(L);
01292 
01293                     lua_pushlstring(L, "__call", 6);
01294                     lua_pushlightuserdata(L, wxlMethod);
01295                     lua_pushcclosure(L, wxlua_wxLuaBindMethod_table__call, 1);
01296                     lua_rawset(L, -3);
01297 
01298                     //lua_pushstring(L, "__metatable");
01299                     //lua_pushstring(L, "Metatable is not accessible");
01300                     //lua_rawset(L, -3);
01301 
01302                 if (!has_meta)
01303                     lua_setmetatable(L, -2);
01304                 else
01305                     lua_pop(L, 1);
01306 
01307             // add table to the binding table t[wxlMethod->name] = { this table }
01308             lua_rawset(L, -3); // set t[key] = value, pops key and value
01309         }
01310     }
01311 
01312     return true;
01313 }
01314 
01315 // ---------------------------------------------------------------------------
01316 
01317 const wxLuaBindEvent* wxLuaBinding::GetBindEvent(wxEventType eventType_) const
01318 {
01319     const wxEventType eventType = eventType_;
01320     wxLuaBindEvent eventItem = { "", &eventType, NULL };
01321 
01322     const wxLuaBindEvent *pLuaEvent = (wxLuaBindEvent *)bsearch(&eventItem,
01323                                                     m_eventArray,
01324                                                     m_eventCount,
01325                                                     sizeof(wxLuaBindEvent),
01326                                                     wxLuaBindEventArrayCompareFn);
01327     return pLuaEvent;
01328 }
01329 
01330 wxString wxLuaBinding::GetEventTypeName(wxEventType eventType) const
01331 {
01332     const wxLuaBindEvent* wxlEvent = GetBindEvent(eventType);
01333     return (wxlEvent != NULL) ? lua2wx(wxlEvent->name) : wxString();
01334 }
01335 
01336 const wxLuaBindClass* wxLuaBinding::GetBindClass(int wxluatype_) const
01337 {
01338     int wxluatype = wxluatype_; // create a local var to get the address of
01339     wxLuaBindClass classItem = { 0, 0, 0, 0, &wxluatype, 0, 0, 0, 0 };
01340 
01341     // this relies on LUA allocating the wxLua types in ascending order of definition
01342     // if LUA stops doing this, then the search may break.
01343     const wxLuaBindClass *wxlClass = (wxLuaBindClass *)bsearch(&classItem,
01344                                                        m_classArray,
01345                                                        m_classCount,
01346                                                        sizeof(wxLuaBindClass),
01347                                                        wxLuaBindClassArrayCompareBywxLuaType);
01348 
01349     return wxlClass;
01350 }
01351 
01352 const wxLuaBindClass* wxLuaBinding::GetBindClass(const char* className) const
01353 {
01354     wxLuaBindClass classItem = { className, 0, 0, 0, 0, 0, 0, 0, 0 };
01355 
01356     // this relies on LUA allocating the wxLua types in ascending order of definition
01357     // if LUA stops doing this, then the search may break.
01358     const wxLuaBindClass *wxlClass = (wxLuaBindClass *)bsearch(&classItem,
01359                                                        m_classArray,
01360                                                        m_classCount,
01361                                                        sizeof(wxLuaBindClass),
01362                                                        wxLuaBindClassArrayCompareFn);
01363 
01364     return wxlClass;
01365 }
01366 
01367 const wxLuaBindClass* wxLuaBinding::GetBindClass(const wxLuaBindMethod* wxlMethod_tofind) const
01368 {
01369     wxLuaBindClass*  wxlClass  = m_classArray;
01370     wxLuaBindMethod* wxlMethod = NULL;
01371 
01372     for (size_t c = 0; c < m_classCount; ++c, ++wxlClass)
01373     {
01374         wxlMethod = wxlClass->wxluamethods;
01375         int m , wxluamethods_n = wxlClass->wxluamethods_n;
01376 
01377         for (m = 0; m < wxluamethods_n; ++m, ++wxlMethod)
01378         {
01379             if (wxlMethod == wxlMethod_tofind)
01380                 return wxlClass;
01381         }
01382     }
01383 
01384     return NULL;
01385 }
01386 
01387 const wxLuaBindClass* wxLuaBinding::GetBindClass(const wxLuaBindCFunc* wxlCFunc_tofind) const
01388 {
01389     size_t c, m, f, methods_n, funcs_n;
01390     wxLuaBindClass*  wxlClass  = m_classArray;
01391     wxLuaBindMethod* wxlMethod = NULL;
01392     wxLuaBindCFunc*  wxlCFunc  = NULL;
01393 
01394     for (c = 0; c < m_classCount; ++c, ++wxlClass)
01395     {
01396         wxlMethod = wxlClass->wxluamethods;
01397         methods_n = wxlClass->wxluamethods_n;
01398 
01399         for (m = 0; m < methods_n; ++m, ++wxlMethod)
01400         {
01401             wxlCFunc = wxlMethod->wxluacfuncs;
01402             funcs_n  = wxlMethod->wxluacfuncs_n;
01403 
01404             for (f = 0; f < funcs_n; ++f, ++wxlCFunc)
01405             {
01406                 if (wxlCFunc == wxlCFunc_tofind)
01407                     return wxlClass;
01408             }
01409         }
01410     }
01411 
01412     return NULL;
01413 }
01414 
01415 // --------------------------------------------------------------------------
01416 
01417 // static
01418 wxLuaBinding* wxLuaBinding::GetLuaBinding(const wxString& bindingName)
01419 {
01420     wxLuaBindingList::compatibility_iterator node = sm_bindingList.GetFirst();
01421 
01422     while (node)
01423     {
01424         wxLuaBinding* binding = node->GetData();
01425         if (binding->GetBindingName() == bindingName)
01426             return binding;
01427 
01428         node = node->GetNext();
01429     }
01430 
01431     return NULL;
01432 }
01433 
01434 // static
01435 const wxLuaBindClass* wxLuaBinding::FindBindClass(const char* className)
01436 {
01437     wxLuaBindingList::compatibility_iterator node = sm_bindingList.GetFirst();
01438 
01439     while (node)
01440     {
01441         wxLuaBinding* binding = node->GetData();
01442         const wxLuaBindClass* wxlClass = binding->GetBindClass(className);
01443 
01444         if (wxlClass)
01445             return wxlClass;
01446 
01447         node = node->GetNext();
01448     }
01449 
01450     return NULL;
01451 }
01452 
01453 // static
01454 const wxLuaBindClass* wxLuaBinding::FindBindClass(int wxluatype)
01455 {
01456     wxLuaBindingList::compatibility_iterator node = sm_bindingList.GetFirst();
01457 
01458     while (node)
01459     {
01460         wxLuaBinding* binding = node->GetData();
01461         const wxLuaBindClass* wxlClass = binding->GetBindClass(wxluatype);
01462 
01463         if (wxlClass)
01464             return wxlClass;
01465 
01466         node = node->GetNext();
01467     }
01468 
01469     return NULL;
01470 }
01471 
01472 // static
01473 const wxLuaBindClass* wxLuaBinding::FindBindClass(const wxLuaBindMethod* wxlMethod)
01474 {
01475     wxLuaBindingList::compatibility_iterator node = sm_bindingList.GetFirst();
01476 
01477     while (node)
01478     {
01479         wxLuaBinding* binding = node->GetData();
01480         const wxLuaBindClass* wxlClass = binding->GetBindClass(wxlMethod);
01481 
01482         if (wxlClass)
01483             return wxlClass;
01484 
01485         node = node->GetNext();
01486     }
01487 
01488     return NULL;
01489 }
01490 
01491 // static
01492 const wxLuaBindClass* wxLuaBinding::FindBindClass(const wxLuaBindCFunc* wxlCFunc)
01493 {
01494     wxLuaBindingList::compatibility_iterator node = sm_bindingList.GetFirst();
01495 
01496     while (node)
01497     {
01498         wxLuaBinding* binding = node->GetData();
01499         const wxLuaBindClass* wxlClass = binding->GetBindClass(wxlCFunc);
01500 
01501         if (wxlClass)
01502             return wxlClass;
01503 
01504         node = node->GetNext();
01505     }
01506 
01507     return NULL;
01508 }
01509 
01510 // static
01511 const wxLuaBindEvent* wxLuaBinding::FindBindEvent(wxEventType eventType)
01512 {
01513     wxLuaBindingList::compatibility_iterator node = sm_bindingList.GetFirst();
01514 
01515     while (node)
01516     {
01517         wxLuaBinding* binding = node->GetData();
01518         const wxLuaBindEvent* wxlEvent = binding->GetBindEvent(eventType);
01519 
01520         if (wxlEvent)
01521             return wxlEvent;
01522 
01523         node = node->GetNext();
01524     }
01525 
01526     return NULL;
01527 }
01528 
01529 // static
01530 wxLuaBinding* wxLuaBinding::FindMethodBinding(const wxLuaBindMethod* wxlMethod)
01531 {
01532     wxLuaBindingList::compatibility_iterator node = sm_bindingList.GetFirst();
01533 
01534     while (node)
01535     {
01536         wxLuaBinding* binding = node->GetData();
01537         size_t n, count = binding->GetFunctionCount();
01538         wxLuaBindMethod* m = binding->GetFunctionArray();
01539 
01540         for (n = 0; n < count; ++n, ++m)
01541         {
01542             if (m == wxlMethod)
01543                 return binding;
01544         }
01545 
01546         node = node->GetNext();
01547     }
01548 
01549     return NULL;
01550 }
01551 
01552 
01553 // --------------------------------------------------------------------------
01554 
01555 // static
01556 wxLuaBindMethod* wxLuaBinding::GetClassMethod(const wxLuaBindClass *wxlClass, const char *methodName, int method_type, bool search_baseclasses)
01557 {
01558     wxCHECK_MSG(wxlClass, NULL, wxT("Invalid wxLuaBindClass to find method from."));
01559 
01560 #if 1
01561 
01562     wxLuaBindMethod methodItem = { methodName, method_type, 0, 0, 0 };
01563 
01564     wxLuaBindMethod *wxlMethod = (wxLuaBindMethod *)bsearch(&methodItem,
01565                                                        wxlClass->wxluamethods,
01566                                                        wxlClass->wxluamethods_n,
01567                                                        sizeof(wxLuaBindMethod),
01568                                                        wxLuaBindMethodArrayCompareFnGet);
01569 
01570     if ((wxlMethod == NULL) && search_baseclasses && wxlClass->baseclassNames)
01571     {
01572         for (size_t i = 0; wxlClass->baseclassNames[i]; ++i)
01573         {
01574             wxlMethod = GetClassMethod(wxlClass->baseBindClasses[i], methodName, method_type, search_baseclasses);
01575             if (wxlMethod != NULL)
01576                 return wxlMethod;
01577         }
01578     }
01579 
01580 #else
01581 
01582     wxLuaBindMethod *wxlMethod = wxlClass->wxluamethods;
01583     int i_method, method_count = wxlClass->wxluamethods_n;
01584 
01585     // find a method in the class, recurse through classes from which this class is derived.
01586     for (i_method = 0; i_method < method_count; ++i_method, ++wxlMethod)
01587     {
01588         if (WXLUA_HASBIT(wxlMethod->type, method_type)
01589                 && (strcmp(wxlMethod->name, methodName) == 0))
01590         {
01591             return wxlMethod;
01592         }
01593     }
01594 
01595     if (search_baseclasses && wxlClass->baseclass)
01596         return GetClassMethod(wxlClass->baseclass, methodName, method_type, search_baseclasses);
01597 
01598 #endif
01599 
01600     return wxlMethod;
01601 }
01602 
01603 // --------------------------------------------------------------------------
01604 
01605 static void wxLuaBinding_RecurseBaseMethods(wxLuaBindClass* wxlClass, wxLuaBindMethod* wxlMethod, bool force_update)
01606 {
01607     // iterate through the base classes to find if this function is
01608     // an overload, but only if we haven't checked already.
01609     if (force_update || !WXLUA_HASBIT(wxlMethod->method_type, WXLUAMETHOD_CHECKED_OVERLOAD|WXLUAMETHOD_DELETE))
01610     {
01611         wxLuaBindMethod *parentMethod = wxlMethod;
01612 
01613         // Use the baseclassNames to check for terminating NULL
01614         for (size_t i = 0; wxlClass->baseclassNames && wxlClass->baseclassNames[i]; ++i)
01615         {
01616             // Note that these may be NULL if the lib/module containing them wasn't loaded
01617             wxLuaBindClass *baseClass = wxlClass->baseBindClasses[i];
01618             if (baseClass != NULL)
01619             {
01620                 parentMethod->method_type |= WXLUAMETHOD_CHECKED_OVERLOAD; // have checked parent
01621 
01622                 wxLuaBindMethod* baseMethod = wxLuaBinding::GetClassMethod(baseClass, wxlMethod->name, WXLUAMETHOD_SEARCH_MASK, false);
01623                 if (baseMethod)
01624                 {
01625                     // don't link to base class delete functions
01626                     if (!WXLUA_HASBIT(baseMethod->method_type, WXLUAMETHOD_DELETE))
01627                     {
01628                         parentMethod->basemethod = baseMethod;
01629                         parentMethod = baseMethod;
01630                     }
01631 
01632                     // we have already checked the base classes below this
01633                     if (!WXLUA_HASBIT(baseMethod->method_type, WXLUAMETHOD_CHECKED_OVERLOAD))
01634                         wxLuaBinding_RecurseBaseMethods(baseClass, parentMethod, force_update);
01635                 }
01636             }
01637         }
01638     }
01639 }
01640 
01641 // static
01642 void wxLuaBinding::InitAllBindings(bool force_update)
01643 {
01644     if (sm_bindingList_initialized && !force_update) return;
01645 
01646     // Initialize the bindings, sort and set the wxLua types
01647     wxLuaBindingList::compatibility_iterator node = sm_bindingList.GetFirst();
01648     while (node)
01649     {
01650         wxLuaBinding* binding = node->GetData();
01651         binding->InitBinding();
01652 
01653         node = node->GetNext();
01654     }
01655 
01656     // set the base class wxLuaBindClass* using the base class names of the parent wxLuaBindClass
01657     node = sm_bindingList.GetFirst();
01658     while (node)
01659     {
01660         wxLuaBinding* binding    = node->GetData();
01661         wxLuaBindClass* wxlClass = binding->GetClassArray();
01662         size_t i, class_count    = binding->GetClassCount();
01663 
01664         for (i = 0; i < class_count; ++i, ++wxlClass)
01665         {
01666             if (wxlClass->baseclassNames) // does it have any base classes at all?
01667             {
01668                 // find the base class using their names in the bindings
01669                 for (size_t j = 0; wxlClass->baseclassNames[j]; ++j)
01670                 {
01671                     wxLuaBindClass* wxlBaseClass = (wxLuaBindClass*)wxLuaBinding::FindBindClass(wxlClass->baseclassNames[j]);
01672                     if (wxlBaseClass)
01673                         wxlClass->baseBindClasses[j] = wxlBaseClass;
01674                 }
01675             }
01676         }
01677 
01678         node = node->GetNext();
01679     }
01680 
01681     // Link together all of the class member functions with base class functions
01682     // with the same name so the overloads work for them too.
01683     node = sm_bindingList.GetFirst();
01684     while (node)
01685     {
01686         wxLuaBinding* binding    = node->GetData();
01687         wxLuaBindClass* wxlClass = binding->GetClassArray();
01688         size_t i, class_count    = binding->GetClassCount();
01689 
01690         for (i = 0; i < class_count; ++i, ++wxlClass)
01691         {
01692             if (wxlClass->baseclassNames) // does it have any base classes at all?
01693             {
01694                 wxLuaBindMethod *wxlMethod = wxlClass->wxluamethods;
01695                 size_t j, method_count = wxlClass->wxluamethods_n;
01696 
01697                 for (j = 0; j < method_count; ++j, ++wxlMethod)
01698                 {
01699                     wxLuaBinding_RecurseBaseMethods(wxlClass, wxlMethod, force_update);
01700                 }
01701             }
01702         }
01703 
01704         node = node->GetNext();
01705     }
01706 
01707     sm_bindingList_initialized = true;
01708 }
Generated on Tue Jul 13 10:30:39 2010 for wxLua by  doxygen 1.6.3