wxlstate.cpp

Go to the documentation of this file.
00001 /////////////////////////////////////////////////////////////////////////////
00002 // Name:        wxlstate.cpp
00003 // Purpose:     wxLuaState, a wxWidgets interface to Lua
00004 // Author:      Ray Gilbert, John Labenski, J Winwood (Reuben Thomas for bitlib at bottom)
00005 // Created:     14/11/2001
00006 // Copyright:   (c) 2001-2002 Lomtick Software. All rights reserved.
00007 // Licence:     wxWidgets licence
00008 /////////////////////////////////////////////////////////////////////////////
00009 
00010 // For compilers that support precompilation, includes "wx/wx.h"
00011 #include "wx/wxprec.h"
00012 
00013 #ifdef __BORLANDC__
00014     #pragma hdrstop
00015 #endif
00016 
00017 // for all others, include the necessary headers
00018 #ifndef WX_PRECOMP
00019     #include "wx/wx.h"
00020 #endif
00021 
00022 #include "wxlua/include/wxlstate.h"
00023 #include "wxlua/include/wxlcallb.h"
00024 #include "wx/tokenzr.h"
00025 
00026 //#include "wxluadebug/include/wxldebug.h" // for debugging only
00027 
00028 const char* wxlua_lreg_types_key               = "wxLua metatable class types";
00029 const char* wxlua_lreg_refs_key                = "wxLua Lua object refs";
00030 const char* wxlua_lreg_debug_refs_key          = "wxLuaDebugData refs";
00031 const char* wxlua_lreg_classes_key             = "wxLuaBindClass structs";
00032 const char* wxlua_lreg_derivedmethods_key      = "wxLua derived class methods";
00033 const char* wxlua_lreg_wxluastate_key          = "wxLuaState";
00034 const char* wxlua_lreg_wxluabindings_key       = "wxLuaBindings";
00035 const char* wxlua_lreg_weakobjects_key         = "wxLua objects pushed";
00036 const char* wxlua_lreg_gcobjects_key           = "wxLua gc objects to delete";
00037 const char* wxlua_lreg_evtcallbacks_key        = "wxLuaEventCallbacks";
00038 const char* wxlua_lreg_windestroycallbacks_key = "wxLuaWinDestoyCallbacks";
00039 const char* wxlua_lreg_topwindows_key          = "wxLua top level wxWindows";
00040 const char* wxlua_lreg_callbaseclassfunc_key   = "wxLua CallBaseClassFunc";
00041 const char* wxlua_lreg_wxeventtype_key         = "wxLua wxEventType";
00042 const char* wxlua_lreg_wxluastatedata_key      = "wxLuaStateData";
00043 const char* wxlua_lreg_regtable_key            = "wxLua LUA_REGISTRYINDEX tables";
00044 
00045 const char* wxlua_metatable_type_key           = "wxLua metatable class type";
00046 const char* wxlua_metatable_wxluabindclass_key = "wxLua metatable wxLuaBindClass";
00047 
00048 wxLuaState wxNullLuaState(false);
00049 
00050 int LUACALL luaopen_bit(lua_State *L); // implemented at bottom of file
00051 
00052 // ----------------------------------------------------------------------------
00053 // C functions for Lua used in wxLuaState
00054 // ----------------------------------------------------------------------------
00055 
00056 // The print function that we push into Lua replacing "print(...)"
00057 // to generate wxLuaEvent(wxEVT_LUA_PRINT, ...)
00058 // Code copied from Lua's luaB_print() function in lbaselib.c
00059 int LUACALL wxlua_printFunction( lua_State *L )
00060 {
00061     wxLuaState wxlState(L); // doesn't have to be ok
00062 
00063     wxString msg;
00064     int i, n = lua_gettop(L);
00065 
00066     // Use the Lua tostring() function to print them as Lua would
00067     lua_getglobal(L, "tostring");
00068 
00069     if (!lua_isfunction(L, -1))
00070     {
00071         // This code is also used in wxledit.cpp, wxLuaShell::RunString()
00072         msg = wxT("wxLua ERROR: Unable to print() without the tostring() function. Did you remove it?");
00073         lua_pop(L, 1);  // pop the nil or whatever replaced tostring()
00074         n = 0;          // don't let for loop run
00075     }
00076 
00077     for (i = 1; i <= n; ++i)
00078     {
00079         if (i > 1) msg.Append(wxT("\t")); // Lua uses a tab too in luaB_print
00080 
00081         const char *s;
00082         lua_pushvalue(L, -1);       /* function to be called */
00083         lua_pushvalue(L, i);        /* value to print */
00084         lua_call(L, 1, 1);
00085         s = lua_tostring(L, -1);    /* get result */
00086         if (s == NULL)
00087         {
00088             // FIXME use wxlua_error here? right now wxlua_error doesn't do anything special - JL
00089             return luaL_error(L, LUA_QL("tostring") " must return a string to "
00090                               LUA_QL("print"));
00091         }
00092         msg += lua2wx(s);
00093         lua_pop(L, 1);  /* pop result */
00094     }
00095 
00096     if (!msg.IsEmpty() && wxlState.Ok())
00097     {
00098         wxLuaEvent event(wxEVT_LUA_PRINT, wxlState.GetId(), wxlState);
00099         event.SetString(msg);
00100         wxlState.SendEvent(event);
00101     }
00102     else if (!msg.IsEmpty())
00103         wxPrintf(wxT("%s\n"), msg.c_str()); // Lua puts a \n too
00104 
00105     return 0; // no items put onto stack
00106 }
00107 
00108 void LUACALL wxlua_debugHookFunction(lua_State *L, lua_Debug *LDebug)
00109 {
00110     // NULL when shutting down.
00111     wxLuaStateData* wxlStateData = wxlua_getwxluastatedata(L);
00112     if (!wxlStateData) return;
00113 
00114     // FIXME - for select event types we don't want to do anything
00115     wxEventType evtType = wxlua_getwxeventtype(L);
00116     if ((evtType != wxEVT_NULL))
00117         //(evtType == wxEVT_IDLE) && (evtType == wxEVT_PAINT) &&
00118         //(evtType == wxEVT_DESTROY) && (evtType == wxEVT_CLOSE_WINDOW))
00119         return;
00120 
00121     // they want to break the program, restore old debug hook, then error out
00122     if (wxlStateData->m_debug_hook_break)
00123     {
00124         // It's ok that we get the wxLuaState here since we're stopping anyway.
00125         wxLuaState wxlState(L);
00126 
00127         // restore hook to previous state
00128         wxlState.ClearDebugHookBreak();
00129         wxlua_error(L, wxlStateData->m_debug_hook_break_msg);
00130         return;
00131     }
00132 
00133     // Assume they've set the wxEvtHandler, ok if not, but it wouldn't make sense
00134     // We use wxLuaState::SendEvent() because it sets wxEvent::SetEventObject() for us.
00135     if (wxlStateData->m_lua_debug_hook_send_evt)
00136     {
00137         wxLuaState wxlState(L);
00138 
00139         int ret = 0;
00140         ret = lua_getinfo(L, "l", LDebug); // line (ldebug.currentline)
00141 
00142         wxLuaEvent event(wxEVT_LUA_DEBUG_HOOK, wxlState.GetId(), wxlState);
00143         event.m_lua_Debug = LDebug;
00144         event.SetInt(LDebug->currentline);
00145         wxlState.SendEvent( event );
00146         if (event.m_debug_hook_break)
00147             wxlState.wxlua_Error("Lua interpreter stopped.");
00148     }
00149 
00150     // Try to yield *after* sending event to allow C++ gui update
00151     if (wxlStateData->m_lua_debug_hook_yield > 0)
00152     {
00153         // yield based on number of ms passed NOT every hook event
00154         unsigned long last_time = wxlStateData->m_last_debug_hook_time;
00155         unsigned long cur_time  = wxGetLocalTimeMillis().GetLo();
00156 
00157         if ((cur_time > last_time + wxlStateData->m_lua_debug_hook_yield) ||
00158             (cur_time < last_time)) // wrapped
00159         {
00160             wxlStateData->m_last_debug_hook_time = cur_time;
00161 
00162             bool painting = (evtType == wxEVT_PAINT);
00163 
00164 /*
00165             wxLongToLongHashMap::iterator it;
00166             wxLongToLongHashMap* hashMap = &wxlState.GetLuaStateRefData()->m_wxlStateData->m_trackedObjects;
00167             for (it = hashMap->begin(); it != hashMap->end(); ++it)
00168             {
00169                 wxObject* obj = (wxObject*)it->second;
00170                 if (obj && wxDynamicCast(obj, wxPaintDC))
00171                 {
00172                     painting = true;
00173                     break;
00174                 }
00175             }
00176 */
00177 
00178             if (!painting)
00179                 wxYield(); //IfNeeded();
00180         }
00181     }
00182 }
00183 
00184 // ----------------------------------------------------------------------------
00185 
00186 void wxlua_lreg_createtable(lua_State* L, void* lightuserdata_reg_key, int narr, int nrec)
00187 {
00188     // clear the old ref to the table, even though it's weak kv
00189     // it doesn't get cleared until the gc runs
00190     lua_pushlightuserdata(L, &wxlua_lreg_regtable_key); // push key
00191     lua_rawget(L, LUA_REGISTRYINDEX);                   // get table
00192       lua_pushlightuserdata(L, lightuserdata_reg_key);  // push key
00193       lua_rawget(L, LUA_REGISTRYINDEX);                 // get table or nil
00194       if (lua_istable(L, -1))
00195       {
00196           lua_pushnil(L);                               // push value
00197           lua_rawset(L, -3);                            // clear t[key] = nil
00198           lua_pop(L, 1);                                // pop wxlua_lreg_regtable_key table
00199       }
00200       else
00201         lua_pop(L, 2); // pop nil and wxlua_lreg_regtable_key table
00202 
00203     // Add new LUA_REGISTRYINDEX[&wxlua_lreg_regtable_key][lightuserdata_reg_key table] = lightuserdata_reg_key
00204     lua_pushlightuserdata(L, lightuserdata_reg_key); // push key
00205     lua_createtable(L, narr, nrec);                  // push value
00206         lua_pushlightuserdata(L, &wxlua_lreg_regtable_key); // push key
00207         lua_rawget(L, LUA_REGISTRYINDEX);                   // get wxlua_lreg_regtable_key table
00208         lua_pushvalue(L, -2);    // push key (copy of the new table)
00209         lua_pushvalue(L, -4);    // push value (copy of lightuserdata key)
00210         lua_rawset(L, -3);       // set t[key] = value; pops key and value
00211         lua_pop(L, 1);           // pop wxlua_lreg_regtable_key table
00212     lua_rawset(L, LUA_REGISTRYINDEX); // set the value
00213 }
00214 
00215 // ----------------------------------------------------------------------------
00216 // Lua helper functions
00217 // ----------------------------------------------------------------------------
00218 
00219 wxString wxlua_LUA_ERR_msg(int LUA_ERRx)
00220 {
00221     switch (LUA_ERRx)
00222     {
00223         case 0             : return wxEmptyString;
00224         case LUA_YIELD     : return wxT("Lua: Thread is suspended");
00225         case LUA_ERRRUN    : return wxT("Lua: Error while running chunk");
00226         case LUA_ERRSYNTAX : return wxT("Lua: Syntax error during pre-compilation");
00227         case LUA_ERRMEM    : return wxT("Lua: Memory allocation error");
00228         case LUA_ERRERR    : return wxT("Lua: Generic error or an error occurred while running the error handler");
00229         case LUA_ERRFILE   : return wxT("Lua: Error occurred while opening file");
00230     }
00231 
00232     return wxT("Lua: Unknown LUA_ERRx error value");
00233 }
00234 
00235 bool wxlua_errorinfo(lua_State* L, int status, int top, wxString* errorMsg_, int* line_num_)
00236 {
00237     if (status == 0)
00238         return false;
00239 
00240     int newtop = lua_gettop(L);
00241 
00242     wxString errorMsg = wxlua_LUA_ERR_msg(status);
00243 
00244     switch(status)
00245     {
00246         case LUA_ERRMEM:
00247         case LUA_ERRERR:
00248         {
00249             if (newtop > top)
00250                 errorMsg += wxT("\n");
00251             break;
00252         }
00253         case LUA_ERRRUN:
00254         case LUA_ERRFILE:
00255         case LUA_ERRSYNTAX:
00256         default:
00257         {
00258             if (newtop > top)
00259                 errorMsg += wxT("\n") + lua2wx(lua_tostring(L, -1));
00260             break;
00261         }
00262     }
00263 
00264     errorMsg += wxT("\n");
00265 
00266     // Why can't I fill a lua_Debug here? Try to get the line number
00267     // by parsing the error message that looks like this, 3 is linenumber
00268     // [string "a = 1("]:3: unexpected symbol near `<eof>'
00269     wxString lineStr = errorMsg;
00270     long line_num = -1;
00271     while(!lineStr.IsEmpty())
00272     {
00273         // search through the str to find ']:LONG:' pattern
00274         lineStr = lineStr.AfterFirst(wxT(']'));
00275         if ((lineStr.Length() > 0) && (lineStr.GetChar(0) == wxT(':')))
00276         {
00277             lineStr = lineStr.AfterFirst(wxT(':'));
00278             if (lineStr.IsEmpty() || lineStr.BeforeFirst(wxT(':')).ToLong(&line_num))
00279                 break;
00280         }
00281     }
00282 
00283     lua_settop(L, top); // pops the message if any
00284 
00285     if (errorMsg_) *errorMsg_ = errorMsg;
00286     if (line_num_) *line_num_ = (int)line_num;
00287 
00288     return true;
00289 }
00290 
00291 void LUACALL wxlua_error(lua_State *L, const char *errorMsg)
00292 {
00293     // Use luaL_error(L, s) and not "lua_pushstring(L, s); lua_error(L)" since
00294     // luaL_error() provides the file and line number too.
00295     luaL_error(L, "%s", errorMsg);
00296 }
00297 
00298 void LUACALL wxlua_argerror(lua_State *L, int stack_idx, const wxString& expectedType)
00299 {
00300     wxString argType = wxlua_luaL_typename(L, stack_idx);
00301 
00302     wxString msg(wxString::Format(_("wxLua: Expected %s for parameter %d, but got a '%s'."),
00303                                     expectedType.c_str(), stack_idx, argType.c_str()));
00304 
00305     wxlua_argerrormsg(L, msg);
00306 }
00307 
00308 void LUACALL wxlua_argerrormsg(lua_State *L, const wxString& msg_)
00309 {
00310     wxString funcArgs(wxT("\n"));
00311     wxString argMsg  = wxlua_getLuaArgsMsg(L, 1, lua_gettop(L));
00312 
00313     wxLuaBindMethod* wxlMethod = (wxLuaBindMethod *)lua_touserdata(L, lua_upvalueindex(1)); // lightuserdata
00314     if (wxlMethod != NULL)
00315     {
00316         // Guarantee that this is a wxLuaBindMethod of ours so we don't crash.
00317         // Since we're going to error out we don't have to be quick about it.
00318 
00319         // check if this method is part of a class
00320         const wxLuaBindClass* wxlClass = wxLuaBinding::FindBindClass(wxlMethod);
00321 
00322         // if not, check if it's a global C style function
00323         wxLuaBinding* binding = NULL;
00324         if (wxlClass == NULL)
00325             binding = wxLuaBinding::FindMethodBinding(wxlMethod);
00326 
00327         if ((wxlClass != NULL) || (binding != NULL))
00328             funcArgs += wxlua_getBindMethodArgsMsg(L, wxlMethod);
00329     }
00330 
00331     wxString msg = msg_ + wxT("\nFunction called: '") + argMsg + wxT("'") + funcArgs;
00332     wxlua_error(L, msg);
00333 }
00334 
00335 void* LUACALL wxlua_touserdata(lua_State *L, int stack_idx, bool null_ptr /*= false*/)
00336 {
00337     void *pdata = NULL;
00338     void **ptr = (void **)lua_touserdata(L, stack_idx);
00339 
00340     if (ptr != NULL)
00341     {
00342         pdata = *ptr;       // get the pointer the userdata holds
00343         if (null_ptr)       // NULL ptr so Lua won't try to gc it
00344             *ptr = NULL;
00345     }
00346 
00347     return pdata;
00348 }
00349 
00350 // ----------------------------------------------------------------------------
00351 // wxluaR_XXX - functions operate on tables in Lua's LUA_REGISTRYINDEX
00352 // ----------------------------------------------------------------------------
00353 
00354 #define ABS_LUA_STKIDX(n, added_items) ((n) > 0 ? (n) : (n)-(added_items))
00355 
00356 // Note about luaL_ref() and luaL_unref().
00357 // ref creates integer numbers from 1 to ...
00358 // unref uses t[0] to hold the last unused reference and when you call unref
00359 // again the next unused ref points back to the first and t[0] points to the
00360 // last unrefed key.
00361 // eg. create 5 refs, get refs 1,2,3,4,5, then call unref on 3 then 4 then
00362 //     call ref 3 times and the new references will be 4, 3, 6
00363 
00364 int wxluaR_ref(lua_State* L, int stack_idx, void* lightuserdata_reg_key)
00365 {
00366     // nothing on stack to insert and don't bother inserting nil
00367     if (lua_isnoneornil(L, stack_idx))
00368         return LUA_REFNIL;
00369 
00370     lua_pushlightuserdata(L, lightuserdata_reg_key);    // push key
00371     lua_rawget(L, LUA_REGISTRYINDEX);                   // pop key, push value (table)
00372 
00373     lua_pushvalue(L, ABS_LUA_STKIDX(stack_idx,1));      // push value to store
00374 
00375     int ref_idx = luaL_ref(L, -2);                      // t[ref_idx] = value; pops value
00376 
00377     // We also store t[value] = table_idx for this table for faster lookup
00378     if (lightuserdata_reg_key == &wxlua_lreg_debug_refs_key)
00379     {
00380         lua_pushvalue(L, ABS_LUA_STKIDX(stack_idx,1));  // push key
00381         lua_pushnumber(L, ref_idx);                     // push value
00382         lua_rawset(L, -3);                              // set t[key] = value; pops key and value
00383     }
00384 
00385     lua_pop(L, 1);                                      // pop table
00386 
00387     return ref_idx;
00388 }
00389 
00390 bool wxluaR_unref(lua_State* L, int ref_idx, void* lightuserdata_reg_key)
00391 {
00392     if (ref_idx == LUA_REFNIL)                       // nothing to remove
00393         return false;
00394 
00395     lua_pushlightuserdata(L, lightuserdata_reg_key); // push key
00396     lua_rawget(L, LUA_REGISTRYINDEX);                // pop key, push value (table)
00397 
00398     // Also remove the t[value] = table_idx for this table
00399     if (lightuserdata_reg_key == &wxlua_lreg_debug_refs_key)
00400     {
00401         lua_pushnumber(L, ref_idx);   // push key
00402         lua_rawget(L, -2);            // get t[key] = value; pop key, push value;
00403 
00404         lua_pushnil(L);
00405         lua_rawset(L, -3);            // t[value] = nil; pops key and value
00406     }
00407 
00408     luaL_unref(L, -1, ref_idx);       // remove key and value in refs table
00409                                       // note: this key will be used for the next wxluaR_ref()
00410 
00411     lua_pop(L, 1);                    // pop table
00412 
00413     return true;
00414 }
00415 
00416 bool LUACALL wxluaR_getref(lua_State *L, int ref_idx, void* lightuserdata_reg_key)
00417 {
00418     if (ref_idx == LUA_REFNIL)          // nothing to get
00419         return false;
00420 
00421     lua_pushlightuserdata(L, lightuserdata_reg_key); // push key
00422     lua_rawget(L, LUA_REGISTRYINDEX);                // pop key, push value (table)
00423 
00424     lua_rawgeti(L, -1, ref_idx);        // get t[ref_idx] = value; push value
00425 
00426     if (lua_isnil(L, -1))               // not a valid table key
00427     {
00428         lua_pop(L, 2);                  // pop nil and table
00429         return false;
00430     }
00431 
00432     lua_remove(L, -2);                  // remove table, leaving value on top
00433 
00434     return true; // return if table has a valid value and it's on the stack
00435 }
00436 
00437 int LUACALL wxluaR_isrefed(lua_State* L, int stack_idx, void* lightuserdata_reg_key)
00438 {
00439     int ref_idx = LUA_NOREF;
00440 
00441     lua_pushlightuserdata(L, lightuserdata_reg_key);    // push key
00442     lua_rawget(L, LUA_REGISTRYINDEX);                   // pop key, push value (table)
00443 
00444     if (lightuserdata_reg_key == &wxlua_lreg_debug_refs_key)
00445     {
00446         // For this table we've pushed the value for a faster lookup
00447         lua_pushvalue(L, ABS_LUA_STKIDX(stack_idx,1));  // push key (the value)
00448         lua_rawget(L, -2);                              // get t[key] = value; pop key push value
00449         ref_idx = (int)lua_tonumber(L, -1);
00450 
00451         if ((ref_idx == 0) && !lua_isnumber(L, -1))     // if !isnumber it returns 0 (faster)
00452             ref_idx = LUA_NOREF;
00453 
00454         lua_pop(L, 2); // pop object we pushed and the ref table
00455     }
00456     else
00457     {
00458         // otherwise search through all the values
00459         lua_pushnil(L);
00460         while (lua_next(L, -2) != 0)
00461         {
00462             // value = -1, key = -2, table = -3, object = stack_idx before 3 added items
00463             if (lua_equal(L, -1, ABS_LUA_STKIDX(stack_idx,3)))
00464             {
00465                 ref_idx = (int)lua_tonumber(L, -2);
00466                 lua_pop(L, 2);               // pop key, value
00467                 break;
00468             }
00469             else
00470                 lua_pop(L, 1);               // pop value, lua_next will pop key at end
00471         }
00472 
00473         lua_pop(L, 1); // pop ref table
00474     }
00475 
00476     return ref_idx;
00477 }
00478 
00479 // ----------------------------------------------------------------------------
00480 // wxluaO_XXX - functions operate on the "Objects"
00481 // ----------------------------------------------------------------------------
00482 
00483 void LUACALL wxluaO_addgcobject(lua_State *L, wxObject* wxobj)
00484 {
00485     wxluaO_addgcobject(L, (void*)wxobj, wxobj);
00486 }
00487 void LUACALL wxluaO_addgcobject(lua_State *L, void *obj_ptr, wxObject* wxobj)
00488 {
00489     lua_pushlightuserdata(L, &wxlua_lreg_gcobjects_key); // push key
00490     lua_rawget(L, LUA_REGISTRYINDEX);                    // pop key, push value (table)
00491 
00492     // Check if it's already tracked since that means the weak udata table isn't working right
00493     lua_pushlightuserdata(L, obj_ptr); // push key
00494     lua_rawget(L, -2);                 // get t[key] = value, pops key
00495     if (!lua_isnil(L, -1))
00496     {
00497         lua_pop(L, 2); // pop table and value
00498         wxFAIL_MSG(wxT("Tracking an object twice in wxluaO_addgcobject: ") + wxString(wxobj->GetClassInfo()->GetClassName()));
00499         return;
00500     }
00501     lua_pop(L, 1); // pop nil
00502 
00503     // Then add it
00504     lua_pushlightuserdata(L, obj_ptr);  // push key
00505     lua_pushlightuserdata(L, wxobj);    // push value
00506     lua_rawset(L, -3);                  // set t[key] = value, pops key and value
00507 
00508     lua_pop(L, 1); // pop table
00509 }
00510 
00511 bool LUACALL wxluaO_deletegcobject(lua_State *L, void* udata, void *obj_ptr, int flags)
00512 {
00513     if (obj_ptr == NULL) return false; // can happen
00514 
00515     bool delete_all = WXLUA_HASBIT(flags, WXLUA_DELETE_OBJECT_ALL);
00516 
00517     // Remove the weak ref to it
00518     int udata_count = wxluaO_untrackweakobject(L, delete_all ? NULL : udata, obj_ptr);
00519 
00520     if (delete_all || (udata_count < 1))
00521     {
00522         wxlua_removederivedmethods(L, obj_ptr);
00523 
00524         lua_pushlightuserdata(L, &wxlua_lreg_gcobjects_key); // push key
00525         lua_rawget(L, LUA_REGISTRYINDEX);                    // pop key, push value (table)
00526 
00527         lua_pushlightuserdata(L, obj_ptr); // push key
00528         lua_rawget(L, -2);                 // get t[key] = value, pops key
00529 
00530         if (lua_islightuserdata(L, -1)) // is the wxObject* we delete
00531         {
00532             // delete the real object for the case where it's encapsulated
00533             wxObject *wxobj = (wxObject*)lua_touserdata(L, -1);
00534             delete wxobj;
00535 
00536             lua_pop(L, 1); // pop lightuserdata value
00537 
00538             lua_pushlightuserdata(L, obj_ptr); // push key
00539             lua_pushnil(L);                    // push value
00540             lua_rawset(L, -3);                 // set t[key] = value, pops key and value
00541 
00542             lua_pop(L, 1); // pop delobj table
00543 
00544             return true;
00545         }
00546         else
00547         {
00548             // no error message since we're called from wxlua_wxLuaBindClass__gc
00549             // automatically for all our objects and this table stores which ones to delete
00550             // so we don't want to have to check first and then call this.
00551             lua_pop(L, 2); // pop nil and delobj
00552         }
00553     }
00554 
00555     return false;
00556 }
00557 
00558 bool LUACALL wxluaO_undeletegcobject(lua_State *L, void *obj_ptr)
00559 {
00560     if (obj_ptr == NULL) return false;
00561 
00562     lua_pushlightuserdata(L, &wxlua_lreg_gcobjects_key); // push key
00563     lua_rawget(L, LUA_REGISTRYINDEX);                    // pop key, push value (table)
00564 
00565     lua_pushlightuserdata(L, obj_ptr); // push key
00566     lua_rawget(L, -2);                 // get t[key] = value, pops key
00567 
00568     if (lua_islightuserdata(L, -1)) // is the wxObject* we delete
00569     {
00570         lua_pop(L, 1); // pop lightuserdata
00571 
00572         lua_pushlightuserdata(L, obj_ptr); // push key
00573         lua_pushnil(L);                    // push value
00574         lua_rawset(L, -3);                 // set t[key] = value, pops key and value
00575 
00576         lua_pop(L, 1); // pop delobj table
00577         return true;
00578     }
00579     else
00580         lua_pop(L, 2); // pop nil and gcobject table
00581 
00582     return false;
00583 }
00584 
00585 bool LUACALL wxluaO_isgcobject(lua_State *L, void *obj_ptr)
00586 {
00587     lua_pushlightuserdata(L, &wxlua_lreg_gcobjects_key); // push key
00588     lua_rawget(L, LUA_REGISTRYINDEX);                    // pop key, push value (table)
00589 
00590     lua_pushlightuserdata(L, obj_ptr); // push key
00591     lua_rawget(L, -2);                 // get t[key] = value, pops key
00592 
00593     bool found = lua_islightuserdata(L, -1);
00594     lua_pop(L, 2); // pop udata and table
00595 
00596     return found;
00597 }
00598 
00599 wxArrayString LUACALL wxluaO_getgcobjectinfo(lua_State *L)
00600 {
00601     wxArrayString arrStr;
00602 
00603     lua_pushlightuserdata(L, &wxlua_lreg_gcobjects_key); // push key
00604     lua_rawget(L, LUA_REGISTRYINDEX);                    // pop key, push value (table)
00605 
00606     lua_pushnil(L);
00607     while (lua_next(L, -2) != 0)
00608     {
00609         // value = -1, key = -2, table = -3
00610         wxString name(wxT("wxObject?"));
00611 
00612         wxObject* obj = (wxObject*)lua_touserdata(L, -1);
00613         if (obj && obj->GetClassInfo() && obj->GetClassInfo()->GetClassName())
00614             name = obj->GetClassInfo()->GetClassName();
00615 
00616         arrStr.Add(wxString::Format(wxT("%s(%p)"), name.c_str(), obj));
00617 
00618         lua_pop(L, 1); // pop value, lua_next will pop key at end
00619     }
00620 
00621     lua_pop(L, 1); // pop table
00622 
00623     arrStr.Sort();
00624     return arrStr;
00625 }
00626 
00627 void LUACALL wxluaO_trackweakobject(lua_State *L, int udata_stack_idx, void *obj_ptr, int wxl_type)
00628 {
00629     lua_pushlightuserdata(L, &wxlua_lreg_weakobjects_key); // push key
00630     lua_rawget(L, LUA_REGISTRYINDEX);                      // pop key, push value (the obj table)
00631 
00632     lua_pushlightuserdata(L, obj_ptr); // push key
00633     lua_rawget(L, -2);
00634 
00635     if (lua_isnil(L, -1)) // not tracked yet, create new table to store items
00636     {
00637         lua_pop(L, 1); // pop nil
00638 
00639         lua_pushlightuserdata(L, obj_ptr);
00640         lua_newtable(L);
00641           lua_newtable(L);                    // metatable
00642             lua_pushlstring(L, "__mode", 6);
00643             lua_pushlstring(L, "v", 1);
00644             lua_rawset(L, -3);                // set mode of main table
00645           lua_setmetatable(L, -2);            // via the metatable
00646         lua_rawset(L, -3);
00647 
00648         lua_pushlightuserdata(L, obj_ptr); // get the table back
00649         lua_rawget(L, -2);
00650     }
00651     else
00652     {
00653         // check for dupes since that's what we're trying to avoid
00654         lua_pushnumber(L, wxl_type);
00655         lua_rawget(L, -2);
00656         // this must never happen
00657         if (!lua_isnil(L, -1)) wxFAIL_MSG(wxT("Trying to push userdata for object with same wxLua type twice"));
00658         lua_pop(L, 1); // pop nil
00659     }
00660 
00661     lua_pushnumber(L, wxl_type);
00662     lua_pushvalue(L, ABS_LUA_STKIDX(udata_stack_idx, 3)); // push the Lua userdata as the value (note: weak valued table)
00663     lua_rawset(L, -3);    // t[key] = value; pops key and value
00664     lua_pop(L, 2);        // pop weakobj table and obj_ptr table
00665 }
00666 
00667 int LUACALL wxluaO_untrackweakobject(lua_State *L, void* udata, void *obj_ptr)
00668 {
00669     lua_pushlightuserdata(L, &wxlua_lreg_weakobjects_key); // push key
00670     lua_rawget(L, LUA_REGISTRYINDEX);                      // pop key, push value (the object table)
00671 
00672     lua_pushlightuserdata(L, (void*)obj_ptr); // push key
00673     lua_rawget(L, -2);                        // get t[key] = value; pop key push value
00674 
00675     int count = 0;
00676 
00677     if (lua_istable(L, -1))
00678     {
00679         // clear the metatables for the userdata
00680         lua_pushnil(L);
00681         while (lua_next(L, -2) != 0)
00682         {
00683             // value = -1, key = -2, table = -3
00684             void *u = lua_touserdata(L, -1);
00685 
00686             if ((udata == NULL) || (udata == u))
00687             {
00688                 lua_pushnil(L);
00689                 lua_setmetatable(L, -2); // remove value's metatable
00690             }
00691 
00692             if (udata == u)
00693             {
00694                 lua_pop(L, 1);        // pop value
00695 
00696                 lua_pushvalue(L, -1); // copy key for next iteration
00697                 lua_pushnil(L);
00698                 lua_rawset(L, -4);    // set t[key] = nil to remove it
00699             }
00700             else
00701             {
00702                 ++count;       // only count ones that still exist
00703                 lua_pop(L, 1); // pop value, leave key for next iteration
00704             }
00705         }
00706 
00707         lua_pop(L, 1); // pop obj_ptr table
00708 
00709         // If we've cleared everything then remove the table
00710         if ((udata == NULL) || (count == 0))
00711         {
00712             count = 0;                                // removed them all
00713             lua_pushlightuserdata(L, (void*)obj_ptr); // push key
00714             lua_pushnil(L);                           // push value
00715             lua_rawset(L, -3);                        // set t[key] = nil; pops key and value
00716         }
00717 
00718         lua_pop(L, 1);                            // pop objects table
00719     }
00720     else
00721         lua_pop(L, 2); // pop nil and weakobj table
00722 
00723     return count;
00724 }
00725 
00726 bool LUACALL wxluaO_istrackedweakobject(lua_State *L, void *obj_ptr, int wxl_type, bool push_on_stack)
00727 {
00728     lua_pushlightuserdata(L, &wxlua_lreg_weakobjects_key); // push key
00729     lua_rawget(L, LUA_REGISTRYINDEX);   // pop key, push value (the obj table)
00730 
00731     lua_pushlightuserdata(L, obj_ptr); // push key
00732     lua_rawget(L, -2);                 // get t[key] value; pop key push value
00733 
00734     if (lua_istable(L, -1))
00735     {
00736         lua_pushnumber(L, wxl_type); // push key
00737         lua_rawget(L, -2);           // get t[key] = value; pops key
00738 
00739         // check if they've dynamic casted the object or if it was casted in C++
00740         if (wxl_type == wxluaT_type(L, -1))
00741         {
00742             if (push_on_stack)
00743             {
00744                 lua_remove(L, -3); // remove the obj table, leave value on the stack
00745                 lua_remove(L, -2); // remove table of userdata, leave value on the stack
00746             }
00747             else
00748                 lua_pop(L, 3);
00749 
00750             return true;
00751         }
00752         else
00753             lua_pop(L, 1); // pop the userdata that is not the right type
00754     }
00755 
00756     lua_pop(L, 2); // pop the weakobj table and the nil.
00757     return false;
00758 }
00759 
00760 wxArrayString LUACALL wxluaO_gettrackedweakobjectinfo(lua_State *L)
00761 {
00762     wxArrayString arrStr;
00763 
00764     lua_pushlightuserdata(L, &wxlua_lreg_weakobjects_key); // push key
00765     lua_rawget(L, LUA_REGISTRYINDEX);                      // pop key, push value (table)
00766 
00767     lua_pushnil(L);
00768     while (lua_next(L, -2) != 0)
00769     {
00770         // value = -1, key = -2, table = -3
00771         void* obj_ptr = lua_touserdata(L, -2); // actually lightuserdata
00772 
00773         wxString name;
00774 
00775         // iterate the table of userdata
00776         lua_pushnil(L);
00777         while (lua_next(L, -2) != 0)
00778         {
00779             // value = -1, key = -2, table = -3
00780             int wxl_type = (int)lua_tonumber(L, -2);
00781             if (!name.IsEmpty()) name += wxT(", ");
00782             name += wxString::Format(wxT("%s(%p, type=%d)"), wxluaT_typename(L, wxl_type).c_str(), lua_touserdata(L, -1), wxl_type);
00783             lua_pop(L, 1); // pop value, lua_next will pop key at end
00784         }
00785 
00786         arrStr.Add(wxString::Format(wxT("%p = %s"), obj_ptr, name.c_str()));
00787 
00788         lua_pop(L, 1); // pop value, lua_next will pop key at end
00789     }
00790 
00791     lua_pop(L, 1); // pop table
00792 
00793     arrStr.Sort();
00794     return arrStr;
00795 }
00796 
00797 // ----------------------------------------------------------------------------
00798 // wxluaW_XXX - functions operate on tracked wxWindows
00799 // ----------------------------------------------------------------------------
00800 
00801 void LUACALL wxluaW_addtrackedwindow(lua_State *L, wxObject* wxobj)
00802 {
00803     if (!wxobj) return; // allow NULL w/o error
00804 
00805     // don't track these "windows" since they're supposed to be attached
00806     // and their parents are not properly set so we can't tell if
00807     // their parents are tracked.
00808     if (wxDynamicCast(wxobj, wxMenuBar) != NULL) return;
00809     if (wxDynamicCast(wxobj, wxToolBar) != NULL) return;
00810 
00811     wxWindow* win = wxDynamicCast(wxobj, wxWindow);
00812 
00813     // only need to track parent window, it deletes children for us
00814     if (win && !wxluaW_istrackedwindow(L, win, true))
00815     {
00816         lua_pushlightuserdata(L, &wxlua_lreg_topwindows_key); // push key
00817         lua_rawget(L, LUA_REGISTRYINDEX);                     // pop key, push value (table)
00818 
00819         lua_pushlightuserdata(L, win); // push key
00820         lua_pushnumber(L, 1);          // push value
00821         lua_rawset(L, -3);             // set t[key] = value, pops key and value
00822 
00823         lua_pop(L, 1); // pop topwindows table
00824     }
00825 }
00826 
00827 void LUACALL wxluaW_removetrackedwindow(lua_State *L, wxWindow* win)
00828 {
00829     lua_pushlightuserdata(L, &wxlua_lreg_topwindows_key); // push key
00830     lua_rawget(L, LUA_REGISTRYINDEX);                     // pop key, push value (table)
00831 
00832     lua_pushlightuserdata(L, win); // push key
00833     lua_pushnil(L);                // push value
00834     lua_rawset(L, -3);             // set t[key] = value, pops key and value
00835 
00836     lua_pop(L, 1); // pop topwindows table
00837 }
00838 
00839 bool LUACALL wxluaW_istrackedwindow(lua_State *L, wxWindow* win, bool check_parents)
00840 {
00841     lua_pushlightuserdata(L, &wxlua_lreg_topwindows_key); // push key
00842     lua_rawget(L, LUA_REGISTRYINDEX);                     // pop key, push value (table)
00843 
00844     wxWindow* parent = win;
00845 
00846     while (parent)
00847     {
00848         lua_pushlightuserdata(L, parent); // push key
00849         lua_rawget(L, -2);                // pop key, push value
00850 
00851         if (lua_isnumber(L, -1))
00852         {
00853             lua_pop(L, 2); // pop topwindows table and value
00854             return true;
00855         }
00856 
00857         parent = check_parents ? parent->GetParent() : NULL;
00858         lua_pop(L, 1); // pop value (nil)
00859     }
00860 
00861     lua_pop(L, 1); // pop topwindows table
00862 
00863     return false;
00864 }
00865 
00866 wxArrayString LUACALL wxluaW_gettrackedwindowinfo(lua_State *L)
00867 {
00868     wxArrayString arrStr;
00869 
00870     lua_pushlightuserdata(L, &wxlua_lreg_topwindows_key); // push key
00871     lua_rawget(L, LUA_REGISTRYINDEX);                     // pop key, push value (table)
00872 
00873     lua_pushnil(L);
00874     while (lua_next(L, -2) != 0)
00875     {
00876         // value = -1, key = -2, table = -3
00877         wxWindow* win = (wxWindow*)lua_touserdata(L, -2);
00878         wxCHECK_MSG(win, arrStr, wxT("Invalid wxWindow"));
00879 
00880         wxString name(win->GetClassInfo()->GetClassName());
00881         arrStr.Add(wxString::Format(wxT("%s(%p id=%d)"), name.c_str(), win, win->GetId()));
00882 
00883         lua_pop(L, 1); // pop value, lua_next will pop key at end
00884     }
00885 
00886     lua_pop(L, 1); // pop table
00887 
00888     arrStr.Sort();
00889     return arrStr;
00890 }
00891 
00892 // ----------------------------------------------------------------------------
00893 // wxluaT_XXX - functions operate on the wxLua types
00894 // ----------------------------------------------------------------------------
00895 
00896 int wxluaT_newmetatable(lua_State* L, int wxl_type)
00897 {
00898     lua_newtable(L);                                     // create a table for our new type
00899     lua_pushlightuserdata(L, &wxlua_metatable_type_key); // push key
00900     lua_pushnumber(L, wxl_type);                         // push value
00901     lua_rawset(L, -3);                                   // set t[key] = value; pop key and value
00902 
00903     lua_pushlightuserdata(L, &wxlua_lreg_types_key);     // push key
00904     lua_rawget(L, LUA_REGISTRYINDEX);                    // pop key, push value (table)
00905 
00906     // make sure that the Lua table array is contiguous
00907     int len = (int)lua_objlen(L, -1);                    // get the length of the table
00908     while (++len < wxl_type)
00909     {
00910         lua_pushnumber(L, 0);
00911         lua_rawseti(L, -2, len);
00912     }
00913 
00914     // It is not allowed to reregister this type
00915     lua_rawgeti(L, -1, wxl_type);
00916     int t = lua_type(L, -1);
00917     wxCHECK_MSG((t == LUA_TNUMBER) || (t == LUA_TNIL), WXLUA_TUNKNOWN, wxT("Attempting to reregister wxLua type"));
00918     lua_pop(L, 1);
00919 
00920     // Add the metatable to the wxlua_lreg_types_key table
00921     lua_pushvalue(L, -2);                                // copy the metatable
00922     lua_rawseti(L, -2, wxl_type);                        // add it, pops table
00923     lua_pop(L, 1);                                       // pop wxlua_lreg_types_key table
00924 
00925     return wxl_type; // leave the table on the stack
00926 }
00927 
00928 bool LUACALL wxluaT_getmetatable(lua_State* L, int wxl_type)
00929 {
00930     if (wxluaR_getref(L, wxl_type, &wxlua_lreg_types_key)) // get the metatable
00931     {
00932         if (lua_type(L, -1) == LUA_TTABLE)
00933             return true;
00934 
00935         lua_pop(L, 1); // pop nil or 0 placeholder
00936     }
00937 
00938     return false;
00939 }
00940 
00941 bool LUACALL wxluaT_setmetatable(lua_State *L, int wxl_type)
00942 {
00943     if (wxluaT_getmetatable(L, wxl_type)) // get the metatable
00944     {
00945         // set it as the metatable of the object at the top of the stack
00946         if (lua_setmetatable(L, -2)) // pops table
00947             return true;
00948         else
00949         {
00950             lua_pop(L, 1); // pop table
00951             wxlua_error(L, "wxLua: Unable to set metatable in wxluaT_setmetatable.");
00952         }
00953     }
00954     else
00955         wxlua_error(L, "wxLua: Unable to get metatable in wxluaT_setmetatable.");
00956 
00957     return false;
00958 }
00959 
00960 int LUACALL wxluaT_type(lua_State *L, int stack_idx)
00961 {
00962     int wxl_type = WXLUA_TUNKNOWN;
00963     int ltype = lua_type(L, stack_idx);
00964 
00965     if ((ltype == LUA_TUSERDATA) && lua_getmetatable(L, stack_idx)) // see wxluaT_newmetatable()
00966     {
00967         lua_pushlightuserdata(L, &wxlua_metatable_type_key); // push key
00968         lua_rawget(L, -2);                                   // get t[key] = value; pop key push value
00969         wxl_type = (int)lua_tonumber(L, -1); // if !isnumber it returns 0 (check below is faster)
00970 
00971         // if it's not a number (it's probably nil) then it's someone else's userdata
00972         if ((wxl_type == 0) && !lua_isnumber(L, -1))
00973             wxl_type = WXLUA_TUSERDATA;
00974 
00975         lua_pop(L, 2); // pop metatable and wxl_type number
00976     }
00977     else
00978         wxl_type = wxlua_luatowxluatype(ltype);
00979 
00980     return wxl_type;
00981 }
00982 
00983 wxString LUACALL wxluaT_typename(lua_State* L, int wxl_type)
00984 {
00985     // try to use wxString's ref counting and return this existing copy
00986     static wxString s[13] = {
00987         wxT("unknown"),
00988         wxT("none"),
00989         wxT("nil"),
00990         wxT("boolean"),
00991         wxT("lightuserdata"),
00992         wxT("number"),
00993         wxT("string"),
00994         wxT("table"),
00995         wxT("function"),
00996         wxT("userdata"),
00997         wxT("thread"),
00998         wxT("integer"),
00999         wxT("cfunction"),
01000     };
01001 
01002     // Check for real type or this is a predefined WXLUA_TXXX type
01003     if ((L == NULL) || (WXLUAT_IS_LUAT(wxl_type)))
01004     {
01005         switch (wxl_type)
01006         {
01007             case WXLUA_TUNKNOWN :       return s[0];
01008             case WXLUA_TNONE :          return s[1];
01009             case WXLUA_TNIL :           return s[2];
01010             case WXLUA_TBOOLEAN :       return s[3];
01011             case WXLUA_TLIGHTUSERDATA : return s[4];
01012             case WXLUA_TNUMBER :        return s[5];
01013             case WXLUA_TSTRING :        return s[6];
01014             case WXLUA_TTABLE :         return s[7];
01015             case WXLUA_TFUNCTION :      return s[8];
01016             case WXLUA_TUSERDATA :      return s[9];
01017             case WXLUA_TTHREAD :        return s[10];
01018 
01019             case WXLUA_TINTEGER :       return s[11];
01020             case WXLUA_TCFUNCTION :     return s[12];
01021         }
01022     }
01023     else
01024     {
01025         const wxLuaBindClass* wxlClass = wxluaT_getclass(L, wxl_type);
01026         if (wxlClass)
01027             return lua2wx(wxlClass->name);
01028     }
01029 
01030     return wxT("Unknown wxLua Type?");
01031 }
01032 
01033 wxString LUACALL wxluaT_gettypename(lua_State* L, int stack_idx)
01034 {
01035     return wxluaT_typename(L, wxluaT_type(L, stack_idx));
01036 }
01037 
01038 wxString LUACALL wxlua_luaL_typename(lua_State* L, int stack_idx)
01039 {
01040     // lua_typename(L, lua_type(L, stack_idx))
01041     return lua2wx(luaL_typename(L, stack_idx));
01042 }
01043 
01044 int LUACALL wxluaT_gettype(lua_State* L, const char* class_name)
01045 {
01046     const wxLuaBindClass* wxlClass = wxluaT_getclass(L, class_name);
01047     if (wxlClass)
01048         return *wxlClass->wxluatype;
01049 
01050     return WXLUA_TUNKNOWN;
01051 }
01052 
01053 const wxLuaBindClass* LUACALL wxluaT_getclass(lua_State* L, int wxl_type)
01054 {
01055     // note: wxluaR_getref() doesn't leave anything on the stack on failure
01056     if (wxluaT_getmetatable(L, wxl_type))
01057     {
01058         // t[wxluatype] = { [bindclass_key] = lightuserdata wxLuaBindClass... (or nil if not a wxLua class type)
01059         lua_pushlightuserdata(L, &wxlua_metatable_wxluabindclass_key);
01060         lua_rawget(L, -2);
01061         const wxLuaBindClass* wxlClass = (wxLuaBindClass *)lua_touserdata(L, -1); // actually lightuserdata
01062 
01063         lua_pop(L, 2); // pop type table and lightuserdata (or nil if none)
01064 
01065         return wxlClass;
01066     }
01067 
01068     return NULL;
01069 }
01070 
01071 const wxLuaBindClass* LUACALL wxluaT_getclass(lua_State* L, const char* class_name)
01072 {
01073     lua_pushlightuserdata(L, &wxlua_lreg_classes_key); // push key
01074     lua_rawget(L, LUA_REGISTRYINDEX);                  // pop key, push value (table)
01075 
01076     lua_pushstring(L, class_name); // push key
01077     lua_rawget(L, -2);             // get t["class_name"] = &wxLuaBindClass; pop key push value
01078     const wxLuaBindClass* wxlClass = (wxLuaBindClass *)lua_touserdata(L, -1); // actually lightuserdata
01079 
01080     lua_pop(L, 2); // pop table and lightuserdata (or nil if none)
01081 
01082     return wxlClass; // may be NULL
01083 }
01084 
01085 bool wxluaT_isuserdatatype(lua_State* L, int stack_idx, int wxl_type)
01086 {
01087     int stack_type = wxluaT_type(L, stack_idx);
01088 
01089     if (wxlua_iswxuserdatatype(stack_type) &&
01090         ((wxluatype_NULL == stack_type) || // FIXME, how to check when NULL is valid or not?
01091         ((wxl_type == WXLUA_TSTRING) && (wxluaT_isderivedtype(L, stack_type, *p_wxluatype_wxString) >= 0)) ||
01092         (wxluaT_isderivedtype(L, stack_type, wxl_type) >= 0)))
01093         return true;
01094 
01095     return false;
01096 }
01097 
01098 void* LUACALL wxluaT_getuserdatatype(lua_State* L, int stack_idx, int wxl_type)
01099 {
01100     int stack_type = wxluaT_type(L, stack_idx);
01101 
01102     if (wxluatype_NULL == stack_type)
01103         return NULL;
01104     else if (wxluaT_isderivedtype(L, stack_type, wxl_type) >= 0)
01105         return wxlua_touserdata(L, stack_idx, false);
01106 
01107     wxlua_argerror(L, stack_idx, wxT("a '") + wxluaT_typename(L, wxl_type) + wxT("'"));
01108 
01109     return NULL;
01110 }
01111 
01112 bool LUACALL wxluaT_pushuserdatatype(lua_State* L, const void *obj_ptr, int wxl_type, bool track, bool allow_NULL)
01113 {
01114     // FIXME allow_NULL is a hack for the NULL userdata type.
01115 
01116     if (allow_NULL || (obj_ptr != NULL))
01117     {
01118         // First check to see if we've already pushed this object into Lua.
01119         // This avoids the problem of the gc deleting a returned pointer to a permanent object.
01120         // Test code is this:
01121         // il = wx.wxImageList(16,16); ... noteBook:SetImageList(il); ... local il2 = noteBook:GetImageList()
01122         // When il2 gets gc it will delete il even though il may still be valid and used by the notebook.
01123 
01124         if (wxluaO_istrackedweakobject(L, (void*)obj_ptr, wxl_type, true))
01125             return true;
01126 
01127         // if the object we are referencing is derived from wxWindow
01128         if (obj_ptr && (wxluaT_isderivedtype(L, wxl_type, *p_wxluatype_wxWindow) >= 0))
01129         {
01130             wxWindow* win = wxDynamicCast(obj_ptr, wxWindow); // double check that it's a wxWindow
01131             if (win != NULL)
01132             {
01133                 // check to make sure that we're not trying to attach another destroy callback
01134                 lua_pushlightuserdata(L, &wxlua_lreg_windestroycallbacks_key); // push key
01135                 lua_rawget(L, LUA_REGISTRYINDEX);                              // pop key, push value (table)
01136 
01137                 lua_pushlightuserdata(L, win); // push key
01138                 lua_rawget(L, -2);             // get t[key] = value; pops key
01139 
01140                 if (!lua_islightuserdata(L, -1))
01141                 {
01142                     // Connect the wxWindow to wxEVT_DESTROY callback so if Lua has
01143                     // a copy(s) of it we can clear the metatable when we get the
01144                     // event so we don't segfault if we try to access it by accident.
01145                     wxLuaState wxlState(L);
01146                     wxCHECK_MSG(wxlState.Ok(), false, wxT("Invalid wxLuaState"));
01147                     wxLuaWinDestroyCallback *pCallback =
01148                             new wxLuaWinDestroyCallback(wxlState, win);
01149 
01150                     if (pCallback == NULL)
01151                         wxlua_error(L, "wxLua: Out of memory creating wxLuaWinDestroyCallback.");
01152                     // assert should have been given in constructor so delete it
01153                     // since it's not attached as a callback user data
01154                     if (!pCallback->Ok())
01155                         delete pCallback;
01156                 }
01157 
01158                 lua_pop(L, 2); // pop windestroy table and value
01159             }
01160         }
01161 
01162         // Wrap the void* pointer in a newuserdata
01163         const void **ptr = (const void **)lua_newuserdata(L, sizeof(void *));
01164         if (ptr != NULL)
01165         {
01166             *ptr = obj_ptr;
01167             // try to get the object's references table and set the metatable to the object
01168             if (wxluaT_getmetatable(L, wxl_type))
01169             {
01170                 // pop the table and set it as the metatable for the newuserdata
01171                 lua_setmetatable(L, -2);
01172 
01173                 if (track)
01174                     wxluaO_trackweakobject(L, -1, (void*)obj_ptr, wxl_type);
01175 
01176                 return true; // leave value on the stack
01177             }
01178             else
01179                 wxlua_error(L, "wxLua: Unable to get metatable in wxluaT_pushuserdatatype.");
01180         }
01181         else
01182             wxlua_error(L, "wxLua: Out of memory");
01183     }
01184     else
01185     {
01186         lua_pushnil(L);
01187         return true;
01188     }
01189 
01190     return false;
01191 }
01192 
01193 // ----------------------------------------------------------------------------
01194 // Functions to get info about the wxLua types
01195 // ----------------------------------------------------------------------------
01196 
01197 static int wxluaT_isderivedtype_recurser(const wxLuaBindClass *wxlClass, int base_wxl_type, int levels)
01198 {
01199     if (wxlClass != NULL)
01200     {
01201         if (*wxlClass->wxluatype == base_wxl_type)
01202             return levels;
01203         else if (wxlClass->baseclassNames != NULL) // check baseclass by baseclass
01204         {
01205             for (size_t i = 0; wxlClass->baseclassNames[i]; ++i)
01206             {
01207                 // Note: base class may be NULL if lib/module containing it is not loaded
01208                 wxLuaBindClass* baseClass = wxlClass->baseBindClasses[i];
01209 
01210                 if (baseClass != NULL)
01211                 {
01212                     if (*baseClass->wxluatype == base_wxl_type)
01213                         return levels;
01214                     else
01215                     {
01216                         int ret = wxluaT_isderivedtype_recurser(baseClass, base_wxl_type, levels+1);
01217                         if (ret > -1)
01218                             return ret;
01219                     }
01220                 }
01221             }
01222         }
01223     }
01224 
01225     return -1; // wxluatype is not derived from base_wxluatype
01226 }
01227 
01228 int LUACALL wxluaT_isderivedtype(lua_State* L, int wxl_type, int base_wxl_type)
01229 {
01230     // couldn't possibly be derived from each other
01231     if (!wxlua_iswxuserdatatype(wxl_type) || !wxlua_iswxuserdatatype(base_wxl_type))
01232         return -1;
01233 
01234     // These two types are the same
01235     if (wxl_type == base_wxl_type)
01236         return 0;
01237 
01238     const wxLuaBindClass *wxlClass = wxluaT_getclass(L, wxl_type);
01239 
01240     return wxluaT_isderivedtype_recurser(wxlClass, base_wxl_type, 1);
01241 }
01242 
01243 int LUACALL wxluaT_isderivedclass(const wxLuaBindClass* wxlClass, const wxLuaBindClass* base_wxlClass)
01244 {
01245     // Ok if either is NULL to allow blindly calling this
01246     if ((wxlClass == NULL) || (base_wxlClass == NULL))
01247         return -1;
01248 
01249     // These two types are the same
01250     if (wxlClass->wxluatype == base_wxlClass->wxluatype) // comparing pointers
01251         return 0;
01252 
01253     return wxluaT_isderivedtype_recurser(wxlClass, *base_wxlClass->wxluatype, 1);
01254 }
01255 
01256 int LUACALL wxlua_iswxluatype(int luatype, int wxl_type, lua_State* L /* = NULL */)
01257 {
01258     int ret = -1; // unknown wxlua arg type
01259 
01260     switch (wxl_type)
01261     {
01262         case WXLUA_TNONE :
01263             ret = (luatype == LUA_TNONE) ? 1 : 0;
01264             break;
01265         case WXLUA_TNIL :
01266             ret = (luatype == LUA_TNIL) ? 1 : 0;
01267             break;
01268         case WXLUA_TBOOLEAN :
01269             // LUA_TNIL:    nil == false
01270             // LUA_TNUMBER: 0 == false as in C
01271             ret = ((luatype == LUA_TBOOLEAN) || (luatype == LUA_TNUMBER) || (luatype == LUA_TNIL)) ? 1 : 0;
01272             break;
01273         case WXLUA_TLIGHTUSERDATA:
01274             ret = (luatype == LUA_TLIGHTUSERDATA) ? 1 : 0;
01275             break;
01276         case WXLUA_TNUMBER :
01277             // LUA_TNIL:     evaluates to 0, too easy to have a typo
01278             // LUA_TSTRING:  will be 0 unless really a number "2"
01279             // LUA_TBOOLEAN: can't do (bool_val or 1)
01280             ret = ((luatype == LUA_TNUMBER) || (luatype == LUA_TBOOLEAN)) ? 1 : 0;
01281             break;
01282         case WXLUA_TSTRING :
01283             // LUA_TNIL:    too easy to have a variable typo, use (str or "")
01284             // LUA_TNUMBER: can convert easily, always works, but breaks overload bindings
01285             ret = (luatype == LUA_TSTRING) ? 1 : 0;
01286             break;
01287         case WXLUA_TTABLE :
01288             ret = (luatype == LUA_TTABLE) ? 1 : 0;
01289             break;
01290         case WXLUA_TFUNCTION :
01291             ret = (luatype == LUA_TFUNCTION) ? 1 : 0;
01292             break;
01293         case WXLUA_TUSERDATA :
01294             ret = (luatype == LUA_TUSERDATA) ? 1 : 0;
01295             break;
01296         case WXLUA_TTHREAD :
01297             ret = (luatype == LUA_TTHREAD) ? 1 : 0;
01298             break;
01299         case WXLUA_TINTEGER :
01300             // LUA_TNIL: evaluates to 0 so wx.ENUM_typo = 0
01301             ret = (luatype == LUA_TNUMBER) ? 1 : 0;
01302             break;
01303         case WXLUA_TCFUNCTION :
01304             ret = (luatype == LUA_TFUNCTION) ? 1 : 0;
01305             break;
01306     }
01307 
01308     // if we don't know the type (it's not predefined)
01309     if ((ret < 0) && L &&(luatype == LUA_TTABLE))
01310     {
01311         const wxLuaBindClass* wxlClass = wxluaT_getclass(L, wxl_type);
01312 
01313         if (wxluaT_isderivedclass(wxlClass, wxluaT_getclass(L, "wxArrayString")) >= 0)
01314             ret = 1;
01315         else if (wxluaT_isderivedclass(wxlClass, wxluaT_getclass(L, "wxSortedArrayString")) >= 0)
01316             ret = 1;
01317         else if (wxluaT_isderivedclass(wxlClass, wxluaT_getclass(L, "wxArrayInt")) >= 0)
01318             ret = 1;
01319     }
01320 
01321     return ret;
01322 }
01323 
01324 int wxlua_luatowxluatype(int luatype)
01325 {
01326     //int wxltype = LUAT_TO_WXLUAT(luatype);
01327     //if (!WXLUAT_IS_LUAT(wxltype))
01328     //    return WXLUA_TUNKNOWN;
01329     //return wxltype;
01330 
01331     switch (luatype)
01332     {
01333         case LUA_TNONE          : return WXLUA_TNONE;
01334         case LUA_TNIL           : return WXLUA_TNIL;
01335         case LUA_TBOOLEAN       : return WXLUA_TBOOLEAN;
01336         case LUA_TLIGHTUSERDATA : return WXLUA_TLIGHTUSERDATA;
01337         case LUA_TNUMBER        : return WXLUA_TNUMBER;
01338         case LUA_TSTRING        : return WXLUA_TSTRING;
01339         case LUA_TTABLE         : return WXLUA_TTABLE;
01340         case LUA_TFUNCTION      : return WXLUA_TFUNCTION;
01341         case LUA_TUSERDATA      : return WXLUA_TUSERDATA;
01342         case LUA_TTHREAD        : return WXLUA_TTHREAD;
01343         //case LUA_T???         : return WXLUA_TINTEGER;
01344         //case LUA_T???         : return WXLUA_TCFUNCTION;
01345     }
01346 
01347     return WXLUA_TUNKNOWN;
01348 }
01349 
01350 int wxlua_wxluatoluatype(int wxlarg)
01351 {
01352     switch (wxlarg)
01353     {
01354         case WXLUA_TNONE :          return LUA_TNONE;
01355         case WXLUA_TNIL :           return LUA_TNIL;
01356         case WXLUA_TBOOLEAN :       return LUA_TBOOLEAN;
01357         case WXLUA_TLIGHTUSERDATA : return LUA_TLIGHTUSERDATA;
01358         case WXLUA_TNUMBER :        return LUA_TNUMBER;
01359         case WXLUA_TSTRING :        return LUA_TSTRING;
01360         case WXLUA_TTABLE :         return LUA_TTABLE;
01361         case WXLUA_TFUNCTION :      return LUA_TFUNCTION;
01362         case WXLUA_TUSERDATA :      return LUA_TUSERDATA;
01363         case WXLUA_TTHREAD :        return LUA_TTHREAD;
01364         case WXLUA_TINTEGER :       return LUA_TNUMBER;
01365         case WXLUA_TCFUNCTION :     return LUA_TFUNCTION;
01366     }
01367 
01368     return -1;
01369 }
01370 
01371 bool wxlua_iswxstringtype(lua_State* L, int stack_idx)
01372 {
01373     // NOTE: If we ever allow numbers to be coerced to strings we must
01374     // change how we handle lua_tostring() calls since it will change a number
01375     // to a string on the stack. This could break people's code.
01376     if (wxlua_iswxluatype(lua_type(L, stack_idx), WXLUA_TSTRING) == 1)
01377         return true;
01378     else if (wxlua_iswxuserdata(L, stack_idx))
01379     {
01380         int wxl_type = wxluaT_type(L, stack_idx);
01381         return (wxluaT_isderivedtype(L, wxl_type, *p_wxluatype_wxString) >= 0);
01382     }
01383 
01384     return false;
01385 }
01386 
01387 const char* LUACALL wxlua_getstringtype(lua_State *L, int stack_idx)
01388 {
01389     if (wxlua_isstringtype(L, stack_idx))
01390         return lua_tostring(L, stack_idx);
01391     else if (wxlua_iswxuserdata(L, stack_idx))
01392     {
01393         int stack_type = wxluaT_type(L, stack_idx);
01394 
01395         if (wxluaT_isderivedtype(L, stack_type, *p_wxluatype_wxString) >= 0)
01396         {
01397             wxString* wxstr = (wxString*)wxlua_touserdata(L, stack_idx, false);
01398             wxCHECK_MSG(wxstr, NULL, wxT("Invalid userdata wxString"));
01399             return wx2lua(*wxstr);
01400         }
01401     }
01402 
01403     wxlua_argerror(L, stack_idx, wxT("a 'string' or 'wxString'"));
01404 
01405     return NULL;
01406 }
01407 
01408 wxString LUACALL wxlua_getwxStringtype(lua_State *L, int stack_idx)
01409 {
01410     if (wxlua_isstringtype(L, stack_idx))
01411         return lua2wx(lua_tostring(L, stack_idx));
01412     else if (wxlua_iswxuserdata(L, stack_idx))
01413     {
01414         int stack_type = wxluaT_type(L, stack_idx);
01415 
01416         if (wxluaT_isderivedtype(L, stack_type, *p_wxluatype_wxString) >= 0)
01417         {
01418             wxString* wxstr = (wxString*)wxlua_touserdata(L, stack_idx, false);
01419             wxCHECK_MSG(wxstr, wxEmptyString, wxT("Invalid userdata wxString"));
01420             return *wxstr;
01421         }
01422     }
01423 
01424     wxlua_argerror(L, stack_idx, wxT("a 'string' or 'wxString'"));
01425 
01426     return wxEmptyString;
01427 }
01428 
01429 bool LUACALL wxlua_getbooleantype(lua_State *L, int stack_idx)
01430 {
01431     int l_type = lua_type(L, stack_idx);
01432 
01433     if (!wxlua_iswxluatype(l_type, WXLUA_TBOOLEAN))
01434         wxlua_argerror(L, stack_idx, wxT("a 'boolean'"));
01435 
01436     int num = 0;
01437     // we also allow 0 = false and !0 = true (Lua thinks 0 == true, i.e. !nil)
01438     if (l_type == LUA_TNUMBER)
01439         num = (int)lua_tonumber(L, stack_idx);
01440     else
01441         num = (int)lua_toboolean(L, stack_idx);
01442 
01443     return (num != 0);
01444 }
01445 long LUACALL wxlua_getenumtype(lua_State *L, int stack_idx)
01446 {
01447     int l_type = lua_type(L, stack_idx);
01448 
01449     if (!wxlua_iswxluatype(l_type, WXLUA_TINTEGER))
01450         wxlua_argerror(L, stack_idx, wxT("an 'integer enum'"));
01451 
01452     // we don't allow bool or round, enums must strictly be integers
01453     double value = lua_tonumber(L, stack_idx);
01454     long long_value = (long)value;
01455 
01456     if (value != long_value)
01457         wxlua_argerror(L, stack_idx, wxT("an 'integer enum'"));
01458 
01459     return long_value;
01460 }
01461 long LUACALL wxlua_getintegertype(lua_State *L, int stack_idx)
01462 {
01463     int l_type = lua_type(L, stack_idx);
01464 
01465     if (!wxlua_iswxluatype(l_type, WXLUA_TINTEGER))
01466         wxlua_argerror(L, stack_idx, wxT("an 'integer'"));
01467 
01468     double value = 0;
01469     // we also allow bool = 1/0 which Lua evaluates to nil in lua_tonumber
01470     if (l_type == LUA_TBOOLEAN)
01471         value = lua_toboolean(L, stack_idx) ? 1 : 0;
01472     else
01473         value = lua_tonumber(L, stack_idx);
01474 
01475     long long_value = (long)value;
01476 
01477     if (value != long_value)
01478         wxlua_argerror(L, stack_idx, wxT("an 'integer'"));
01479 
01480     return long_value;
01481 }
01482 unsigned long LUACALL wxlua_getuintegertype(lua_State *L, int stack_idx)
01483 {
01484     int l_type = lua_type(L, stack_idx);
01485 
01486     if (!wxlua_iswxluatype(l_type, WXLUA_TINTEGER))
01487         wxlua_argerror(L, stack_idx, wxT("an 'unsigned integer'"));
01488 
01489     double value = 0;
01490     // we also allow bool = 1/0 which Lua evaluates to nil in lua_tonumber
01491     if (l_type == LUA_TBOOLEAN)
01492         value = lua_toboolean(L, stack_idx) ? 1 : 0;
01493     else
01494         value = lua_tonumber(L, stack_idx);
01495 
01496     unsigned long ulong_value = (unsigned long)value;
01497 
01498     if ((value != ulong_value) || (value < 0))
01499         wxlua_argerror(L, stack_idx, wxT("an 'unsigned integer'"));
01500 
01501     return ulong_value;
01502 }
01503 double LUACALL wxlua_getnumbertype(lua_State *L, int stack_idx)
01504 {
01505     int l_type = lua_type(L, stack_idx);
01506 
01507     if (!wxlua_iswxluatype(l_type, WXLUA_TNUMBER))
01508         wxlua_argerror(L, stack_idx, wxT("a 'number'"));
01509 
01510     double value = 0;
01511     // we also allow bool = 1/0 which Lua evaluates to nil in lua_tonumber
01512     if (l_type == LUA_TBOOLEAN)
01513         value = lua_toboolean(L, stack_idx) ? 1 : 0;
01514     else
01515         value = lua_tonumber(L, stack_idx);
01516 
01517     return value;
01518 }
01519 
01520 const char** LUACALL wxlua_getchararray(lua_State *L, int stack_idx, int &count)
01521 {
01522     const char **arrChar = NULL;
01523     count = 0;
01524 
01525     if (lua_istable(L, stack_idx))
01526     {
01527         int table_len = lua_objlen(L, stack_idx);
01528         if (table_len > 0)
01529             arrChar = new const char *[table_len];
01530 
01531         if (arrChar != NULL)
01532         {
01533             for (int n = 0; n < table_len; ++n)
01534             {
01535                 lua_rawgeti(L, stack_idx, n+1); // Lua array starts at 1
01536                 const char *s = wxlua_getstringtype(L, -1);
01537                 arrChar[n] = s; // share Lua string
01538                 lua_pop(L, 1);
01539             }
01540         }
01541 
01542         count = table_len;
01543     }
01544     else
01545         wxlua_argerror(L, stack_idx, wxT("a 'table' array of strings"));
01546 
01547     return arrChar;
01548 }
01549 
01550 wxString* LUACALL wxlua_getwxStringarray(lua_State* L, int stack_idx, int& count)
01551 {
01552     wxString *strArray = NULL;
01553     count = 0; // zero it in case we do a long jmp
01554     wxLuaSmartwxArrayString arr(wxlua_getwxArrayString(L, stack_idx));
01555 
01556     count = (int)((wxArrayString&)arr).GetCount();
01557     strArray = new wxString[count];
01558     for (int n = 0; n < count; ++n)
01559         strArray[n] = ((wxArrayString&)arr)[n];
01560 
01561     return strArray;
01562 }
01563 
01564 int* LUACALL wxlua_getintarray(lua_State* L, int stack_idx, int& count)
01565 {
01566     int *intArray = NULL;
01567     count = 0; // zero it in case we do a long jmp
01568     wxLuaSmartwxArrayInt arr(wxlua_getwxArrayInt(L, stack_idx));
01569 
01570     count = (int)((wxArrayInt&)arr).GetCount();
01571     intArray = new int[count];
01572     for (int n = 0; n < count; ++n)
01573         intArray[n] = ((wxArrayInt&)arr)[n];
01574 
01575     return intArray;
01576 }
01577 
01578 wxLuaSmartwxArrayString LUACALL wxlua_getwxArrayString(lua_State* L, int stack_idx)
01579 {
01580     wxLuaSmartwxArrayString arr(NULL, true); // will added to or replaced
01581     int count = -1;                          // used to check for failure
01582 
01583     if (lua_istable(L, stack_idx))
01584     {
01585         count = 0;
01586 
01587         while (1)
01588         {
01589             lua_rawgeti(L, stack_idx, count+1);
01590 
01591             if (wxlua_iswxstringtype(L, -1))
01592             {
01593                 ((wxArrayString&)arr).Add(wxlua_getwxStringtype(L, -1));
01594                 ++count;
01595 
01596                 lua_pop(L, 1);
01597             }
01598             else if (lua_isnil(L, -1))
01599             {
01600                 lua_pop(L, 1);
01601                 break;
01602             }
01603             else
01604             {
01605                 wxlua_argerror(L, stack_idx, wxT("a 'wxArrayString' or table array of strings"));
01606                 return arr;
01607             }
01608         }
01609     }
01610     else if (wxlua_iswxuserdata(L, stack_idx))
01611     {
01612         int arrstr_wxltype = wxluaT_gettype(L, "wxArrayString");
01613 
01614         if (wxluaT_isuserdatatype(L, stack_idx, arrstr_wxltype))
01615         {
01616             wxArrayString *arrStr = (wxArrayString *)wxluaT_getuserdatatype(L, stack_idx, arrstr_wxltype);
01617             if (arrStr)
01618             {
01619                 arr = wxLuaSmartwxArrayString(arrStr, false); // replace
01620                 count = arrStr->GetCount();
01621             }
01622         }
01623     }
01624 
01625     if (count < 0)
01626         wxlua_argerror(L, stack_idx, wxT("a 'wxArrayString' or table array of strings"));
01627 
01628     return arr;
01629 }
01630 
01631 wxLuaSmartwxSortedArrayString LUACALL wxlua_getwxSortedArrayString(lua_State* L, int stack_idx)
01632 {
01633     wxLuaSmartwxSortedArrayString arr(NULL, true); // will be replaced
01634     int count = -1;                                // used to check for failure
01635 
01636     if (lua_istable(L, stack_idx))
01637     {
01638         wxLuaSmartwxArrayString a = wxlua_getwxArrayString(L, stack_idx);
01639         arr = wxLuaSmartwxSortedArrayString(new wxSortedArrayString(a), true);
01640         count = 0;
01641     }
01642     else if (wxlua_iswxuserdata(L, stack_idx))
01643     {
01644         int arrstr_wxltype = wxluaT_gettype(L, "wxArrayString");
01645 
01646         if (wxluaT_isuserdatatype(L, stack_idx, arrstr_wxltype))
01647         {
01648             wxSortedArrayString *arrStr = (wxSortedArrayString *)wxluaT_getuserdatatype(L, stack_idx, arrstr_wxltype);
01649             if (arrStr)
01650             {
01651                 arr = wxLuaSmartwxSortedArrayString(arrStr, false); // replace
01652                 count = arrStr->GetCount();
01653             }
01654         }
01655     }
01656 
01657     if (count < 0)
01658         wxlua_argerror(L, stack_idx, wxT("a 'wxArrayString' or table array of strings"));
01659 
01660     return arr;
01661 }
01662 
01663 wxLuaSmartwxArrayInt LUACALL wxlua_getwxArrayInt(lua_State* L, int stack_idx)
01664 {
01665     wxLuaSmartwxArrayInt arr(NULL, true); // will be replaced
01666     int count = -1;                       // used to check for failure
01667 
01668     if (lua_istable(L, stack_idx))
01669     {
01670         count = 0;
01671 
01672         while(1)
01673         {
01674             lua_rawgeti(L, stack_idx, count+1);
01675 
01676             if (wxlua_isnumbertype(L, -1))
01677             {
01678                 ((wxArrayInt&)arr).Add((int)lua_tonumber(L, -1));
01679                 ++count;
01680 
01681                 lua_pop(L, 1);
01682             }
01683             else if (lua_isnil(L, -1))
01684             {
01685                 lua_pop(L, 1);
01686                 break;
01687             }
01688             else
01689             {
01690                 wxlua_argerror(L, stack_idx, wxT("a 'wxArrayInt' or a table array of integers"));
01691                 return arr;
01692             }
01693         }
01694     }
01695     else if (wxlua_iswxuserdata(L, stack_idx))
01696     {
01697         int arrint_wxltype = wxluaT_gettype(L, "wxArrayInt");
01698 
01699         if (wxluaT_isuserdatatype(L, stack_idx, arrint_wxltype))
01700         {
01701             wxArrayInt *arrInt = (wxArrayInt *)wxluaT_getuserdatatype(L, stack_idx, arrint_wxltype);
01702             if (arrInt)
01703             {
01704                 arr = wxLuaSmartwxArrayInt(arrInt, false); // replace
01705                 count = arrInt->GetCount();
01706             }
01707         }
01708     }
01709 
01710     if (count < 0)
01711         wxlua_argerror(L, stack_idx, wxT("a 'wxArrayInt' or a table array of integers"));
01712 
01713     return arr;
01714 }
01715 
01716 
01717 int LUACALL wxlua_pushwxArrayStringtable(lua_State *L, const wxArrayString &strArray)
01718 {
01719     size_t idx, count = strArray.GetCount();
01720     lua_createtable(L, count, 0);
01721 
01722     for (idx = 0; idx < count; ++idx)
01723     {
01724         wxlua_pushwxString(L, strArray[idx]);
01725         lua_rawseti(L, -2, idx + 1);
01726     }
01727     return idx;
01728 }
01729 
01730 int LUACALL wxlua_pushwxArrayInttable(lua_State *L, const wxArrayInt &intArray)
01731 {
01732     size_t idx, count = intArray.GetCount();
01733     lua_createtable(L, count, 0);
01734 
01735     for (idx = 0; idx < count; ++idx)
01736     {
01737         lua_pushnumber(L, intArray[idx]);
01738         lua_rawseti(L, -2, idx + 1);
01739     }
01740     return idx;
01741 }
01742 
01743 void LUACALL wxlua_pushwxString(lua_State* L, const wxString& str)
01744 {
01745     lua_pushstring(L, wx2lua(str));
01746 }
01747 
01748 wxString wxlua_concatwxArrayString(const wxArrayString& arr, const wxString& sep)
01749 {
01750     wxString s;
01751     size_t n, count = arr.GetCount();
01752     for (n = 0; n < count; ++n)
01753     {
01754         s += arr[n];
01755         if (n < count - 1) s += sep;
01756     }
01757 
01758     return s;
01759 }
01760 
01761 int wxlua_pushargs(lua_State* L, wxChar **argv, int argc, int start_n)
01762 {
01763     if (argc == 0) return 0;
01764 
01765     int i = 0;
01766     int narg = argc - (start_n + 1);  // number of arguments to the script
01767     luaL_checkstack(L, narg + 3, "too many arguments to script");
01768     for (i = start_n+1; i < argc; i++)
01769         lua_pushstring(L, wx2lua(argv[i]));
01770 
01771     lua_createtable(L, narg, start_n + 1);
01772 
01773     for (i = 0; i < argc; i++)
01774     {
01775         lua_pushstring(L, wx2lua(argv[i]));
01776         lua_rawseti(L, -2, i - start_n);
01777     }
01778 
01779     lua_setglobal(L, "arg");
01780 
01781     return narg;
01782 }
01783 
01784 //----------------------------------------------------------------------------
01785 // Derived class member functions for classes in wxLua
01786 //----------------------------------------------------------------------------
01787 
01788 bool LUACALL wxlua_setderivedmethod(lua_State* L, void *obj_ptr, const char *method_name, wxLuaObject* wxlObj)
01789 {
01790     lua_pushlightuserdata(L, &wxlua_lreg_derivedmethods_key); // push key
01791     lua_rawget( L, LUA_REGISTRYINDEX );                       // pop key, push value (table)
01792 
01793     lua_pushlightuserdata(L, (void *)obj_ptr); // push key
01794     lua_rawget(L, -2);                         // get t[key] = value, pop key push value
01795 
01796     if (!lua_istable(L, -1))
01797     {
01798         lua_pop(L, 1); // pop nil value
01799 
01800         // add new table for this object
01801         lua_pushlightuserdata(L, (void *)obj_ptr); // push key
01802         lua_newtable(L);                           // push value
01803         lua_rawset(L, -3);                         // set t[key] = value; pops key and value
01804 
01805         // put the new table back on the top of the stack
01806         lua_pushlightuserdata(L, (void *)obj_ptr);
01807         lua_rawget(L, -2);
01808     }
01809     else
01810     {
01811         // see if there already is a method
01812         lua_pushstring( L, method_name );
01813         lua_rawget(L, -2);
01814 
01815         if (lua_islightuserdata(L, -1))
01816         {
01817             // already have a method, delete it before replacing it
01818             wxLuaObject* o = (wxLuaObject*)lua_touserdata( L, -1 );
01819             delete o;
01820         }
01821 
01822         lua_pop(L, 1); // pop the deleted old object, or nil
01823     }
01824 
01825     lua_pushstring( L, method_name );        // push key
01826     lua_pushlightuserdata(L, (void*)wxlObj); // push value
01827     lua_rawset(L, -3);                       // set t[key] = value; pops key and value
01828 
01829     lua_pop(L, 2); // pop the object and overridden function table
01830 
01831     return true;
01832 }
01833 bool LUACALL wxlua_hasderivedmethod(lua_State* L, void *obj_ptr, const char *method_name, bool push_method)
01834 {
01835     bool found = false;
01836     wxLuaObject* wxlObj = NULL;
01837 
01838     lua_pushlightuserdata(L, &wxlua_lreg_derivedmethods_key);
01839     lua_rawget( L, LUA_REGISTRYINDEX ); // pop key, push table
01840 
01841     lua_pushlightuserdata(L, (void *)obj_ptr);
01842     lua_rawget(L, -2); // pop key, push table or nil
01843 
01844     if (lua_istable(L, -1))
01845     {
01846         // see if there is a method with the same name
01847         lua_pushstring( L, method_name );
01848         lua_rawget(L, -2);
01849 
01850         if (lua_islightuserdata(L, -1))
01851             wxlObj = (wxLuaObject*)lua_touserdata( L, -1 );
01852 
01853         lua_pop(L, 1); // pop the method object or nil
01854     }
01855 
01856     lua_pop(L, 2); // pop registry table and object table or nil
01857 
01858     if (wxlObj != NULL)
01859     {
01860         // if we've got the object, put it on top of the stack
01861         if (push_method && wxlObj->GetObject())
01862             found = true;
01863         else if (!push_method)
01864             found = true;
01865     }
01866 
01867     return found;
01868 }
01869 bool LUACALL wxlua_removederivedmethods(lua_State* L, void *obj_ptr)
01870 {
01871     bool found = false;
01872 
01873     lua_pushlightuserdata(L, &wxlua_lreg_derivedmethods_key);
01874     lua_rawget( L, LUA_REGISTRYINDEX ); // pop key, push table
01875 
01876     lua_pushlightuserdata(L, (void *)obj_ptr);
01877     lua_rawget(L, -2); // pop key, push table or nil
01878 
01879     if (lua_istable(L, -1))
01880     {
01881         found = true;
01882 
01883         // delete all of the derived methods we've pushed
01884         lua_pushnil(L);
01885         while (lua_next(L, -2) != 0)
01886         {
01887             // value at -1, key at -2, table at -3
01888             if (lua_islightuserdata(L, -1))
01889             {
01890                 wxLuaObject* o = (wxLuaObject*)lua_touserdata(L, -1);
01891                 delete o;
01892             }
01893 
01894             lua_pop(L, 1); // remove value; keep key for next iteration
01895         }
01896 
01897         lua_pop(L, 1);     // pop the obj table
01898 
01899         lua_pushlightuserdata(L, (void *)obj_ptr); // push key
01900         lua_pushnil(L);                            // push value, to remove it
01901         lua_rawset(L, -3);                         // set t[key] = value; pop key and value
01902 
01903         lua_pop(L, 1); // pop the derived table
01904     }
01905     else
01906         lua_pop(L, 2); // pop the derived table and nil for the obj table
01907 
01908     return found;
01909 }
01910 
01911 //----------------------------------------------------------------------------
01912 // Other functions for wxLua's keys in the
01913 //----------------------------------------------------------------------------
01914 
01915 bool LUACALL wxlua_getcallbaseclassfunction(lua_State* L)
01916 {
01917     lua_pushlightuserdata(L, &wxlua_lreg_callbaseclassfunc_key);
01918     lua_rawget( L, LUA_REGISTRYINDEX ); // pop key, push bool
01919 
01920     bool call_base = (bool)lua_toboolean(L, -1); // nil == 0 too
01921     lua_pop(L, 1);                               // pop bool
01922 
01923     return call_base;
01924 }
01925 
01926 void LUACALL wxlua_setcallbaseclassfunction(lua_State* L, bool call_base)
01927 {
01928     lua_pushlightuserdata(L, &wxlua_lreg_callbaseclassfunc_key);
01929     lua_pushboolean(L, call_base);
01930     lua_rawset( L, LUA_REGISTRYINDEX ); // pop key and bool
01931 }
01932 
01933 wxEventType LUACALL wxlua_getwxeventtype(lua_State* L)
01934 {
01935     lua_pushlightuserdata(L, &wxlua_lreg_wxeventtype_key);
01936     lua_rawget( L, LUA_REGISTRYINDEX ); // pop key, push bool
01937 
01938     wxEventType evt_type = (wxEventType)lua_tonumber(L, -1);
01939     lua_pop(L, 1); // pop number
01940 
01941     return evt_type;
01942 }
01943 
01944 void LUACALL wxlua_setwxeventtype(lua_State* L, wxEventType evt_type)
01945 {
01946     lua_pushlightuserdata(L, &wxlua_lreg_wxeventtype_key);
01947     lua_pushnumber(L, evt_type);
01948     lua_rawset( L, LUA_REGISTRYINDEX ); // pop key and number
01949 }
01950 
01951 wxLuaStateData* LUACALL wxlua_getwxluastatedata(lua_State* L)
01952 {
01953     lua_pushlightuserdata(L, &wxlua_lreg_wxluastatedata_key);
01954     lua_rawget( L, LUA_REGISTRYINDEX ); // pop key, push bool
01955 
01956     wxLuaStateData* data = (wxLuaStateData*)lua_touserdata(L, -1);
01957     lua_pop(L, 1); // pop udata
01958 
01959     return data;
01960 }
01961 
01962 // ----------------------------------------------------------------------------
01963 // wxFindWindowByPointer - find a window by its pointer
01964 //     return NULL if doesn't exist, see wxFindWindowByID and wxFindWindowByLabel
01965 // ----------------------------------------------------------------------------
01966 static wxWindow *wxFindWindowPointerRecursively(const wxWindow *parent, const wxWindow *win)
01967 {
01968     wxCHECK_MSG(win, NULL, wxT("invalid window in wxFindWindowPointerRecursively"));
01969 
01970     if ( parent )
01971     {
01972         // see if this is the one we're looking for
01973         if ( parent == win )
01974             return (wxWindow*)win;
01975 
01976         // It wasn't, so check all its children
01977         for ( wxWindowList::compatibility_iterator node = parent->GetChildren().GetFirst();
01978               node;
01979               node = node->GetNext() )
01980         {
01981             // recursively check each child
01982             wxWindow *child_win = (wxWindow *)node->GetData();
01983             wxWindow *retwin = wxFindWindowPointerRecursively(child_win, win);
01984             if (retwin)
01985                 return retwin;
01986         }
01987     }
01988 
01989     return NULL; // Not found
01990 }
01991 
01992 // Check to see if wxWidgets still thinks "win" is a valid window
01993 //   parent is the window to start with, if parent=NULL check all windows
01994 static wxWindow* wxFindWindowByPointer(const wxWindow *parent, const wxWindow *win)
01995 {
01996     wxCHECK_MSG(win, NULL, wxT("Invalid window in wxFindWindowByPointer"));
01997 
01998     if ( parent )
01999     {
02000         // just check parent and all its children
02001         return wxFindWindowPointerRecursively(parent, win);
02002     }
02003     // start at very top of wx's windows
02004     for ( wxWindowList::compatibility_iterator top_node = wxTopLevelWindows.GetFirst();
02005           top_node;
02006           top_node = top_node->GetNext() )
02007     {
02008         // recursively check each window & its children
02009         wxWindow *top_win = top_node->GetData();
02010         wxWindow *retwin = wxFindWindowPointerRecursively(top_win, win);
02011         if (retwin)
02012             return retwin;
02013     }
02014 
02015     return NULL; // Not found
02016 }
02017 
02018 // ----------------------------------------------------------------------------
02019 // wxLuaCleanupWindows - given a wxWindowList of wxWindows it runs wxFindWindowByPointer
02020 //   on it to remove dead pointers from the list if only_check=true or
02021 //   Destroy() the windows and remove them from the list if !only_check.
02022 // Returns true if any windows are removed, i.e. the list has changed
02023 // ----------------------------------------------------------------------------
02024 bool wxLuaCleanupWindows(lua_State* L, bool only_check)
02025 {
02026     wxCHECK_MSG(L, false, wxT("Invalid wxLuaState"));
02027 
02028     bool removed = false;
02029 
02030     lua_pushlightuserdata(L, &wxlua_lreg_topwindows_key); // push key
02031     lua_rawget(L, LUA_REGISTRYINDEX);                     // pop key, push value (table)
02032 
02033     bool try_again = true;
02034 
02035     while (try_again)
02036     {
02037         try_again = false;
02038 
02039         lua_pushnil(L);
02040         while (lua_next(L, -2) != 0)
02041         {
02042             // value = -1, key = -2, table = -3
02043             wxWindow* win = (wxWindow*)lua_touserdata(L, -2);
02044             wxCHECK_MSG(win, false, wxT("Invalid wxWindow"));
02045 
02046             if (wxFindWindowByPointer(NULL, win) == NULL)
02047             {
02048                 // simply remove dead window from the list
02049                 removed = true;
02050                 lua_pop(L, 1);        // pop value
02051 
02052                 lua_pushvalue(L, -1); // copy key for next iteration
02053                 lua_pushnil(L);
02054                 lua_rawset(L, -4);    // set t[key] = nil to remove it
02055             }
02056             else if (!only_check)
02057             {
02058                 removed = true;
02059                 if (win->HasCapture())
02060                     win->ReleaseMouse();
02061 
02062                 // release capture for children since we may be abruptly ending
02063                 for ( wxWindowList::compatibility_iterator childNode = win->GetChildren().GetFirst();
02064                     childNode;
02065                     childNode = childNode->GetNext() )
02066                 {
02067                     wxWindow *child = childNode->GetData();
02068 
02069                     lua_pushlightuserdata(L, child);
02070                     lua_pushnil(L);
02071                     lua_rawset(L, -5);
02072 
02073                     if (child->HasCapture())
02074                         child->ReleaseMouse();
02075                 }
02076 
02077                 if (!win->IsBeingDeleted())
02078                 {
02079                     delete win;
02080                 }
02081 
02082                 // wxLuaWindowDestroyHandler should destroy this node
02083                 //  and also delete all the children and their nodes
02084                 //  it's probably best to start from the top again
02085                 lua_pop(L, 1);        // pop value
02086 
02087                 lua_pushnil(L);
02088                 lua_rawset(L, -3);    // set t[key] = nil to remove it
02089 
02090                 try_again = true;
02091                 break;
02092             }
02093             else
02094                 lua_pop(L, 1); // pop value, lua_next will pop key at end
02095         }
02096     }
02097 
02098     lua_pop(L, 1); // pop table
02099 
02100     return removed;
02101 }
02102 
02103 //----------------------------------------------------------------------------
02104 // wxLuaStateData
02105 //----------------------------------------------------------------------------
02106 
02107 wxLuaStateData::wxLuaStateData()
02108                :m_is_running(false),
02109                 m_is_closing(false),
02110                 m_lua_debug_hook_count(100), m_lua_debug_hook_yield(50),
02111                 m_lua_debug_hook(0), m_lua_debug_hook_send_evt(false),
02112                 m_last_debug_hook_time(0), m_debug_hook_break(false),
02113                 m_debug_hook_break_msg(wxT("Break")),
02114                 m_evtHandler(NULL),
02115                 m_id(wxID_ANY)
02116 {
02117 }
02118 
02119 wxLuaStateData::~wxLuaStateData()
02120 {
02121     // no events here, the handler may already be gone
02122     m_evtHandler = NULL;
02123 }
02124 
02125 //----------------------------------------------------------------------------
02126 // wxLuaStateRefData
02127 //----------------------------------------------------------------------------
02128 
02129 wxLuaStateRefData::wxLuaStateRefData(bool create_data)
02130                   :m_lua_State(NULL),
02131                    m_lua_State_static(false),
02132                    m_lua_State_coroutine(false),
02133                    m_wxlStateData(NULL),
02134                    m_own_stateData(false)
02135 {
02136     if (create_data)
02137     {
02138         m_wxlStateData = new wxLuaStateData();
02139         m_own_stateData = true;
02140     }
02141 }
02142 
02143 wxLuaStateRefData::~wxLuaStateRefData()
02144 {
02145     wxCHECK_RET((m_lua_State_static == true) || (m_lua_State == NULL),
02146                 wxT("You must ALWAYS call wxLuaState::Destroy and not wxObject::UnRef"));
02147 
02148     CloseLuaState(true);
02149     if (m_own_stateData)
02150         delete m_wxlStateData;
02151 }
02152 
02153 bool wxLuaStateRefData::CloseLuaState(bool force)
02154 {
02155     if ((m_lua_State == NULL) || m_wxlStateData->m_is_closing || m_lua_State_coroutine)
02156         return true;
02157 
02158     m_wxlStateData->m_is_closing = true;
02159 
02160     //wxCHECK_MSG(m_lua_State, false, wxT("Interpreter not created"));
02161     // wxCHECK_MSG(!m_is_running, false, wxT("Interpreter still running, can't destroy"));  FIXME
02162 
02163     // remove deleted windows first
02164     wxLuaCleanupWindows(m_lua_State, true);
02165 
02166     // are there still windows? ask to abort deleting them if !force
02167     bool tlwindows_open = false;
02168     lua_pushlightuserdata(m_lua_State, &wxlua_lreg_topwindows_key); // push key
02169     lua_rawget(m_lua_State, LUA_REGISTRYINDEX);                     // pop key, push value (table)
02170 
02171     lua_pushnil(m_lua_State);
02172     if (lua_next(m_lua_State, -2))
02173     {
02174         tlwindows_open = true;
02175         lua_pop(m_lua_State, 3); // pop key, value, table
02176     }
02177     else
02178         lua_pop(m_lua_State, 1); // pop table
02179 
02180     if (tlwindows_open)
02181     {
02182         int ret = wxOK;
02183 
02184         if (!force)
02185         {
02186             ret = wxMessageBox(wxT("Windows are still open, would you like to delete them?"),
02187                                wxT("Delete existing windows?"), wxOK|wxCANCEL|wxICON_QUESTION);
02188         }
02189 
02190         if (ret == wxCANCEL)
02191         {
02192             m_wxlStateData->m_is_closing = false;
02193             return false;
02194         }
02195 
02196         //wxPrintf(wxT("Deleting windows\n"));
02197 
02198         // delete windows and their eventhandler since they delete the wxLuaEventCallbacks
02199         //  which require a lua_State
02200         wxLuaCleanupWindows(m_lua_State, false);
02201         // wait for wxWindow::Destroy() to really delete the windows
02202         //wxYieldIfNeeded();
02203     }
02204 
02205     // clear the wxlua_lreg_wxluastatedata_key which we test for in the debug hook
02206     // to know if the lua_State is being closed
02207     lua_pushlightuserdata(m_lua_State, &wxlua_lreg_wxluastatedata_key);
02208     lua_pushnil(m_lua_State);
02209     lua_rawset( m_lua_State, LUA_REGISTRYINDEX ); // pop key, push bool
02210 
02211     ClearCallbacks();
02212 
02213 /*
02214     // Let the Lua garbage collector do it for shutdown.
02215 
02216     // Delete all the wxObject data
02217     lua_pushlightuserdata(m_lua_State, &wxlua_lreg_gcobjects_key);
02218     lua_rawget(m_lua_State, LUA_REGISTRYINDEX);
02219 
02220     lua_pushnil(m_lua_State);
02221     while (lua_next(m_lua_State, -2) != 0)
02222     {
02223         // value = -1, key = -2, table = -3
02224         wxObject* o = (wxObject*)lua_touserdata(m_lua_State, -1); // delete object not key
02225         delete o;
02226 
02227         lua_pop(m_lua_State, 1); // pop value, lua_next will pop key at end
02228     }
02229 
02230     lua_pop(m_lua_State, 1); // pop table
02231 
02232     // remove table since we've deleted everything in it
02233     lua_pushlightuserdata(m_lua_State, &wxlua_lreg_gcobjects_key);
02234     lua_newtable(m_lua_State);
02235     lua_rawset(m_lua_State, LUA_REGISTRYINDEX);
02236 */
02237 
02238     // remove refs table to try to clear memory gracefully
02239     wxlua_lreg_createtable(m_lua_State, &wxlua_lreg_refs_key);
02240     wxlua_lreg_createtable(m_lua_State, &wxlua_lreg_debug_refs_key);
02241     //wxlua_lreg_createtable(m_lua_State, &wxlua_lreg_derivedmethods_key); // gc will delete them
02242 
02243     lua_gc(m_lua_State, LUA_GCCOLLECT, 0); // round up dead refs
02244 
02245     if (!m_lua_State_static)
02246         lua_close(m_lua_State);
02247 
02248     // Clear out the wxLuaState we hashed, note it's not refed so we have
02249     // NULL its ref data.
02250     // Note: even though the lua_State is closed the pointer value is still good.
02251     // The wxLuaState we pushed into the reg table is a light userdata so
02252     // it didn't get deleted.
02253     wxHashMapLuaState::iterator it = wxLuaState::s_wxHashMapLuaState.find(m_lua_State);
02254     if (it != wxLuaState::s_wxHashMapLuaState.end())
02255     {
02256         wxLuaState* wxlState = it->second;
02257         wxlState->SetRefData(NULL);
02258         delete wxlState;
02259         wxLuaState::s_wxHashMapLuaState.erase(m_lua_State);
02260     }
02261 
02262     m_lua_State = NULL;
02263 
02264     return true;
02265 }
02266 
02267 void wxLuaStateRefData::ClearCallbacks()
02268 {
02269     wxCHECK_RET(m_lua_State, wxT("Invalid lua_State"));
02270 
02271     lua_State* L = m_lua_State;
02272 
02273     lua_pushlightuserdata(L, &wxlua_lreg_evtcallbacks_key); // push key
02274     lua_rawget(L, LUA_REGISTRYINDEX);                       // pop key, push value (table)
02275 
02276     lua_pushnil(L);
02277     while (lua_next(L, -2) != 0)
02278     {
02279         // value = -1, key = -2, table = -3
02280         wxLuaEventCallback* cb = (wxLuaEventCallback*)lua_touserdata(L, -2);
02281         cb->ClearwxLuaState();
02282 
02283         lua_pop(L, 1);               // pop value, lua_next will pop key at end
02284     }
02285 
02286     lua_pop(L, 1); // pop table
02287 
02288     wxlua_lreg_createtable(m_lua_State, &wxlua_lreg_evtcallbacks_key);
02289 
02290     // ----------------------------------------------------------------------
02291     // These should already be gone from wxLuaCleanupWindows, make sure...
02292 
02293     lua_pushlightuserdata(L, &wxlua_lreg_windestroycallbacks_key); // push key
02294     lua_rawget(L, LUA_REGISTRYINDEX);                              // pop key, push value (table)
02295 
02296     lua_pushnil(L);
02297     while (lua_next(L, -2) != 0)
02298     {
02299         // value = -1, key = -2, table = -3
02300         wxLuaWinDestroyCallback* cb = (wxLuaWinDestroyCallback*)lua_touserdata(L, -1);
02301         cb->ClearwxLuaState();
02302 
02303         lua_pop(L, 1);               // pop value, lua_next will pop key at end
02304     }
02305 
02306     lua_pop(L, 1); // pop table
02307 
02308     wxlua_lreg_createtable(m_lua_State, &wxlua_lreg_windestroycallbacks_key);
02309 }
02310 
02311 //----------------------------------------------------------------------------
02312 // wxLuaState
02313 //----------------------------------------------------------------------------
02314 
02315 IMPLEMENT_DYNAMIC_CLASS(wxLuaState, wxObject)
02316 
02317 wxHashMapLuaState wxLuaState::s_wxHashMapLuaState;
02318 bool wxLuaState::sm_wxAppMainLoop_will_run = false;
02319 
02320 
02321 #define M_WXLSTATEDATA ((wxLuaStateRefData*)m_refData)
02322 
02323 wxObjectRefData *wxLuaState::CreateRefData() const
02324 {
02325     return new wxLuaStateRefData;
02326 }
02327 //wxObjectRefData *wxLuaState::CloneRefData(const wxObjectRefData *data) const
02328 //{
02329 //    return new wxLuaStateRefData(*(const wxLuaStateRefData *)data);
02330 //}
02331 
02332 void wxLuaState::Create( const wxLuaState& wxlState )
02333 {
02334     Destroy();
02335     Ref(wxlState);
02336 }
02337 
02338 bool wxLuaState::Create(wxEvtHandler *handler, wxWindowID id)
02339 {
02340     Destroy();
02341 
02342     lua_State* L = lua_open();
02343     // load some useful libraries, loads all of them
02344     luaL_openlibs(L);
02345 
02346     bool ok = Create(L, wxLUASTATE_SETSTATE|wxLUASTATE_OPENBINDINGS);
02347 
02348     M_WXLSTATEDATA->m_wxlStateData->m_evtHandler = handler;
02349     M_WXLSTATEDATA->m_wxlStateData->m_id = id;
02350 
02351     // alert people that we've been created so they can finish setting us up
02352     wxLuaEvent event(wxEVT_LUA_CREATION, GetId(), *this);
02353     SendEvent( event );
02354 
02355     return ok;
02356 }
02357 
02358 bool wxLuaState::Create(lua_State* L, int state_type)
02359 {
02360     wxCHECK_MSG(L != NULL, false, wxT("Invalid lua_State"));
02361     Destroy();
02362 
02363     if (WXLUA_HASBIT(state_type, wxLUASTATE_GETSTATE))
02364     {
02365         // returns an invalid, wxNullLuaState on failure
02366         Ref(wxLuaState::GetwxLuaState(L));
02367     }
02368     else if (WXLUA_HASBIT(state_type, wxLUASTATE_SETSTATE))
02369     {
02370         m_refData = new wxLuaStateRefData();
02371 
02372         M_WXLSTATEDATA->m_lua_State = L;
02373         M_WXLSTATEDATA->m_lua_State_static = WXLUA_HASBIT(state_type, wxLUASTATE_STATICSTATE);
02374 
02375         // Make the GC a little more aggressive since we push void* data
02376         // that may be quite large. The upshot is that Lua runs faster.
02377         // Empirically found by timing: "for i = 1, 1E6 do local p = wx.wxPoint() end"
02378         lua_gc(L, LUA_GCSETPAUSE, 120);
02379         lua_gc(L, LUA_GCSETSTEPMUL, 400);
02380 
02381         // Create a new state to push into Lua, the last wxLuaStateRefData will delete it.
02382         // Note: we call SetRefData() so that we don't increase the ref count.
02383         wxLuaState* hashState = new wxLuaState(false);
02384         hashState->SetRefData(m_refData);
02385         wxLuaState::s_wxHashMapLuaState[L] = hashState;
02386 
02387         // Stick us into the Lua registry table - push key, value
02388         lua_pushlightuserdata(L, &wxlua_lreg_wxluastate_key);
02389         lua_pushlightuserdata( L, (void*)hashState );
02390         lua_rawset( L, LUA_REGISTRYINDEX ); // set the value
02391 
02392         // start off not in an event
02393         wxlua_setwxeventtype(L, wxEVT_NULL);
02394 
02395         // Push our wxLuaStateData
02396         lua_pushlightuserdata(L, &wxlua_lreg_wxluastatedata_key);
02397         lua_pushlightuserdata(L, M_WXLSTATEDATA->m_wxlStateData);
02398         lua_rawset(L, LUA_REGISTRYINDEX); // set the value
02399 
02400         // These tables are expected to exist no matter what.
02401         // They're in the registry so even if they're not used they
02402         // shouldn't bother anyone.
02403 
02404         lua_pushlightuserdata(L, &wxlua_lreg_regtable_key);
02405         lua_newtable(L);      // main table
02406           lua_newtable(L);    // metatable
02407           lua_pushlstring(L, "__mode", 6);
02408           lua_pushlstring(L, "kv", 2);
02409           lua_rawset(L, -3);                  // set mode of main table
02410           lua_setmetatable(L, -2);            // via the metatable
02411         lua_rawset(L, LUA_REGISTRYINDEX); // set the value
02412 
02413         // create the types table in registry
02414         wxlua_lreg_createtable(L, &wxlua_lreg_types_key);
02415 
02416         // create the refs table in registry
02417         wxlua_lreg_createtable(L, &wxlua_lreg_refs_key);
02418 
02419         // create the debug refs table in registry
02420         wxlua_lreg_createtable(L, &wxlua_lreg_debug_refs_key);
02421 
02422         // create the wxLuaBindClasses table in the registry
02423         wxlua_lreg_createtable(L, &wxlua_lreg_classes_key);
02424 
02425         // Create a table for overridden methods for C++ userdata objects
02426         wxlua_lreg_createtable(L, &wxlua_lreg_derivedmethods_key);
02427 
02428         // Create a table for the wxLuaBindings we've installed
02429         wxlua_lreg_createtable(L, &wxlua_lreg_wxluabindings_key);
02430 
02431         // Create a table for the userdata that we've pushed into Lua
02432         wxlua_lreg_createtable(L, &wxlua_lreg_weakobjects_key);
02433 
02434         // Create a table for objects to delete
02435         wxlua_lreg_createtable(L, &wxlua_lreg_gcobjects_key);
02436 
02437         // Create a table for wxLuaEventCallbacks
02438         wxlua_lreg_createtable(L, &wxlua_lreg_evtcallbacks_key);
02439 
02440         // Create a table for wxLuaWinDestroyCallbacks
02441         wxlua_lreg_createtable(L, &wxlua_lreg_windestroycallbacks_key);
02442 
02443         // Create a table for top level wxWindows
02444         wxlua_lreg_createtable(L, &wxlua_lreg_topwindows_key);
02445 
02446         // copy Lua's print function in case someone really wants to use it
02447         lua_pushlstring(L, "print", 5);
02448         lua_rawget( L, LUA_GLOBALSINDEX );  // pop key, push print function
02449         lua_pushlstring(L, "print_lua", 9);
02450         lua_pushvalue(L, -2);               // copy print function
02451         lua_rawset(L, LUA_GLOBALSINDEX);    // set t[key] = value, pops key and value
02452         lua_pop(L, 1);                      // pop the print function
02453 
02454         // register wxLua's print handler to send events, replaces Lua's print function
02455         RegisterFunction(wxlua_printFunction, "print");
02456 
02457         // register our NULL type
02458         //wxluatype_NULL = wxluaT_newmetatable(L, wxluatype_NULL);
02459         wxLuaBinding::InstallClassMetatable(L, &wxLuaBindClass_NULL);
02460 
02461         // now register bindings
02462         if (WXLUA_HASBIT(state_type, wxLUASTATE_OPENBINDINGS))
02463         {
02464             // load the bit lib, this is the accepted way, see luaL_openlibs(L)
02465             lua_pushcfunction(L, luaopen_bit);
02466             lua_pushstring(L, "bit");
02467             lua_call(L, 1, 0);
02468 
02469             RegisterBindings();
02470         }
02471     }
02472     else
02473         wxFAIL_MSG(wxT("Unknown state_type for wxLuaState::Create()"));
02474 
02475     return Ok();
02476 }
02477 
02478 // --------------------------------------------------------------------------
02479 
02480 bool wxLuaState::Ok() const
02481 {
02482     return (m_refData != NULL) && (M_WXLSTATEDATA->m_lua_State != NULL);
02483 }
02484 
02485 // --------------------------------------------------------------------------
02486 
02487 void wxLuaState::Destroy()
02488 {
02489     if (m_refData == NULL) return;
02490 
02491     // we don't want recursion in UnRef and wxlua_garbageCollect
02492     if (GetRefData()->GetRefCount() == 1)
02493         M_WXLSTATEDATA->CloseLuaState(true);
02494 
02495     UnRef();
02496 }
02497 
02498 bool wxLuaState::CloseLuaState(bool force)
02499 {
02500     wxCHECK_MSG(Ok(), false, wxT("Invalid wxLuaState"));
02501     return M_WXLSTATEDATA->CloseLuaState(force);
02502 }
02503 
02504 bool wxLuaState::IsClosing() const
02505 {
02506     wxCHECK_MSG(m_refData && M_WXLSTATEDATA->m_wxlStateData, false, wxT("Invalid wxLuaState"));
02507     return M_WXLSTATEDATA->m_wxlStateData->m_is_closing;
02508 }
02509 
02510 // --------------------------------------------------------------------------
02511 
02512 lua_State* wxLuaState::GetLuaState() const
02513 {
02514     wxCHECK_MSG(Ok(), NULL, wxT("Invalid wxLuaState"));
02515     return M_WXLSTATEDATA->m_lua_State;
02516 }
02517 
02518 wxLuaStateData* wxLuaState::GetLuaStateData() const
02519 {
02520     wxCHECK_MSG(m_refData != NULL, NULL, wxT("Invalid wxLuaState, missing ref data"));
02521     return M_WXLSTATEDATA->m_wxlStateData;
02522 }
02523 
02524 wxLuaState wxLuaState::GetwxLuaState(lua_State* L) // static function
02525 {
02526     // try our hashtable for faster lookup
02527     wxHashMapLuaState::iterator it = s_wxHashMapLuaState.find(L);
02528     if (it != s_wxHashMapLuaState.end())
02529     {
02530         return wxLuaState(*it->second);
02531     }
02532 
02533     // else it's a coroutine? look up the state data from Lua
02534     wxLuaState* wxlState = NULL;
02535 
02536     // try to get the state we've stored
02537     lua_pushlightuserdata(L, &wxlua_lreg_wxluastate_key);
02538     lua_rawget( L, LUA_REGISTRYINDEX );
02539 
02540     // if nothing was returned or it wasn't a ptr, abort
02541     if ( lua_islightuserdata(L, -1) )
02542         wxlState = (wxLuaState*)lua_touserdata( L, -1 );
02543 
02544     lua_pop(L, 1); // pop the wxLuaStateRefData or nil on failure
02545 
02546     if (wxlState && (wxlState->GetLuaState() != L))
02547     {
02548         // Create a new wxLuaState for the coroutine and set the wxLuaStateData
02549         //  to the original wxLuaState's data
02550         wxLuaStateRefData* refData = new wxLuaStateRefData(false);
02551         refData->m_lua_State = L;
02552         refData->m_lua_State_static = true;
02553         refData->m_lua_State_coroutine = true;
02554 
02555         refData->m_wxlStateData = wxlState->GetLuaStateData();
02556         refData->m_own_stateData = false;
02557 
02558         wxLuaState wxlState2(false);
02559         wxlState2.SetRefData(refData);
02560         return wxlState2;
02561     }
02562     else if (wxlState)
02563     {
02564         return wxLuaState(*wxlState); // Ref it
02565     }
02566 
02567     return wxNullLuaState;
02568 }
02569 
02570 // --------------------------------------------------------------------------
02571 
02572 void wxLuaState::SetEventHandler(wxEvtHandler *evtHandler)
02573 {
02574     wxCHECK_RET(m_refData && M_WXLSTATEDATA->m_wxlStateData, wxT("Invalid wxLuaState"));
02575     M_WXLSTATEDATA->m_wxlStateData->m_evtHandler = evtHandler;
02576 }
02577 wxEvtHandler *wxLuaState::GetEventHandler() const
02578 {
02579     wxCHECK_MSG(m_refData && M_WXLSTATEDATA->m_wxlStateData, NULL, wxT("Invalid wxLuaState"));
02580     return M_WXLSTATEDATA->m_wxlStateData->m_evtHandler;
02581 }
02582 
02583 void wxLuaState::SetId(wxWindowID id)
02584 {
02585     wxCHECK_RET(m_refData && M_WXLSTATEDATA->m_wxlStateData, wxT("Invalid wxLuaState"));
02586     M_WXLSTATEDATA->m_wxlStateData->m_id = id;
02587 }
02588 wxWindowID  wxLuaState::GetId() const
02589 {
02590     wxCHECK_MSG(m_refData && M_WXLSTATEDATA->m_wxlStateData, wxID_ANY, wxT("Invalid wxLuaState"));
02591     return M_WXLSTATEDATA->m_wxlStateData->m_id;
02592 }
02593 
02594 bool wxLuaState::SendEvent( wxLuaEvent &event ) const
02595 {
02596     wxCHECK_MSG(m_refData && M_WXLSTATEDATA->m_wxlStateData, false, wxT("Invalid wxLuaState"));
02597 
02598     if (M_WXLSTATEDATA->m_wxlStateData->m_evtHandler)
02599     {
02600         event.SetEventObject( (wxObject*)this );
02601         return M_WXLSTATEDATA->m_wxlStateData->m_evtHandler->ProcessEvent(event);
02602     }
02603 
02604     return false;
02605 }
02606 
02607 // ----------------------------------------------------------------------------
02608 
02609 int wxLuaState::RunFile(const wxString &filename, int nresults)
02610 {
02611     wxCHECK_MSG(Ok(), LUA_ERRRUN, wxT("Lua interpreter not created"));
02612     wxCHECK_MSG(!M_WXLSTATEDATA->m_wxlStateData->m_is_running, LUA_ERRRUN, wxT("Lua interpreter is already running"));
02613 
02614     M_WXLSTATEDATA->m_wxlStateData->m_debug_hook_break = false;
02615     M_WXLSTATEDATA->m_wxlStateData->m_is_running = true;
02616 
02617     int top = lua_GetTop();
02618     int status = luaL_LoadFile(wx2lua(filename));
02619     if (status == 0)
02620         status = LuaPCall(0, nresults); // no args and nresults
02621     else
02622         SendLuaErrorEvent(status, top); // compilation error
02623 
02624     if (nresults == 0)
02625         lua_SetTop(top); // restore original top (removes err msg)
02626 
02627     M_WXLSTATEDATA->m_wxlStateData->m_debug_hook_break = false;
02628     M_WXLSTATEDATA->m_wxlStateData->m_is_running = false;
02629 
02630     return status;
02631 }
02632 
02633 int wxLuaState::RunString(const wxString &script, const wxString& name, int nresults)
02634 {
02635     wxLuaCharBuffer buf(script);
02636     return RunBuffer(buf.GetData(), buf.Length(), name, nresults);
02637 }
02638 
02639 int wxLuaState::RunBuffer(const char buf[], size_t size, const wxString &name, int nresults)
02640 {
02641     wxCHECK_MSG(Ok(), LUA_ERRRUN, wxT("Invalid wxLuaState"));
02642     wxCHECK_MSG(!M_WXLSTATEDATA->m_wxlStateData->m_is_running, LUA_ERRRUN, wxT("Lua interpreter is already running"));
02643 
02644     M_WXLSTATEDATA->m_wxlStateData->m_debug_hook_break = false;
02645     M_WXLSTATEDATA->m_wxlStateData->m_is_running = true;
02646 
02647     int top = lua_GetTop();
02648     int status = luaL_LoadBuffer(buf, size, wx2lua(name));
02649     if (status == 0)
02650         status = LuaPCall(0, nresults); // no args and nresults
02651     else
02652         SendLuaErrorEvent(status, top); // compilation error
02653 
02654     if (nresults == 0)
02655         lua_SetTop(top); // restore original top (removes err msg)
02656 
02657     M_WXLSTATEDATA->m_wxlStateData->m_debug_hook_break = false;
02658     M_WXLSTATEDATA->m_wxlStateData->m_is_running = false;
02659 
02660     return status;
02661 }
02662 
02663 bool wxLuaState::IsRunning() const
02664 {
02665     wxCHECK_MSG(Ok(), false, wxT("Invalid wxLuaState"));
02666     return M_WXLSTATEDATA->m_wxlStateData->m_is_running;
02667 }
02668 
02669 // this function taken from lua.c, the lua executable
02670 static int LUACALL wxlua_traceback (lua_State *L) {
02671   if (!lua_isstring(L, 1))  /* 'message' not a string? */
02672     return 1;  /* keep it intact */
02673   lua_getfield(L, LUA_GLOBALSINDEX, "debug");
02674   if (!lua_istable(L, -1)) {
02675     lua_pop(L, 1);
02676   }
02677   lua_getfield(L, -1, "traceback");
02678   if (!lua_isfunction(L, -1)) {
02679     lua_pop(L, 2);
02680     return 1;
02681   }
02682   lua_pushvalue(L, 1);      /* pass error message */
02683   lua_pushinteger(L, 2);    /* skip this function and traceback */
02684   lua_call(L, 2, 1);        /* call debug.traceback */
02685   return 1;
02686 }
02687 
02688 int wxLuaState::LuaPCall(int narg, int nresults)
02689 {
02690     wxCHECK_MSG(Ok(), LUA_ERRRUN, wxT("Invalid wxLuaState"));
02691     lua_State* L = M_WXLSTATEDATA->m_lua_State;
02692 
02693     int status = 0;
02694     int top  = lua_gettop(L);
02695     int base = top - narg;                  // function index
02696 
02697     lua_pushcfunction(L, wxlua_traceback);  // push our traceback function
02698 
02699     lua_insert(L, base);                    // put it under chunk and args
02700     status = lua_pcall(L, narg, nresults, base);
02701     lua_remove(L, base);                    // remove traceback function
02702 
02703     if (status != 0)
02704     {
02705         SendLuaErrorEvent(status, top - (narg + 1));
02706         lua_settop(L, top); // restore original top (removes err msg)
02707     }
02708 
02709     return status;
02710 }
02711 
02712 bool wxLuaState::SendLuaErrorEvent(int status, int top)
02713 {
02714     wxCHECK_MSG(Ok(), false, wxT("Invalid wxLuaState"));
02715     wxString errorMsg;
02716     int line_num = -1;
02717 
02718     wxlua_errorinfo(GetLuaState(), status, top, &errorMsg, &line_num);
02719 
02720     wxLuaEvent event(wxEVT_LUA_ERROR, GetId(), *this);
02721     event.SetString(errorMsg);
02722     event.SetInt(line_num);
02723     return SendEvent(event);
02724 }
02725 
02726 wxEventType wxLuaState::GetInEventType() const
02727 {
02728     wxCHECK_MSG(Ok(), wxEVT_NULL, wxT("Invalid wxLuaState"));
02729     return wxlua_getwxeventtype(M_WXLSTATEDATA->m_lua_State);
02730 }
02731 
02732 void wxLuaState::SetInEventType(wxEventType eventType)
02733 {
02734     wxCHECK_RET(Ok(), wxT("Invalid wxLuaState"));
02735     wxlua_setwxeventtype(M_WXLSTATEDATA->m_lua_State, eventType);
02736 }
02737 
02738 int wxLuaState::CompileString(const wxString &script, const wxString& name, wxString* errMsg_, int* line_num_)
02739 {
02740     wxLuaCharBuffer buf(script);
02741     return CompileBuffer(buf.GetData(), buf.Length(), name, errMsg_, line_num_);
02742 }
02743 int wxLuaState::CompileBuffer(const char buf[], size_t size, const wxString &name, wxString* errMsg_, int* line_num_)
02744 {
02745     // create a new lua_State so we don't mess up our own
02746     lua_State *L = lua_open();
02747     luaL_openlibs(L); // load some useful libraries, loads all of them
02748     int top = lua_gettop(L);
02749     int status = luaL_loadbuffer(L, (const char*)buf, size, wx2lua(name));
02750     wxlua_errorinfo(L, status, top, errMsg_, line_num_);
02751     lua_close(L);
02752     return status;
02753 }
02754 
02755 void wxLuaState::DebugHookBreak(const wxString &msg)
02756 {
02757     wxCHECK_RET(Ok(), wxT("Invalid wxLuaState"));
02758     wxCHECK_RET(M_WXLSTATEDATA->m_wxlStateData->m_is_running, wxT("Lua interpreter not running"));
02759 
02760     // Lua likes to be stopped within the debug hook, you get funny wxYield
02761     //  recursion asserts if you call wxlua_Error() within another wxYield, i.e. from a gui button
02762 
02763     M_WXLSTATEDATA->m_wxlStateData->m_debug_hook_break_msg = msg;
02764     M_WXLSTATEDATA->m_wxlStateData->m_debug_hook_break = true;
02765     lua_sethook(GetLuaState(), wxlua_debugHookFunction, LUA_MASKCALL|LUA_MASKRET|LUA_MASKLINE|LUA_MASKCOUNT, 1);
02766     M_WXLSTATEDATA->m_wxlStateData->m_is_running = false;
02767 }
02768 
02769 void wxLuaState::ClearDebugHookBreak()
02770 {
02771     wxCHECK_RET(Ok(), wxT("Invalid wxLuaState"));
02772 
02773     M_WXLSTATEDATA->m_wxlStateData->m_debug_hook_break = false;
02774     SetLuaDebugHook(GetLuaDebugHookCount(),
02775                     GetLuaDebugHookYield(),
02776                     GetLuaDebugHookSendEvt(),
02777                     GetLuaDebugHook());
02778 }
02779 
02780 bool wxLuaState::GetDebugHookBreak() const
02781 {
02782     wxCHECK_MSG(Ok(), false, wxT("Invalid wxLuaState"));
02783     return M_WXLSTATEDATA->m_wxlStateData->m_debug_hook_break;
02784 }
02785 wxString wxLuaState::GetDebugHookBreakMessage() const
02786 {
02787     wxCHECK_MSG(Ok(), wxEmptyString, wxT("Invalid wxLuaState"));
02788     return M_WXLSTATEDATA->m_wxlStateData->m_debug_hook_break_msg;
02789 }
02790 
02791 // ----------------------------------------------------------------------------
02792 
02793 void wxLuaState::SetLuaDebugHook(int hook, int count, int yield_ms, bool send_debug_evt)
02794 {
02795     wxCHECK_RET(Ok(), wxT("Invalid wxLuaState"));
02796 
02797     M_WXLSTATEDATA->m_wxlStateData->m_lua_debug_hook = hook;
02798     M_WXLSTATEDATA->m_wxlStateData->m_lua_debug_hook_count = count;
02799     M_WXLSTATEDATA->m_wxlStateData->m_lua_debug_hook_yield = yield_ms;
02800     M_WXLSTATEDATA->m_wxlStateData->m_lua_debug_hook_send_evt = send_debug_evt;
02801 
02802     // These are the various hooks you can install
02803     //LUA_MASKCALL, LUA_MASKRET, LUA_MASKLINE, and LUA_MASKCOUNT
02804     lua_sethook(M_WXLSTATEDATA->m_lua_State, wxlua_debugHookFunction, hook, count);
02805 }
02806 
02807 int wxLuaState::GetLuaDebugHook() const
02808 {
02809     wxCHECK_MSG(Ok(), 0, wxT("Invalid wxLuaState"));
02810     return M_WXLSTATEDATA->m_wxlStateData->m_lua_debug_hook;
02811 }
02812 int wxLuaState::GetLuaDebugHookCount() const
02813 {
02814     wxCHECK_MSG(Ok(), 0, wxT("Invalid wxLuaState"));
02815     return M_WXLSTATEDATA->m_wxlStateData->m_lua_debug_hook_count;
02816 }
02817 int wxLuaState::GetLuaDebugHookYield() const
02818 {
02819     wxCHECK_MSG(Ok(), 0, wxT("Invalid wxLuaState"));
02820     return M_WXLSTATEDATA->m_wxlStateData->m_lua_debug_hook_yield;
02821 }
02822 bool wxLuaState::GetLuaDebugHookSendEvt() const
02823 {
02824     wxCHECK_MSG(Ok(), false, wxT("Invalid wxLuaState"));
02825     return M_WXLSTATEDATA->m_wxlStateData->m_lua_debug_hook_send_evt;
02826 }
02827 
02828 unsigned long wxLuaState::GetLastLuaDebugHookTime() const
02829 {
02830     wxCHECK_MSG(Ok(), 0, wxT("Invalid wxLuaState"));
02831     return M_WXLSTATEDATA->m_wxlStateData->m_last_debug_hook_time;
02832 }
02833 void wxLuaState::SetLastLuaDebugHookTime(unsigned long t)
02834 {
02835     wxCHECK_RET(Ok(), wxT("Invalid wxLuaState"));
02836     M_WXLSTATEDATA->m_wxlStateData->m_last_debug_hook_time = t;
02837 }
02838 
02839 // ----------------------------------------------------------------------------
02840 
02841 void wxLuaState::RegisterFunction(lua_CFunction func, const char* funcName)
02842 {
02843     wxCHECK_RET(Ok(), wxT("Invalid wxLuaState"));
02844     lua_register( M_WXLSTATEDATA->m_lua_State, funcName, func );
02845 }
02846 
02847 bool wxLuaState::RegisterBinding(wxLuaBinding* binding)
02848 {
02849     wxCHECK_MSG(Ok(), false, wxT("Invalid wxLuaState"));
02850     wxCHECK_MSG(binding, false, wxT("Invalid wxLuaState"));
02851 
02852     wxLuaBinding::InitAllBindings(); // only runs the first time through
02853 
02854     bool ret = binding->RegisterBinding(*this);
02855     if (ret) lua_Pop(1);
02856 
02857     return ret;
02858 }
02859 
02860 bool wxLuaState::RegisterBindings()
02861 {
02862     wxCHECK_MSG(Ok(), false, wxT("Invalid wxLuaState"));
02863     wxLuaBinding::InitAllBindings(); // only runs the first time through
02864 
02865     // Register bindings
02866     wxLuaBindingList::compatibility_iterator node = wxLuaBinding::GetBindingList()->GetFirst();
02867     while (node)
02868     {
02869         wxLuaBinding* binding = node->GetData();
02870         binding->RegisterBinding(*this);
02871         lua_Pop(1); // pop the Lua table the binding was installed into
02872 
02873         node = node->GetNext();
02874     }
02875 
02876     return true;
02877 }
02878 
02879 wxLuaBinding* wxLuaState::GetLuaBinding(const wxString& bindingName) const
02880 {
02881     wxCHECK_MSG(GetRefData() != NULL, NULL, wxT("Invalid wxLuaState"));
02882     return wxLuaBinding::GetLuaBinding(bindingName);
02883 }
02884 
02885 const wxLuaBindClass* wxLuaState::GetBindClass(int wxluatype) const
02886 {
02887     wxCHECK_MSG(Ok(), NULL, wxT("Invalid wxLuaState"));
02888 
02889     // try to get the wxLuaBindClass from the Lua registry table first
02890     const wxLuaBindClass* wxlClass = wxluaT_getclass(M_WXLSTATEDATA->m_lua_State, wxluatype);
02891 
02892     // we shouldn't ever need this code
02893     if (wxlClass == NULL)
02894         wxlClass = wxLuaBinding::FindBindClass(wxluatype);
02895 
02896     return wxlClass;
02897 }
02898 const wxLuaBindClass* wxLuaState::GetBindClass(const char* className) const
02899 {
02900     wxCHECK_MSG(Ok(), NULL, wxT("Invalid wxLuaState"));
02901     return wxluaT_getclass(M_WXLSTATEDATA->m_lua_State, className);
02902 }
02903 const wxLuaBindClass* wxLuaState::GetBindClass(const wxLuaBindMethod* wxlMethod) const
02904 {
02905     wxCHECK_MSG(GetRefData() != NULL, NULL, wxT("Invalid wxLuaState"));
02906     return wxLuaBinding::FindBindClass(wxlMethod);
02907 }
02908 const wxLuaBindClass* wxLuaState::GetBindClass(const wxLuaBindCFunc* wxlClass) const
02909 {
02910     wxCHECK_MSG(GetRefData() != NULL, NULL, wxT("Invalid wxLuaState"));
02911     return wxLuaBinding::FindBindClass(wxlClass);
02912 }
02913 
02914 int wxLuaState::IsDerivedType(int wxl_type, int base_wxl_type) const
02915 {
02916     wxCHECK_MSG(Ok(), -1, wxT("Invalid wxLuaState"));
02917     return wxluaT_isderivedtype(M_WXLSTATEDATA->m_lua_State, wxl_type, base_wxl_type);
02918 }
02919 
02920 const wxLuaBindEvent* wxLuaState::GetBindEvent(wxEventType eventType) const
02921 {
02922     wxCHECK_MSG(Ok(), NULL, wxT("Invalid wxLuaState"));
02923     return wxLuaBinding::FindBindEvent(eventType);
02924 }
02925 
02926 void wxLuaState::SetCallBaseClassFunction(bool call_base)
02927 {
02928     wxCHECK_RET(Ok(), wxT("Invalid wxLuaState"));
02929     wxlua_setcallbaseclassfunction(M_WXLSTATEDATA->m_lua_State, call_base);
02930 }
02931 bool wxLuaState::GetCallBaseClassFunction()
02932 {
02933     wxCHECK_MSG(Ok(), false, wxT("Invalid wxLuaState"));
02934     return wxlua_getcallbaseclassfunction(M_WXLSTATEDATA->m_lua_State);
02935 }
02936 
02937 // ----------------------------------------------------------------------------
02938 // memory tracking functions
02939 
02940 void wxLuaState::AddGCObject(wxObject *wxobj)
02941 {
02942     AddGCObject(wxobj, wxobj);
02943 }
02944 
02945 void wxLuaState::AddGCObject(void* obj_ptr, wxObject *wxobj)
02946 {
02947     wxCHECK_RET(Ok() && wxobj, wxT("Invalid wxLuaState or wxObject to track"));
02948     wxluaO_addgcobject(M_WXLSTATEDATA->m_lua_State, obj_ptr, wxobj);
02949 }
02950 
02951 bool wxLuaState::DeleteGCObject(void* udata, void *obj_ptr, int flags)
02952 {
02953     wxCHECK_MSG(Ok() && obj_ptr, false, wxT("Invalid wxLuaState or object"));
02954     return wxluaO_deletegcobject(M_WXLSTATEDATA->m_lua_State, udata, obj_ptr, flags);
02955 }
02956 
02957 bool wxLuaState::IsGCObject(void *obj_ptr) const
02958 {
02959     wxCHECK_MSG(Ok(), false, wxT("Invalid wxLuaState"));
02960     return wxluaO_isgcobject(M_WXLSTATEDATA->m_lua_State, obj_ptr);
02961 }
02962 
02963 wxArrayString wxLuaState::GetGCObjectInfo() const
02964 {
02965     wxCHECK_MSG(Ok(), wxArrayString(), wxT("Invalid wxLuaState"));
02966     return wxluaO_getgcobjectinfo(M_WXLSTATEDATA->m_lua_State);
02967 }
02968 
02969 void wxLuaState::AddTrackedWindow(wxObject *obj)
02970 {
02971     wxCHECK_RET(Ok(), wxT("Invalid wxLuaState"));
02972     wxluaW_addtrackedwindow(M_WXLSTATEDATA->m_lua_State, obj);
02973 }
02974 
02975 void wxLuaState::RemoveTrackedWindow(wxWindow *win)
02976 {
02977     wxCHECK_RET(Ok() && win, wxT("Invalid wxLuaState or wxWindow"));
02978     wxluaW_removetrackedwindow(M_WXLSTATEDATA->m_lua_State, win);
02979 }
02980 
02981 bool wxLuaState::IsTrackedWindow(wxWindow *win, bool check_parents) const
02982 {
02983     wxCHECK_MSG(Ok() && win, false, wxT("Invalid wxLuaState or wxWindow"));
02984     return wxluaW_istrackedwindow(M_WXLSTATEDATA->m_lua_State, win, check_parents);
02985 }
02986 
02987 wxArrayString wxLuaState::GetTrackedWindowInfo() const
02988 {
02989     wxCHECK_MSG(Ok(), wxArrayString(), wxT("Invalid wxLuaState"));
02990     return wxluaW_gettrackedwindowinfo(M_WXLSTATEDATA->m_lua_State);
02991 }
02992 
02993 void wxLuaState::GarbageCollectWindows(bool closeWindows)
02994 {
02995     wxCHECK_RET(Ok(), wxT("Invalid wxLuaState"));
02996     // remove deleted windows
02997     wxLuaCleanupWindows(M_WXLSTATEDATA->m_lua_State, !closeWindows);
02998 }
02999 
03000 void wxLuaState::AddTrackedEventCallback(wxLuaEventCallback* callback)
03001 {
03002     wxCHECK_RET(Ok(), wxT("Invalid wxLuaState"));
03003     lua_State* L = M_WXLSTATEDATA->m_lua_State;
03004 
03005     lua_pushlightuserdata(L, &wxlua_lreg_evtcallbacks_key); // push key
03006     lua_rawget(L, LUA_REGISTRYINDEX);                       // pop key, push value (table)
03007 
03008     lua_pushlightuserdata(L, callback);                  // push key
03009     lua_pushlightuserdata(L, callback->GetEvtHandler()); // push value
03010     lua_rawset(L, -3); // set t[key] = value; pops key and value
03011 
03012     lua_pop(L, 1);     // pop table
03013 }
03014 bool wxLuaState::RemoveTrackedEventCallback(wxLuaEventCallback* callback)
03015 {
03016     wxCHECK_MSG(Ok(), false, wxT("Invalid wxLuaState"));
03017     lua_State* L = M_WXLSTATEDATA->m_lua_State;
03018 
03019     lua_pushlightuserdata(L, &wxlua_lreg_evtcallbacks_key); // push key
03020     lua_rawget(L, LUA_REGISTRYINDEX);                       // pop key, push value (table)
03021 
03022     lua_pushlightuserdata(L, callback); // push key
03023     lua_pushnil(L);                     // push value
03024     lua_rawset(L, -3); // set t[key] = value; pops key and value
03025 
03026     lua_pop(L, 1);     // pop table
03027 
03028     return true; // FIXME return a real value
03029 }
03030 
03031 wxArrayString wxLuaState::GetTrackedEventCallbackInfo() const
03032 {
03033     wxArrayString names;
03034 
03035     wxCHECK_MSG(Ok(), names, wxT("Invalid wxLuaState"));
03036     lua_State* L = M_WXLSTATEDATA->m_lua_State;
03037 
03038     lua_pushlightuserdata(L, &wxlua_lreg_evtcallbacks_key); // push key
03039     lua_rawget(L, LUA_REGISTRYINDEX);                       // pop key, push value (table)
03040 
03041     lua_pushnil(L);
03042     while (lua_next(L, -2) != 0)
03043     {
03044         // value = -1, key = -2, table = -3
03045         wxLuaEventCallback* wxlCallback = (wxLuaEventCallback*)lua_touserdata(L, -2);
03046         wxCHECK_MSG(wxlCallback, names, wxT("Invalid wxLuaEventCallback"));
03047 
03048         names.Add(wxlCallback->GetInfo());
03049 
03050         lua_pop(L, 1); // pop value, lua_next will pop key at end
03051     }
03052 
03053     lua_pop(L, 1); // pop table
03054 
03055     names.Sort();
03056     return names;
03057 }
03058 
03059 void wxLuaState::AddTrackedWinDestroyCallback(wxLuaWinDestroyCallback* callback)
03060 {
03061     wxCHECK_RET(Ok(), wxT("Invalid wxLuaState"));
03062     lua_State* L = M_WXLSTATEDATA->m_lua_State;
03063 
03064     lua_pushlightuserdata(L, &wxlua_lreg_windestroycallbacks_key); // push key
03065     lua_rawget(L, LUA_REGISTRYINDEX);                              // pop key, push value (table)
03066 
03067     lua_pushlightuserdata(L, callback->GetWindow()); // push key
03068     lua_pushlightuserdata(L, callback);              // push value
03069     lua_rawset(L, -3); // set t[key] = value; pops key and value
03070 
03071     lua_pop(L, 1);     // pop table
03072 }
03073 bool wxLuaState::RemoveTrackedWinDestroyCallback(wxLuaWinDestroyCallback* callback)
03074 {
03075     wxCHECK_MSG(Ok(), false, wxT("Invalid wxLuaState"));
03076     lua_State* L = M_WXLSTATEDATA->m_lua_State;
03077 
03078     lua_pushlightuserdata(L, &wxlua_lreg_windestroycallbacks_key); // push key
03079     lua_rawget(L, LUA_REGISTRYINDEX);                              // pop key, push value (table)
03080 
03081     lua_pushlightuserdata(L, callback->GetWindow()); // push key
03082     lua_pushnil(L);                                  // push value
03083     lua_rawset(L, -3); // set t[key] = value; pops key and value
03084 
03085     lua_pop(L, 1);     // pop table
03086 
03087     return true; // FIXME return if it was here or not
03088 }
03089 
03090 wxArrayString wxLuaState::GetTrackedWinDestroyCallbackInfo() const
03091 {
03092     wxArrayString names;
03093 
03094     wxCHECK_MSG(Ok(), names, wxT("Invalid wxLuaState"));
03095     lua_State* L = M_WXLSTATEDATA->m_lua_State;
03096 
03097     lua_pushlightuserdata(L, &wxlua_lreg_windestroycallbacks_key); // push key
03098     lua_rawget(L, LUA_REGISTRYINDEX);                              // pop key, push value (table)
03099 
03100     lua_pushnil(L);
03101     while (lua_next(L, -2) != 0)
03102     {
03103         // value = -1, key = -2, table = -3
03104         wxLuaWinDestroyCallback* wxlDestroyCallBack = (wxLuaWinDestroyCallback*)lua_touserdata(L, -1);
03105         wxCHECK_MSG(wxlDestroyCallBack, names, wxT("Invalid wxLuaWinDestroyCallback"));
03106 
03107         names.Add(wxlDestroyCallBack->GetInfo());
03108 
03109         lua_pop(L, 1); // pop value, lua_next will pop key at end
03110     }
03111 
03112     names.Sort();
03113     return names;
03114 }
03115 
03116 // ----------------------------------------------------------------------------
03117 
03118 void wxLuaState::wxlua_Error(const char *errorMsg) const
03119 {
03120     wxCHECK_RET(Ok(), wxT("Invalid wxLuaState"));
03121     wxlua_error(M_WXLSTATEDATA->m_lua_State, errorMsg);
03122 }
03123 
03124 void* wxLuaState::wxlua_ToUserdata(int stack_idx, bool reset /* = false*/) const
03125 {
03126     wxCHECK_MSG(Ok(), NULL, wxT("Invalid wxLuaState"));
03127     return wxlua_touserdata(M_WXLSTATEDATA->m_lua_State, stack_idx, reset);
03128 }
03129 
03130 // ----------------------------------------------------------------------------
03131 // wxLua Lua Registry Table Functions
03132 
03133 int wxLuaState::wxluaR_Ref(int stack_idx, void* lightuserdata_reg_key)
03134 {
03135     wxCHECK_MSG(Ok(), LUA_REFNIL, wxT("Invalid wxLuaState"));
03136     return wxluaR_ref(M_WXLSTATEDATA->m_lua_State, stack_idx, lightuserdata_reg_key);
03137 }
03138 
03139 bool wxLuaState::wxluaR_Unref(int wxlref_index, void* lightuserdata_reg_key)
03140 {
03141     wxCHECK_MSG(Ok(), false, wxT("Invalid wxLuaState"));
03142     return wxluaR_unref(M_WXLSTATEDATA->m_lua_State, wxlref_index, lightuserdata_reg_key);
03143 }
03144 
03145 bool wxLuaState::wxluaR_GetRef(int wxlref_index, void* lightuserdata_reg_key)
03146 {
03147     wxCHECK_MSG(Ok(), false, wxT("Invalid wxLuaState"));
03148     return wxluaR_getref(M_WXLSTATEDATA->m_lua_State, wxlref_index, lightuserdata_reg_key);
03149 }
03150 
03151 // ----------------------------------------------------------------------------
03152 
03153 int wxLuaState::wxluaT_NewMetatable(int wxl_type)
03154 {
03155     wxCHECK_MSG(Ok(), WXLUA_TUNKNOWN, wxT("Invalid wxLuaState"));
03156     return wxluaT_newmetatable(M_WXLSTATEDATA->m_lua_State, wxl_type);
03157 }
03158 
03159 bool wxLuaState::wxluaT_SetMetatable(int wxl_type)
03160 {
03161     wxCHECK_MSG(Ok(), false, wxT("Invalid wxLuaState"));
03162     return wxluaT_setmetatable(M_WXLSTATEDATA->m_lua_State, wxl_type);
03163 }
03164 
03165 int wxLuaState::wxluaT_Type(int stack_idx) const
03166 {
03167     wxCHECK_MSG(Ok(), WXLUA_TUNKNOWN, wxT("Invalid wxLuaState"));
03168     return wxluaT_type(M_WXLSTATEDATA->m_lua_State, stack_idx);
03169 }
03170 
03171 bool wxLuaState::wxluaT_PushUserDataType(const void *obj_ptr, int wxl_type, bool track)
03172 {
03173     wxCHECK_MSG(Ok(), false, wxT("Invalid wxLuaState"));
03174     return wxluaT_pushuserdatatype(M_WXLSTATEDATA->m_lua_State, obj_ptr, wxl_type, track);
03175 }
03176 
03177 // ----------------------------------------------------------------------------
03178 // wxLua get data type
03179 
03180 int wxLuaState::IswxLuaType(int luatype, int wxl_type) const
03181 {
03182     wxCHECK_MSG(Ok(), -1, wxT("Invalid wxLuaState"));
03183     return wxlua_iswxluatype(luatype, wxl_type, M_WXLSTATEDATA->m_lua_State);
03184 }
03185 
03186 bool wxLuaState::IsUserDataType(int stack_idx, int wxl_type) const
03187 {
03188     wxCHECK_MSG(Ok(), false, wxT("Invalid wxLuaState"));
03189     return wxluaT_isuserdatatype(M_WXLSTATEDATA->m_lua_State, stack_idx, wxl_type);
03190 }
03191 
03192 void* wxLuaState::GetUserDataType(int stack_idx, int wxl_type) const
03193 {
03194     wxCHECK_MSG(Ok(), NULL, wxT("Invalid wxLuaState"));
03195     return wxluaT_getuserdatatype(M_WXLSTATEDATA->m_lua_State, stack_idx, wxl_type);
03196 }
03197 
03198 const char* wxLuaState::GetStringType(int stack_idx)
03199 {
03200     wxCHECK_MSG(Ok(), NULL, wxT("Invalid wxLuaState"));
03201     return wxlua_getstringtype(M_WXLSTATEDATA->m_lua_State, stack_idx);
03202 }
03203 wxString wxLuaState::GetwxStringType(int stack_idx)
03204 {
03205     wxCHECK_MSG(Ok(), wxEmptyString, wxT("Invalid wxLuaState"));
03206     return wxlua_getwxStringtype(M_WXLSTATEDATA->m_lua_State, stack_idx);
03207 }
03208 bool wxLuaState::GetBooleanType(int stack_idx)
03209 {
03210     wxCHECK_MSG(Ok(), false, wxT("Invalid wxLuaState"));
03211     return wxlua_getbooleantype(M_WXLSTATEDATA->m_lua_State, stack_idx);
03212 }
03213 long wxLuaState::GetIntegerType(int stack_idx)
03214 {
03215     wxCHECK_MSG(Ok(), 0, wxT("Invalid wxLuaState"));
03216     return wxlua_getintegertype(M_WXLSTATEDATA->m_lua_State, stack_idx);
03217 }
03218 double wxLuaState::GetNumberType(int stack_idx)
03219 {
03220     wxCHECK_MSG(Ok(), 0, wxT("Invalid wxLuaState"));
03221     return wxlua_getnumbertype(M_WXLSTATEDATA->m_lua_State, stack_idx);
03222 }
03223 
03224 bool wxLuaState::IsStringType(int stack_idx) const
03225 {
03226     wxCHECK_MSG(Ok(), false, wxT("Invalid wxLuaState"));
03227     return wxlua_isstringtype(M_WXLSTATEDATA->m_lua_State, stack_idx);
03228 }
03229 
03230 bool wxLuaState::IswxStringType(int stack_idx) const
03231 {
03232     wxCHECK_MSG(Ok(), false, wxT("Invalid wxLuaState"));
03233     return wxlua_iswxstringtype(M_WXLSTATEDATA->m_lua_State, stack_idx);
03234 }
03235 
03236 bool wxLuaState::IsBooleanType(int stack_idx) const
03237 {
03238     wxCHECK_MSG(Ok(), false, wxT("Invalid wxLuaState"));
03239     return wxlua_isbooleantype(M_WXLSTATEDATA->m_lua_State, stack_idx);
03240 }
03241 bool wxLuaState::IsIntegerType(int stack_idx) const
03242 {
03243     wxCHECK_MSG(Ok(), false, wxT("Invalid wxLuaState"));
03244     return wxlua_isintegertype(M_WXLSTATEDATA->m_lua_State, stack_idx);
03245 }
03246 bool wxLuaState::IsNumberType(int stack_idx) const
03247 {
03248     wxCHECK_MSG(Ok(), false, wxT("Invalid wxLuaState"));
03249     return wxlua_isnumbertype(M_WXLSTATEDATA->m_lua_State, stack_idx);
03250 }
03251 
03252 wxString* wxLuaState::GetwxStringArray(int stack_idx, int &count)
03253 {
03254     wxCHECK_MSG(Ok(), NULL, wxT("Invalid wxLuaState"));
03255     return wxlua_getwxStringarray(M_WXLSTATEDATA->m_lua_State, stack_idx, count);
03256 }
03257 
03258 wxLuaSmartwxArrayString wxLuaState::GetwxArrayString(int stack_idx)
03259 {
03260     wxCHECK_MSG(Ok(), wxLuaSmartwxArrayString(NULL, true), wxT("Invalid wxLuaState"));
03261     return wxlua_getwxArrayString(M_WXLSTATEDATA->m_lua_State, stack_idx);
03262 }
03263 
03264 const char** wxLuaState::GetCharArray(int stack_idx, int &count)
03265 {
03266     wxCHECK_MSG(Ok(), NULL, wxT("Invalid wxLuaState"));
03267     return wxlua_getchararray(M_WXLSTATEDATA->m_lua_State, stack_idx, count);
03268 }
03269 
03270 int wxLuaState::PushwxArrayStringTable(const wxArrayString &strArray)
03271 {
03272     wxCHECK_MSG(Ok(), 0, wxT("Invalid wxLuaState"));
03273     return wxlua_pushwxArrayStringtable(M_WXLSTATEDATA->m_lua_State, strArray);
03274 }
03275 
03276 int wxLuaState::PushwxArrayIntTable(const wxArrayInt &intArray)
03277 {
03278     wxCHECK_MSG(Ok(), 0, wxT("Invalid wxLuaState"));
03279     return wxlua_pushwxArrayInttable(M_WXLSTATEDATA->m_lua_State, intArray);
03280 }
03281 
03282 int* wxLuaState::GetIntArray(int stack_idx, int &count)
03283 {
03284     wxCHECK_MSG(Ok(), NULL, wxT("Invalid wxLuaState"));
03285     return wxlua_getintarray(M_WXLSTATEDATA->m_lua_State, stack_idx, count);
03286 }
03287 
03288 wxLuaSmartwxArrayInt wxLuaState::GetwxArrayInt(int stack_idx)
03289 {
03290     wxCHECK_MSG(Ok(), wxLuaSmartwxArrayInt(NULL, true), wxT("Invalid wxLuaState"));
03291     return wxlua_getwxArrayInt(M_WXLSTATEDATA->m_lua_State, stack_idx);
03292 }
03293 
03294 wxString wxLuaState::GetwxLuaTypeName(int wxl_type) const
03295 {
03296     wxCHECK_MSG(Ok(), wxEmptyString, wxT("Invalid wxLuaState"));
03297     return wxluaT_typename(M_WXLSTATEDATA->m_lua_State, wxl_type);
03298 }
03299 
03300 bool wxLuaState::SetDerivedMethod(void *obj_ptr, const char *method_name, wxLuaObject* wxlObj)
03301 {
03302     wxCHECK_MSG(Ok() && obj_ptr, false, wxT("Invalid wxLuaState or object to set derived method for."));
03303     return wxlua_setderivedmethod(M_WXLSTATEDATA->m_lua_State, obj_ptr, method_name, wxlObj);
03304 }
03305 
03306 bool wxLuaState::HasDerivedMethod(void *obj_ptr, const char *method_name, bool push_method) const
03307 {
03308     wxCHECK_MSG(Ok(), false, wxT("Invalid wxLuaState"));
03309     return wxlua_hasderivedmethod(M_WXLSTATEDATA->m_lua_State, obj_ptr, method_name, push_method);
03310 }
03311 
03312 bool wxLuaState::RemoveDerivedMethods(void *obj_ptr) const
03313 {
03314     wxCHECK_MSG(Ok() && obj_ptr, false, wxT("Invalid wxLuaState or object to remove."));
03315     return wxlua_removederivedmethods(M_WXLSTATEDATA->m_lua_State, obj_ptr);
03316 }
03317 
03318 wxLuaState wxLuaState::GetDerivedMethodState(void *obj_ptr, const char *method_name)
03319 {
03320     wxCHECK_MSG(obj_ptr, wxNullLuaState, wxT("Invalid object to wxLuaState::GetDerivedMethod"));
03321 
03322     wxHashMapLuaState::iterator it;
03323     for (it = wxLuaState::s_wxHashMapLuaState.begin();
03324          it != wxLuaState::s_wxHashMapLuaState.end(); ++it)
03325     {
03326         wxLuaState wxlState((wxLuaState*)it->second);
03327         if (wxlState.HasDerivedMethod(obj_ptr, method_name, false))
03328             return wxlState;
03329     }
03330 
03331     return wxNullLuaState;
03332 }
03333 
03334 // ----------------------------------------------------------------------------
03335 // Raw basic Lua stack functions.
03336 
03337 int wxLuaState::lua_GetTop() const
03338 {
03339     wxCHECK_MSG(Ok(), 0, wxT("Invalid wxLuaState"));
03340     return lua_gettop(M_WXLSTATEDATA->m_lua_State);
03341 }
03342 void wxLuaState::lua_SetTop(int index)
03343 {
03344     wxCHECK_RET(Ok(), wxT("Invalid wxLuaState"));
03345     lua_settop(M_WXLSTATEDATA->m_lua_State, index);
03346 }
03347 void wxLuaState::lua_PushValue(int index)
03348 {
03349     wxCHECK_RET(Ok(), wxT("Invalid wxLuaState"));
03350     lua_pushvalue(M_WXLSTATEDATA->m_lua_State, index);
03351 }
03352 void wxLuaState::lua_Remove(int index)
03353 {
03354     wxCHECK_RET(Ok(), wxT("Invalid wxLuaState"));
03355     lua_remove(M_WXLSTATEDATA->m_lua_State, index);
03356 }
03357 void wxLuaState::lua_Pop(int count)
03358 {
03359     wxCHECK_RET(Ok(), wxT("Invalid wxLuaState"));
03360     lua_pop(M_WXLSTATEDATA->m_lua_State, count);
03361 }
03362 void wxLuaState::lua_Insert(int index)
03363 {
03364     wxCHECK_RET(Ok(), wxT("Invalid wxLuaState"));
03365     lua_insert(M_WXLSTATEDATA->m_lua_State, index);
03366 }
03367 void wxLuaState::lua_Replace(int index)
03368 {
03369     wxCHECK_RET(Ok(), wxT("Invalid wxLuaState"));
03370     lua_replace(M_WXLSTATEDATA->m_lua_State, index);
03371 }
03372 int wxLuaState::lua_CheckStack(int size)
03373 {
03374     wxCHECK_MSG(Ok(), 0, wxT("Invalid wxLuaState"));
03375     return lua_checkstack(M_WXLSTATEDATA->m_lua_State, size);
03376 }
03377 void wxLuaState::lua_XMove(const wxLuaState& to, int n)
03378 {
03379     wxCHECK_RET(Ok() && to.Ok(), wxT("Invalid wxLuaState"));
03380     lua_xmove(M_WXLSTATEDATA->m_lua_State, to.GetLuaState(), n);
03381 }
03382 
03383 // ----------------------------------------------------------------------------
03384 // access functions (stack -> C)
03385 
03386 bool wxLuaState::lua_IsNumber(int index) const
03387 {
03388     wxCHECK_MSG(Ok(), false, wxT("Invalid wxLuaState"));
03389     return lua_isnumber(M_WXLSTATEDATA->m_lua_State, index) != 0;
03390 }
03391 bool wxLuaState::lua_IsString(int index) const
03392 {
03393     wxCHECK_MSG(Ok(), false, wxT("Invalid wxLuaState"));
03394     return lua_isstring(M_WXLSTATEDATA->m_lua_State, index) != 0;
03395 }
03396 bool wxLuaState::lua_IsCFunction(int index) const
03397 {
03398     wxCHECK_MSG(Ok(), false, wxT("Invalid wxLuaState"));
03399     return lua_iscfunction(M_WXLSTATEDATA->m_lua_State, index) != 0;
03400 }
03401 bool wxLuaState::lua_IsUserdata(int index) const
03402 {
03403     wxCHECK_MSG(Ok(), false, wxT("Invalid wxLuaState"));
03404     return lua_isuserdata(M_WXLSTATEDATA->m_lua_State, index) != 0;
03405 }
03406 int wxLuaState::lua_Type(int index) const
03407 {
03408     wxCHECK_MSG(Ok(), 0, wxT("Invalid wxLuaState"));
03409     return lua_type(M_WXLSTATEDATA->m_lua_State, index);
03410 }
03411 wxString wxLuaState::lua_TypeName(int type) const
03412 {
03413     wxCHECK_MSG(Ok(), wxEmptyString, wxT("Invalid wxLuaState"));
03414     return lua2wx(lua_typename(M_WXLSTATEDATA->m_lua_State, type));
03415 }
03416 
03417 int wxLuaState::lua_Equal(int index1, int index2) const
03418 {
03419     wxCHECK_MSG(Ok(), 0, wxT("Invalid wxLuaState"));
03420     return lua_equal(M_WXLSTATEDATA->m_lua_State, index1, index2);
03421 }
03422 int wxLuaState::lua_RawEqual(int index1, int index2) const
03423 {
03424     wxCHECK_MSG(Ok(), 0, wxT("Invalid wxLuaState"));
03425     return lua_rawequal(M_WXLSTATEDATA->m_lua_State, index1, index2);
03426 }
03427 int wxLuaState::lua_LessThan(int index1, int index2) const
03428 {
03429     wxCHECK_MSG(Ok(), 0, wxT("Invalid wxLuaState"));
03430     return lua_lessthan(M_WXLSTATEDATA->m_lua_State, index1, index2);
03431 }
03432 
03433 double wxLuaState::lua_ToNumber(int index) const
03434 {
03435     wxCHECK_MSG(Ok(), 0, wxT("Invalid wxLuaState"));
03436     return lua_tonumber(M_WXLSTATEDATA->m_lua_State, index);
03437 }
03438 int wxLuaState::lua_ToInteger(int index) const
03439 {
03440     wxCHECK_MSG(Ok(), 0, wxT("Invalid wxLuaState"));
03441     return lua_tointeger(M_WXLSTATEDATA->m_lua_State, index);
03442 }
03443 int wxLuaState::lua_ToBoolean(int index) const
03444 {
03445     wxCHECK_MSG(Ok(), 0, wxT("Invalid wxLuaState"));
03446     return lua_toboolean(M_WXLSTATEDATA->m_lua_State, index);
03447 }
03448 const char* wxLuaState::lua_ToString(int index) const
03449 {
03450     wxCHECK_MSG(Ok(), NULL, wxT("Invalid wxLuaState"));
03451     return lua_tostring(M_WXLSTATEDATA->m_lua_State, index);
03452 }
03453 wxString wxLuaState::lua_TowxString(int index) const
03454 {
03455     wxCHECK_MSG(Ok(), wxEmptyString, wxT("Invalid wxLuaState"));
03456     return lua2wx(lua_tostring(M_WXLSTATEDATA->m_lua_State, index));
03457 }
03458 size_t wxLuaState::lua_StrLen(int index) const
03459 {
03460     wxCHECK_MSG(Ok(), 0, wxT("Invalid wxLuaState"));
03461     return lua_strlen(M_WXLSTATEDATA->m_lua_State, index);
03462 }
03463 size_t wxLuaState::luaL_ObjLen(int t) const
03464 {
03465     wxCHECK_MSG(Ok(), 0, wxT("Invalid wxLuaState"));
03466     return lua_objlen(M_WXLSTATEDATA->m_lua_State, t);
03467 }
03468 lua_CFunction wxLuaState::lua_ToCFunction(int index) const
03469 {
03470     wxCHECK_MSG(Ok(), NULL, wxT("Invalid wxLuaState"));
03471     return lua_tocfunction(M_WXLSTATEDATA->m_lua_State, index);
03472 }
03473 void *wxLuaState::lua_ToUserdata(int index) const
03474 {
03475     wxCHECK_MSG(Ok(), NULL, wxT("Invalid wxLuaState"));
03476     return lua_touserdata(M_WXLSTATEDATA->m_lua_State, index);
03477 }
03478 wxLuaState wxLuaState::lua_ToThread(int index) const
03479 {
03480     wxCHECK_MSG(Ok(), false, wxT("Invalid wxLuaState"));
03481     return wxLuaState(lua_tothread(M_WXLSTATEDATA->m_lua_State, index));
03482 }
03483 const void* wxLuaState::lua_ToPointer(int index) const
03484 {
03485     wxCHECK_MSG(Ok(), NULL, wxT("Invalid wxLuaState"));
03486     return lua_topointer(M_WXLSTATEDATA->m_lua_State, index);
03487 }
03488 
03489 // ----------------------------------------------------------------------------
03490 // Raw Lua push functions (C -> stack)
03491 
03492 void wxLuaState::lua_PushNil()
03493 {
03494     wxCHECK_RET(Ok(), wxT("Invalid wxLuaState"));
03495     lua_pushnil(M_WXLSTATEDATA->m_lua_State);
03496 }
03497 void wxLuaState::lua_PushNumber(lua_Number n)
03498 {
03499     wxCHECK_RET(Ok(), wxT("Invalid wxLuaState"));
03500     lua_pushnumber(M_WXLSTATEDATA->m_lua_State, n);
03501 }
03502 void wxLuaState::lua_PushInteger(lua_Integer n)
03503 {
03504     wxCHECK_RET(Ok(), wxT("Invalid wxLuaState"));
03505     lua_pushinteger(M_WXLSTATEDATA->m_lua_State, n);
03506 }
03507 void wxLuaState::lua_PushLString(const char* s, size_t len)
03508 {
03509     wxCHECK_RET(Ok(), wxT("Invalid wxLuaState"));
03510     lua_pushlstring(M_WXLSTATEDATA->m_lua_State, s, len);
03511 }
03512 void wxLuaState::lua_PushString(const char* s)
03513 {
03514     wxCHECK_RET(Ok(), wxT("Invalid wxLuaState"));
03515     lua_pushstring(M_WXLSTATEDATA->m_lua_State, s);
03516 }
03517 void wxLuaState::lua_PushCClosure(lua_CFunction fn, int n)
03518 {
03519     wxCHECK_RET(Ok(), wxT("Invalid wxLuaState"));
03520     lua_pushcclosure(M_WXLSTATEDATA->m_lua_State, fn, n);
03521 }
03522 void wxLuaState::lua_PushBoolean(bool b)
03523 {
03524     wxCHECK_RET(Ok(), wxT("Invalid wxLuaState"));
03525     lua_pushboolean(M_WXLSTATEDATA->m_lua_State, b ? 1 : 0);
03526 }
03527 void wxLuaState::lua_PushLightUserdata(void* p)
03528 {
03529     wxCHECK_RET(Ok(), wxT("Invalid wxLuaState"));
03530     lua_pushlightuserdata(M_WXLSTATEDATA->m_lua_State, p);
03531 }
03532 
03533 // ----------------------------------------------------------------------------
03534 // Raw Lua get functions (Lua -> stack)
03535 
03536 void wxLuaState::lua_GetTable(int idx)
03537 {
03538     wxCHECK_RET(Ok(), wxT("Invalid wxLuaState"));
03539     lua_gettable(M_WXLSTATEDATA->m_lua_State, idx);
03540 }
03541 void wxLuaState::lua_GetField(int idx, const char* k)
03542 {
03543     wxCHECK_RET(Ok(), wxT("Invalid wxLuaState"));
03544     lua_getfield(M_WXLSTATEDATA->m_lua_State, idx, k);
03545 }
03546 void wxLuaState::lua_RawGet(int idx)
03547 {
03548     wxCHECK_RET(Ok(), wxT("Invalid wxLuaState"));
03549     lua_rawget(M_WXLSTATEDATA->m_lua_State, idx);
03550 }
03551 void wxLuaState::lua_RawGeti(int idx, int n)
03552 {
03553     wxCHECK_RET(Ok(), wxT("Invalid wxLuaState"));
03554     lua_rawgeti(M_WXLSTATEDATA->m_lua_State, idx, n);
03555 }
03556 void wxLuaState::lua_CreateTable(int narr, int nrec)
03557 {
03558     wxCHECK_RET(Ok(), wxT("Invalid wxLuaState"));
03559     lua_createtable(M_WXLSTATEDATA->m_lua_State, narr, nrec);
03560 }
03561 void wxLuaState::lua_NewTable()
03562 {
03563     wxCHECK_RET(Ok(), wxT("Invalid wxLuaState"));
03564     lua_newtable(M_WXLSTATEDATA->m_lua_State);
03565 }
03566 void* wxLuaState::lua_NewUserdata(size_t sz)
03567 {
03568     wxCHECK_MSG(Ok(), NULL, wxT("Invalid wxLuaState"));
03569     return lua_newuserdata(M_WXLSTATEDATA->m_lua_State, sz);
03570 }
03571 int wxLuaState::lua_GetMetatable(int objindex)
03572 {
03573     wxCHECK_MSG(Ok(), 0, wxT("Invalid wxLuaState"));
03574     return lua_getmetatable(M_WXLSTATEDATA->m_lua_State, objindex);
03575 }
03576 void wxLuaState::lua_GetFenv(int idx)
03577 {
03578     wxCHECK_RET(Ok(), wxT("Invalid wxLuaState"));
03579     lua_getfenv(M_WXLSTATEDATA->m_lua_State, idx);
03580 }
03581 
03582 // -----------------------------------------------------------------------
03583 // Raw Lua set functions (stack -> Lua)
03584 
03585 void wxLuaState::lua_SetTable(int idx)
03586 {
03587     wxCHECK_RET(Ok(), wxT("Invalid wxLuaState"));
03588     lua_settable(M_WXLSTATEDATA->m_lua_State, idx);
03589 }
03590 void wxLuaState::lua_SetField(int idx, const char* k)
03591 {
03592     wxCHECK_RET(Ok(), wxT("Invalid wxLuaState"));
03593     lua_setfield(M_WXLSTATEDATA->m_lua_State, idx, k);
03594 }
03595 void wxLuaState::lua_RawSet(int idx)
03596 {
03597     wxCHECK_RET(Ok(), wxT("Invalid wxLuaState"));
03598     lua_rawset(M_WXLSTATEDATA->m_lua_State, idx);
03599 }
03600 void wxLuaState::lua_RawSeti(int idx, int n)
03601 {
03602     wxCHECK_RET(Ok(), wxT("Invalid wxLuaState"));
03603     lua_rawseti(M_WXLSTATEDATA->m_lua_State, idx, n);
03604 }
03605 int wxLuaState::lua_SetMetatable(int objindex)
03606 {
03607     wxCHECK_MSG(Ok(), 0, wxT("Invalid wxLuaState"));
03608     return lua_setmetatable(M_WXLSTATEDATA->m_lua_State, objindex);
03609 }
03610 int wxLuaState::lua_SetFenv(int idx)
03611 {
03612     wxCHECK_MSG(Ok(), 0, wxT("Invalid wxLuaState"));
03613     return lua_setfenv(M_WXLSTATEDATA->m_lua_State, idx);
03614 }
03615 
03616 // ----------------------------------------------------------------------------
03617 // Raw Lua `load' and `call' functions (load and run Lua code)
03618 
03619 void wxLuaState::lua_Call(int nargs, int nresults)
03620 {
03621     wxCHECK_RET(Ok(), wxT("Invalid wxLuaState"));
03622     lua_call(M_WXLSTATEDATA->m_lua_State, nargs, nresults);
03623 }
03624 int wxLuaState::lua_PCall(int nargs, int nresults, int errfunc)
03625 {
03626     wxCHECK_MSG(Ok(), 0, wxT("Invalid wxLuaState"));
03627     return lua_pcall(M_WXLSTATEDATA->m_lua_State, nargs, nresults, errfunc);
03628 }
03629 int wxLuaState::lua_CPCall(lua_CFunction func, void *ud)
03630 {
03631     wxCHECK_MSG(Ok(), 0, wxT("Invalid wxLuaState"));
03632     return lua_cpcall(M_WXLSTATEDATA->m_lua_State, func, ud);
03633 }
03634 int  wxLuaState::lua_Load(lua_Chunkreader reader, void *dt, const char* chunkname)
03635 {
03636     wxCHECK_MSG(Ok(), 0, wxT("Invalid wxLuaState"));
03637     return lua_load(M_WXLSTATEDATA->m_lua_State, reader, dt, chunkname);
03638 }
03639 int wxLuaState::lua_Dump(lua_Writer writer, void *data)
03640 {
03641     wxCHECK_MSG(Ok(), 0, wxT("Invalid wxLuaState"));
03642     return lua_dump(M_WXLSTATEDATA->m_lua_State, writer, data);
03643 }
03644 
03645 // ----------------------------------------------------------------------------
03646 // Raw Lua coroutine functions
03647 
03648 int wxLuaState::lua_Yield(int nresults)
03649 {
03650     wxCHECK_MSG(Ok(), 0, wxT("Invalid wxLuaState"));
03651     return lua_yield(M_WXLSTATEDATA->m_lua_State, nresults);
03652 }
03653 int wxLuaState::lua_Resume(int narg)
03654 {
03655     wxCHECK_MSG(Ok(), 0, wxT("Invalid wxLuaState"));
03656     return lua_resume(M_WXLSTATEDATA->m_lua_State, narg);
03657 }
03658 int wxLuaState::lua_Status()
03659 {
03660     wxCHECK_MSG(Ok(), 0, wxT("Invalid wxLuaState"));
03661     return lua_status(M_WXLSTATEDATA->m_lua_State);
03662 }
03663 
03664 // ----------------------------------------------------------------------------
03665 // Raw Lua garbage-collection functions
03666 
03667 int wxLuaState::lua_GetGCCount()
03668 {
03669     wxCHECK_MSG(Ok(), 0, wxT("Invalid wxLuaState"));
03670     return lua_getgccount(M_WXLSTATEDATA->m_lua_State);
03671 }
03672 
03673 // ----------------------------------------------------------------------------
03674 // Raw Lua miscellaneous functions
03675 
03676 wxString wxLuaState::lua_Version() const
03677 {
03678     return lua2wx(LUA_VERSION);
03679 }
03680 int wxLuaState::lua_Error()
03681 {
03682     wxCHECK_MSG(Ok(), 0, wxT("Invalid wxLuaState"));
03683     return lua_error(M_WXLSTATEDATA->m_lua_State);
03684 }
03685 int wxLuaState::lua_Next(int idx)
03686 {
03687     wxCHECK_MSG(Ok(), 0, wxT("Invalid wxLuaState"));
03688     return lua_next(M_WXLSTATEDATA->m_lua_State, idx);
03689 }
03690 void wxLuaState::lua_Concat(int n)
03691 {
03692     wxCHECK_RET(Ok(), wxT("Invalid wxLuaState"));
03693     lua_concat(M_WXLSTATEDATA->m_lua_State, n);
03694 }
03695 
03696 // -----------------------------------------------------------------------
03697 // Raw Lua some useful "macros", lua.h
03698 
03699 void wxLuaState::lua_Register(const char* funcName, lua_CFunction f)
03700 {
03701     wxCHECK_RET(Ok(), wxT("Invalid wxLuaState"));
03702     lua_register(M_WXLSTATEDATA->m_lua_State, funcName, f);
03703 }
03704 void wxLuaState::lua_PushCFunction(lua_CFunction f)
03705 {
03706     wxCHECK_RET(Ok(), wxT("Invalid wxLuaState"));
03707     lua_pushcfunction(M_WXLSTATEDATA->m_lua_State, f);
03708 }
03709 
03710 bool wxLuaState::lua_IsFunction(int idx) const
03711 {
03712     wxCHECK_MSG(Ok(), false, wxT("Invalid wxLuaState"));
03713     return lua_isfunction(M_WXLSTATEDATA->m_lua_State, idx);
03714 }
03715 bool wxLuaState::lua_IsTable(int idx) const
03716 {
03717     wxCHECK_MSG(Ok(), false, wxT("Invalid wxLuaState"));
03718     return lua_istable(M_WXLSTATEDATA->m_lua_State, idx);
03719 }
03720 bool wxLuaState::lua_IsLightUserdata(int idx) const
03721 {
03722     wxCHECK_MSG(Ok(), false, wxT("Invalid wxLuaState"));
03723     return lua_islightuserdata(M_WXLSTATEDATA->m_lua_State, idx);
03724 }
03725 bool wxLuaState::lua_IsNil(int idx) const
03726 {
03727     wxCHECK_MSG(Ok(), false, wxT("Invalid wxLuaState"));
03728     return lua_isnil(M_WXLSTATEDATA->m_lua_State, idx);
03729 }
03730 bool wxLuaState::lua_IsBoolean(int idx) const
03731 {
03732     wxCHECK_MSG(Ok(), false, wxT("Invalid wxLuaState"));
03733     return lua_isboolean(M_WXLSTATEDATA->m_lua_State, idx);
03734 }
03735 bool wxLuaState::lua_IsThread(int idx) const
03736 {
03737     wxCHECK_MSG(Ok(), false, wxT("Invalid wxLuaState"));
03738     return lua_isthread(M_WXLSTATEDATA->m_lua_State, idx);
03739 }
03740 bool wxLuaState::lua_IsNone(int idx) const
03741 {
03742     wxCHECK_MSG(Ok(), false, wxT("Invalid wxLuaState"));
03743     return lua_isnone(M_WXLSTATEDATA->m_lua_State, idx);
03744 }
03745 bool wxLuaState::lua_IsNoneOrNil(int idx) const
03746 {
03747     wxCHECK_MSG(Ok(), false, wxT("Invalid wxLuaState"));
03748     return lua_isnoneornil(M_WXLSTATEDATA->m_lua_State, idx);
03749 }
03750 
03751 void wxLuaState::lua_SetGlobal(const char* s)
03752 {
03753     wxCHECK_RET(Ok(), wxT("Invalid wxLuaState"));
03754     lua_setglobal(M_WXLSTATEDATA->m_lua_State, s);
03755 }
03756 void wxLuaState::lua_GetGlobal(const char* s)
03757 {
03758     wxCHECK_RET(Ok(), wxT("Invalid wxLuaState"));
03759     lua_getglobal(M_WXLSTATEDATA->m_lua_State, s);
03760 }
03761 
03762 // ----------------------------------------------------------------------------
03763 // Raw Lua Debug functions, lua.h
03764 
03765 int wxLuaState::lua_GetStack(int level, lua_Debug* ar)
03766 {
03767     wxCHECK_MSG(Ok(), 0, wxT("Invalid wxLuaState"));
03768     return lua_getstack(M_WXLSTATEDATA->m_lua_State, level, ar);
03769 }
03770 int wxLuaState::lua_GetInfo(const char* what, lua_Debug* ar)
03771 {
03772     wxCHECK_MSG(Ok(), 0, wxT("Invalid wxLuaState"));
03773     return lua_getinfo(M_WXLSTATEDATA->m_lua_State, what, ar);
03774 }
03775 const char* wxLuaState::lua_GetLocal(const lua_Debug* ar, int n)
03776 {
03777     wxCHECK_MSG(Ok(), NULL, wxT("Invalid wxLuaState"));
03778     return lua_getlocal(M_WXLSTATEDATA->m_lua_State, ar, n);
03779 }
03780 const char* wxLuaState::lua_SetLocal(const lua_Debug* ar, int n)
03781 {
03782     wxCHECK_MSG(Ok(), NULL, wxT("Invalid wxLuaState"));
03783     return lua_setlocal(M_WXLSTATEDATA->m_lua_State, ar, n);
03784 }
03785 const char* wxLuaState::lua_GetUpvalue(int funcindex, int n)
03786 {
03787     wxCHECK_MSG(Ok(), NULL, wxT("Invalid wxLuaState"));
03788     return lua_getupvalue(M_WXLSTATEDATA->m_lua_State, funcindex, n);
03789 }
03790 const char* wxLuaState::lua_SetUpvalue(int funcindex, int n)
03791 {
03792     wxCHECK_MSG(Ok(), NULL, wxT("Invalid wxLuaState"));
03793     return lua_setupvalue(M_WXLSTATEDATA->m_lua_State, funcindex, n);
03794 }
03795 
03796 int wxLuaState::lua_SetHook(lua_Hook func, int mask, int count)
03797 {
03798     wxCHECK_MSG(Ok(), 0, wxT("Invalid wxLuaState"));
03799     return lua_sethook(M_WXLSTATEDATA->m_lua_State, func, mask, count);
03800 }
03801 lua_Hook wxLuaState::lua_GetHook()
03802 {
03803     wxCHECK_MSG(Ok(), 0, wxT("Invalid wxLuaState"));
03804     return lua_gethook(M_WXLSTATEDATA->m_lua_State);
03805 }
03806 int wxLuaState::lua_GetHookMask()
03807 {
03808     wxCHECK_MSG(Ok(), 0, wxT("Invalid wxLuaState"));
03809     return lua_gethookmask(M_WXLSTATEDATA->m_lua_State);
03810 }
03811 int wxLuaState::lua_GetHookCount()
03812 {
03813     wxCHECK_MSG(Ok(), 0, wxT("Invalid wxLuaState"));
03814     return lua_gethookcount(M_WXLSTATEDATA->m_lua_State);
03815 }
03816 
03817 // ----------------------------------------------------------------------------
03818 // Raw Lua auxlib functions, lauxlib.h
03819 
03820 void wxLuaState::luaI_OpenLib(const char *libname, const luaL_reg *l, int nup)
03821 {
03822     wxCHECK_RET(Ok(), wxT("Invalid wxLuaState"));
03823     luaI_openlib(M_WXLSTATEDATA->m_lua_State, libname, l, nup);
03824 }
03825 void wxLuaState::luaL_Register(const char *libname, const luaL_reg *l)
03826 {
03827     wxCHECK_RET(Ok(), wxT("Invalid wxLuaState"));
03828     luaL_register(M_WXLSTATEDATA->m_lua_State, libname, l);
03829 }
03830 int wxLuaState::luaL_GetMetafield(int obj, const char *e)
03831 {
03832     wxCHECK_MSG(Ok(), 0, wxT("Invalid wxLuaState"));
03833     return luaL_getmetafield(M_WXLSTATEDATA->m_lua_State, obj, e);
03834 }
03835 int wxLuaState::luaL_CallMeta(int obj, const char *e)
03836 {
03837     wxCHECK_MSG(Ok(), 0, wxT("Invalid wxLuaState"));
03838     return luaL_callmeta(M_WXLSTATEDATA->m_lua_State, obj, e);
03839 }
03840 int wxLuaState::luaL_TypeError(int narg, const char *tname)
03841 {
03842     wxCHECK_MSG(Ok(), 0, wxT("Invalid wxLuaState"));
03843     return luaL_typerror(M_WXLSTATEDATA->m_lua_State, narg, tname);
03844 }
03845 int wxLuaState::luaL_ArgError(int numarg, const char *extramsg)
03846 {
03847     wxCHECK_MSG(Ok(), 0, wxT("Invalid wxLuaState"));
03848     return luaL_argerror(M_WXLSTATEDATA->m_lua_State, numarg, extramsg);
03849 }
03850 const char* wxLuaState::luaL_CheckLString(int numArg, size_t *l)
03851 {
03852     wxCHECK_MSG(Ok(), NULL, wxT("Invalid wxLuaState"));
03853     return luaL_checklstring(M_WXLSTATEDATA->m_lua_State, numArg, l);
03854 }
03855 const char* wxLuaState::luaL_OptLString(int numArg, const char *def, size_t *l)
03856 {
03857     wxCHECK_MSG(Ok(), NULL, wxT("Invalid wxLuaState"));
03858     return luaL_optlstring(M_WXLSTATEDATA->m_lua_State, numArg, def, l);
03859 }
03860 lua_Number wxLuaState::luaL_CheckNumber(int numArg)
03861 {
03862     wxCHECK_MSG(Ok(), 0, wxT("Invalid wxLuaState"));
03863     return luaL_checknumber(M_WXLSTATEDATA->m_lua_State, numArg);
03864 }
03865 lua_Number wxLuaState::luaL_OptNumber(int nArg, lua_Number def)
03866 {
03867     wxCHECK_MSG(Ok(), def, wxT("Invalid wxLuaState"));
03868     return luaL_optnumber(M_WXLSTATEDATA->m_lua_State, nArg, def);
03869 }
03870 lua_Integer wxLuaState::luaL_CheckInteger(int numArg)
03871 {
03872     wxCHECK_MSG(Ok(), 0, wxT("Invalid wxLuaState"));
03873     return luaL_checkinteger(M_WXLSTATEDATA->m_lua_State, numArg);
03874 }
03875 lua_Integer wxLuaState::luaL_OptInteger(int nArg, lua_Integer def)
03876 {
03877     wxCHECK_MSG(Ok(), def, wxT("Invalid wxLuaState"));
03878     return luaL_optinteger(M_WXLSTATEDATA->m_lua_State, nArg, def);
03879 }
03880 
03881 void wxLuaState::luaL_CheckStack(int sz, const char *msg)
03882 {
03883     wxCHECK_RET(Ok(), wxT("Invalid wxLuaState"));
03884     luaL_checkstack(M_WXLSTATEDATA->m_lua_State, sz, msg);
03885 }
03886 void wxLuaState::luaL_CheckType(int narg, int t)
03887 {
03888     wxCHECK_RET(Ok(), wxT("Invalid wxLuaState"));
03889     luaL_checktype(M_WXLSTATEDATA->m_lua_State, narg, t);
03890 }
03891 void wxLuaState::luaL_CheckAny(int narg)
03892 {
03893     wxCHECK_RET(Ok(), wxT("Invalid wxLuaState"));
03894     luaL_checkany(M_WXLSTATEDATA->m_lua_State, narg);
03895 }
03896 
03897 int   wxLuaState::luaL_NewMetatable(const char *tname)
03898 {
03899     wxCHECK_MSG(Ok(), 0, wxT("Invalid wxLuaState"));
03900     return luaL_newmetatable(M_WXLSTATEDATA->m_lua_State, tname);
03901 }
03902 void  wxLuaState::luaL_GetMetatable(const char *tname)
03903 {
03904     wxCHECK_RET(Ok(), wxT("Invalid wxLuaState"));
03905     luaL_getmetatable(M_WXLSTATEDATA->m_lua_State, tname);
03906 }
03907 void* wxLuaState::luaL_CheckUdata(int ud, const char *tname)
03908 {
03909     wxCHECK_MSG(Ok(), NULL, wxT("Invalid wxLuaState"));
03910     return luaL_checkudata(M_WXLSTATEDATA->m_lua_State, ud, tname);
03911 }
03912 
03913 void wxLuaState::luaL_Where(int lvl)
03914 {
03915     wxCHECK_RET(Ok(), wxT("Invalid wxLuaState"));
03916     luaL_where(M_WXLSTATEDATA->m_lua_State, lvl);
03917 }
03918 int wxLuaState::luaL_Error(const char *fmt, ...)
03919 {
03920     wxCHECK_MSG(Ok(), 0, wxT("Invalid wxLuaState"));
03921     return luaL_error(M_WXLSTATEDATA->m_lua_State, fmt);
03922 }
03923 
03924 int wxLuaState::luaL_CheckOption(int narg, const char *def, const char *const lst[])
03925 {
03926     wxCHECK_MSG(Ok(), 0, wxT("Invalid wxLuaState"));
03927     return luaL_checkoption(M_WXLSTATEDATA->m_lua_State, narg, def, lst);
03928 }
03929 
03930 int wxLuaState::luaL_Ref(int t)
03931 {
03932     wxCHECK_MSG(Ok(), 0, wxT("Invalid wxLuaState"));
03933     return luaL_ref(M_WXLSTATEDATA->m_lua_State, t);
03934 }
03935 void wxLuaState::luaL_Unref(int t, int ref)
03936 {
03937     wxCHECK_RET(Ok(), wxT("Invalid wxLuaState"));
03938     luaL_unref(M_WXLSTATEDATA->m_lua_State, t, ref);
03939 }
03940 
03941 int wxLuaState::luaL_LoadFile(const char *filename)
03942 {
03943     wxCHECK_MSG(Ok(), 0, wxT("Invalid wxLuaState"));
03944     return luaL_loadfile(M_WXLSTATEDATA->m_lua_State, filename);
03945 }
03946 int wxLuaState::luaL_LoadBuffer(const char *buff, size_t sz, const char *name)
03947 {
03948     wxCHECK_MSG(Ok(), 0, wxT("Invalid wxLuaState"));
03949     return luaL_loadbuffer(M_WXLSTATEDATA->m_lua_State, buff, sz, name);
03950 }
03951 int wxLuaState::luaL_LoadString(const char *s)
03952 {
03953     wxCHECK_MSG(Ok(), 0, wxT("Invalid wxLuaState"));
03954     return luaL_loadstring(M_WXLSTATEDATA->m_lua_State, s);
03955 }
03956 
03957 void wxLuaState::luaL_ArgCheck(bool condition, int numarg, const char* extramsg)
03958 {
03959     wxCHECK_RET(Ok(), wxT("Invalid wxLuaState"));
03960     luaL_argcheck(M_WXLSTATEDATA->m_lua_State, condition, numarg, extramsg);
03961 }
03962 const char* wxLuaState::luaL_CheckString(int numArg)
03963 {
03964     wxCHECK_MSG(Ok(), NULL, wxT("Invalid wxLuaState"));
03965     return luaL_checkstring(M_WXLSTATEDATA->m_lua_State, numArg);
03966 }
03967 const char* wxLuaState::luaL_OptString(int numArg, const char* def)
03968 {
03969     wxCHECK_MSG(Ok(), NULL, wxT("Invalid wxLuaState"));
03970     return luaL_optstring(M_WXLSTATEDATA->m_lua_State, numArg, def);
03971 }
03972 int wxLuaState::luaL_CheckInt(int numArg)
03973 {
03974     wxCHECK_MSG(Ok(), 0, wxT("Invalid wxLuaState"));
03975     return (int)luaL_checkint(M_WXLSTATEDATA->m_lua_State, numArg);
03976 }
03977 int wxLuaState::luaL_OptInt(int numArg, int def)
03978 {
03979     wxCHECK_MSG(Ok(), 0, wxT("Invalid wxLuaState"));
03980     return (int)luaL_optint(M_WXLSTATEDATA->m_lua_State, numArg, def);
03981 }
03982 long wxLuaState::luaL_CheckLong(int numArg)
03983 {
03984     wxCHECK_MSG(Ok(), 0, wxT("Invalid wxLuaState"));
03985     return (long)luaL_checklong(M_WXLSTATEDATA->m_lua_State, numArg);
03986 }
03987 long wxLuaState::luaL_OptLong(int numArg, int def)
03988 {
03989     wxCHECK_MSG(Ok(), 0, wxT("Invalid wxLuaState"));
03990     return (long)luaL_optlong(M_WXLSTATEDATA->m_lua_State, numArg, def);
03991 }
03992 
03993 // ----------------------------------------------------------------------------
03994 // others
03995 
03996 void wxLuaState::GetGlobals()
03997 {
03998     wxCHECK_RET(Ok(), wxT("Invalid wxLuaState"));
03999     lua_pushvalue(M_WXLSTATEDATA->m_lua_State, LUA_GLOBALSINDEX);
04000 }
04001 
04002 #define LUA_PATH "LUA_PATH"
04003 
04004 // get LUA_PATH
04005 wxString wxLuaState::GetLuaPath()
04006 {
04007     wxCHECK_MSG(Ok(), wxEmptyString, wxT("Invalid wxLuaState"));
04008     lua_GetGlobal(LUA_PATH);
04009     wxString path = lua_TowxString(-1);
04010     lua_Pop(1);
04011 
04012     return path;
04013 }
04014 
04015 // add path list to LUA_PATH
04016 void wxLuaState::AddLuaPath(const wxPathList& pathlist)
04017 {
04018     size_t i, count = pathlist.GetCount();
04019     for (i = 0; i < count; ++i)
04020     {
04021         wxFileName fname(pathlist[i]);
04022         AddLuaPath(fname);
04023     }
04024 }
04025 
04026 // add filename path to LUA_PATH
04027 void wxLuaState::AddLuaPath(const wxFileName& filename)
04028 {
04029     wxFileName fname = filename;
04030     fname.SetName(wxT("?"));
04031     fname.SetExt(wxT("lua"));
04032 
04033     wxString path    = fname.GetFullPath();
04034     wxString luapath = GetLuaPath();
04035 
04036     // check if path
04037     wxStringTokenizer tkz(luapath, wxT(";"));
04038     while (tkz.HasMoreTokens())
04039     {
04040         wxString token = tkz.GetNextToken();
04041 
04042         if ((token == path) || (!wxFileName::IsCaseSensitive() && token.CmpNoCase(path) == 0))
04043             return;
04044     }
04045 
04046     // append separator
04047     if (!luapath.IsEmpty() && (luapath.Last() != wxT(';')))
04048         luapath += wxT(';');
04049 
04050     // append path
04051     luapath += path + wxT(';');
04052 
04053     lua_PushString(luapath);
04054     lua_SetGlobal(LUA_PATH);
04055 }
04056 
04057 //-----------------------------------------------------------------------------
04058 // wxLuaEvent
04059 //-----------------------------------------------------------------------------
04060 
04061 DEFINE_LOCAL_EVENT_TYPE(wxEVT_LUA_CREATION)
04062 DEFINE_LOCAL_EVENT_TYPE(wxEVT_LUA_PRINT)
04063 DEFINE_LOCAL_EVENT_TYPE(wxEVT_LUA_ERROR)
04064 DEFINE_LOCAL_EVENT_TYPE(wxEVT_LUA_DEBUG_HOOK)
04065 //DEFINE_LOCAL_EVENT_TYPE(wxEVT_LUA_INIT)
04066 //DEFINE_LOCAL_EVENT_TYPE(wxEVT_LUA_DEBUGGERATTACHED)
04067 
04068 wxLuaEvent::wxLuaEvent(wxEventType commandType, wxWindowID id, const wxLuaState& wxlState)
04069            :wxNotifyEvent(commandType, id),  m_wxlState(wxlState),
04070             m_debug_hook_break(false),
04071             m_lua_Debug(NULL)
04072 {
04073 }
04074 
04075 wxLuaEvent::wxLuaEvent( const wxLuaEvent &event )
04076            :wxNotifyEvent(event), m_wxlState(event.m_wxlState),
04077             m_debug_hook_break(event.m_debug_hook_break),
04078             m_lua_Debug(event.m_lua_Debug)
04079 {
04080 }
04081 
04082 
04083 //-----------------------------------------------------------------------------
04084 // bitlib release 25 - Bitwise operations library
04085 // by Reuben Thomas <rrt@sc3d.org>
04086 // http://luaforge.net/projects/bitlib
04087 // copyright Reuben Thomas 2000-2008, and is released under the MIT license
04088 //-----------------------------------------------------------------------------
04089 
04090 // This is the code copied directly from lbitlib.c and ever so slightly modified
04091 // to allow it to work here.
04092 
04093 /* Bitwise operations library */
04094 /* (c) Reuben Thomas 2000-2008 */
04095 /* See README for license */
04096 
04097 //#include "config.h"
04098 
04099 //#include <lua.h>
04100 //#include <lauxlib.h>
04101 #include <limits.h>
04102 
04103 //#include "bit_limits.h"
04104 #define BITLIB_FLOAT_BITS 53
04105 #define BITLIB_FLOAT_MAX  0xfffffffffffffL
04106 #define BITLIB_FLOAT_MIN  (-0x10000000000000L)
04107 #if defined(__VISUALC__)
04108     #define BITLIB_FLOAT_UMAX 0x1fffffffffffffUL
04109 #else
04110     #define BITLIB_FLOAT_UMAX 0x1fffffffffffffULL
04111 #endif
04112 
04113 /* FIXME: Assume lua_Integer is ptrdiff_t */
04114 #define LUA_INTEGER_MAX PTRDIFF_MAX
04115 #define LUA_INTEGER_MIN PTRDIFF_MIN
04116 
04117 #ifndef SIZE_MAX
04118 #define SIZE_MAX ((size_t)-1)
04119 #endif
04120 
04121 /* FIXME: Assume size_t is an unsigned lua_Integer */
04122 typedef size_t lua_UInteger;
04123 #define LUA_UINTEGER_MAX SIZE_MAX
04124 
04125 
04126 /* Bit type size and limits */
04127 
04128 #define BIT_BITS                                                        \
04129   (CHAR_BIT * sizeof(lua_Integer) > BITLIB_FLOAT_BITS ?                 \
04130    BITLIB_FLOAT_BITS : (CHAR_BIT * sizeof(lua_Integer)))
04131 
04132 /* This code may give warnings if BITLIB_FLOAT_* are too big to fit in
04133    long, but that doesn't matter since in that case they won't be
04134    used. */
04135 #define BIT_MAX                                                         \
04136   (CHAR_BIT * sizeof(lua_Integer) > BITLIB_FLOAT_BITS ? BITLIB_FLOAT_MAX : LUA_INTEGER_MAX)
04137 
04138 #define BIT_MIN                                                         \
04139   (CHAR_BIT * sizeof(lua_Integer) > BITLIB_FLOAT_BITS ? BITLIB_FLOAT_MIN : LUA_INTEGER_MIN)
04140 
04141 #define BIT_UMAX                                                        \
04142   (CHAR_BIT * sizeof(lua_Integer) > BITLIB_FLOAT_BITS ? BITLIB_FLOAT_UMAX : LUA_UINTEGER_MAX)
04143 
04144 
04145 #define BUILTIN_CAST
04146 
04147 /* Define TOBIT to get a bit value */
04148 #ifdef BUILTIN_CAST
04149 #define TOBIT(L, n, res)                    \
04150   ((void)(res), luaL_checkinteger((L), (n)))
04151 #else
04152 #include <stdint.h>
04153 #include <math.h>
04154 
04155 /* FIXME: Assume lua_Number fits in a double (use of fmod). */
04156 #define TOBIT(L, n, res)                                            \
04157   ((lua_Integer)(((res) = fmod(luaL_checknumber(L, (n)), (double)BIT_UMAX + 1.0)), \
04158                  (res) > BIT_MAX ? ((res) -= (double)BIT_UMAX, (res) -= 1) : \
04159                  ((res) < BIT_MIN ? ((res) += (double)BIT_UMAX, (res) += 1) : (res))))
04160 #endif
04161 
04162 
04163 #define BIT_TRUNCATE(i)                         \
04164   ((i) & BIT_UMAX)
04165 
04166 /* Operations
04167 
04168    The macros MONADIC and VARIADIC only deal with bitwise operations.
04169 
04170    LOGICAL_SHIFT truncates its left-hand operand before shifting so
04171    that any extra bits at the most-significant end are not shifted
04172    into the result.
04173 
04174    ARITHMETIC_SHIFT does not truncate its left-hand operand, so that
04175    the sign bits are not removed and right shift work properly.
04176    */
04177 
04178 #define MONADIC(name, op)                                       \
04179   static int bit_ ## name(lua_State *L) {                       \
04180     lua_Number f;                                               \
04181     lua_pushinteger(L, BIT_TRUNCATE(op TOBIT(L, 1, f)));        \
04182     return 1;                                                   \
04183   }
04184 
04185 #define VARIADIC(name, op)                      \
04186   static int bit_ ## name(lua_State *L) {       \
04187     lua_Number f;                               \
04188     int n = lua_gettop(L), i;                   \
04189     lua_Integer w = TOBIT(L, 1, f);             \
04190     for (i = 2; i <= n; i++)                    \
04191       w op TOBIT(L, i, f);                      \
04192     lua_pushinteger(L, BIT_TRUNCATE(w));        \
04193     return 1;                                   \
04194   }
04195 
04196 #define LOGICAL_SHIFT(name, op)                                         \
04197   static int bit_ ## name(lua_State *L) {                               \
04198     lua_Number f;                                                       \
04199     lua_pushinteger(L, BIT_TRUNCATE(BIT_TRUNCATE((lua_UInteger)TOBIT(L, 1, f)) op \
04200                                     (unsigned)luaL_checknumber(L, 2))); \
04201     return 1;                                                           \
04202   }
04203 
04204 #define ARITHMETIC_SHIFT(name, op)                                      \
04205   static int bit_ ## name(lua_State *L) {                               \
04206     lua_Number f;                                                       \
04207     lua_pushinteger(L, BIT_TRUNCATE((lua_Integer)TOBIT(L, 1, f) op      \
04208                                     (unsigned)luaL_checknumber(L, 2))); \
04209     return 1;                                                           \
04210   }
04211 
04212 MONADIC(cast,  +)
04213 MONADIC(bnot,  ~)
04214 VARIADIC(band, &=)
04215 VARIADIC(bor,  |=)
04216 VARIADIC(bxor, ^=)
04217 ARITHMETIC_SHIFT(lshift,  <<)
04218 LOGICAL_SHIFT(rshift,     >>)
04219 ARITHMETIC_SHIFT(arshift, >>)
04220 
04221 static const struct luaL_reg bitlib[] = {
04222   {"cast",    bit_cast},
04223   {"bnot",    bit_bnot},
04224   {"band",    bit_band},
04225   {"bor",     bit_bor},
04226   {"bxor",    bit_bxor},
04227   {"lshift",  bit_lshift},
04228   {"rshift",  bit_rshift},
04229   {"arshift", bit_arshift},
04230 
04231   {NULL, NULL}
04232 };
04233 
04234 int LUACALL luaopen_bit (lua_State *L) {
04235   luaL_register(L, "bit", bitlib);
04236   lua_pushnumber(L, BIT_BITS);
04237   lua_setfield(L, -2, "bits");
04238   return 1;
04239 }
Generated on Tue Jul 13 10:30:39 2010 for wxLua by  doxygen 1.6.3