Skip to content
Snippets Groups Projects
FXRuby.cpp 64.2 KiB
Newer Older
/***********************************************************************
 * 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 "lyle@lylejohnson.name".
 ***********************************************************************/

/***********************************************************************
 * $Id: FXRuby.cpp 2933 2008-12-29 20:19:33Z lyle $
 ***********************************************************************/

#ifdef _MSC_VER
#pragma warning (disable : 4786)
#endif

#include "FXRbCommon.h"
#include "impl.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"
extern "C" {
#include "st.h"
#include "rubyio.h"     // for GetOpenFile(), etc.
// Opaque type declaration from SWIG runtime
struct swig_type_info;

// 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_Ruby_TypeQuery(desc);
    st_insert(types,reinterpret_cast<st_data_t>(strdup(desc)),reinterpret_cast<st_data_t>(typeinfo));
    }
  FXASSERT(typeinfo!=0);
  return typeinfo;
  }


/**
 * The FXRuby_Objects hash table basically maps C++ objects to Ruby instances.
 * Each key in the table is a pointer to a C++ object we've seen before, and
 * the corresponding value is an FXRubyObjDesc struct (see below) that tells
 * us which Ruby instance corresponds to that C++ object.
 */

static st_table * FXRuby_Objects;

/**
 * Each value in the FXRuby_Objects hash table is an instance of this
 * struct. It identifies the Ruby instance associated with a C++ object.
 * It also indicates whether this is merely a "borrowed" reference to
 * some C++ object (i.e. it's not one we need to destroy later).
 *
 * in_gc is set for FXWindows that are in garbage collection and must
 * not call ruby code anymore.
 */

struct FXRubyObjDesc {
  VALUE obj;
  bool borrowed;
  bool in_gc;
  };


/**
 * FXRbNewPointerObj() is a wrapper around SWIG_Ruby_NewPointerObj() that also
 * registers this C++ object & Ruby instance pair in our FXRuby_Objects
 * hash table. This function should only get called for methods that return
 * a reference to an already-existing C++ object (i.e. one that FOX "owns")
 * and for that reason we mark these objects as "borrowed".
 */

VALUE FXRbNewPointerObj(void *ptr,swig_type_info* ty){
  if(ptr!=0){
    FXASSERT(ty!=0);
    VALUE obj;
    FXRubyObjDesc *desc;
    if(FXMALLOC(&desc,FXRubyObjDesc,1)){
      obj=SWIG_Ruby_NewPointerObj(ptr,ty,1);
      FXTRACE((1,"FXRbNewPointerObj(rubyObj=%d,foxObj=%p)\n",static_cast<int>(obj),ptr));
      desc->obj=obj;
      desc->borrowed=true;
      desc->in_gc=false;
      int overwritten = st_insert(FXRuby_Objects,reinterpret_cast<st_data_t>(ptr),reinterpret_cast<st_data_t>(desc));
      FXASSERT(!overwritten);
      return obj;
      }
    else{
      FXASSERT(FALSE);
      return Qnil;
      }
    }
  else{
    return Qnil;
    }
  }


/**
 * FXRbIsBorrowed() returns true if the specified C++ object is one that
 * FOX owns (i.e. it's borrowed).
 */

bool FXRbIsBorrowed(void* ptr){
  FXASSERT(ptr!=0);
  FXRubyObjDesc *desc;
  if(st_lookup(FXRuby_Objects,reinterpret_cast<st_data_t>(ptr),reinterpret_cast<st_data_t *>(&desc))!=0){
    return desc->borrowed;
    }
  else{
    return true;
    }
  }

bool FXRbSetInGC(const void* ptr, bool enabled){
  FXASSERT(ptr!=0);
  FXRubyObjDesc *desc;
  if(st_lookup(FXRuby_Objects,reinterpret_cast<st_data_t>(ptr),reinterpret_cast<st_data_t *>(&desc))!=0){
    desc->in_gc=enabled;
    return enabled;
    }
  return false;
  }

bool FXRbIsInGC(const void* ptr){
  FXASSERT(ptr!=0);
  FXRubyObjDesc *desc;
  if(st_lookup(FXRuby_Objects,reinterpret_cast<st_data_t>(ptr),reinterpret_cast<st_data_t *>(&desc))!=0){
    return desc->in_gc;
    }
  return false;
  }


/**
 * FXRbConvertPtr() is just a wrapper around SWIG_Ruby_ConvertPtr().
 */

void* FXRbConvertPtr(VALUE obj,swig_type_info* ty){
  void *ptr;
  SWIG_Ruby_ConvertPtr(obj,&ptr,ty,1);
  return ptr;
  }


// Should we catch exceptions thrown by message handlers?
FXbool FXRbCatchExceptions=FALSE;

// Returns an FXInputHandle for this Ruby file object
FXInputHandle FXRbGetReadFileHandle(VALUE obj) {
  int fd;
  fd = FIX2INT(rb_funcall(obj, rb_intern("fileno"), 0));
#ifdef WIN32
#ifdef __CYGWIN__
  return (FXInputHandle) get_osfhandle(fd);
  return (FXInputHandle) _get_osfhandle(fd);
#endif
  }


// Returns an FXInputHandle for this Ruby file object
Loading
Loading full blame...