
Contents of /wx-0.5/handcoded.cc:
// wxhello.cpp
// Version using dynamic event routing
// Robert Roebling, Martin Bernreuther
#include <wx/wx.h>
/*
wxPike - (c) 2005 Julio César Gázquez
handcoded.cc:
Wrapper functions implemented by hand for main functionality
*/
#include "wx.h"
#include <iostream>
/*
Functions that interface with Pike needs C interfaces
*/
extern "C" {
void f_wxEvent__m_callbackUserData(INT32 args);
void f_wxEvent__GetEventObject(INT32 args);
void f_wxEvtHandler__Connect(INT32 args);
void f_wxGetApp(INT32 args);
void f_implement_app(INT32 args);
}
extern struct program* wxEvent_program;
extern struct program* wxApp_program;
struct svalue app_program;
struct object *app_object=NULL;
/*
Event handling
*/
// used to be public wxObject for wx 2.4, but 2.5.4 changed
// the class for function callbacks to wxEvtHandler
class WXDLLEXPORT ThunkObject : public wxEvtHandler
{
private:
struct svalue method;
struct object* eventObject;
struct object* data;
public:
ThunkObject(struct svalue* method, struct object* eventObject, struct object* data);
~ThunkObject();
void eventThunker(wxEvent& event);
void run(wxEvent& event);
struct object* getObject() { return eventObject; };
struct object* getData() { return data; };
};
ThunkObject::ThunkObject(struct svalue* method, struct object* eventObject, struct object* data)
{
assign_svalue_no_free(&(this->method),method);
// eventObject != NULL!!!
this->eventObject=eventObject;
add_ref(eventObject);
if (data) {
this->data=data;
add_ref(data);
}
}
ThunkObject::~ThunkObject()
{
free_svalue(&(this->method));
free_object(eventObject);
if (data)
free_object(data);
}
void ThunkObject::eventThunker(wxEvent& event)
{
ThunkObject* thunk=static_cast<ThunkObject*>(event.m_callbackUserData);
thunk->run(event);
}
void ThunkObject::run(wxEvent& event)
{
// The next block allows to return a different wrappers
// according the exact wxEvent subclass
const char *pn=event.GetClassInfo()->GetClassName();
push_constant_text("wx.");
push_text(pn+2);
f_add(2);
push_constant_text("-");
APPLY_MASTER("resolv", 2);
if (Pike_sp[-1].type == PIKE_T_PROGRAM) {
struct program *p = Pike_sp[-1].u.program;
struct object *o = low_clone( p );
call_c_initializers( o );
static_cast<wxEvent*>(STORAGE(o,wxEvent)->cppobject)=&event;
STORAGE(o,wxEvent)->foreign=true;
push_object( o );
apply_svalue(&(this->method),1);
} else {
std::cout << "Event casting failed!\n";
struct object *o = low_clone( wxEvent_program );
call_c_initializers( o );
static_cast<wxEvent*>(STORAGE(o,wxEvent)->cppobject)=&event;
STORAGE(o,wxEvent)->foreign=true;
push_object( o );
apply_svalue(&(this->method),1);
}
}
// Do not expose C++ thunk but Pike object as data to the Pike side
void f_wxEvent__m_callbackUserData(INT32 args)
{
pop_n_elems(args);
struct object *o = static_cast<ThunkObject*>(static_cast<wxEvent*>(THIS->cppobject)->m_callbackUserData)->getData();
if (o)
ref_push_object( o );
else
push_undefined();
}
// For returning always the same wrapper. Maybe redundant with proper generator code, though.
void f_wxEvent__GetEventObject(INT32 args)
{
pop_n_elems(args);
struct object *o = static_cast<ThunkObject*>(static_cast<wxEvent*>(THIS->cppobject)->m_callbackUserData)->getObject();
ref_push_object( o );
}
void f_wxEvtHandler__Connect(INT32 args)
{
/*
int id;
wxEventType eventType;
get_all_args("Connect", args, "%d.%d", &id, &eventType);
*/
if (args<3)
SIMPLE_TOO_FEW_ARGS_ERROR("Connect",3);
if (Pike_sp[0-args].type!=T_INT)
SIMPLE_BAD_ARG_ERROR("Connect",0,"int");
INT_TYPE id = Pike_sp[0-args].u.integer;
if (Pike_sp[1-args].type!=T_INT)
SIMPLE_BAD_ARG_ERROR("Connect",1,"int");
wxEventType eventType = Pike_sp[1-args].u.integer;
if (Pike_sp[2-args].type!=T_FUNCTION)
SIMPLE_BAD_ARG_ERROR("Connect",2,"function");
struct svalue* method=&Pike_sp[2-args];
object* data;
if (args<4)
data=NULL;
else {
if (Pike_sp[3-args].type!=T_OBJECT)
SIMPLE_BAD_ARG_ERROR("Connect",3,"object");
data=Pike_sp[3-args].u.object;
}
ThunkObject* thunk = new ThunkObject(method,Pike_fp->current_object,data);
static_cast<wxEvtHandler*>(THIS->cppobject)
->Connect(id, eventType, static_cast<wxObjectEventFunction>(&ThunkObject::eventThunker), thunk );
pop_n_elems(args);
}
/*
wxWidgets startup
*/
#if wxMINOR_VERSION == 4
wxApp *wxCreateApp()
{
wxApp::CheckBuildOptions(wxBuildOptions());
apply_svalue( &app_program, 0 );
app_object = Pike_sp[-1].u.object;
add_ref(app_object);
pop_stack();
return (wxApp*)
( (struct wrapper_storage*)get_storage(app_object,app_object->prog)) ->cppobject;
}
#else
wxAppConsole *wxCreateApp()
{
wxAppConsole::CheckBuildOptions(WX_BUILD_OPTIONS_SIGNATURE,
"your program");
apply_svalue( &app_program, 0 );
app_object = Pike_sp[-1].u.object;
add_ref(app_object);
pop_stack();
return (wxApp*)
( (struct wrapper_storage*)get_storage(app_object,app_object->prog)) ->cppobject;
}
#endif
wxAppInitializer wxTheAppInitializer((wxAppInitializerFunction) wxCreateApp);
wxApp__pv& wxGetApp()
{
#if wxMINOR_VERSION == 4
return *(wxApp__pv *)wxTheApp;
#else
return *(wxApp__pv *)((wxApp *)wxApp::GetInstance());
#endif
}
void f_wxGetApp(INT32 args)
{
if (args!=0)
SIMPLE_TOO_FEW_ARGS_ERROR("wxGetApp",1);
if (app_object)
ref_push_object( app_object );
else
push_undefined();
}
void f_implement_app(INT32 args)
{
if (args<1)
SIMPLE_TOO_FEW_ARGS_ERROR("implement_app",1);
if (Pike_sp[0-args].type!=T_FUNCTION)
SIMPLE_BAD_ARG_ERROR("implement_app",0,"program");
assign_svalue_no_free(&app_program,&Pike_sp[0-args]);
pop_n_elems(args);
// Allocar aqui el argv (o bien ver de tomarlo directamente del
// argv de Pike y no pedir parámetros
static int argc=1;
char *argv[] ={ "wxPike" };
int r=wxEntry(argc, argv);
if (r<0) r=0;
push_int(r);
}