/***********************************************************************
* FXRuby -- the Ruby language bindings for the FOX GUI toolkit.
* Copyright (c) 2001-2009 by Lyle Johnson. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* For further information please contact the author by e-mail
* at "[email protected]".
***********************************************************************/
/***********************************************************************
* $Id: FXRuby.cpp 2933 2008-12-29 20:19:33Z lyle $
***********************************************************************/
#ifdef _MSC_VER
#pragma warning (disable : 4786)
#endif
#include "FXRbCommon.h"
#include "FXRbObjRegistry.h"
#include "impl.h"
// SWIG runtime functions we need
#include "swigruby.h"
#ifdef __CYGWIN__
#include <io.h> // for get_osf_handle()
#endif
#ifdef HAVE_SIGNAL_H
#include <signal.h> // for definitions of SIGINT, etc.
#endif
#include "ruby/io.h"
#include "ruby/st.h"
// Opaque type declaration from SWIG runtime
struct swig_type_info;
static int FXSWIG_ConvertPtr(VALUE obj, void **ptr, swig_type_info *ty, int flags){
return SWIG_ConvertPtr(obj, ptr, ty, flags);
}
// Wrapper around SWIG_TypeQuery() that caches results for performance
swig_type_info *FXRbTypeQuery(const char *desc){
FXASSERT(desc!=0);
static st_table *types=st_init_strtable();
swig_type_info *typeinfo=0;
if(st_lookup(types,reinterpret_cast<st_data_t>(const_cast<char*>(desc)),reinterpret_cast<st_data_t *>(&typeinfo))==0){
typeinfo=SWIG_TypeQuery(desc);
st_insert(types,reinterpret_cast<st_data_t>(strdup(desc)),reinterpret_cast<st_data_t>(typeinfo));
}
FXASSERT(typeinfo!=0);
return typeinfo;
}
VALUE FXRbNewPointerObj(void *ptr,swig_type_info* ty){
return FXRbObjRegistry::main.NewBorrowedObj(ptr,ty);
}
VALUE FXRbNewPointerObjCb(void *ptr,swig_type_info* ty){
return SWIG_Ruby_NewPointerObj(ptr, ty, 1);
}
/**
* FXRbIsBorrowed() returns true if the specified C++ object is one that
* FOX owns (i.e. it's borrowed).
*/
bool FXRbIsBorrowed(void* ptr){
return FXRbObjRegistry::main.IsBorrowed(ptr);
}
bool FXRbSetInGC(const void* ptr, bool enabled){
return FXRbObjRegistry::main.SetInGC(ptr, enabled);
}
bool FXRbIsInGC(const void* ptr){
return FXRbObjRegistry::main.IsInGC(ptr);
}
// Register this Ruby class instance
void FXRbRegisterRubyObj(VALUE rubyObj,const void* foxObj) {
return FXRbObjRegistry::main.RegisterRubyObj(rubyObj, foxObj);
}
static void FXRbUnregisterRubyObj2(const void* foxObj, bool alsoOwned){
return FXRbObjRegistry::main.UnregisterRubyObj(foxObj, alsoOwned);
}
/**
* Remove this mapping between a Ruby instance and a C++ object
*/
void FXRbUnregisterRubyObj(const void* foxObj){
FXRbUnregisterRubyObj2(foxObj, true);
}
/* We now have 3 types of FXObject wrappers:
*
* Own objects :
* These objects are allocated by FXRuby on the heap.
* They are free'd when the FXRuby wrapper is GC'ed and no other reference to the object exists.
* They are registered in FXRbObjRegistry as owned object.
* They are built per FXRbRegisterRubyObj().
*
* Borrowed objects :
* These objects are allocated by libfox on the heap.
* They are free'd by libfox when the owning fox object gets destroyed.
* Only the ruby wrapper is GC'ed.
* They are registered in FXRbObjRegistry as borrowed object.
* They are built per FXGetRubyObj().
*
* Callback objects :
* This is the new type.
* These objects are allocated by libfox on the heap or on the stack.
* They are wrapped for the time of one callback only, because stack memory is free'd afterwards.
* They are not registered in FXRbObjRegistry, but stored on the stack only.
* Therefore callback objects aren't re-used, but newly wrapped for each call.
* The same goes for arguments to ruby blocks.
* They are built per FXGetRubyObjCb().
*/
/**
* Return the registered Ruby class instance associated with this
* FOX object, or Qnil if not found.
*/
VALUE FXRbGetRubyObj(const void *foxObj,bool alsoBorrowed, bool in_gc_mark){
return FXRbObjRegistry::main.GetRubyObj(foxObj, alsoBorrowed, in_gc_mark);
}
/**
* Return the registered Ruby class instance associated with this
* FOX object, or a new registered instance of a borrowed object if not found.
*
* This is suitable for objects on the heap, but not suitable for callbacks,
* because callback values might be on the stack.
* These stack objects should not be registered, because they are temporary only.
*/
VALUE FXRbGetRubyObj(const void *foxObj,swig_type_info* ty){
if(foxObj!=0){
VALUE rbObj=FXRbGetRubyObj(foxObj,true);
if( NIL_P(rbObj) ){
return FXRbNewPointerObj(const_cast<void*>(foxObj),ty);
}else{
// The requested type should match the registered class.
FXASSERT(SWIG_CheckConvert(rbObj, ty));
return rbObj;
}
}else{
return Qnil;
}
}
VALUE FXRbGetRubyObj(const void *foxObj,const char *type){
return FXRbGetRubyObj(foxObj, FXRbTypeQuery(type));
}
/* Get an already registered object or wrap a new one for use in a callback.
*
* This is suitable for objects on the heap or on the stack.
* If an object is already registered per FXRbGetRubyObj(), this instance is returned.
* If it is not registered, a new wrapping object is built and returned, but is not registered.
*/
VALUE FXRbGetRubyObjCb(const void *foxObj,swig_type_info* ty){
if(foxObj!=0){
VALUE rbObj=FXRbGetRubyObj(foxObj, true);
if( NIL_P(rbObj) ){
return FXRbNewPointerObjCb(const_cast<void*>(foxObj), ty);
}else{
// The requested type should match the registered class.
FXASSERT(SWIG_CheckConvert(rbObj, ty));
return rbObj;
}
}else{
return Qnil;
}
}
static VALUE to_ruby_obj(const FXObject* obj, VALUE (*get_value)(const void*, swig_type_info*)){
if(obj){
FXString className = obj->getClassName();
if(className.length() > 3){
if(className.left(4)=="FXRb"){ className.replace(0,4,"FX"); }
}
FXString desc = className+" *";
return get_value(obj, FXRbTypeQuery(desc.text()));
}
return Qnil;
}
VALUE to_ruby(const FXObject* obj){
return to_ruby_obj(obj, FXRbGetRubyObj);
}
VALUE to_ruby_cb(const FXObject* obj){
return to_ruby_obj(obj, FXRbGetRubyObjCb);
}
/**
* Look up the Ruby instance associated with this C++ object, if any, and mark
* that instance as in use.
*
* We previously only marked those Ruby instances that were "non-borrowed"
* references to C++ objects, as a way to reduce the number of Ruby instances
* on the heap.
*/
void FXRbGcMark(void *obj){
if(obj){
/**
* If the 2nd argument to FXRbGetRubyObj() is false, we only mark
* non-borrowed references. This has led to problems in the past
* (see e.g. SourceForge Bug #703721). I think the correct solution
* is to mark any Ruby reference this object, "borrowed" or not;
* so the 2nd argument to FXRbGetRubyObj() is now true.
*
* If you feel compelled to change this back to FXGetRubyObj(obj,false),
* please think about it first. Especially make sure that the shutter.rb
* example program works if you invoke the GC in ShutterWindow#create;
* make sure that the shutter items' contents don't get blown away!
*/
VALUE value=FXRbGetRubyObj(obj, true, true);
if(!NIL_P(value)){
rb_gc_mark(value);
}
}
}
//----------------------------------------------------------------------
// Returns a Ruby array of floats
VALUE FXRbMakeArray(const FXfloat* values,FXint size){
VALUE result=rb_ary_new();
for(FXint i=0; i<size; i++)
rb_ary_push(result,rb_float_new(values[i]));
return result;
}
// Returns a Ruby array of floats
VALUE FXRbMakeArray(const FXdouble* values,FXint size){
VALUE result=rb_ary_new();
for(FXint i=0; i<size; i++)
rb_ary_push(result,rb_float_new(values[i]));
return result;
}
// Returns a Ruby array of integers
VALUE FXRbMakeArray(const FXint* values,FXint size){
VALUE result=rb_ary_new();
for(FXint i=0; i<size; i++)
rb_ary_push(result,INT2NUM(values[i]));
return result;
}
// Returns a Ruby array of integers
VALUE FXRbMakeArray(const FXuint* values,FXint size){
VALUE result=rb_ary_new();
for(FXint i=0; i<size; i++)
rb_ary_push(result,UINT2NUM(values[i]));
return result;
}
// Returns a Ruby array of integers
VALUE FXRbMakeArray(const FXchar* dashpattern,FXuint dashlength){
VALUE result=rb_ary_new();
for(FXuint i=0; i<dashlength; i++)
rb_ary_push(result,INT2NUM(dashpattern[i]));
return result;
}
// Returns a Ruby array of FXArcs
VALUE FXRbMakeArray(const FXArc* arcs,FXuint narcs){
VALUE result=rb_ary_new();
for(FXuint i=0; i<narcs; i++)
rb_ary_push(result, FXRbNewPointerObjCb(const_cast<FXArc*>(&arcs[i]), FXRbTypeQuery("FXArc *")));
return result;
}
// Returns a Ruby array of FXPoints
VALUE FXRbMakeArray(const FXPoint* points,FXuint npoints){
VALUE result=rb_ary_new();
for(FXuint i=0; i<npoints; i++)
rb_ary_push(result,FXRbNewPointerObjCb(const_cast<FXPoint*>(&points[i]), FXRbTypeQuery("FXPoint *")));
return result;
}
// Returns a Ruby array of FXRectangles
VALUE FXRbMakeArray(const FXRectangle* rectangles,FXuint nrectangles){
VALUE result=rb_ary_new();
for(FXuint i=0; i<nrectangles; i++)
rb_ary_push(result,FXRbNewPointerObjCb(const_cast<FXRectangle*>(&rectangles[i]), FXRbTypeQuery("FXRectangle *")));
return result;
}
// Returns a Ruby array of FXSegments
VALUE FXRbMakeArray(const FXSegment* segments,FXuint nsegments){
VALUE result=rb_ary_new();
for(FXuint i=0; i<nsegments; i++)
rb_ary_push(result,FXRbNewPointerObjCb(const_cast<FXSegment*>(&segments[i]), FXRbTypeQuery("FXSegment *")));
return result;
}
// Returns a Ruby array of FXColor values
VALUE FXRbMakeColorArray(const FXColor* colors,FXint w,FXint h){
VALUE result=rb_ary_new();
FXuint size=w*h;
for(FXuint i=0; i<size; i++)
rb_ary_push(result,to_ruby(colors[i]));
return result;
}
FXuint FXRbNumberOfFXColors(VALUE string_or_ary){
FXuint len;
if(TYPE(string_or_ary) == T_ARRAY){
len = RARRAY_LEN(string_or_ary);
}else{
Check_Type(string_or_ary,T_STRING);
if(RSTRING_LEN(string_or_ary) % sizeof(FXColor) != 0 )
rb_raise( rb_eArgError, "String size is no multiple of %lu", sizeof(FXColor) );
len = RSTRING_LEN(string_or_ary) / sizeof(FXColor);
}
return len;
}
FXColor *FXRbConvertToFXColors(VALUE string_or_ary, FXuint *opts){
FXColor* pix=0;
if(TYPE(string_or_ary) == T_ARRAY){
if(FXMALLOC(&pix,FXColor,RARRAY_LEN(string_or_ary))){
*opts |= IMAGE_OWNED;
for(long i=0; i<RARRAY_LEN(string_or_ary); i++){
pix[i]=static_cast<FXColor>(NUM2UINT(rb_ary_entry(string_or_ary,i)));
}
}
}else{
if( *opts & IMAGE_OWNED ){
if(FXMALLOC(&pix,FXColor,RSTRING_LEN(string_or_ary)/sizeof(FXColor))){
memcpy(pix, RSTRING_PTR(string_or_ary), RSTRING_LEN(string_or_ary));
}
}else{
rb_str_modify(string_or_ary);
pix = (FXColor*)(RSTRING_PTR(string_or_ary));
}
}
return pix;
}
//----------------------------------------------------------------------
/**
* Based on the sender object's class and the selector, convert the message
* data stored in the void pointer (ptr) to a suitable Ruby object.
*
* This function is used when we need to pass message data into a Ruby
* code block (or method) that is acting as a FOX message handler.
*/
static VALUE FXRbConvertMessageData(FXObject* sender,FXObject* recv,FXSelector sel,void* ptr){
FXTRACE((1,"FXRbConvertMessageData(%s(%p),FXSEL(%s,%d),%p)\n",sender->getClassName(),sender,FXDebugTarget::messageTypeName[FXSELTYPE(sel)],FXSELID(sel),ptr));
FXushort type=FXSELTYPE(sel);
FXushort id=FXSELID(sel);
FXASSERT(type!=SEL_NONE);
FXASSERT(type!=SEL_LAST);
if(type==SEL_KEYPRESS ||
type==SEL_KEYRELEASE ||
type==SEL_LEFTBUTTONPRESS ||
type==SEL_LEFTBUTTONRELEASE ||
type==SEL_MIDDLEBUTTONPRESS ||
type==SEL_MIDDLEBUTTONRELEASE ||
type==SEL_RIGHTBUTTONPRESS ||
type==SEL_RIGHTBUTTONRELEASE ||
type==SEL_MOTION ||
type==SEL_ENTER ||
type==SEL_LEAVE ||
type==SEL_FOCUSIN ||
type==SEL_FOCUSOUT ||
type==SEL_KEYMAP ||
type==SEL_UNGRABBED ||
type==SEL_PAINT ||
type==SEL_CREATE ||
type==SEL_DESTROY ||
type==SEL_UNMAP ||
type==SEL_MAP ||
type==SEL_CONFIGURE ||
type==SEL_SELECTION_LOST ||
type==SEL_SELECTION_GAINED ||
type==SEL_SELECTION_REQUEST ||
type==SEL_RAISED ||
type==SEL_LOWERED ||
type==SEL_MOUSEWHEEL ||
type==SEL_BEGINDRAG ||
type==SEL_ENDDRAG ||
type==SEL_TIMEOUT ||
type==SEL_CLIPBOARD_LOST ||
type==SEL_CLIPBOARD_GAINED ||
type==SEL_CLIPBOARD_REQUEST ||
type==SEL_CHORE ||
type==SEL_FOCUS_SELF ||
type==SEL_FOCUS_RIGHT ||
type==SEL_FOCUS_LEFT ||
type==SEL_FOCUS_DOWN ||
type==SEL_FOCUS_UP ||
type==SEL_FOCUS_NEXT ||
type==SEL_FOCUS_PREV ||
type==SEL_DND_ENTER ||
type==SEL_DND_LEAVE ||
type==SEL_DND_DROP ||
type==SEL_DND_MOTION ||
type==SEL_DND_REQUEST ||
type==SEL_PICKED ||
type==SEL_SESSION_NOTIFY ||
type==SEL_SESSION_CLOSED) {
return to_ruby_cb(reinterpret_cast<FXEvent*>(ptr));
}
else if(type==SEL_DRAGGED && !sender->isMemberOf(FXMETACLASS(FXGLViewer))){
return to_ruby_cb(reinterpret_cast<FXEvent*>(ptr));
}
else if(type==SEL_SIGNAL){
return to_ruby_cb(static_cast<int>(reinterpret_cast<FXuval>(ptr)));
}
else if(type==SEL_IO_READ ||
type==SEL_IO_WRITE ||
type==SEL_IO_EXCEPT){
return Qnil;
}
else if(type==SEL_CLOSE ||
type==SEL_DELETE ||
type==SEL_MINIMIZE ||
type==SEL_RESTORE ||
type==SEL_MAXIMIZE ||
type==SEL_UPDATE ||
type==SEL_QUERY_HELP ||
type==SEL_QUERY_TIP){
FXASSERT(ptr==0);
return Qnil;
}
else if(sender->isMemberOf(FXMETACLASS(FX4Splitter))){
if(type==SEL_CHANGED||type==SEL_COMMAND) return Qnil;
}
else if(sender->isMemberOf(FXMETACLASS(FXArrowButton))){
if(type==SEL_COMMAND) return to_ruby_cb(static_cast<FXuint>(reinterpret_cast<FXuval>(ptr)));
}
else if(sender->isMemberOf(FXMETACLASS(FXPicker))){
if(type==SEL_COMMAND || type==SEL_CHANGED) return to_ruby_cb(reinterpret_cast<FXPoint*>(ptr));
}
else if(sender->isMemberOf(FXMETACLASS(FXButton))){
if(type==SEL_CLICKED ||
type==SEL_DOUBLECLICKED ||
type==SEL_TRIPLECLICKED ||
type==SEL_COMMAND) return to_ruby_cb(static_cast<FXuint>(reinterpret_cast<FXuval>(ptr)));
}
else if(sender->isMemberOf(FXMETACLASS(FXCheckButton))){
if(type==SEL_COMMAND) return to_ruby_cb(static_cast<FXuchar>(reinterpret_cast<FXuval>(ptr)));
}
else if(sender->isMemberOf(FXMETACLASS(FXColorBar))){
if(type==SEL_CHANGED || type==SEL_COMMAND){
FXfloat* hsv=reinterpret_cast<FXfloat*>(ptr);
return rb_ary_new3(3,to_ruby_cb(hsv[0]),to_ruby_cb(hsv[1]),to_ruby_cb(hsv[2]));
}
}
else if(sender->isMemberOf(FXMETACLASS(FXColorDialog))){
if(type==SEL_CHANGED || type==SEL_COMMAND) return to_ruby_cb(static_cast<FXColor>(reinterpret_cast<FXuval>(ptr)));
}
else if(sender->isMemberOf(FXMETACLASS(FXColorRing))){
if(type==SEL_CHANGED || type==SEL_COMMAND){
FXfloat* hsv=reinterpret_cast<FXfloat*>(ptr);
return rb_ary_new3(3,to_ruby_cb(hsv[0]),to_ruby_cb(hsv[1]),to_ruby_cb(hsv[2]));
}
}
else if(sender->isMemberOf(FXMETACLASS(FXColorSelector))){
if(type==SEL_CHANGED || type==SEL_COMMAND) return to_ruby_cb(static_cast<FXColor>(reinterpret_cast<FXuval>(ptr)));
}
else if(sender->isMemberOf(FXMETACLASS(FXColorWell))){
if(type==SEL_CHANGED ||
type==SEL_COMMAND ||
type==SEL_CLICKED ||
type==SEL_DOUBLECLICKED ||
type==SEL_TRIPLECLICKED) {
VALUE v=to_ruby_cb(static_cast<FXColor>(reinterpret_cast<FXuval>(ptr)));
return v;
}
}
else if(sender->isMemberOf(FXMETACLASS(FXColorWheel))){
if(type==SEL_CHANGED || type==SEL_COMMAND){
FXfloat* hsv=reinterpret_cast<FXfloat*>(ptr);
return rb_ary_new3(3,to_ruby_cb(hsv[0]),to_ruby_cb(hsv[1]),to_ruby_cb(hsv[2]));
}
}
else if(sender->isMemberOf(FXMETACLASS(FXComboBox))){
if(type==SEL_CHANGED || type==SEL_COMMAND) return to_ruby_cb(reinterpret_cast<FXchar*>(ptr));
}
else if(sender->isMemberOf(FXMETACLASS(FXDataTarget))){
if(type==SEL_COMMAND || type==SEL_CHANGED){
if(recv->isMemberOf(FXMETACLASS(FXWindow))){
switch(id){
case FXWindow::ID_SETINTVALUE:
return to_ruby_cb(*reinterpret_cast<FXint*>(ptr));
case FXWindow::ID_SETREALVALUE:
return to_ruby_cb(*reinterpret_cast<FXdouble*>(ptr));
case FXWindow::ID_SETSTRINGVALUE:
return to_ruby_cb(*reinterpret_cast<FXString*>(ptr));
case FXWindow::ID_GETINTVALUE:
case FXWindow::ID_GETREALVALUE:
case FXWindow::ID_GETSTRINGVALUE:
FXASSERT(FALSE);
break;
default:
FXASSERT(FALSE);
}
}
else{
// It's not a window object...
FXASSERT(sender->isMemberOf(FXMETACLASS(FXRbDataTarget)));
return dynamic_cast<FXRbDataTarget*>(sender)->getValue();
}
}
}
else if(sender->isMemberOf(FXMETACLASS(FXDial))){
if(type==SEL_CHANGED || type==SEL_COMMAND) return to_ruby_cb(static_cast<FXint>(reinterpret_cast<FXival>(ptr)));
}
else if(sender->isMemberOf(FXMETACLASS(FXDirBox))){
if(type==SEL_CHANGED || type==SEL_COMMAND) return to_ruby_cb(reinterpret_cast<FXchar*>(ptr));
}
else if(sender->isMemberOf(FXMETACLASS(FXDockBar))){
if(type==SEL_DOCKED || type==SEL_FLOATED) return FXRbGetRubyObjCb(ptr,FXRbTypeQuery("FXDockSite *"));
}
else if(sender->isMemberOf(FXMETACLASS(FXFileList))){
if (type==SEL_CHANGED ||
type==SEL_CLICKED ||
type==SEL_DOUBLECLICKED ||
type==SEL_TRIPLECLICKED ||
type==SEL_COMMAND) return to_ruby_cb(static_cast<FXint>(reinterpret_cast<FXival>(ptr)));
}
else if(sender->isMemberOf(FXMETACLASS(FXFoldingList))){
if(type==SEL_COLLAPSED ||
type==SEL_EXPANDED ||
type==SEL_COMMAND ||
type==SEL_CHANGED ||
type==SEL_CLICKED ||
type==SEL_DOUBLECLICKED ||
type==SEL_TRIPLECLICKED ||
type==SEL_OPENED ||
type==SEL_CLOSED ||
type==SEL_SELECTED ||
type==SEL_DESELECTED ||
type==SEL_INSERTED ||
type==SEL_DELETED){
return FXRbGetRubyObjCb(ptr,FXRbTypeQuery("FXFoldingItem *"));
}
}
else if(sender->isMemberOf(FXMETACLASS(FXGLViewer))){
if(type==SEL_CHANGED ||
type==SEL_CLICKED ||
type==SEL_DOUBLECLICKED ||
type==SEL_TRIPLECLICKED ||
type==SEL_DRAGGED){
return FXRbGetRubyObjCb(ptr,FXRbTypeQuery("FXGLObject *"));
}
else if(type==SEL_COMMAND){
if(id==FXWindow::ID_QUERY_MENU)
return to_ruby_cb(reinterpret_cast<FXEvent*>(ptr));
else
return FXRbGetRubyObjCb(ptr,FXRbTypeQuery("FXGLObject *"));
}
else if(type==SEL_LASSOED ||
type==SEL_INSERTED ||
type==SEL_DELETED ||
type==SEL_SELECTED ||
type==SEL_DESELECTED){
VALUE ary=rb_ary_new();
// FXGLObject** objlist=reinterpret_cast<FXGLObject**>(ptr);
// FIXME: objlist is a NULL-terminated array of pointers to FXGLObject
return ary;
}
}
else if(sender->isMemberOf(FXMETACLASS(FXGradientBar))){
if(type==SEL_CHANGED){
return to_ruby_cb(static_cast<FXint>(reinterpret_cast<FXival>(ptr)));
}
else if(type==SEL_SELECTED || type==SEL_DESELECTED){
return Qnil;
}
}
else if(sender->isMemberOf(FXMETACLASS(FXHeader))){
if(type==SEL_COMMAND ||
type==SEL_CHANGED ||
type==SEL_CLICKED ||
type==SEL_REPLACED ||
type==SEL_INSERTED ||
type==SEL_DELETED) return to_ruby_cb(static_cast<FXint>(reinterpret_cast<FXival>(ptr)));
}
else if(sender->isMemberOf(FXMETACLASS(FXIconList))){
if(type==SEL_CHANGED ||
type==SEL_CLICKED ||
type==SEL_DOUBLECLICKED ||
type==SEL_TRIPLECLICKED ||
type==SEL_COMMAND ||
type==SEL_SELECTED ||
type==SEL_DESELECTED ||
type==SEL_REPLACED ||
type==SEL_INSERTED ||
type==SEL_DELETED) return to_ruby_cb(static_cast<FXint>(reinterpret_cast<FXival>(ptr)));
}
else if(sender->isMemberOf(FXMETACLASS(FXKnob))){
if(type==SEL_CHANGED || type==SEL_COMMAND) return to_ruby_cb(static_cast<FXint>(reinterpret_cast<FXival>(ptr)));
}
else if(sender->isMemberOf(FXMETACLASS(FXList))){
if(type==SEL_CHANGED ||
type==SEL_CLICKED ||
type==SEL_DOUBLECLICKED ||
type==SEL_TRIPLECLICKED ||
type==SEL_SELECTED ||
type==SEL_DESELECTED ||
type==SEL_REPLACED ||
type==SEL_INSERTED ||
type==SEL_DELETED ||
type==SEL_COMMAND) return to_ruby_cb(static_cast<FXint>(reinterpret_cast<FXival>(ptr)));
}
else if(sender->isMemberOf(FXMETACLASS(FXListBox))){
if(type==SEL_COMMAND) return to_ruby_cb(static_cast<FXint>(reinterpret_cast<FXival>(ptr)));
else if(type==SEL_CHANGED) return Qnil;
}
else if(sender->isMemberOf(FXMETACLASS(FXMDIChild))){
if(type==SEL_MINIMIZE ||
type==SEL_MAXIMIZE ||
type==SEL_CLOSE ||
type==SEL_RESTORE){
return Qnil;
}
else if(type==SEL_SELECTED ||
type==SEL_DESELECTED){
return FXRbGetRubyObjCb(ptr,FXRbTypeQuery("FXMDIChild *"));
}
}
else if(sender->isMemberOf(FXMETACLASS(FXMDIClient))){
if(type==SEL_CHANGED) return FXRbGetRubyObjCb(ptr,FXRbTypeQuery("FXMDIChild *"));
}
else if(sender->isMemberOf(FXMETACLASS(FXMenuCheck))){
if(type==SEL_COMMAND) return to_ruby_cb(reinterpret_cast<FXuval>(ptr));
}
else if(sender->isMemberOf(FXMETACLASS(FXMenuRadio))){
if(type==SEL_COMMAND) return to_ruby_cb(reinterpret_cast<FXuval>(ptr));
}
else if(sender->isMemberOf(FXMETACLASS(FXMenuCommand))){
if(type==SEL_COMMAND) return to_ruby_cb(true);
}
else if(sender->isMemberOf(FXMETACLASS(FXOption))){
if(type==SEL_COMMAND) return to_ruby_cb(reinterpret_cast<FXEvent*>(ptr));
}
else if(sender->isMemberOf(FXMETACLASS(FXOptionMenu))){
if(type==SEL_COMMAND) return to_ruby_cb(static_cast<FXint>(reinterpret_cast<FXival>(ptr)));
}
else if(sender->isMemberOf(FXMETACLASS(FXRadioButton))){
if(type==SEL_COMMAND) return to_ruby_cb(static_cast<FXuchar>(reinterpret_cast<FXuval>(ptr)));
}
else if(sender->isMemberOf(FXMETACLASS(FXRealSlider))){
if(type==SEL_CHANGED || type==SEL_COMMAND)
return to_ruby_cb(*(reinterpret_cast<FXdouble *>(ptr)));
}
else if(sender->isMemberOf(FXMETACLASS(FXRealSpinner))){
if(type==SEL_COMMAND || type==SEL_CHANGED) return to_ruby_cb(*(reinterpret_cast<FXdouble *>(ptr)));
}
else if(sender->isMemberOf(FXMETACLASS(FXRecentFiles))){
if(type==SEL_COMMAND) return to_ruby_cb(reinterpret_cast<FXchar*>(ptr));
}
else if(sender->isMemberOf(FXMETACLASS(FXRuler))){
if(type==SEL_CHANGED) return Qnil;
}
else if(sender->isMemberOf(FXMETACLASS(FXScrollBar))){
if(type==SEL_CHANGED || type==SEL_COMMAND) return to_ruby_cb(static_cast<FXint>(reinterpret_cast<FXival>(ptr)));
}
else if(sender->isMemberOf(FXMETACLASS(FXShutter))){
if(type==SEL_COMMAND) return to_ruby_cb(static_cast<FXint>(reinterpret_cast<FXival>(ptr)));
}
else if(sender->isMemberOf(FXMETACLASS(FXSlider))){
if(type==SEL_CHANGED || type==SEL_COMMAND)
return to_ruby_cb(static_cast<FXint>(reinterpret_cast<FXival>(ptr)));
}
else if(sender->isMemberOf(FXMETACLASS(FXSpinner))){
if(type==SEL_CHANGED || type==SEL_COMMAND)
return to_ruby_cb(static_cast<FXint>(reinterpret_cast<FXuval>(ptr)));
}
else if(sender->isMemberOf(FXMETACLASS(FXSplitter))){
if(type==SEL_CHANGED || type==SEL_COMMAND)
return to_ruby_cb(reinterpret_cast<FXWindow *>(ptr));
}
else if(sender->isMemberOf(FXMETACLASS(FXSwitcher))){
if(type==SEL_COMMAND) return to_ruby_cb(static_cast<FXint>(reinterpret_cast<FXival>(ptr)));
}
else if(sender->isMemberOf(FXMETACLASS(FXTabBar))){
if(type==SEL_COMMAND) return to_ruby_cb(static_cast<FXint>(reinterpret_cast<FXival>(ptr)));
}
else if(sender->isMemberOf(FXMETACLASS(FXTable))){
if(type==SEL_CLICKED ||
type==SEL_DOUBLECLICKED ||
type==SEL_TRIPLECLICKED ||
type==SEL_CHANGED ||
type==SEL_COMMAND ||
type==SEL_SELECTED ||
type == SEL_DESELECTED) return to_ruby_cb(reinterpret_cast<FXTablePos*>(ptr));
else if(type == SEL_INSERTED ||
type == SEL_DELETED ||
type == SEL_REPLACED){
return to_ruby_cb(reinterpret_cast<FXTableRange*>(ptr));
}
}
else if(sender->isMemberOf(FXMETACLASS(FXText))){
if (type == SEL_COMMAND) {
switch(id){
case FXText::ID_COPY_SEL:
case FXText::ID_PASTE_SEL:
case FXText::ID_DELETE_SEL:
return Qnil;
break;
default:
FXASSERT(FALSE);
return reinterpret_cast<VALUE>(ptr); // pass-through as is
}
}
else if(type==SEL_CHANGED){
return to_ruby_cb(static_cast<FXint>(reinterpret_cast<FXival>(ptr)));
}
else if(type==SEL_SELECTED ||
type == SEL_DESELECTED) {
FXint* what=reinterpret_cast<FXint*>(ptr);
FXASSERT(what!=0);
VALUE ary=rb_ary_new();
rb_ary_push(ary,to_ruby_cb(what[0])); // start position of text
rb_ary_push(ary,to_ruby_cb(what[1])); // length of text
return ary;
}
else if(type==SEL_INSERTED || type==SEL_DELETED || type==SEL_REPLACED) {
return to_ruby_cb(reinterpret_cast<FXTextChange*>(ptr));
}
}
else if(sender->isMemberOf(FXMETACLASS(FXTextField))){
if(type==SEL_CHANGED ||
type==SEL_COMMAND ||
type==SEL_VERIFY) return to_ruby_cb(reinterpret_cast<FXchar*>(ptr));
}
else if(sender->isMemberOf(FXMETACLASS(FXToggleButton))){
if(type==SEL_COMMAND) return to_ruby_cb(static_cast<FXuchar>(reinterpret_cast<FXuval>(ptr)));
}
else if(sender->isMemberOf(FXMETACLASS(FXToolBarTab))){
if (type==SEL_COMMAND) return to_ruby_cb(static_cast<FXbool>(reinterpret_cast<FXuval>(ptr)));
}
else if(sender->isMemberOf(FXMETACLASS(FXTopWindow))){
if(type==SEL_MINIMIZE ||
type==SEL_MAXIMIZE ||
type==SEL_RESTORE ||
type==SEL_CLOSE){
return Qnil;
}
else if (type==SEL_SESSION_NOTIFY ||
type==SEL_SESSION_CLOSED) {
return to_ruby_cb(reinterpret_cast<FXEvent*>(ptr));
}
}
else if(sender->isMemberOf(FXMETACLASS(FXTreeList))){
if(type==SEL_COLLAPSED ||
type==SEL_EXPANDED ||
type==SEL_COMMAND ||
type==SEL_CHANGED ||
type==SEL_CLICKED ||
type==SEL_DOUBLECLICKED ||
type==SEL_TRIPLECLICKED ||
type==SEL_OPENED ||
type==SEL_CLOSED ||
type==SEL_SELECTED ||
type==SEL_DESELECTED ||
type==SEL_INSERTED ||
type==SEL_DELETED){
return FXRbGetRubyObjCb(ptr,FXRbTypeQuery("FXTreeItem *"));
}
}
else if(sender->isMemberOf(FXMETACLASS(FXTreeListBox))){
if(type==SEL_CHANGED || type==SEL_COMMAND)
return FXRbGetRubyObjCb(ptr,FXRbTypeQuery("FXTreeItem *"));
}
#ifdef WITH_FXSCINTILLA
else if(sender->isMemberOf(FXMETACLASS(FXScintilla))){
if(type==SEL_COMMAND){
return FXRbGetRubyObjCb(ptr,FXRbTypeQuery("SCNotification *"));
}
}
#endif
else{
FXTRACE((100,"%s:%d: message data passed through as-is\n",__FILE__,__LINE__));
return reinterpret_cast<VALUE>(ptr); // pass-through as is
}
FXTRACE((100,"%s:%d: message data passed through as-is\n",__FILE__,__LINE__));
return reinterpret_cast<VALUE>(ptr); // pass-through as is
}
/**
* When a Ruby instance (e.g. one of your widgets) calls handle() on another
* object, e.g.
*
* def onUpdAnswer(sender, sel, ptr)
* if theAnswerIsTwo?
* sender.handle(self, FXSEL(SEL_COMMAND,FXWindow::ID_SETVALUE), 2)
* else
* sender.handle(self, FXSEL(SEL_COMMAND,FXWindow::ID_SETVALUE), 3)
* end
* return 1
* end
*
* it's usually the case that this will get passed along to the underlying
* C++ object. In that case, we need to convert the message data (e.g. the
* Fixnums "2" or "3" in the example above) from Ruby objects back into
* the appropriate C++ objects. That's what this function is for.
*/
void* FXRbGetExpectedData(VALUE recv,FXSelector key,VALUE value){
void *ptr;
static FXint intValue;
static FXint intRange[2];
static FXdouble realValue;
static FXdouble realRange[2];
static FXString stringValue;
static FXColor colorValue;
FXushort type=FXSELTYPE(key);
FXushort id=FXSELID(key);
// Extract the FOX object (the receiver) from this Ruby instance
FXObject* obj;
Data_Get_Struct(recv,FXObject,obj);
FXASSERT(type!=SEL_NONE);
FXASSERT(type!=SEL_LAST);
switch(type){
case SEL_KEYPRESS:
case SEL_KEYRELEASE:
case SEL_LEFTBUTTONPRESS:
case SEL_LEFTBUTTONRELEASE:
case SEL_MIDDLEBUTTONPRESS:
case SEL_MIDDLEBUTTONRELEASE:
case SEL_RIGHTBUTTONPRESS:
case SEL_RIGHTBUTTONRELEASE:
case SEL_MOTION:
case SEL_ENTER:
case SEL_LEAVE:
case SEL_FOCUSIN:
case SEL_FOCUSOUT:
case SEL_KEYMAP:
case SEL_UNGRABBED:
case SEL_PAINT:
case SEL_CREATE:
case SEL_DESTROY:
case SEL_UNMAP:
case SEL_MAP:
case SEL_CONFIGURE:
case SEL_SELECTION_LOST:
case SEL_SELECTION_GAINED:
case SEL_SELECTION_REQUEST:
case SEL_RAISED:
case SEL_LOWERED:
case SEL_MOUSEWHEEL:
case SEL_BEGINDRAG:
case SEL_ENDDRAG:
case SEL_LASSOED:
case SEL_TIMEOUT:
case SEL_CLIPBOARD_LOST:
case SEL_CLIPBOARD_GAINED:
case SEL_CLIPBOARD_REQUEST:
case SEL_CHORE:
case SEL_FOCUS_SELF:
case SEL_FOCUS_RIGHT:
case SEL_FOCUS_LEFT:
case SEL_FOCUS_DOWN:
case SEL_FOCUS_UP:
case SEL_FOCUS_NEXT:
case SEL_FOCUS_PREV:
case SEL_DND_ENTER:
case SEL_DND_LEAVE:
case SEL_DND_DROP:
case SEL_DND_MOTION:
case SEL_DND_REQUEST:
case SEL_PICKED:
SWIG_ConvertPtr(value,&ptr,FXRbTypeQuery("FXEvent *"),1);
return ptr;
case SEL_IO_READ:
case SEL_IO_WRITE:
case SEL_IO_EXCEPT:
return 0; // should be an FXInputHandle?
case SEL_SIGNAL:
return reinterpret_cast<void*>(static_cast<long>(NUM2INT(value)));
case SEL_CLOSE:
case SEL_DELETE:
case SEL_MINIMIZE:
case SEL_RESTORE:
case SEL_MAXIMIZE:
case SEL_UPDATE:
case SEL_QUERY_TIP:
case SEL_QUERY_HELP:
return NULL;
case SEL_VERIFY:
return reinterpret_cast<void*>(StringValuePtr(value));
case SEL_CLICKED:
case SEL_DOUBLECLICKED:
case SEL_TRIPLECLICKED:
case SEL_DESELECTED:
case SEL_SELECTED:
case SEL_INSERTED:
case SEL_REPLACED:
case SEL_DELETED:
case SEL_OPENED:
case SEL_CLOSED:
case SEL_EXPANDED:
case SEL_COLLAPSED:
return NULL;
default:
/* Ignore */
break;
}
if(type==SEL_COMMAND){
// Handle FXText-specific messages
if(obj->isMemberOf(FXMETACLASS(FXText))){
switch(id){
case FXText::ID_COPY_SEL:
case FXText::ID_PASTE_SEL:
case FXText::ID_DELETE_SEL:
return NULL;
default:
break;
}
}
// Handle FXTextField-specific message
if(obj->isMemberOf(FXMETACLASS(FXTextField))){
switch(id){
case FXTextField::ID_INSERT_STRING:
return reinterpret_cast<void*>(StringValuePtr(value));;
default:
break;
}
}
// Handle messages applicable to all FXWindow descendants
if(obj->isMemberOf(FXMETACLASS(FXWindow))){
switch(id){
case FXWindow::ID_HIDE:
case FXWindow::ID_SHOW:
case FXWindow::ID_TOGGLESHOWN:
case FXWindow::ID_LOWER:
case FXWindow::ID_RAISE:
case FXWindow::ID_DELETE:
case FXWindow::ID_DISABLE:
case FXWindow::ID_ENABLE:
case FXWindow::ID_UNCHECK:
case FXWindow::ID_CHECK:
case FXWindow::ID_UNKNOWN:
case FXWindow::ID_UPDATE:
case FXWindow::ID_AUTOSCROLL:
case FXWindow::ID_QUERY_MENU:
case FXWindow::ID_HOTKEY:
case FXWindow::ID_ACCEL:
case FXWindow::ID_UNPOST:
case FXWindow::ID_POST:
case FXWindow::ID_MDI_TILEHORIZONTAL:
case FXWindow::ID_MDI_TILEVERTICAL:
case FXWindow::ID_MDI_CASCADE:
case FXWindow::ID_MDI_MAXIMIZE:
case FXWindow::ID_MDI_MINIMIZE:
case FXWindow::ID_MDI_RESTORE:
case FXWindow::ID_MDI_CLOSE:
case FXWindow::ID_MDI_WINDOW:
case FXWindow::ID_MDI_MENUWINDOW:
case FXWindow::ID_MDI_MENUMINIMIZE:
case FXWindow::ID_MDI_MENURESTORE:
case FXWindow::ID_MDI_MENUCLOSE:
case FXWindow::ID_MDI_NEXT:
case FXWindow::ID_MDI_PREV:
return NULL;
case FXWindow::ID_SETVALUE:
if(obj->isMemberOf(FXMETACLASS(FXButton)) ||
obj->isMemberOf(FXMETACLASS(FXCheckButton)) ||
obj->isMemberOf(FXMETACLASS(FXDial)) ||
obj->isMemberOf(FXMETACLASS(FXRadioButton)) ||
obj->isMemberOf(FXMETACLASS(FXShutter)) ||
obj->isMemberOf(FXMETACLASS(FXSpinner)) ||
obj->isMemberOf(FXMETACLASS(FXTabBar)) ||
obj->isMemberOf(FXMETACLASS(FXToggleButton)) ||
obj->isMemberOf(FXMETACLASS(FXScrollBar)) ||
obj->isMemberOf(FXMETACLASS(FXSlider)) ||
obj->isMemberOf(FXMETACLASS(FXSwitcher))){
return reinterpret_cast<void*>(static_cast<long>(NUM2INT(value)));
}
else if(obj->isMemberOf(FXMETACLASS(FXColorSelector)) ||
obj->isMemberOf(FXMETACLASS(FXColorWell))){
return reinterpret_cast<void*>(static_cast<unsigned long>(NUM2UINT(value)));
}
else if(obj->isMemberOf(FXMETACLASS(FXProgressBar))){
return reinterpret_cast<void*>(static_cast<unsigned long>(NUM2UINT(value)));
}
else if(obj->isMemberOf(FXMETACLASS(FXComboBox)) ||
obj->isMemberOf(FXMETACLASS(FXTextField)) ||
obj->isMemberOf(FXMETACLASS(FXDirBox)) ||
obj->isMemberOf(FXMETACLASS(FXDirList)) ||
obj->isMemberOf(FXMETACLASS(FXDriveBox)) ||
obj->isMemberOf(FXMETACLASS(FXFileList))){
return reinterpret_cast<void*>(StringValuePtr(value));
}
else if(obj->isMemberOf(FXMETACLASS(FXMenuCheck))){
return reinterpret_cast<void*>(static_cast<FXuval>(RTEST(value) ? 1 : 0));
}
else if(obj->isMemberOf(FXMETACLASS(FXMenuRadio))){
return reinterpret_cast<void*>(static_cast<FXuval>(RTEST(value) ? 1 : 0));
}
else if(obj->isMemberOf(FXMETACLASS(FXMenuCommand))){
return reinterpret_cast<void*>(static_cast<FXuval>(RTEST(value) ? 1 : 0));
}
return NULL;
case FXWindow::ID_HSCROLLED:
case FXWindow::ID_VSCROLLED:
return reinterpret_cast<void*>(static_cast<long>(NUM2INT(value)));
case FXWindow::ID_SETINTVALUE:
if(obj->isMemberOf(FXMETACLASS(FXColorWell))){
colorValue=NUM2UINT(value);
return reinterpret_cast<void*>(&colorValue);
}
else{
intValue=NUM2INT(value);
return reinterpret_cast<void*>(&intValue);
}
case FXWindow::ID_SETREALVALUE:
realValue=NUM2DBL(value);
return reinterpret_cast<void*>(&realValue);
case FXWindow::ID_SETSTRINGVALUE:
stringValue=FXString(StringValuePtr(value));
return reinterpret_cast<void*>(&stringValue);
case FXWindow::ID_SETINTRANGE:
intRange[0]=NUM2INT(rb_ary_entry(value,0));
intRange[1]=NUM2INT(rb_ary_entry(value,1));
return reinterpret_cast<void*>(intRange);
case FXWindow::ID_SETREALRANGE:
realRange[0]=NUM2DBL(rb_ary_entry(value,0));
realRange[1]=NUM2DBL(rb_ary_entry(value,1));
return reinterpret_cast<void*>(realRange);
case FXWindow::ID_GETINTVALUE:
case FXWindow::ID_GETREALVALUE:
case FXWindow::ID_GETSTRINGVALUE:
case FXWindow::ID_GETINTRANGE:
case FXWindow::ID_GETREALRANGE:
return NULL;
default:
// Pass this data along as-is
break;
}
}
}
if(type==SEL_CHANGED){
if(obj->isMemberOf(FXMETACLASS(FXPicker))){
SWIG_ConvertPtr(value,&ptr,FXRbTypeQuery("FXPoint *"),1);
return ptr;
}
if(obj->isMemberOf(FXMETACLASS(FXWindow))){
switch(id){
case FXWindow::ID_HSCROLLED:
case FXWindow::ID_VSCROLLED:
return reinterpret_cast<void*>(static_cast<long>(NUM2INT(value)));
}
}
return 0;
}
if(type==SEL_DRAGGED){
SWIG_ConvertPtr(value,&ptr,FXRbTypeQuery("FXEvent *"),1);
return ptr;
}
// Pass through as-is
return reinterpret_cast<void*>(value);
}
static ID id_assocs;
/**
* Look up the name of the message handler function for this
* receiver and message (type, id) combination and return it;
* or return zero if the designated receiver doesn't handle this
* message.
*/
ID FXRbLookupHandler_gvlcb(FXObject* recv,FXSelector key){
FXTRACE((100,"FXRbLookupHandler(recv=%p(%s),FXSEL(%d,%d))\n",recv,recv->getClassName(),FXSELTYPE(key),FXSELID(key)));
ID id=0;
VALUE rubyObj=to_ruby(recv);
FXASSERT((recv==0 && rubyObj==Qnil) || (recv!=0 && rubyObj!=Qnil));
if(rb_ivar_defined(rubyObj,id_assocs)==Qtrue){
VALUE assocs=rb_ivar_get(rubyObj,id_assocs);
VALUE entry;
FXSelector keylo,keyhi;
for(long i=0;i<RARRAY_LEN(assocs);i++){
entry=rb_ary_entry(assocs,i);
keylo=NUM2UINT(rb_ary_entry(entry,0));
keyhi=NUM2UINT(rb_ary_entry(entry,1));
if(keylo<=key && key<=keyhi){
id=SYM2ID(rb_ary_entry(entry,2));
FXASSERT(id!=0);
break;
}
}
}
return id;
}
struct FXRbHandleArgs {
VALUE recv;
VALUE id;
int nargs;
VALUE sender;
VALUE key;
VALUE data;
};
static VALUE handle_body(VALUE args){
FXRbHandleArgs* hArgs=reinterpret_cast<FXRbHandleArgs*>(args);
FXASSERT(hArgs!=0);
return rb_funcall(hArgs->recv,hArgs->id,hArgs->nargs,hArgs->sender,hArgs->key,hArgs->data);
}
static ID id_backtrace;
static VALUE handle_rescue(VALUE args,VALUE error){
VALUE info=rb_gv_get("$!");
VALUE errat=rb_funcall(info,id_backtrace,0);
VALUE mesg=rb_ary_entry(errat, 0);
VALUE info_str=rb_obj_as_string(info);
fprintf(stderr,"%s: %s (%s)\n",
StringValueCStr(mesg),
StringValueCStr(info_str),
rb_class2name(CLASS_OF(info)));
for(int i=1;i<RARRAY_LEN(errat);i++){
VALUE entry = rb_ary_entry(errat, i);
if(TYPE(entry)==T_STRING){
fprintf(stderr,"\tfrom %s\n",StringValueCStr(entry));
}
}
return Qnil;
}
// Should we catch exceptions thrown by message handlers?
FXbool FXRbCatchExceptions=FALSE;
// Call the designated function and return its result (which should be a long).
long FXRbHandleMessage_gvlcb(FXObject* recv,ID func,FXObject* sender,FXSelector key,void* ptr){
FXRbHandleArgs hArgs;
hArgs.recv=to_ruby_cb(recv);
hArgs.sender=to_ruby_cb(sender);
hArgs.key=to_ruby_cb(key);
hArgs.data=FXRbConvertMessageData(sender,recv,key,ptr);
hArgs.id=func;
hArgs.nargs=3;
VALUE retval;
FXTRACE((100,"FXRbHandleMessage(recv=%p(%s),FXSEL(%s,%d)\n",recv,recv->getClassName(),FXDebugTarget::messageTypeName[FXSELTYPE(key)],FXSELID(key)));
if(FXRbCatchExceptions){
retval=rb_rescue2(RUBY_VALUE_METHOD_FUNC(handle_body), reinterpret_cast<VALUE>(&hArgs),
RUBY_VALUE_METHOD_FUNC(handle_rescue), Qnil,
rb_eStandardError, rb_eNameError, 0);
}
else{
retval=handle_body(reinterpret_cast<VALUE>(&hArgs));
}
/**
* Process the return value. For boolean return values, convert "true"
* to 1 and "false" to zero. For numeric types, convert it to a long value
* but trap the result to either 0 or 1 since these are usually what
* FOX is looking for. For any other type result (including nil) return 1.
* Thanks to Ted Meng for this suggestion.
*/
long lresult;
switch(TYPE(retval)){
case T_TRUE:
lresult=1;
break;
case T_FALSE:
lresult=0;
break;
case T_BIGNUM:
lresult=1;
break;
case T_FIXNUM:
case T_FLOAT:
lresult=(NUM2LONG(retval) == 0) ? 0 : 1; // trap any numeric result to either 0 or 1
break;
default:
lresult=1;
}
return lresult;
}
//----------------------------------------------------------------------
static ID id_begin;
static ID id_end;
static ID id_exclude_endp;
void FXRbRange2LoHi(VALUE range,FXint& lo,FXint& hi){
if(Qtrue!=rb_obj_is_instance_of(range,rb_cRange)){
rb_raise(rb_eTypeError,"wrong argument type %s (expected %s)",rb_class2name(CLASS_OF(range)),rb_class2name(rb_cRange));
}
else{
VALUE beg=rb_funcall(range,id_begin,0);
VALUE end=rb_funcall(range,id_end,0);
VALUE excl=rb_funcall(range,id_exclude_endp,0);
lo=NUM2INT(beg);
hi=NUM2INT(end);
if(excl==Qtrue){
hi--;
}
}
}
void FXRbRange2LoHi(VALUE range,FXdouble& lo,FXdouble& hi){
if(Qtrue!=rb_obj_is_instance_of(range,rb_cRange)){
rb_raise(rb_eTypeError,"wrong argument type %s (expected %s)",rb_class2name(CLASS_OF(range)),rb_class2name(rb_cRange));
}
else{
VALUE beg=rb_funcall(range,id_begin,0);
VALUE end=rb_funcall(range,id_end,0);
VALUE excl=rb_funcall(range,id_exclude_endp,0);
lo=NUM2DBL(beg);
hi=NUM2DBL(end);
if(excl==Qtrue){
hi--;
}
}
}
//----------------------------------------------------------------------
void FXRbCallVoidMethod_gvlcb(FXObject* recv, const char *func) {
VALUE obj=FXRbGetRubyObj(recv,false);
FXASSERT(!NIL_P(obj));
FXASSERT(!FXRbIsInGC(recv));
rb_funcall(obj,rb_intern(func),0);
}
void FXRbCallVoidMethod_gvlcb(FXDC* recv,const char *func) {
VALUE obj=FXRbGetRubyObj(recv,false);
FXASSERT(!NIL_P(obj));
rb_funcall(obj,rb_intern(func),0);
}
//----------------------------------------------------------------------
bool FXRbCallBoolMethod_gvlcb(const FXObject* recv,const char *func){
VALUE obj=FXRbGetRubyObj(recv,false);
FXASSERT(!NIL_P(obj));
VALUE v=rb_funcall(obj,rb_intern(func),0);
return (v==Qtrue);
}
//----------------------------------------------------------------------
// Call function with "FXint" return value
FXint FXRbCallIntMethod_gvlcb(const FXObject* recv,const char *func){
VALUE obj=FXRbGetRubyObj(recv,false);
FXASSERT(!NIL_P(obj));
VALUE result=rb_funcall(obj,rb_intern(func),0);
return static_cast<FXint>(NUM2INT(result));
}
//----------------------------------------------------------------------
// Call function with "FXGLObject*" return value
FXGLObject* FXRbCallGLObjectMethod_gvlcb(FXGLObject* recv,const char *func){
VALUE obj=FXRbGetRubyObj(recv,false);
FXASSERT(!NIL_P(obj));
VALUE result=rb_funcall(obj,rb_intern(func),0);
return NIL_P(result) ? 0 : reinterpret_cast<FXGLObject*>(DATA_PTR(result));
}
FXGLObject* FXRbCallGLObjectMethod_gvlcb(FXGLViewer* recv,const char *func,FXint x,FXint y){
VALUE obj=FXRbGetRubyObj(recv,false);
FXASSERT(!NIL_P(obj));
VALUE result=rb_funcall(obj,rb_intern(func),2,INT2NUM(x),INT2NUM(y));
return NIL_P(result) ? 0 : reinterpret_cast<FXGLObject*>(DATA_PTR(result));
}
FXGLObject* FXRbCallGLObjectMethod_gvlcb(FXGLObject* recv,const char *func,FXuint* path,FXint n){
VALUE obj=FXRbGetRubyObj(recv,false);
FXASSERT(!NIL_P(obj));
VALUE result=rb_funcall(obj,rb_intern(func),1,FXRbMakeArray(path,n));
return NIL_P(result) ? 0 : reinterpret_cast<FXGLObject*>(DATA_PTR(result));
}
//----------------------------------------------------------------------
// Call function with "FXGLObject**" return value
FXGLObject** FXRbCallGLObjectArrayMethod_gvlcb(FXGLViewer* recv,const char *func,FXint x,FXint y,FXint w,FXint h){
FXGLObject** objects=NULL;
VALUE obj=FXRbGetRubyObj(recv,false);
FXASSERT(!NIL_P(obj));
VALUE result=rb_funcall(obj,rb_intern(func),4,INT2NUM(x),INT2NUM(y),INT2NUM(w),INT2NUM(h));
if(!NIL_P(result)){
Check_Type(result,T_ARRAY);
if(FXMALLOC(&objects,FXGLObject*,RARRAY_LEN(result)+1)){
for(long i=0; i<RARRAY_LEN(result); i++){
objects[i]=reinterpret_cast<FXGLObject*>(DATA_PTR(rb_ary_entry(result,i)));
}
objects[RARRAY_LEN(result)]=0;
}
}
return objects; // caller must free this
}
//----------------------------------------------------------------------
FXTableItem* FXRbCallTableItemMethod_gvlcb(FXTable* recv,const char *func,const FXString& text,FXIcon* icon,void* ptr){
VALUE itemData=(ptr==0)?Qnil:reinterpret_cast<VALUE>(ptr);
VALUE obj=FXRbGetRubyObj(recv,false);
FXASSERT(!NIL_P(obj));
VALUE result=rb_funcall(obj,rb_intern(func),3,to_ruby(text),to_ruby_cb(icon),itemData);
return NIL_P(result)?0:reinterpret_cast<FXTableItem*>(DATA_PTR(result));
}
FXTableItem* FXRbCallTableItemMethod_gvlcb(FXTable* recv,const char *func,FXint row,FXint col,FXbool notify){
VALUE obj=FXRbGetRubyObj(recv,false);
FXASSERT(!NIL_P(obj));
VALUE result=rb_funcall(obj,rb_intern(func),3,to_ruby(row),to_ruby(col),to_ruby(notify));
return NIL_P(result)?0:reinterpret_cast<FXTableItem*>(DATA_PTR(result));
}
//----------------------------------------------------------------------
FXTreeItem* FXRbCallTreeItemMethod_gvlcb(const FXTreeList* recv,const char *func,FXint x,FXint y){
VALUE obj=FXRbGetRubyObj(recv,false);
FXASSERT(!NIL_P(obj));
VALUE result=rb_funcall(obj,rb_intern(func),2,INT2NUM(x),INT2NUM(y));
return NIL_P(result) ? 0 : reinterpret_cast<FXTreeItem*>(DATA_PTR(result));
}
//----------------------------------------------------------------------
FXFoldingItem* FXRbCallFoldingItemMethod_gvlcb(const FXFoldingList* recv,const char *func,FXint x,FXint y){
VALUE obj=FXRbGetRubyObj(recv,false);
FXASSERT(!NIL_P(obj));
VALUE result=rb_funcall(obj,rb_intern(func),2,INT2NUM(x),INT2NUM(y));
return NIL_P(result) ? 0 : reinterpret_cast<FXFoldingItem*>(DATA_PTR(result));
}
//----------------------------------------------------------------------
FXFileAssoc* FXRbCallFileAssocMethod_gvlcb(const FXFileDict* recv,const char *func,const FXchar* pathname){
VALUE obj=FXRbGetRubyObj(recv,false);
FXASSERT(!NIL_P(obj));
VALUE result=rb_funcall(obj,rb_intern(func),1,to_ruby(pathname));
return NIL_P(result) ? 0 : reinterpret_cast<FXFileAssoc*>(DATA_PTR(result));
}
//----------------------------------------------------------------------
FXIcon* FXRbCallIconMethod_gvlcb(const FXTableItem* recv,const char *func){
VALUE obj=FXRbGetRubyObj(recv,false);
FXASSERT(!NIL_P(obj));
if(!NIL_P(obj)){
VALUE result=rb_funcall(obj,rb_intern(func),0);
return NIL_P(result) ? 0 : reinterpret_cast<FXIcon*>(DATA_PTR(result));
}
else{
return 0;
}
}
//----------------------------------------------------------------------
FXWindow* FXRbCallWindowMethod_gvlcb(const FXTableItem* recv,const char *func,FXTable* table){
VALUE obj=FXRbGetRubyObj(recv,false);
FXASSERT(!NIL_P(obj));
VALUE result=rb_funcall(obj,rb_intern(func),1,to_ruby_cb(table));
return NIL_P(result) ? 0 : reinterpret_cast<FXWindow*>(DATA_PTR(result));
}
//----------------------------------------------------------------------
// Call function with "FXRange" return value
FXRangef FXRbCallRangeMethod_gvlcb(FXObject* recv,const char *func){
VALUE obj=FXRbGetRubyObj(recv,false);
FXASSERT(!NIL_P(obj));
VALUE result=rb_funcall(obj,rb_intern(func),0);
return *reinterpret_cast<FXRangef*>(DATA_PTR(result));
}
//----------------------------------------------------------------------
// Call functions with FXString return value
FXString FXRbCallStringMethod_gvlcb(const FXObject* recv, const char *func){
VALUE obj=FXRbGetRubyObj(recv,false);
FXASSERT(!NIL_P(obj));
VALUE result=rb_funcall(obj,rb_intern(func),0);
return FXString(StringValuePtr(result));
}
//----------------------------------------------------------------------
// Call functions with const FXchar* return value
const FXchar* FXRbCallCStringMethod_gvlcb(const FXObject* recv, const char *func, const FXchar* message, const FXchar* hint){
VALUE obj=FXRbGetRubyObj(recv,false);
FXASSERT(!NIL_P(obj));
VALUE result=rb_funcall(obj,rb_intern(func),2,to_ruby(message),to_ruby(hint));
return NIL_P(result) ? 0 : StringValuePtr(result);
}
// Call functions with const FXchar* return value
const FXchar* FXRbCallCStringMethod_gvlcb(const FXObject* recv, const char *func, const FXchar* context, const FXchar* message, const FXchar* hint){
VALUE obj=FXRbGetRubyObj(recv,false);
FXASSERT(!NIL_P(obj));
VALUE result=rb_funcall(obj,rb_intern(func),3,to_ruby(context),to_ruby(message),to_ruby(hint));
return NIL_P(result) ? 0 : StringValuePtr(result);
}
//----------------------------------------------------------------------
// Call functions with FXwchar return value
FXwchar FXRbCallWCharMethod_gvlcb(const FXObject* recv, const char *func){
VALUE obj=FXRbGetRubyObj(recv,false);
FXASSERT(!NIL_P(obj));
VALUE result=rb_funcall(obj,rb_intern(func),0);
return static_cast<FXwchar>(NUM2ULONG(result));
}
void FXRbCallSetDashes_gvlcb(FXDC* recv,const char *func,FXuint dashoffset,const FXchar *dashpattern,FXuint dashlength){
rb_funcall(FXRbGetRubyObj(recv,false),rb_intern(func),2,to_ruby(dashoffset),FXRbMakeArray(dashpattern,dashlength));
}
void FXRbCallDCDrawMethod_gvlcb(FXDC* recv, const char * func, FXint x,FXint y,const FXString& string){
rb_funcall(FXRbGetRubyObj(recv,false),rb_intern(func),3,to_ruby(x),to_ruby(y),to_ruby(string)); \
}
void FXRbCallDCDrawMethod_gvlcb(FXDC* recv, const char * func, FXint x,FXint y,const FXchar* string,FXuint length){
rb_funcall(FXRbGetRubyObj(recv,false),rb_intern(func),3,to_ruby(x),to_ruby(y),to_ruby(string,length)); \
}
//----------------------------------------------------------------------
// Special destructors to handle order dependencies
FXRbMenuCommand::~FXRbMenuCommand(){
FXAccelTable *table;
FXWindow *owner;
if(acckey && !FXRbIsInGC(this)){
owner=getShell()->getOwner();
if(owner){
table=owner->getAccelTable();
if(table && table!=reinterpret_cast<FXAccelTable*>(-1)){
table->removeAccel(acckey);
}
}
}
acckey=(FXHotKey)0;
FXRbUnregisterRubyObj(this);
}
FXRbMenuCheck::~FXRbMenuCheck(){
FXAccelTable *table;
FXWindow *owner;
if(acckey && !FXRbIsInGC(this)){
owner=getShell()->getOwner();
if(owner){
table=owner->getAccelTable();
if(table && table!=reinterpret_cast<FXAccelTable*>(-1)){
table->removeAccel(acckey);
}
}
}
acckey=(FXHotKey)0;
FXRbUnregisterRubyObj(this);
}
FXRbMenuRadio::~FXRbMenuRadio(){
FXAccelTable *table;
FXWindow *owner;
if(acckey && !FXRbIsInGC(this)){
owner=getShell()->getOwner();
if(owner){
table=owner->getAccelTable();
if(table && table!=reinterpret_cast<FXAccelTable*>(-1)){
table->removeAccel(acckey);
}
}
}
acckey=(FXHotKey)0;
FXRbUnregisterRubyObj(this);
}
//----------------------------------------------------------------------
// Visit all of the items between fm and to (inclusive), plus their
// child items, and add to the items list
void FXRbTreeList::enumerateItem(FXTreeItem* item,FXObjectListOf<FXTreeItem>& items){
// Add this item to the list
items.append(item);
// Add this item's children
FXRbTreeList::enumerateItems(item->getFirst(),item->getLast(),items);
}
// Visit all of the items between fm and to (inclusive), plus their
// child items, and add to the items list
void FXRbTreeList::enumerateItems(FXTreeItem* fm,FXTreeItem* to,FXObjectListOf<FXTreeItem>& items){
register FXTreeItem *item;
if(fm && to){
do{
item=fm;
fm=fm->getNext();
FXRbTreeList::enumerateItem(item,items);
}
while(item!=to);
}
}
//----------------------------------------------------------------------
/**
* Visit all of the items between fm and to (inclusive), plus their
* child items, and add to the items list.
*/
void FXRbFoldingList::enumerateItem(FXFoldingItem* item,FXObjectListOf<FXFoldingItem>& items){
// Add this item to the list
items.append(item);
// Add this item's children
FXRbFoldingList::enumerateItems(item->getFirst(),item->getLast(),items);
}
/**
* Visit all of the items between fm and to (inclusive), plus their
* child items, and add to the items list.
*/
void FXRbFoldingList::enumerateItems(FXFoldingItem* fm,FXFoldingItem* to,FXObjectListOf<FXFoldingItem>& items){
register FXFoldingItem *item;
if(fm && to){
do{
item=fm;
fm=fm->getNext();
FXRbFoldingList::enumerateItem(item,items);
}
while(item!=to);
}
}
//----------------------------------------------------------------------
static ID id_cmp;
#define SORTFUNC(list, item) \
FXint list::sortFunc(const item* a,const item* b){ \
return list##_sortFunc(a, b); \
} \
FXint list##_sortFunc_gvlcb(const item* a,const item* b){ \
VALUE itemA = FXRbGetRubyObj(const_cast<item*>(a), #item " *"); \
VALUE itemB = FXRbGetRubyObj(const_cast<item*>(b), #item " *"); \
VALUE result=rb_funcall(itemA,id_cmp,1,itemB); \
return static_cast<FXint>(NUM2INT(result)); \
}
SORTFUNC( FXRbComboBox, FXListItem )
SORTFUNC( FXRbFoldingList, FXFoldingItem )
SORTFUNC( FXRbIconList, FXIconItem )
SORTFUNC( FXRbList, FXListItem )
SORTFUNC( FXRbListBox, FXListItem )
SORTFUNC( FXRbTreeList, FXTreeItem )
#undef SORTFUNC
// Feedback buffer sort routine stand-in for FXGLViewer
FXbool FXRbGLViewer::sortProc(FXfloat*& buffer,FXint& used,FXint& size){
return TRUE;
}
/**
* FXRbConvertPtr() is just a wrapper around SWIG_ConvertPtr().
*/
void* FXRbConvertPtr(VALUE obj,swig_type_info* ty){
void *ptr;
SWIG_ConvertPtr(obj,&ptr,ty,1);
return ptr;
}
// Returns an FXInputHandle for this Ruby file object
FXInputHandle FXRbGetReadFileHandle(VALUE obj,FXuint mode) {
int fd;
fd = FIX2INT(rb_funcall(obj, rb_intern("fileno"), 0));
#ifdef WIN32
#ifdef __CYGWIN__
return (FXInputHandle) get_osfhandle(fd);
#else
WSAEVENT hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
long events = 0;
if(mode&INPUT_READ) events |= FD_READ|FD_ACCEPT|FD_OOB;
if(mode&INPUT_EXCEPT) events |= FD_CLOSE|FD_QOS|FD_GROUP_QOS|FD_ROUTING_INTERFACE_CHANGE|FD_ADDRESS_LIST_CHANGE;
if ( WSAEventSelect(_get_osfhandle(fd), hEvent, events) == SOCKET_ERROR ) {
WSACloseEvent( hEvent );
rb_raise( rb_eRuntimeError, "WSAEventSelect sockett error: %d", WSAGetLastError() );
}
rb_iv_set(obj, "FXRuby::FXRbGetReadFileHandle", ULL2NUM((intptr_t)hEvent));
return (FXInputHandle) hEvent;
#endif
#else
return (FXInputHandle) fd;
#endif
}
void FXRbRemoveReadFileHandle(VALUE obj,FXuint mode) {
#ifdef WIN32
WSAEVENT hEvent = (HANDLE)NUM2ULL(rb_iv_get(obj, "FXRuby::FXRbGetReadFileHandle"));
CloseHandle( hEvent );
#endif
}
// Returns an FXInputHandle for this Ruby file object
FXInputHandle FXRbGetWriteFileHandle(VALUE obj,FXuint mode) {
int fd;
#if defined(RUBINIUS)
VALUE vwrite = rb_intern("@write");
if(rb_ivar_defined(obj, vwrite)) obj = rb_ivar_get(obj, vwrite);
fd = FIX2INT(rb_funcall(obj, rb_intern("fileno"), 0));
#else
rb_io_t *fptr;
GetOpenFile(obj, fptr);
VALUE wrio = fptr->tied_io_for_writing;
if(wrio) obj = wrio;
fd = FIX2INT(rb_funcall(obj, rb_intern("fileno"), 0));
#endif
#ifdef WIN32
#ifdef __CYGWIN__
return (FXInputHandle) get_osfhandle(fd);
#else
WSAEVENT hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
long events = 0;
if(mode&INPUT_WRITE) events |= FD_WRITE|FD_CONNECT;
if(mode&INPUT_EXCEPT) events |= FD_CLOSE|FD_QOS|FD_GROUP_QOS|FD_ROUTING_INTERFACE_CHANGE|FD_ADDRESS_LIST_CHANGE;
if ( WSAEventSelect(_get_osfhandle(fd), hEvent, events) == SOCKET_ERROR ) {
WSACloseEvent( hEvent );
rb_raise( rb_eRuntimeError, "WSAEventSelect sockettt error: %d", WSAGetLastError() );
}
rb_iv_set(obj, "FXRuby::FXRbGetWriteFileHandle", ULL2NUM((intptr_t)hEvent));
return (FXInputHandle) hEvent;
#endif
#else
return (FXInputHandle) fd;
#endif
}
void FXRbRemoveWriteFileHandle(VALUE obj,FXuint mode) {
#ifdef WIN32
WSAEVENT hEvent = (HANDLE)NUM2ULL(rb_iv_get(obj, "FXRuby::FXRbGetWriteFileHandle"));
CloseHandle( hEvent );
#endif
}
//----------------------------------------------------------------------
// Copied from the Ruby 1.8.6 sources (signal.c)
static struct signals {
const char *signm;
int signo;
} siglist [] = {
{"EXIT", 0},
#ifdef SIGHUP
{"HUP", SIGHUP},
#endif
{"INT", SIGINT},
#ifdef SIGQUIT
{"QUIT", SIGQUIT},
#endif
#ifdef SIGILL
{"ILL", SIGILL},
#endif
#ifdef SIGTRAP
{"TRAP", SIGTRAP},
#endif
#ifdef SIGIOT
{"IOT", SIGIOT},
#endif
#ifdef SIGABRT
{"ABRT", SIGABRT},
#endif
#ifdef SIGEMT
{"EMT", SIGEMT},
#endif
#ifdef SIGFPE
{"FPE", SIGFPE},
#endif
#ifdef SIGKILL
{"KILL", SIGKILL},
#endif
#ifdef SIGBUS
{"BUS", SIGBUS},
#endif
#ifdef SIGSEGV
{"SEGV", SIGSEGV},
#endif
#ifdef SIGSYS
{"SYS", SIGSYS},
#endif
#ifdef SIGPIPE
{"PIPE", SIGPIPE},
#endif
#ifdef SIGALRM
{"ALRM", SIGALRM},
#endif
#ifdef SIGTERM
{"TERM", SIGTERM},
#endif
#ifdef SIGURG
{"URG", SIGURG},
#endif
#ifdef SIGSTOP
{"STOP", SIGSTOP},
#endif
#ifdef SIGTSTP
{"TSTP", SIGTSTP},
#endif
#ifdef SIGCONT
{"CONT", SIGCONT},
#endif
#ifdef SIGCHLD
{"CHLD", SIGCHLD},
#endif
#ifdef SIGCLD
{"CLD", SIGCLD},
#else
# ifdef SIGCHLD
{"CLD", SIGCHLD},
# endif
#endif
#ifdef SIGTTIN
{"TTIN", SIGTTIN},
#endif
#ifdef SIGTTOU
{"TTOU", SIGTTOU},
#endif
#ifdef SIGIO
{"IO", SIGIO},
#endif
#ifdef SIGXCPU
{"XCPU", SIGXCPU},
#endif
#ifdef SIGXFSZ
{"XFSZ", SIGXFSZ},
#endif
#ifdef SIGVTALRM
{"VTALRM", SIGVTALRM},
#endif
#ifdef SIGPROF
{"PROF", SIGPROF},
#endif
#ifdef SIGWINCH
{"WINCH", SIGWINCH},
#endif
#ifdef SIGUSR1
{"USR1", SIGUSR1},
#endif
#ifdef SIGUSR2
{"USR2", SIGUSR2},
#endif
#ifdef SIGLOST
{"LOST", SIGLOST},
#endif
#ifdef SIGMSG
{"MSG", SIGMSG},
#endif
#ifdef SIGPWR
{"PWR", SIGPWR},
#endif
#ifdef SIGPOLL
{"POLL", SIGPOLL},
#endif
#ifdef SIGDANGER
{"DANGER", SIGDANGER},
#endif
#ifdef SIGMIGRATE
{"MIGRATE", SIGMIGRATE},
#endif
#ifdef SIGPRE
{"PRE", SIGPRE},
#endif
#ifdef SIGGRANT
{"GRANT", SIGGRANT},
#endif
#ifdef SIGRETRACT
{"RETRACT", SIGRETRACT},
#endif
#ifdef SIGSOUND
{"SOUND", SIGSOUND},
#endif
#ifdef SIGINFO
{"INFO", SIGINFO},
#endif
{NULL, 0}
};
FXint FXRbSignalNameToNumber(const char* s){
#ifdef HAVE_SIGNAL_H
const char *nm=s;
if(strncmp("SIG",nm,3)==0){
nm+=3;
}
for(signals* sigs=siglist;sigs->signm;sigs++){
if(strcmp(sigs->signm,nm)==0)
return sigs->signo;
}
#endif /* HAVE_SIGNAL_H */
return 0;
}
//----------------------------------------------------------------------
/*
* The Ruby header files define a TYPE(x) macro that conflicts with the
* TYPE template parameter used in FXArray.h and FXElement.h.
*/
#ifdef TYPE
#undef TYPE
#endif
#include <new>
#include "FXArray.h"
#include "FXElement.h"
static st_table * appSensitiveObjs;
static st_table * appSensitiveDCs;
void FXRbRegisterAppSensitiveObject(FXObject* obj){
FXASSERT(obj!=0);
FXTRACE((100,"%s:%d: FXRbRegisterAppSensitiveObject(obj=%p(%s))\n",__FILE__,__LINE__,obj,obj->getClassName()));
st_insert(appSensitiveObjs,reinterpret_cast<st_data_t>(obj),(st_data_t)0);
FXASSERT(st_lookup(appSensitiveObjs,reinterpret_cast<st_data_t>(obj),reinterpret_cast<st_data_t *>(0))!=0);
}
void FXRbRegisterAppSensitiveObject(FXDC* dc){
FXASSERT(dc!=0);
FXTRACE((100,"%s:%d: FXRbRegisterAppSensitiveObject(dc=%p)\n",__FILE__,__LINE__,dc));
st_insert(appSensitiveDCs,reinterpret_cast<st_data_t>(dc),(st_data_t)0);
FXASSERT(st_lookup(appSensitiveDCs,reinterpret_cast<st_data_t>(dc),reinterpret_cast<st_data_t *>(0))!=0);
}
void FXRbUnregisterAppSensitiveObject(FXObject* obj){
FXASSERT(obj!=0);
FXTRACE((100,"%s:%d: FXRbUnregisterAppSensitiveObject(obj=%p(%s))\n",__FILE__,__LINE__,obj,obj->getClassName()));
st_delete(appSensitiveObjs,reinterpret_cast<st_data_t *>(&obj),reinterpret_cast<st_data_t *>(0));
FXASSERT(st_lookup(appSensitiveObjs,reinterpret_cast<st_data_t>(obj),reinterpret_cast<st_data_t *>(0))==0);
}
void FXRbUnregisterAppSensitiveObject(FXDC* dc){
FXASSERT(dc!=0);
FXTRACE((100,"%s:%d: FXRbUnregisterAppSensitiveObject(dc=%p)\n",__FILE__,__LINE__,dc));
st_delete(appSensitiveDCs,reinterpret_cast<st_data_t *>(&dc),reinterpret_cast<st_data_t *>(0));
FXASSERT(st_lookup(appSensitiveDCs,reinterpret_cast<st_data_t>(dc),reinterpret_cast<st_data_t *>(0))==0);
}
static int st_cbfunc_obj(st_data_t key,st_data_t,st_data_t arg){
FXASSERT(key!=0);
FXASSERT(arg!=0);
FXObjectListOf<FXObject> *pObjectList=reinterpret_cast<FXObjectListOf<FXObject>*>(arg);
FXObject *pObject=reinterpret_cast<FXObject*>(key);
pObjectList->append(pObject);
return 0;
}
static int st_cbfunc_dc(st_data_t key,st_data_t,st_data_t arg){
FXASSERT(key!=0);
FXASSERT(arg!=0);
FXArray<FXDC*> *pDCArray=reinterpret_cast<FXArray<FXDC*>*>(arg);
FXDC *pDC=reinterpret_cast<FXDC*>(key);
pDCArray->append(pDC);
return 0;
}
void FXRbDestroyAppSensitiveObjects(){
FXTRACE((100,"%s:%d: Begin destroying objects that hold references to the FXApp...\n",__FILE__,__LINE__));
FXObjectListOf<FXObject> objs;
st_foreach(appSensitiveObjs,RUBY_INT_METHOD_FUNC(st_cbfunc_obj),reinterpret_cast<st_data_t>(&objs));
for(FXint i=0;i<objs.no();i++){
if(objs[i]->isMemberOf(FXMETACLASS(FXRbCursor))){
if(dynamic_cast<FXRbCursor*>(objs[i])->ownedByApp)
continue;
}
else if(objs[i]->isMemberOf(FXMETACLASS(FXRbCURCursor))){
if(dynamic_cast<FXRbCURCursor*>(objs[i])->ownedByApp)
continue;
}
else if(objs[i]->isMemberOf(FXMETACLASS(FXRbGIFCursor))){
if(dynamic_cast<FXRbGIFCursor*>(objs[i])->ownedByApp)
continue;
}
else if(objs[i]->isMemberOf(FXMETACLASS(FXRbFont))){
if(dynamic_cast<FXRbFont*>(objs[i])->ownedByApp)
continue;
}
else if(objs[i]->isMemberOf(FXMETACLASS(FXRbGLVisual))){
if(dynamic_cast<FXRbGLVisual*>(objs[i])->ownedByApp)
continue;
}
else if(objs[i]->isMemberOf(FXMETACLASS(FXRbVisual))){
if(dynamic_cast<FXRbVisual*>(objs[i])->ownedByApp)
continue;
}
delete objs[i];
}
FXArray<FXDC*> dcs;
st_foreach(appSensitiveDCs,RUBY_INT_METHOD_FUNC(st_cbfunc_dc),reinterpret_cast<st_data_t>(&dcs));
for(FXint j=0;j<dcs.no();j++){
delete dcs[j];
}
FXTRACE((100,"%s:%d: Finished destroying objects that hold references to the FXApp.\n",__FILE__,__LINE__));
}
int utf8_enc_idx;
//----------------------------------------------------------------------
extern "C" void Init_core(void);
extern "C" void Init_dc(void);
extern "C" void Init_dialogs(void);
extern "C" void Init_frames(void);
extern "C" void Init_fx3d(void);
extern "C" void Init_image(void);
extern "C" void Init_iconlist(void);
extern "C" void Init_icons(void);
extern "C" void Init_label(void);
extern "C" void Init_layout(void);
extern "C" void Init_list(void);
extern "C" void Init_mdi(void);
extern "C" void Init_menu(void);
#ifdef WITH_FXSCINTILLA
extern "C" void Init_scintilla(void);
#endif
extern "C" void Init_table(void);
extern "C" void Init_text(void);
extern "C" void Init_treelist(void);
extern "C" void Init_ui(void);
extern "C" void
#if defined _WIN32
__declspec(dllexport)
#endif
Init_fox16_c(void) {
Init_core();
Init_dc();
Init_frames();
Init_layout();
Init_label();
Init_ui();
Init_iconlist();
Init_list();
Init_dialogs();
Init_image();
Init_icons();
Init_menu();
Init_mdi();
Init_fx3d();
#ifdef WITH_FXSCINTILLA
Init_scintilla();
#endif
Init_table();
Init_text();
Init_treelist();
id_assocs=rb_intern("@assocs");
id_backtrace=rb_intern("backtrace");
id_cmp=rb_intern("<=>");
id_begin=rb_intern("begin");
id_end=rb_intern("end");
id_exclude_endp=rb_intern("exclude_end?");
#ifdef HAVE_RUBY_ENCODING_H
utf8_enc_idx = rb_enc_find_index("UTF-8");
#endif
appSensitiveObjs=st_init_numtable();
appSensitiveDCs=st_init_numtable();
}