TDE programming language bindings
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1988 lines
51 KiB

/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include <tqstring.h>
#include <tqregexp.h>
#include <tqapplication.h>
#include <tqcanvas.h>
#include <tqlistview.h>
#include <tqiconview.h>
#include <tqtable.h>
#include <tqpopupmenu.h>
#include <tqlayout.h>
#include <tqmetaobject.h>
#include <tqvaluelist.h>
#include <tqobjectlist.h>
#include <tqtextcodec.h>
#include <tqhostaddress.h>
#include <tqpair.h>
#include <private/qucomextra_p.h>
#include "smoke.h"
#undef DEBUG
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#ifndef __USE_POSIX
#define __USE_POSIX
#endif
#ifndef __USE_XOPEN
#define __USE_XOPEN
#endif
#include <ruby.h>
#include "marshall.h"
#include "qtruby.h"
#include "smokeruby.h"
#ifndef HINT_BYTES
#define HINT_BYTES HINT_BYTE
#endif
#define HAVE_STRLCAT_PROTO 1
#define HAVE_STRLCPY_PROTO 1
#include "config.h"
#ifndef HAVE_RUBY_1_9
#define RARRAY_LEN(x) (RARRAY(x)->len)
#define RSTRING_LEN(x) (RSTRING(x)->len)
#define rb_str_catf_1 rb_str_catf
#endif
extern "C" {
extern VALUE set_obj_info(const char * className, smokeruby_object * o);
extern VALUE qt_internal_module;
extern VALUE qvariant_class;
extern bool application_terminated;
};
extern bool isDerivedFromByName(Smoke *smoke, const char *className, const char *baseClassName);
extern void mapPointer(VALUE obj, smokeruby_object *o, Smoke::Index classId, void *lastptr);
static const char * (*_kde_resolve_classname)(Smoke*, int, void*) = 0;
extern "C" {
void
set_kde_resolve_classname(const char * (*kde_resolve_classname) (Smoke*, int, void *))
{
_kde_resolve_classname = kde_resolve_classname;
}
};
void
mark_qobject_children(TQObject * qobject)
{
VALUE obj;
const TQObjectList *l = qobject->children();
if (l == 0) {
return;
}
TQObjectListIt it( *l ); // iterate over the children
TQObject *child;
while ( (child = it.current()) != 0 ) {
++it;
obj = getPointerObject(child);
if (obj != Qnil) {
if(do_debug & qtdb_gc) tqWarning("Marking (%s*)%p -> %p\n", child->className(), child, (void*)obj);
rb_gc_mark(obj);
}
mark_qobject_children(child);
}
}
void
smokeruby_mark(void * p)
{
VALUE obj;
smokeruby_object * o = (smokeruby_object *) p;
const char *className = o->smoke->classes[o->classId].className;
if(do_debug & qtdb_gc) tqWarning("Checking for mark (%s*)%p\n", className, o->ptr);
if(o->ptr && o->allocated) {
if (isDerivedFromByName(o->smoke, className, "TQListView")) {
TQListView * listview = (TQListView *) o->smoke->cast(o->ptr, o->classId, o->smoke->idClass("TQListView"));
TQListViewItemIterator it(listview);
TQListViewItem *item;
while ( (item = it.current()) != 0 ) {
++it;
obj = getPointerObject(item);
if (obj != Qnil) {
if(do_debug & qtdb_gc) tqWarning("Marking (%s*)%p -> %p\n", className, item, (void*)obj);
rb_gc_mark(obj);
}
}
return;
}
if (isDerivedFromByName(o->smoke, className, "TQTable")) {
TQTable * table = (TQTable *) o->smoke->cast(o->ptr, o->classId, o->smoke->idClass("TQTable"));
TQTableItem *item;
for ( int row = 0; row < table->numRows(); row++ ) {
for ( int col = 0; col < table->numCols(); col++ ) {
item = table->item(row, col);
obj = getPointerObject(item);
if (obj != Qnil) {
if(do_debug & qtdb_gc) tqWarning("Marking (%s*)%p -> %p\n", className, item, (void*)obj);
rb_gc_mark(obj);
}
}
}
return;
}
if (isDerivedFromByName(o->smoke, className, "TQCanvas")) {
TQCanvas * canvas = (TQCanvas *) o->smoke->cast(o->ptr, o->classId, o->smoke->idClass("TQCanvas"));
TQCanvasItemList list = canvas->allItems();
for ( TQCanvasItemList::iterator it = list.begin(); it != list.end(); ++it ) {
obj = getPointerObject(*it);
if (obj != Qnil) {
if(do_debug & qtdb_gc) tqWarning("Marking (%s*)%p -> %p\n", className, *it, (void*)obj);
rb_gc_mark(obj);
}
}
return;
}
if (isDerivedFromByName(o->smoke, className, "TQCanvasItem")) {
TQCanvasItem * item = (TQCanvasItem *) o->smoke->cast(o->ptr, o->classId, o->smoke->idClass("TQCanvasItem"));
TQCanvas * canvas = item->canvas();
obj = getPointerObject(canvas);
if (obj != Qnil) {
if(do_debug & qtdb_gc) tqWarning("Marking (%s*)%p -> %p\n", "TQCanvas", canvas, (void*)obj);
rb_gc_mark(obj);
}
return;
}
if (isDerivedFromByName(o->smoke, className, "TQObject")) {
TQObject * qobject = (TQObject *) o->smoke->cast(o->ptr, o->classId, o->smoke->idClass("TQObject"));
mark_qobject_children(qobject);
return;
}
}
}
void
smokeruby_free(void * p)
{
smokeruby_object *o = (smokeruby_object*)p;
const char *className = o->smoke->classes[o->classId].className;
if(do_debug & qtdb_gc) tqWarning("Checking for delete (%s*)%p allocated: %s\n", className, o->ptr, o->allocated ? "true" : "false");
if(application_terminated || !o->allocated || o->ptr == 0) {
free(o);
return;
}
unmapPointer(o, o->classId, 0);
object_count --;
if ( tqstrcmp(className, "TQObject") == 0
|| tqstrcmp(className, "TQListBoxItem") == 0
|| tqstrcmp(className, "TQStyleSheetItem") == 0
|| tqstrcmp(className, "KCommand") == 0
|| tqstrcmp(className, "KNamedCommand") == 0
|| tqstrcmp(className, "KMacroCommand") == 0
|| tqstrcmp(className, "TDEAboutData") == 0
|| tqstrcmp(className, "TDECmdLineArgs") == 0
|| tqstrcmp(className, "TQSqlCursor") == 0 )
{
// Don't delete instances of these classes for now
free(o);
return;
} else if (isDerivedFromByName(o->smoke, className, "TQLayoutItem")) {
TQLayoutItem * item = (TQLayoutItem *) o->smoke->cast(o->ptr, o->classId, o->smoke->idClass("TQLayoutItem"));
if (item->layout() != 0 || item->widget() != 0 || item->spacerItem() != 0) {
free(o);
return;
}
} else if (tqstrcmp(className, "TQIconViewItem") == 0) {
TQIconViewItem * item = (TQIconViewItem *) o->ptr;
if (item->iconView() != 0) {
free(o);
return;
}
} else if (tqstrcmp(className, "TQCheckListItem") == 0) {
TQCheckListItem * item = (TQCheckListItem *) o->ptr;
if (item->parent() != 0 || item->listView() != 0) {
free(o);
return;
}
} else if (tqstrcmp(className, "TQListViewItem") == 0) {
TQListViewItem * item = (TQListViewItem *) o->ptr;
if (item->parent() != 0 || item->listView() != 0) {
free(o);
return;
}
} else if (isDerivedFromByName(o->smoke, className, "TQTableItem")) {
TQTableItem * item = (TQTableItem *) o->smoke->cast(o->ptr, o->classId, o->smoke->idClass("TQTableItem"));
if (item->table() != 0) {
free(o);
return;
}
} else if (tqstrcmp(className, "TQPopupMenu") == 0) {
TQPopupMenu * item = (TQPopupMenu *) o->ptr;
if (item->parentWidget(false) != 0) {
free(o);
return;
}
} else if (isDerivedFromByName(o->smoke, className, "TQWidget")) {
TQWidget * qwidget = (TQWidget *) o->smoke->cast(o->ptr, o->classId, o->smoke->idClass("TQWidget"));
if (qwidget->parentWidget(true) != 0) {
free(o);
return;
}
} else if (isDerivedFromByName(o->smoke, className, "TQObject")) {
TQObject * qobject = (TQObject *) o->smoke->cast(o->ptr, o->classId, o->smoke->idClass("TQObject"));
if (qobject->parent() != 0) {
free(o);
return;
}
}
if(do_debug & qtdb_gc) tqWarning("Deleting (%s*)%p\n", className, o->ptr);
char *methodName = new char[strlen(className) + 2];
methodName[0] = '~';
strcpy(methodName + 1, className);
Smoke::Index nameId = o->smoke->idMethodName(methodName);
Smoke::Index meth = o->smoke->findMethod(o->classId, nameId);
if(meth > 0) {
Smoke::Method &m = o->smoke->methods[o->smoke->methodMaps[meth].method];
Smoke::ClassFn fn = o->smoke->classes[m.classId].classFn;
Smoke::StackItem i[1];
(*fn)(m.method, o->ptr, i);
}
delete[] methodName;
free(o);
return;
}
/*
* Given an approximate classname and a qt instance, try to improve the resolution of the name
* by using the various Qt rtti mechanisms for TQObjects, TQEvents and TQCanvasItems
*/
static const char *
resolve_classname(Smoke* smoke, int classId, void * ptr)
{
if (isDerivedFromByName(smoke, smoke->classes[classId].className, "TQEvent")) {
TQEvent * qevent = (TQEvent *) smoke->cast(ptr, classId, smoke->idClass("TQEvent"));
switch (qevent->type()) {
case TQEvent::ChildInserted:
case TQEvent::ChildRemoved:
return "TQt::ChildEvent";
case TQEvent::Close:
return "TQt::CloseEvent";
case TQEvent::ContextMenu:
return "TQt::ContextMenuEvent";
// case TQEvent::User:
// return "TQt::CustomEvent";
case TQEvent::DragEnter:
return "TQt::DragEnterEvent";
case TQEvent::DragLeave:
return "TQt::DragLeaveEvent";
case TQEvent::DragMove:
return "TQt::DragMoveEvent";
case TQEvent::DragResponse:
return "TQt::DragResponseEvent";
case TQEvent::Drop:
return "TQt::DropEvent";
case TQEvent::FocusIn:
case TQEvent::FocusOut:
return "TQt::FocusEvent";
case TQEvent::Hide:
return "TQt::HideEvent";
case TQEvent::KeyPress:
case TQEvent::KeyRelease:
return "TQt::KeyEvent";
case TQEvent::IMStart:
case TQEvent::IMCompose:
case TQEvent::IMEnd:
return "TQt::IMEvent";
case TQEvent::MouseButtonPress:
case TQEvent::MouseButtonRelease:
case TQEvent::MouseButtonDblClick:
case TQEvent::MouseMove:
return "TQt::MouseEvent";
case TQEvent::Move:
return "TQt::MoveEvent";
case TQEvent::Paint:
return "TQt::PaintEvent";
case TQEvent::Resize:
return "TQt::ResizeEvent";
case TQEvent::Show:
return "TQt::ShowEvent";
// case TQEvent::Tablet:
// return "TQt::TabletEvent";
case TQEvent::Timer:
return "TQt::TimerEvent";
case TQEvent::Wheel:
return "TQt::WheelEvent";
default:
break;
}
} else if (isDerivedFromByName(smoke, smoke->classes[classId].className, "TQObject")) {
TQObject * qobject = (TQObject *) smoke->cast(ptr, classId, smoke->idClass("TQObject"));
TQMetaObject * meta = qobject->metaObject();
while (meta != 0) {
Smoke::Index classId = smoke->idClass(meta->className());
if (classId != 0) {
return smoke->binding->className(classId);
}
meta = meta->superClass();
}
} else if (isDerivedFromByName(smoke, smoke->classes[classId].className, "TQCanvasItem")) {
TQCanvasItem * qcanvasitem = (TQCanvasItem *) smoke->cast(ptr, classId, smoke->idClass("TQCanvasItem"));
switch (qcanvasitem->rtti()) {
case TQCanvasItem::Rtti_Sprite:
return "TQt::CanvasSprite";
case TQCanvasItem::Rtti_PolygonalItem:
return "TQt::CanvasPolygonalItem";
case TQCanvasItem::Rtti_Text:
return "TQt::CanvasText";
case TQCanvasItem::Rtti_Polygon:
return "TQt::CanvasPolygon";
case TQCanvasItem::Rtti_Rectangle:
return "TQt::CanvasRectangle";
case TQCanvasItem::Rtti_Ellipse:
return "TQt::CanvasEllipse";
case TQCanvasItem::Rtti_Line:
return "TQt::CanvasLine";
case TQCanvasItem::Rtti_Spline:
return "TQt::CanvasSpline";
default:
break;
}
} else if (isDerivedFromByName(smoke, smoke->classes[classId].className, "TQListViewItem")) {
TQListViewItem * item = (TQListViewItem *) smoke->cast(ptr, classId, smoke->idClass("TQListViewItem"));
switch (item->rtti()) {
case 0:
return "TQt::ListViewItem";
case 1:
return "TQt::CheckListItem";
default:
return "TQt::ListViewItem";
break;
}
} else if (isDerivedFromByName(smoke, smoke->classes[classId].className, "TQTableItem")) {
TQTableItem * item = (TQTableItem *) smoke->cast(ptr, classId, smoke->idClass("TQTableItem"));
switch (item->rtti()) {
case 0:
return "TQt::TableItem";
case 1:
return "TQt::ComboTableItem";
case 2:
return "TQt::CheckTableItem";
default:
return "TQt::TableItem";
break;
}
}
if (_kde_resolve_classname != 0) {
return (*_kde_resolve_classname)(smoke, classId, ptr);
}
return smoke->binding->className(classId);
}
bool
matches_arg(Smoke *smoke, Smoke::Index meth, Smoke::Index argidx, const char *argtype)
{
Smoke::Index *arg = smoke->argumentList + smoke->methods[meth].args + argidx;
SmokeType type = SmokeType(smoke, *arg);
return type.name() && tqstrcmp(type.name(), argtype) == 0;
}
void *
construct_copy(smokeruby_object *o)
{
const char *className = o->smoke->className(o->classId);
int classNameLen = strlen(className);
char *ccSig = new char[classNameLen + 2]; // copy constructor signature
strcpy(ccSig, className);
strcat(ccSig, "#");
Smoke::Index ccId = o->smoke->idMethodName(ccSig);
delete[] ccSig;
char *ccArg = new char[classNameLen + 8];
sprintf(ccArg, "const %s&", className);
Smoke::Index ccMeth = o->smoke->findMethod(o->classId, ccId);
if(!ccMeth) {
delete[] ccArg;
return 0;
}
Smoke::Index method = o->smoke->methodMaps[ccMeth].method;
if(method > 0) {
// Make sure it's a copy constructor
if(!matches_arg(o->smoke, method, 0, ccArg)) {
delete[] ccArg;
return 0;
}
delete[] ccArg;
ccMeth = method;
} else {
// ambiguous method, pick the copy constructor
Smoke::Index i = -method;
while(o->smoke->ambiguousMethodList[i]) {
if(matches_arg(o->smoke, o->smoke->ambiguousMethodList[i], 0, ccArg))
break;
i++;
}
delete[] ccArg;
ccMeth = o->smoke->ambiguousMethodList[i];
if(!ccMeth)
return 0;
}
// Okay, ccMeth is the copy constructor. Time to call it.
Smoke::StackItem args[2];
args[0].s_voidp = 0;
args[1].s_voidp = o->ptr;
Smoke::ClassFn fn = o->smoke->classes[o->classId].classFn;
(*fn)(o->smoke->methods[ccMeth].method, 0, args);
return args[0].s_voidp;
}
void
marshall_basetype(Marshall *m)
{
switch(m->type().elem()) {
case Smoke::t_bool:
switch(m->action()) {
case Marshall::FromVALUE:
if (TYPE(*(m->var())) == T_OBJECT) {
// A TQt::Boolean has been passed as a value
VALUE temp = rb_funcall(qt_internal_module, rb_intern("get_qboolean"), 1, *(m->var()));
m->item().s_bool = (temp == Qtrue ? true : false);
} else {
m->item().s_bool = (*(m->var()) == Qtrue ? true : false);
}
break;
case Marshall::ToVALUE:
*(m->var()) = m->item().s_bool ? Qtrue : Qfalse;
break;
default:
m->unsupported();
break;
}
break;
case Smoke::t_char:
switch(m->action()) {
case Marshall::FromVALUE:
m->item().s_char = NUM2CHR(*(m->var()));
break;
case Marshall::ToVALUE:
*(m->var()) = CHR2FIX(m->item().s_char);
break;
default:
m->unsupported();
break;
}
break;
case Smoke::t_uchar:
switch(m->action()) {
case Marshall::FromVALUE:
m->item().s_uchar = NUM2CHR(*(m->var()));
break;
case Marshall::ToVALUE:
*(m->var()) = CHR2FIX(m->item().s_uchar);
break;
default:
m->unsupported();
break;
}
break;
case Smoke::t_short:
switch(m->action()) {
case Marshall::FromVALUE:
m->item().s_short = (short) NUM2INT(*(m->var()));
break;
case Marshall::ToVALUE:
*(m->var()) = INT2NUM(m->item().s_short);
break;
default:
m->unsupported();
break;
}
break;
case Smoke::t_ushort:
switch(m->action()) {
case Marshall::FromVALUE:
m->item().s_ushort = (unsigned short) NUM2UINT(*(m->var()));
break;
case Marshall::ToVALUE:
*(m->var()) = UINT2NUM(m->item().s_ushort);
break;
default:
m->unsupported();
break;
}
break;
case Smoke::t_int:
switch(m->action()) {
case Marshall::FromVALUE:
if (TYPE(*(m->var())) == T_OBJECT) {
m->item().s_int = (int) NUM2INT(rb_funcall(qt_internal_module, rb_intern("get_qinteger"), 1, *(m->var())));
} else {
m->item().s_int = (int) NUM2INT(*(m->var()));
}
break;
case Marshall::ToVALUE:
*(m->var()) = INT2NUM(m->item().s_int);
break;
default:
m->unsupported();
break;
}
break;
case Smoke::t_uint:
switch(m->action()) {
case Marshall::FromVALUE:
if (TYPE(*(m->var())) == T_OBJECT) {
m->item().s_int = (unsigned int) NUM2UINT(rb_funcall(qt_internal_module, rb_intern("get_qinteger"), 1, *(m->var())));
} else {
m->item().s_uint = (unsigned int) NUM2UINT(*(m->var()));
}
break;
case Marshall::ToVALUE:
*(m->var()) = UINT2NUM(m->item().s_uint);
break;
default:
m->unsupported();
break;
}
break;
case Smoke::t_long:
switch(m->action()) {
case Marshall::FromVALUE:
if (TYPE(*(m->var())) == T_OBJECT) {
m->item().s_int = (long) NUM2LONG(rb_funcall(qt_internal_module, rb_intern("get_qinteger"), 1, *(m->var())));
} else {
m->item().s_long = (long) NUM2LONG(*(m->var()));
}
break;
case Marshall::ToVALUE:
*(m->var()) = INT2NUM(m->item().s_long);
break;
default:
m->unsupported();
break;
}
break;
case Smoke::t_ulong:
switch(m->action()) {
case Marshall::FromVALUE:
if (TYPE(*(m->var())) == T_OBJECT) {
m->item().s_int = (unsigned long) NUM2ULONG(rb_funcall(qt_internal_module, rb_intern("get_qinteger"), 1, *(m->var())));
} else {
m->item().s_ulong = (unsigned long) NUM2ULONG(*(m->var()));
}
break;
case Marshall::ToVALUE:
*(m->var()) = INT2NUM(m->item().s_ulong);
break;
default:
m->unsupported();
break;
}
break;
case Smoke::t_float:
switch(m->action()) {
case Marshall::FromVALUE:
m->item().s_float = (float) NUM2DBL(*(m->var()));
break;
case Marshall::ToVALUE:
*(m->var()) = rb_float_new((double) m->item().s_float);
break;
default:
m->unsupported();
break;
}
break;
case Smoke::t_double:
switch(m->action()) {
case Marshall::FromVALUE:
m->item().s_double = (double) NUM2DBL(*(m->var()));
break;
case Marshall::ToVALUE:
*(m->var()) = rb_float_new(m->item().s_double);
break;
default:
m->unsupported();
break;
}
break;
case Smoke::t_enum:
switch(m->action()) {
case Marshall::FromVALUE:
{
if (TYPE(*(m->var())) == T_OBJECT) {
// A TQt::Enum is a subclass of TQt::Integer, so 'get_qinteger()' can be called ok
VALUE temp = rb_funcall(qt_internal_module, rb_intern("get_qinteger"), 1, *(m->var()));
m->item().s_enum = (long) NUM2LONG(temp);
} else {
m->item().s_enum = (long) NUM2LONG(*(m->var()));
}
}
break;
case Marshall::ToVALUE:
*(m->var()) = rb_funcall( qt_internal_module,
rb_intern("create_qenum"),
2, INT2NUM(m->item().s_enum), rb_str_new2(m->type().name()) );
break;
default:
m->unsupported();
break;
}
break;
case Smoke::t_class:
switch(m->action()) {
case Marshall::FromVALUE:
{
if(*(m->var()) == Qnil) {
m->item().s_class = 0;
break;
}
if(TYPE(*(m->var())) != T_DATA) {
rb_raise(rb_eArgError, "Invalid type, expecting %s\n", m->type().name());
break;
}
smokeruby_object *o = value_obj_info(*(m->var()));
if(!o || !o->ptr) {
if(m->type().isRef()) {
rb_warning("References can't be nil\n");
m->unsupported();
}
m->item().s_class = 0;
break;
}
void *ptr = o->ptr;
if(!m->cleanup() && m->type().isStack()) {
ptr = construct_copy(o);
}
const Smoke::Class &c = m->smoke()->classes[m->type().classId()];
ptr = o->smoke->cast(
ptr, // pointer
o->classId, // from
o->smoke->idClass(c.className) // to
);
m->item().s_class = ptr;
break;
}
break;
case Marshall::ToVALUE:
{
if(m->item().s_voidp == 0) {
*(m->var()) = Qnil;
break;
}
void *p = m->item().s_voidp;
VALUE obj = getPointerObject(p);
if(obj != Qnil) {
*(m->var()) = obj;
break;
}
smokeruby_object * o = (smokeruby_object *) malloc(sizeof(smokeruby_object));
o->smoke = m->smoke();
o->classId = m->type().classId();
o->ptr = p;
o->allocated = false;
const char * classname = resolve_classname(o->smoke, o->classId, o->ptr);
if(m->type().isConst() && m->type().isRef()) {
p = construct_copy( o );
if(p) {
o->ptr = p;
o->allocated = true;
}
}
obj = set_obj_info(classname, o);
if (do_debug & qtdb_calls) {
tqWarning("allocating %s %p -> %p\n", classname, o->ptr, (void*)obj);
}
if(m->type().isStack()) {
o->allocated = true;
// Keep a mapping of the pointer so that it is only wrapped once as a ruby VALUE
mapPointer(obj, o, o->classId, 0);
}
*(m->var()) = obj;
}
break;
default:
m->unsupported();
break;
}
break;
default:
m->unsupported();
break;
}
}
static void marshall_void(Marshall * /*m*/) {}
static void marshall_unknown(Marshall *m) {
m->unsupported();
}
static void marshall_charP(Marshall *m) {
switch(m->action()) {
case Marshall::FromVALUE:
{
VALUE rv = *(m->var());
if (rv == Qnil) {
m->item().s_voidp = 0;
break;
}
int len = RSTRING_LEN(rv);
char* mem = (char*) malloc(len+1);
memcpy(mem, StringValuePtr(rv), len);
mem[len] ='\0';
m->item().s_voidp = mem;
}
break;
case Marshall::ToVALUE:
{
char *p = (char*)m->item().s_voidp;
if(p)
*(m->var()) = rb_str_new2(p);
else
*(m->var()) = Qnil;
if(m->cleanup())
delete[] p;
}
break;
default:
m->unsupported();
break;
}
}
void marshall_ucharP(Marshall *m) {
switch(m->action()) {
case Marshall::FromVALUE:
{
VALUE rv = *(m->var());
if (rv == Qnil) {
m->item().s_voidp = 0;
break;
}
int len = RSTRING_LEN(rv);
char* mem = (char*) malloc(len+1);
memcpy(mem, StringValuePtr(rv), len);
mem[len] ='\0';
m->item().s_voidp = mem;
}
break;
case Marshall::ToVALUE:
default:
m->unsupported();
break;
}
}
static const char * KCODE = 0;
static TQTextCodec *codec = 0;
static void
init_codec() {
VALUE temp = rb_gv_get("$KCODE");
KCODE = StringValuePtr(temp);
if (tqstrcmp(KCODE, "EUC") == 0) {
codec = TQTextCodec::codecForName("eucJP");
} else if (tqstrcmp(KCODE, "SJIS") == 0) {
codec = TQTextCodec::codecForName("Shift-JIS");
}
}
TQString*
qstringFromRString(VALUE rstring) {
if (KCODE == 0) {
init_codec();
}
TQString * s;
if (tqstrcmp(KCODE, "UTF8") == 0)
s = new TQString(TQString::fromUtf8(StringValuePtr(rstring), RSTRING_LEN(rstring)));
else if (tqstrcmp(KCODE, "EUC") == 0)
s = new TQString(codec->toUnicode(StringValuePtr(rstring)));
else if (tqstrcmp(KCODE, "SJIS") == 0)
s = new TQString(codec->toUnicode(StringValuePtr(rstring)));
else if(tqstrcmp(KCODE, "NONE") == 0)
s = new TQString(TQString::fromLatin1(StringValuePtr(rstring)));
else
s = new TQString(TQString::fromLocal8Bit(StringValuePtr(rstring), RSTRING_LEN(rstring)));
return s;
}
VALUE
rstringFromTQString(TQString * s) {
if (KCODE == 0) {
init_codec();
}
if (tqstrcmp(KCODE, "UTF8") == 0)
return rb_str_new2(s->utf8());
else if (tqstrcmp(KCODE, "EUC") == 0)
return rb_str_new2(codec->fromUnicode(*s));
else if (tqstrcmp(KCODE, "SJIS") == 0)
return rb_str_new2(codec->fromUnicode(*s));
else if (tqstrcmp(KCODE, "NONE") == 0)
return rb_str_new2(s->latin1());
else
return rb_str_new2(s->local8Bit());
}
static void marshall_TQString(Marshall *m) {
switch(m->action()) {
case Marshall::FromVALUE:
{
TQString* s = 0;
if ( *(m->var()) != Qnil) {
s = qstringFromRString(*(m->var()));
} else {
s = new TQString(TQString::null);
}
m->item().s_voidp = s;
m->next();
if (!m->type().isConst() && *(m->var()) != Qnil && s != 0 && !s->isNull()) {
rb_str_resize(*(m->var()), 0);
VALUE temp = rstringFromTQString(s);
rb_str_cat2(*(m->var()), StringValuePtr(temp));
}
if (s != 0 && m->cleanup()) {
delete s;
}
}
break;
case Marshall::ToVALUE:
{
TQString *s = (TQString*)m->item().s_voidp;
if (s != 0) {
if (s->isNull()) {
*(m->var()) = Qnil;
} else {
*(m->var()) = rstringFromTQString(s);
}
if (m->cleanup() || m->type().isStack()) {
delete s;
}
} else {
*(m->var()) = Qnil;
}
}
break;
default:
m->unsupported();
break;
}
}
// The only way to convert a TQChar to a TQString is to
// pass a TQChar to a TQString constructor. However,
// TQStrings aren't in the QtRuby api, so add this
// convenience method 'TQt::Char.to_s' to get a ruby
// string from a TQt::Char.
VALUE
qchar_to_s(VALUE self)
{
smokeruby_object *o = value_obj_info(self);
if (o == 0 || o->ptr == 0) {
return Qnil;
}
TQChar * qchar = (TQChar*) o->ptr;
TQString s(*qchar);
return rstringFromTQString(&s);
}
#if 0
static const char *not_ascii(const char *s, uint &len)
{
bool r = false;
for(; *s ; s++, len--)
if((uint)*s > 0x7F)
{
r = true;
break;
}
return r ? s : 0L;
}
#endif
static void marshall_TQCString(Marshall *m) {
switch(m->action()) {
case Marshall::FromVALUE:
{
TQCString *s = 0;
VALUE rv = *(m->var());
if (rv == Qnil) {
s = new TQCString();
} else {
// Add 1 to the ruby string length to allow for a TQCString '\0' terminator
s = new TQCString(StringValuePtr(*(m->var())), RSTRING_LEN(*(m->var())) + 1);
}
m->item().s_voidp = s;
m->next();
if (!m->type().isConst() && rv != Qnil && s != 0) {
rb_str_resize(rv, 0);
rb_str_cat2(rv, (const char *)*s);
}
if(s && m->cleanup())
delete s;
}
break;
case Marshall::ToVALUE:
{
TQCString *s = (TQCString*)m->item().s_voidp;
if(s && (const char *) *s != 0) {
*(m->var()) = rb_str_new2((const char *)*s);
// const char * p = (const char *)*s;
// uint len = s->length();
// if(not_ascii(p,len))
// {
// #if PERL_VERSION == 6 && PERL_SUBVERSION == 0
// TQTextCodec* c = TQTextCodec::codecForMib(106); // utf8
// if(c->heuristicContentMatch(p,len) >= 0)
// #else
// if(is_utf8_string((U8 *)p,len))
// #endif
// SvUTF8_on(*(m->var()));
// }
} else {
if (m->type().isConst()) {
*(m->var()) = Qnil;
} else {
*(m->var()) = rb_str_new2("");
}
}
m->next();
if (!m->type().isConst() && s != 0) {
*s = (const char *) StringValuePtr(*(m->var()));
}
if(s && m->cleanup())
delete s;
}
break;
default:
m->unsupported();
break;
}
}
static void marshall_TQCOORD_array(Marshall *m) {
switch(m->action()) {
case Marshall::FromVALUE:
{
VALUE av = *(m->var());
if (TYPE(av) != T_ARRAY) {
m->item().s_voidp = 0;
break;
}
int count = RARRAY_LEN(av);
TQCOORD *coord = new TQCOORD[count + 2];
for(long i = 0; i < count; i++) {
VALUE svp = rb_ary_entry(av, i);
coord[i] = NUM2INT(svp);
}
m->item().s_voidp = coord;
m->next();
}
break;
default:
m->unsupported();
}
}
static void marshall_longlong(Marshall *m) {
switch(m->action()) {
case Marshall::FromVALUE:
{
m->item().s_voidp = new long long;
*(long long *)m->item().s_voidp = rb_num2ll(*(m->var()));
m->next();
if(m->cleanup() && m->type().isConst()) {
delete (long long *) m->item().s_voidp;
}
}
break;
case Marshall::ToVALUE:
{
*(m->var()) = rb_ll2inum(*(long long *) m->item().s_voidp);
}
break;
default:
m->unsupported();
break;
}
}
static void marshall_ulonglong(Marshall *m) {
switch(m->action()) {
case Marshall::FromVALUE:
{
m->item().s_voidp = new unsigned long long;
*(long long *)m->item().s_voidp = rb_num2ull(*(m->var()));
m->next();
if(m->cleanup() && m->type().isConst()) {
delete (unsigned long long *) m->item().s_voidp;
}
}
break;
case Marshall::ToVALUE:
{
*(m->var()) = rb_ull2inum(*(unsigned long long *) m->item().s_voidp);
}
break;
default:
m->unsupported();
break;
}
}
static void marshall_intR(Marshall *m) {
switch(m->action()) {
case Marshall::FromVALUE:
{
VALUE rv = *(m->var());
int * i = new int;
if (TYPE(rv) == T_OBJECT) {
// A TQt::Integer has been passed as an integer value
VALUE temp = rb_funcall(qt_internal_module, rb_intern("get_qinteger"), 1, rv);
*i = NUM2INT(temp);
m->item().s_voidp = i;
m->next();
rb_funcall(qt_internal_module, rb_intern("set_qinteger"), 2, rv, INT2NUM(*i));
rv = temp;
} else {
*i = NUM2INT(rv);
m->item().s_voidp = i;
m->next();
}
if(m->cleanup() && m->type().isConst()) {
delete i;
} else {
m->item().s_voidp = new int((int)NUM2INT(rv));
}
}
break;
case Marshall::ToVALUE:
{
int *ip = (int*)m->item().s_voidp;
VALUE rv = *(m->var());
if(!ip) {
rv = Qnil;
break;
}
*(m->var()) = INT2NUM(*ip);
m->next();
if(!m->type().isConst())
*ip = NUM2INT(*(m->var()));
}
break;
default:
m->unsupported();
break;
}
}
static void marshall_boolR(Marshall *m) {
switch(m->action()) {
case Marshall::FromVALUE:
{
VALUE rv = *(m->var());
bool * b = new bool;
if (TYPE(rv) == T_OBJECT) {
// A TQt::Boolean has been passed as a value
VALUE temp = rb_funcall(qt_internal_module, rb_intern("get_qboolean"), 1, rv);
*b = (temp == Qtrue ? true : false);
m->item().s_voidp = b;
m->next();
rb_funcall(qt_internal_module, rb_intern("set_qboolean"), 2, rv, (*b ? Qtrue : Qfalse));
} else {
*b = (rv == Qtrue ? true : false);
m->item().s_voidp = b;
m->next();
}
if(m->cleanup() && m->type().isConst()) {
delete b;
}
}
break;
case Marshall::ToVALUE:
{
bool *ip = (bool*)m->item().s_voidp;
if(!ip) {
*(m->var()) = Qnil;
break;
}
*(m->var()) = (*ip?Qtrue:Qfalse);
m->next();
if(!m->type().isConst())
*ip = *(m->var()) == Qtrue ? true : false;
}
break;
default:
m->unsupported();
break;
}
}
static void marshall_charP_array(Marshall *m) {
switch(m->action()) {
case Marshall::FromVALUE:
{
VALUE arglist = *(m->var());
if (arglist == Qnil
|| TYPE(arglist) != T_ARRAY
|| RARRAY_LEN(arglist) == 0 )
{
m->item().s_voidp = 0;
break;
}
char **argv = new char *[RARRAY_LEN(arglist) + 1];
long i;
for(i = 0; i < RARRAY_LEN(arglist); i++) {
VALUE item = rb_ary_entry(arglist, i);
char *s = StringValuePtr(item);
argv[i] = new char[strlen(s) + 1];
strcpy(argv[i], s);
}
argv[i] = 0;
m->item().s_voidp = argv;
m->next();
if(m->cleanup()) {
rb_ary_clear(arglist);
for(i = 0; argv[i]; i++)
rb_ary_push(arglist, rb_str_new2(argv[i]));
}
}
break;
default:
m->unsupported();
break;
}
}
void marshall_TQStringList(Marshall *m) {
switch(m->action()) {
case Marshall::FromVALUE:
{
VALUE list = *(m->var());
if (TYPE(list) != T_ARRAY) {
m->item().s_voidp = 0;
break;
}
int count = RARRAY_LEN(list);
TQStringList *stringlist = new TQStringList;
for(long i = 0; i < count; i++) {
VALUE item = rb_ary_entry(list, i);
if(TYPE(item) != T_STRING) {
stringlist->append(TQString());
continue;
}
stringlist->append(*(qstringFromRString(item)));
}
m->item().s_voidp = stringlist;
m->next();
if (stringlist != 0 && !m->type().isConst()) {
rb_ary_clear(list);
for(TQStringList::Iterator it = stringlist->begin(); it != stringlist->end(); ++it)
rb_ary_push(list, rstringFromTQString(&(*it)));
}
if (m->cleanup())
delete stringlist;
break;
}
case Marshall::ToVALUE:
{
TQStringList *stringlist = static_cast<TQStringList *>(m->item().s_voidp);
if(!stringlist) {
*(m->var()) = Qnil;
break;
}
VALUE av = rb_ary_new();
for(TQStringList::Iterator it = stringlist->begin(); it != stringlist->end(); ++it) {
VALUE rv = rstringFromTQString(&(*it));
rb_ary_push(av, rv);
}
if(m->cleanup())
delete stringlist;
*(m->var()) = av;
}
break;
default:
m->unsupported();
break;
}
}
void marshall_TQStrList(Marshall *m) {
switch(m->action()) {
case Marshall::FromVALUE:
{
VALUE list = *(m->var());
if (TYPE(list) != T_ARRAY) {
m->item().s_voidp = 0;
break;
}
int count = RARRAY_LEN(list);
TQStrList *stringlist = new TQStrList;
for(long i = 0; i < count; i++) {
VALUE item = rb_ary_entry(list, i);
if(TYPE(item) != T_STRING) {
stringlist->append(TQString());
continue;
}
stringlist->append(TQString::fromUtf8(StringValuePtr(item), RSTRING_LEN(item)));
}
m->item().s_voidp = stringlist;
m->next();
if (!m->type().isConst()) {
rb_ary_clear(list);
for(const char * it = stringlist->first(); it != 0; it = stringlist->next())
rb_ary_push(list, rb_str_new2(it));
}
if (m->cleanup()) {
delete stringlist;
}
break;
}
case Marshall::ToVALUE:
{
TQStrList *stringlist = static_cast<TQStrList *>(m->item().s_voidp);
if(!stringlist) {
*(m->var()) = Qnil;
break;
}
VALUE av = rb_ary_new();
for(const char * it = stringlist->first(); it != 0; it = stringlist->next()) {
VALUE rv = rb_str_new2(it);
rb_ary_push(av, rv);
}
if(m->cleanup())
delete stringlist;
*(m->var()) = av;
}
break;
default:
m->unsupported();
break;
}
}
template <class Item, class ItemList, class ItemListIterator, const char *ItemSTR >
void marshall_ItemList(Marshall *m) {
switch(m->action()) {
case Marshall::FromVALUE:
{
VALUE list = *(m->var());
if (TYPE(list) != T_ARRAY) {
m->item().s_voidp = 0;
break;
}
int count = RARRAY_LEN(list);
ItemList *cpplist = new ItemList;
long i;
for(i = 0; i < count; i++) {
VALUE item = rb_ary_entry(list, i);
// TODO do type checking!
smokeruby_object *o = value_obj_info(item);
if(!o || !o->ptr)
continue;
void *ptr = o->ptr;
ptr = o->smoke->cast(
ptr, // pointer
o->classId, // from
o->smoke->idClass(ItemSTR) // to
);
cpplist->append((Item*)ptr);
}
m->item().s_voidp = cpplist;
m->next();
if (!m->type().isConst()) {
rb_ary_clear(list);
for(ItemListIterator it = cpplist->begin();
it != cpplist->end();
++it )
{
VALUE obj = getPointerObject((void*)(*it));
rb_ary_push(list, obj);
}
}
if (m->cleanup()) {
delete cpplist;
}
}
break;
case Marshall::ToVALUE:
{
ItemList *valuelist = (ItemList*)m->item().s_voidp;
if(!valuelist) {
*(m->var()) = Qnil;
break;
}
VALUE av = rb_ary_new();
for(ItemListIterator it = valuelist->begin();
it != valuelist->end();
++it) {
void *p = *it;
if(m->item().s_voidp == 0) {
*(m->var()) = Qnil;
break;
}
VALUE obj = getPointerObject(p);
if(obj == Qnil) {
smokeruby_object * o = ALLOC(smokeruby_object);
o->smoke = m->smoke();
o->classId = m->smoke()->idClass(ItemSTR);
o->ptr = p;
o->allocated = false;
obj = set_obj_info(resolve_classname(o->smoke, o->classId, o->ptr), o);
}
rb_ary_push(av, obj);
}
if(m->cleanup())
delete valuelist;
else
*(m->var()) = av;
}
break;
default:
m->unsupported();
break;
}
}
void marshall_TQValueListInt(Marshall *m) {
switch(m->action()) {
case Marshall::FromVALUE:
{
VALUE list = *(m->var());
if (TYPE(list) != T_ARRAY) {
m->item().s_voidp = 0;
break;
}
int count = RARRAY_LEN(list);
TQValueList<int> *valuelist = new TQValueList<int>;
long i;
for(i = 0; i < count; i++) {
VALUE item = rb_ary_entry(list, i);
if(TYPE(item) != T_FIXNUM && TYPE(item) != T_BIGNUM) {
valuelist->append(0);
continue;
}
valuelist->append(NUM2INT(item));
}
m->item().s_voidp = valuelist;
m->next();
if (!m->type().isConst()) {
rb_ary_clear(list);
for(TQValueListIterator<int> it = valuelist->begin();
it != valuelist->end();
++it)
rb_ary_push(list, INT2NUM((int)*it));
}
if (m->cleanup()) {
delete valuelist;
}
}
break;
case Marshall::ToVALUE:
{
TQValueList<int> *valuelist = (TQValueList<int>*)m->item().s_voidp;
if(!valuelist) {
*(m->var()) = Qnil;
break;
}
VALUE av = rb_ary_new();
for(TQValueListIterator<int> it = valuelist->begin();
it != valuelist->end();
++it)
rb_ary_push(av, INT2NUM(*it));
*(m->var()) = av;
if(m->cleanup())
delete valuelist;
}
break;
default:
m->unsupported();
break;
}
}
void marshall_voidP(Marshall *m) {
switch(m->action()) {
case Marshall::FromVALUE:
{
VALUE rv = *(m->var());
if (rv != Qnil)
m->item().s_voidp = (void*)NUM2INT(*(m->var()));
else
m->item().s_voidp = 0;
}
break;
case Marshall::ToVALUE:
{
*(m->var()) = Data_Wrap_Struct(rb_cObject, 0, 0, m->item().s_voidp);
}
break;
default:
m->unsupported();
break;
}
}
void marshall_TQMapTQStringTQString(Marshall *m) {
switch(m->action()) {
case Marshall::FromVALUE:
{
VALUE hash = *(m->var());
if (TYPE(hash) != T_HASH) {
m->item().s_voidp = 0;
break;
}
TQMap<TQString,TQString> * map = new TQMap<TQString,TQString>;
// Convert the ruby hash to an array of key/value arrays
VALUE temp = rb_funcall(hash, rb_intern("to_a"), 0);
for (long i = 0; i < RARRAY_LEN(temp); i++) {
VALUE key = rb_ary_entry(rb_ary_entry(temp, i), 0);
VALUE value = rb_ary_entry(rb_ary_entry(temp, i), 1);
(*map)[TQString(StringValuePtr(key))] = TQString(StringValuePtr(value));
}
m->item().s_voidp = map;
m->next();
if(m->cleanup())
delete map;
}
break;
case Marshall::ToVALUE:
{
TQMap<TQString,TQString> *map = (TQMap<TQString,TQString>*)m->item().s_voidp;
if(!map) {
*(m->var()) = Qnil;
break;
}
VALUE hv = rb_hash_new();
TQMap<TQString,TQString>::Iterator it;
for (it = map->begin(); it != map->end(); ++it) {
rb_hash_aset(hv, rstringFromTQString((TQString*)&(it.key())), rstringFromTQString((TQString*) &(it.data())));
}
*(m->var()) = hv;
m->next();
if(m->cleanup())
delete map;
}
break;
default:
m->unsupported();
break;
}
}
void marshall_TQMapTQStringTQVariant(Marshall *m) {
switch(m->action()) {
case Marshall::FromVALUE:
{
VALUE hash = *(m->var());
if (TYPE(hash) != T_HASH) {
m->item().s_voidp = 0;
break;
}
TQStringVariantMap * map = new TQStringVariantMap;
// Convert the ruby hash to an array of key/value arrays
VALUE temp = rb_funcall(hash, rb_intern("to_a"), 0);
for (long i = 0; i < RARRAY_LEN(temp); i++) {
VALUE key = rb_ary_entry(rb_ary_entry(temp, i), 0);
VALUE value = rb_ary_entry(rb_ary_entry(temp, i), 1);
smokeruby_object *o = value_obj_info(value);
if (!o || !o->ptr || o->classId != o->smoke->idClass("TQVariant")) {
// If the value isn't a TQt::Variant, then try and construct
// a TQt::Variant from it
value = rb_funcall(qvariant_class, rb_intern("new"), 1, value);
if (value == Qnil) {
continue;
}
o = value_obj_info(value);
}
void * ptr = o->ptr;
ptr = o->smoke->cast(ptr, o->classId, o->smoke->idClass("TQVariant"));
(*map)[TQString(StringValuePtr(key))] = (TQVariant)*(TQVariant*)ptr;
}
m->item().s_voidp = map;
m->next();
if(m->cleanup())
delete map;
}
break;
case Marshall::ToVALUE:
{
TQStringVariantMap *map = (TQStringVariantMap*)m->item().s_voidp;
if(!map) {
*(m->var()) = Qnil;
break;
}
VALUE hv = rb_hash_new();
TQStringVariantMap::Iterator it;
for (it = map->begin(); it != map->end(); ++it) {
void *p = new TQVariant(it.data());
VALUE obj = getPointerObject(p);
if (obj == Qnil) {
smokeruby_object * o = ALLOC(smokeruby_object);
o->classId = m->smoke()->idClass("TQVariant");
o->smoke = m->smoke();
o->ptr = p;
o->allocated = true;
obj = set_obj_info("TQt::Variant", o);
}
rb_hash_aset(hv, rstringFromTQString((TQString*)&(it.key())), obj);
}
*(m->var()) = hv;
m->next();
if(m->cleanup())
delete map;
}
break;
default:
m->unsupported();
break;
}
}
void marshall_TQUObject(Marshall *m) {
switch(m->action()) {
case Marshall::FromVALUE:
{
VALUE array = *(m->var());
if (array != Qnil && TYPE(array) == T_ARRAY) {
VALUE rv = rb_ary_entry(array, 0);
Data_Get_Struct(rv, TQUObject, m->item().s_voidp);
} else {
m->item().s_voidp = 0;
}
}
break;
case Marshall::ToVALUE:
{
VALUE rv = Data_Wrap_Struct(rb_cObject, 0, 0, m->item().s_voidp);
VALUE array = rb_ary_new2(1);
rb_ary_push(array, rv);
*(m->var()) = array;
}
break;
default:
m->unsupported();
break;
}
}
void marshall_TQRgb_array(Marshall *m) {
switch(m->action()) {
case Marshall::FromVALUE:
{
VALUE list = *(m->var());
if (TYPE(list) != T_ARRAY) {
m->item().s_voidp = 0;
break;
}
int count = RARRAY_LEN(list);
TQRgb *rgb = new TQRgb[count + 2];
long i;
for(i = 0; i < count; i++) {
VALUE item = rb_ary_entry(list, i);
if(TYPE(item) != T_FIXNUM && TYPE(item) != T_BIGNUM) {
rgb[i] = 0;
continue;
}
rgb[i] = NUM2UINT(item);
}
m->item().s_voidp = rgb;
m->next();
}
break;
case Marshall::ToVALUE:
// Implement this with a tied array or something
default:
m->unsupported();
break;
}
}
void marshall_TQPairintint(Marshall *m) {
switch(m->action()) {
case Marshall::FromVALUE:
{
VALUE list = *(m->var());
if (TYPE(list) != T_ARRAY || RARRAY_LEN(list) != 2) {
m->item().s_voidp = 0;
break;
}
int int0;
int int1;
VALUE item = rb_ary_entry(list, 0);
if(TYPE(item) != T_FIXNUM && TYPE(item) != T_BIGNUM) {
int0 = 0;
} else {
int0 = NUM2INT(item);
}
item = rb_ary_entry(list, 1);
if(TYPE(item) != T_FIXNUM && TYPE(item) != T_BIGNUM) {
int1 = 0;
} else {
int1 = NUM2INT(item);
}
TQPair<int,int> * qpair = new TQPair<int,int>(int0,int1);
m->item().s_voidp = qpair;
m->next();
if(m->cleanup())
delete qpair;
}
break;
case Marshall::ToVALUE:
default:
m->unsupported();
break;
}
}
#define DEF_LIST_MARSHALLER(ListIdent,ItemList,Item,Itr) namespace { char ListIdent##STR[] = #Item; }; \
Marshall::HandlerFn marshall_##ListIdent = marshall_ItemList<Item,ItemList,Itr,ListIdent##STR>;
#include <tqcanvas.h>
#include <tqdir.h>
#include <tqobjectlist.h>
#include <tqwidgetlist.h>
#include <tqdockwindow.h>
#include <tqnetworkprotocol.h>
#include <tqtoolbar.h>
#include <tqtabbar.h>
#if TQT_VERSION >= 0x030200
DEF_LIST_MARSHALLER( TQPtrListTQNetworkOperation, TQPtrList<TQNetworkOperation>, TQNetworkOperation, TQPtrListStdIterator<TQNetworkOperation> )
DEF_LIST_MARSHALLER( TQPtrListTQToolBar, TQPtrList<TQToolBar>, TQToolBar, TQPtrListStdIterator<TQToolBar> )
DEF_LIST_MARSHALLER( TQPtrListTQTab, TQPtrList<TQTab>, TQTab, TQPtrListStdIterator<TQTab> )
DEF_LIST_MARSHALLER( TQPtrListTQDockWindow, TQPtrList<TQDockWindow>, TQDockWindow, TQPtrListStdIterator<TQDockWindow> )
DEF_LIST_MARSHALLER( TQFileInfoList, TQFileInfoList, TQFileInfo, TQFileInfoList::Iterator )
DEF_LIST_MARSHALLER( TQObjectList, TQObjectList, TQObject, TQPtrListStdIterator<TQObject> )
DEF_LIST_MARSHALLER( TQWidgetList, TQWidgetList, TQWidget, TQPtrListStdIterator<TQWidget> )
#endif
DEF_LIST_MARSHALLER( TQCanvasItemList, TQCanvasItemList, TQCanvasItem, TQValueListIterator<TQCanvasItem*> )
template <class Item, class ItemList, class ItemListIterator, const char *ItemSTR >
void marshall_ValueItemList(Marshall *m) {
switch(m->action()) {
case Marshall::FromVALUE:
{
VALUE list = *(m->var());
if (TYPE(list) != T_ARRAY) {
m->item().s_voidp = 0;
break;
}
int count = RARRAY_LEN(list);
ItemList *cpplist = new ItemList;
long i;
for(i = 0; i < count; i++) {
VALUE item = rb_ary_entry(list, i);
// TODO do type checking!
smokeruby_object *o = value_obj_info(item);
// Special case for the TQValueList<TQVariant> type
if ( tqstrcmp(ItemSTR, "TQVariant") == 0
&& (!o || !o->ptr || o->classId != o->smoke->idClass("TQVariant")) )
{
// If the value isn't a TQt::Variant, then try and construct
// a TQt::Variant from it
item = rb_funcall(qvariant_class, rb_intern("new"), 1, item);
if (item == Qnil) {
continue;
}
o = value_obj_info(item);
}
if(!o || !o->ptr)
continue;
void *ptr = o->ptr;
ptr = o->smoke->cast(
ptr, // pointer
o->classId, // from
o->smoke->idClass(ItemSTR) // to
);
cpplist->append(*(Item*)ptr);
}
m->item().s_voidp = cpplist;
m->next();
if (!m->type().isConst()) {
rb_ary_clear(list);
for(ItemListIterator it = cpplist->begin();
it != cpplist->end();
++it)
{
VALUE obj = getPointerObject((void*)&(*it));
rb_ary_push(list, obj);
}
}
if (m->cleanup()) {
delete cpplist;
}
}
break;
case Marshall::ToVALUE:
{
ItemList *valuelist = (ItemList*)m->item().s_voidp;
if(!valuelist) {
*(m->var()) = Qnil;
break;
}
VALUE av = rb_ary_new();
int ix = m->smoke()->idClass(ItemSTR);
const char * className = m->smoke()->binding->className(ix);
for(ItemListIterator it = valuelist->begin();
it != valuelist->end();
++it) {
void *p = &(*it);
if(m->item().s_voidp == 0) {
*(m->var()) = Qnil;
break;
}
VALUE obj = getPointerObject(p);
if(obj == Qnil) {
smokeruby_object * o = ALLOC(smokeruby_object);
o->smoke = m->smoke();
o->classId = o->smoke->idClass(ItemSTR);
o->ptr = p;
o->allocated = false;
obj = set_obj_info(className, o);
}
rb_ary_push(av, obj);
}
if(m->cleanup())
delete valuelist;
else
*(m->var()) = av;
}
break;
default:
m->unsupported();
break;
}
}
#define DEF_VALUELIST_MARSHALLER(ListIdent,ItemList,Item,Itr) namespace dummy { char ListIdent##STR[] = #Item; }; \
Marshall::HandlerFn marshall_##ListIdent = marshall_ValueItemList<Item,ItemList,Itr,dummy::ListIdent##STR>;
DEF_VALUELIST_MARSHALLER( TQVariantList, TQValueList<TQVariant>, TQVariant, TQValueList<TQVariant>::Iterator )
DEF_VALUELIST_MARSHALLER( TQPixmapList, TQValueList<TQPixmap>, TQPixmap, TQValueList<TQPixmap>::Iterator )
DEF_VALUELIST_MARSHALLER( TQIconDragItemList, TQValueList<TQIconDragItem>, TQIconDragItem, TQValueList<TQIconDragItem>::Iterator )
DEF_VALUELIST_MARSHALLER( TQImageTextKeyLangList, TQValueList<TQImageTextKeyLang>, TQImageTextKeyLang, TQValueList<TQImageTextKeyLang>::Iterator )
DEF_VALUELIST_MARSHALLER( TQUrlInfoList, TQValueList<TQUrlInfo>, TQUrlInfo, TQValueList<TQUrlInfo>::Iterator )
DEF_VALUELIST_MARSHALLER( TQTranslatorMessageList, TQValueList<TQTranslatorMessage>, TQTranslatorMessage, TQValueList<TQTranslatorMessage>::Iterator )
DEF_VALUELIST_MARSHALLER( TQHostAddressList, TQValueList<TQHostAddress>, TQHostAddress, TQValueList<TQHostAddress>::Iterator )
TypeHandler Qt_handlers[] = {
{ "TQString", marshall_TQString },
{ "TQString&", marshall_TQString },
{ "TQString*", marshall_TQString },
{ "TQCString", marshall_TQCString },
{ "TQCString&", marshall_TQCString },
{ "TQCString*", marshall_TQCString },
{ "TQStringList", marshall_TQStringList },
{ "TQStringList&", marshall_TQStringList },
{ "TQStringList*", marshall_TQStringList },
{ "TQStrList", marshall_TQStrList },
{ "TQStrList&", marshall_TQStrList },
{ "TQStrList*", marshall_TQStrList },
{ "long long int", marshall_longlong },
{ "long long int&", marshall_longlong },
{ "TQ_INT64", marshall_longlong },
{ "TQ_INT64&", marshall_longlong },
{ "TQ_LLONG", marshall_longlong },
{ "TQ_LLONG&", marshall_longlong },
{ "TDEIO::filesize_t", marshall_longlong },
{ "DOM::DOMTimeStamp", marshall_ulonglong },
{ "unsigned long long int", marshall_ulonglong },
{ "unsigned long long int&", marshall_ulonglong },
{ "TQ_UINT64", marshall_ulonglong },
{ "TQ_UINT64&", marshall_ulonglong },
{ "TQ_ULLONG", marshall_ulonglong },
{ "TQ_ULLONG&", marshall_ulonglong },
{ "signed int&", marshall_intR },
{ "int&", marshall_intR },
{ "int*", marshall_intR },
{ "bool&", marshall_boolR },
{ "bool*", marshall_boolR },
{ "char*", marshall_charP },
{ "char**", marshall_charP_array },
{ "uchar*", marshall_ucharP },
{ "TQRgb*", marshall_TQRgb_array },
{ "TQPair<int,int>&", marshall_TQPairintint },
{ "TQUObject*", marshall_TQUObject },
{ "const TQCOORD*", marshall_TQCOORD_array },
{ "void", marshall_void },
{ "TQValueList<int>", marshall_TQValueListInt },
{ "TQValueList<int>&", marshall_TQValueListInt },
{ "TQValueList<TQVariant>", marshall_TQVariantList },
{ "TQValueList<TQVariant>&", marshall_TQVariantList },
{ "TQValueList<TQPixmap>", marshall_TQPixmapList },
{ "TQValueList<TQIconDragItem>&", marshall_TQIconDragItemList },
{ "TQValueList<TQImageTextKeyLang>", marshall_TQImageTextKeyLangList },
{ "TQValueList<TQUrlInfo>&", marshall_TQUrlInfoList },
{ "TQValueList<TQTranslatorMessage>", marshall_TQTranslatorMessageList },
{ "TQValueList<TQHostAddress>", marshall_TQHostAddressList },
{ "TQCanvasItemList", marshall_TQCanvasItemList },
{ "TQMap<TQString,TQString>", marshall_TQMapTQStringTQString },
{ "TQMap<TQString,TQString>&", marshall_TQMapTQStringTQString },
{ "TQStringVariantMap", marshall_TQMapTQStringTQVariant },
{ "TQStringVariantMap&", marshall_TQMapTQStringTQVariant },
#if TQT_VERSION >= 0x030200
{ "TQWidgetList", marshall_TQWidgetList },
{ "TQWidgetList*", marshall_TQWidgetList },
{ "TQWidgetList&", marshall_TQWidgetList },
{ "TQObjectList*", marshall_TQObjectList },
{ "TQObjectList&", marshall_TQObjectList },
{ "TQFileInfoList*", marshall_TQFileInfoList },
{ "TQPtrList<TQToolBar>", marshall_TQPtrListTQToolBar },
{ "TQPtrList<TQTab>*", marshall_TQPtrListTQTab },
{ "TQPtrList<TQDockWindow>", marshall_TQPtrListTQDockWindow },
{ "TQPtrList<TQDockWindow>*", marshall_TQPtrListTQDockWindow },
{ "TQPtrList<TQNetworkOperation>", marshall_TQPtrListTQNetworkOperation },
{ "TQPtrList<TQNetworkOperation>&", marshall_TQPtrListTQNetworkOperation },
#endif
{ 0, 0 }
};
TQAsciiDict<TypeHandler> type_handlers(199);
void install_handlers(TypeHandler *h) {
while(h->name) {
type_handlers.insert(h->name, h);
h++;
}
}
Marshall::HandlerFn getMarshallFn(const SmokeType &type) {
if(type.elem())
return marshall_basetype;
if(!type.name())
return marshall_void;
TypeHandler *h = type_handlers[type.name()];
if(h == 0 && type.isConst() && strlen(type.name()) > strlen("const ")) {
h = type_handlers[type.name() + strlen("const ")];
}
if(h != 0) {
return h->fn;
}
return marshall_unknown;
}