|
|
|
/***************************************************************************
|
|
|
|
* *
|
|
|
|
* 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
|
|
|
|
|
|
|
|
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(TTQObject * qobject)
|
|
|
|
{
|
|
|
|
VALUE obj;
|
|
|
|
|
|
|
|
const TTQObjectList *l = qobject->children();
|
|
|
|
if (l == 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
TTQObjectListIt it( *l ); // iterate over the children
|
|
|
|
TTQObject *child;
|
|
|
|
|
|
|
|
while ( (child = it.current()) != 0 ) {
|
|
|
|
++it;
|
|
|
|
obj = getPointerObject(child);
|
|
|
|
if (obj != Qnil) {
|
|
|
|
if(do_debug & qtdb_gc) qWarning("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) qWarning("Checking for mark (%s*)%p\n", className, o->ptr);
|
|
|
|
|
|
|
|
if(o->ptr && o->allocated) {
|
|
|
|
if (isDerivedFromByName(o->smoke, className, "TTQListView")) {
|
|
|
|
TTQListView * listview = (TTQListView *) o->smoke->cast(o->ptr, o->classId, o->smoke->idClass("TTQListView"));
|
|
|
|
TTQListViewItemIterator it(listview);
|
|
|
|
TTQListViewItem *item;
|
|
|
|
|
|
|
|
while ( (item = it.current()) != 0 ) {
|
|
|
|
++it;
|
|
|
|
obj = getPointerObject(item);
|
|
|
|
if (obj != Qnil) {
|
|
|
|
if(do_debug & qtdb_gc) qWarning("Marking (%s*)%p -> %p\n", className, item, (void*)obj);
|
|
|
|
rb_gc_mark(obj);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (isDerivedFromByName(o->smoke, className, "TTQTable")) {
|
|
|
|
TTQTable * table = (TTQTable *) o->smoke->cast(o->ptr, o->classId, o->smoke->idClass("TTQTable"));
|
|
|
|
TTQTableItem *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) qWarning("Marking (%s*)%p -> %p\n", className, item, (void*)obj);
|
|
|
|
rb_gc_mark(obj);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (isDerivedFromByName(o->smoke, className, "TTQCanvas")) {
|
|
|
|
TTQCanvas * canvas = (TTQCanvas *) o->smoke->cast(o->ptr, o->classId, o->smoke->idClass("TTQCanvas"));
|
|
|
|
TTQCanvasItemList list = canvas->allItems();
|
|
|
|
for ( TTQCanvasItemList::iterator it = list.begin(); it != list.end(); ++it ) {
|
|
|
|
obj = getPointerObject(*it);
|
|
|
|
if (obj != Qnil) {
|
|
|
|
if(do_debug & qtdb_gc) qWarning("Marking (%s*)%p -> %p\n", className, *it, (void*)obj);
|
|
|
|
rb_gc_mark(obj);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (isDerivedFromByName(o->smoke, className, "TTQCanvasItem")) {
|
|
|
|
TTQCanvasItem * item = (TTQCanvasItem *) o->smoke->cast(o->ptr, o->classId, o->smoke->idClass("TTQCanvasItem"));
|
|
|
|
TTQCanvas * canvas = item->canvas();
|
|
|
|
obj = getPointerObject(canvas);
|
|
|
|
if (obj != Qnil) {
|
|
|
|
if(do_debug & qtdb_gc) qWarning("Marking (%s*)%p -> %p\n", "TTQCanvas", canvas, (void*)obj);
|
|
|
|
rb_gc_mark(obj);
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (isDerivedFromByName(o->smoke, className, "TTQObject")) {
|
|
|
|
TTQObject * qobject = (TTQObject *) o->smoke->cast(o->ptr, o->classId, o->smoke->idClass("TTQObject"));
|
|
|
|
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) qWarning("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 ( qstrcmp(className, "TTQObject") == 0
|
|
|
|
|| qstrcmp(className, "TTQListBoxItem") == 0
|
|
|
|
|| qstrcmp(className, "TTQStyleSheetItem") == 0
|
|
|
|
|| qstrcmp(className, "KCommand") == 0
|
|
|
|
|| qstrcmp(className, "KNamedCommand") == 0
|
|
|
|
|| qstrcmp(className, "KMacroCommand") == 0
|
|
|
|
|| qstrcmp(className, "KAboutData") == 0
|
|
|
|
|| qstrcmp(className, "KCmdLineArgs") == 0
|
|
|
|
|| qstrcmp(className, "TTQSqlCursor") == 0 )
|
|
|
|
{
|
|
|
|
// Don't delete instances of these classes for now
|
|
|
|
free(o);
|
|
|
|
return;
|
|
|
|
} else if (isDerivedFromByName(o->smoke, className, "TTQLayoutItem")) {
|
|
|
|
TTQLayoutItem * item = (TTQLayoutItem *) o->smoke->cast(o->ptr, o->classId, o->smoke->idClass("TTQLayoutItem"));
|
|
|
|
if (item->layout() != 0 || item->widget() != 0 || item->spacerItem() != 0) {
|
|
|
|
free(o);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
} else if (qstrcmp(className, "TTQIconViewItem") == 0) {
|
|
|
|
TTQIconViewItem * item = (TTQIconViewItem *) o->ptr;
|
|
|
|
if (item->iconView() != 0) {
|
|
|
|
free(o);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
} else if (qstrcmp(className, "TTQCheckListItem") == 0) {
|
|
|
|
TTQCheckListItem * item = (TTQCheckListItem *) o->ptr;
|
|
|
|
if (item->parent() != 0 || item->listView() != 0) {
|
|
|
|
free(o);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
} else if (qstrcmp(className, "TTQListViewItem") == 0) {
|
|
|
|
TTQListViewItem * item = (TTQListViewItem *) o->ptr;
|
|
|
|
if (item->parent() != 0 || item->listView() != 0) {
|
|
|
|
free(o);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
} else if (isDerivedFromByName(o->smoke, className, "TTQTableItem")) {
|
|
|
|
TTQTableItem * item = (TTQTableItem *) o->smoke->cast(o->ptr, o->classId, o->smoke->idClass("TTQTableItem"));
|
|
|
|
if (item->table() != 0) {
|
|
|
|
free(o);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
} else if (qstrcmp(className, "TTQPopupMenu") == 0) {
|
|
|
|
TTQPopupMenu * item = (TTQPopupMenu *) o->ptr;
|
|
|
|
if (item->parentWidget(false) != 0) {
|
|
|
|
free(o);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
} else if (isDerivedFromByName(o->smoke, className, "TTQWidget")) {
|
|
|
|
TTQWidget * qwidget = (TTQWidget *) o->smoke->cast(o->ptr, o->classId, o->smoke->idClass("TTQWidget"));
|
|
|
|
if (qwidget->parentWidget(true) != 0) {
|
|
|
|
free(o);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
} else if (isDerivedFromByName(o->smoke, className, "TTQObject")) {
|
|
|
|
TTQObject * qobject = (TTQObject *) o->smoke->cast(o->ptr, o->classId, o->smoke->idClass("TTQObject"));
|
|
|
|
if (qobject->parent() != 0) {
|
|
|
|
free(o);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(do_debug & qtdb_gc) qWarning("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, "TTQEvent")) {
|
|
|
|
TTQEvent * qevent = (TTQEvent *) smoke->cast(ptr, classId, smoke->idClass("TTQEvent"));
|
|
|
|
switch (qevent->type()) {
|
|
|
|
case TTQEvent::ChildInserted:
|
|
|
|
case TTQEvent::ChildRemoved:
|
|
|
|
return "TQt::ChildEvent";
|
|
|
|
case TTQEvent::Close:
|
|
|
|
return "TQt::CloseEvent";
|
|
|
|
case TTQEvent::ContextMenu:
|
|
|
|
return "TQt::ContextMenuEvent";
|
|
|
|
// case TTQEvent::User:
|
|
|
|
// return "TQt::CustomEvent";
|
|
|
|
case TTQEvent::DragEnter:
|
|
|
|
return "TQt::DragEnterEvent";
|
|
|
|
case TTQEvent::DragLeave:
|
|
|
|
return "TQt::DragLeaveEvent";
|
|
|
|
case TTQEvent::DragMove:
|
|
|
|
return "TQt::DragMoveEvent";
|
|
|
|
case TTQEvent::DragResponse:
|
|
|
|
return "TQt::DragResponseEvent";
|
|
|
|
case TTQEvent::Drop:
|
|
|
|
return "TQt::DropEvent";
|
|
|
|
case TTQEvent::FocusIn:
|
|
|
|
case TTQEvent::FocusOut:
|
|
|
|
return "TQt::FocusEvent";
|
|
|
|
case TTQEvent::Hide:
|
|
|
|
return "TQt::HideEvent";
|
|
|
|
case TTQEvent::KeyPress:
|
|
|
|
case TTQEvent::KeyRelease:
|
|
|
|
return "TQt::KeyEvent";
|
|
|
|
case TTQEvent::IMStart:
|
|
|
|
case TTQEvent::IMCompose:
|
|
|
|
case TTQEvent::IMEnd:
|
|
|
|
return "TQt::IMEvent";
|
|
|
|
case TTQEvent::MouseButtonPress:
|
|
|
|
case TTQEvent::MouseButtonRelease:
|
|
|
|
case TTQEvent::MouseButtonDblClick:
|
|
|
|
case TTQEvent::MouseMove:
|
|
|
|
return "TQt::MouseEvent";
|
|
|
|
case TTQEvent::Move:
|
|
|
|
return "TQt::MoveEvent";
|
|
|
|
case TTQEvent::Paint:
|
|
|
|
return "TQt::PaintEvent";
|
|
|
|
case TTQEvent::Resize:
|
|
|
|
return "TQt::ResizeEvent";
|
|
|
|
case TTQEvent::Show:
|
|
|
|
return "TQt::ShowEvent";
|
|
|
|
// case TTQEvent::Tablet:
|
|
|
|
// return "TQt::TabletEvent";
|
|
|
|
case TTQEvent::Timer:
|
|
|
|
return "TQt::TimerEvent";
|
|
|
|
case TTQEvent::Wheel:
|
|
|
|
return "TQt::WheelEvent";
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else if (isDerivedFromByName(smoke, smoke->classes[classId].className, "TTQObject")) {
|
|
|
|
TTQObject * qobject = (TTQObject *) smoke->cast(ptr, classId, smoke->idClass("TTQObject"));
|
|
|
|
TTQMetaObject * 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, "TTQCanvasItem")) {
|
|
|
|
TTQCanvasItem * qcanvasitem = (TTQCanvasItem *) smoke->cast(ptr, classId, smoke->idClass("TTQCanvasItem"));
|
|
|
|
switch (qcanvasitem->rtti()) {
|
|
|
|
case TTQCanvasItem::Rtti_Sprite:
|
|
|
|
return "TQt::CanvasSprite";
|
|
|
|
case TTQCanvasItem::Rtti_PolygonalItem:
|
|
|
|
return "TQt::CanvasPolygonalItem";
|
|
|
|
case TTQCanvasItem::Rtti_Text:
|
|
|
|
return "TQt::CanvasText";
|
|
|
|
case TTQCanvasItem::Rtti_Polygon:
|
|
|
|
return "TQt::CanvasPolygon";
|
|
|
|
case TTQCanvasItem::Rtti_Rectangle:
|
|
|
|
return "TQt::CanvasRectangle";
|
|
|
|
case TTQCanvasItem::Rtti_Ellipse:
|
|
|
|
return "TQt::CanvasEllipse";
|
|
|
|
case TTQCanvasItem::Rtti_Line:
|
|
|
|
return "TQt::CanvasLine";
|
|
|
|
case TTQCanvasItem::Rtti_Spline:
|
|
|
|
return "TQt::CanvasSpline";
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else if (isDerivedFromByName(smoke, smoke->classes[classId].className, "TTQListViewItem")) {
|
|
|
|
TTQListViewItem * item = (TTQListViewItem *) smoke->cast(ptr, classId, smoke->idClass("TTQListViewItem"));
|
|
|
|
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, "TTQTableItem")) {
|
|
|
|
TTQTableItem * item = (TTQTableItem *) smoke->cast(ptr, classId, smoke->idClass("TTQTableItem"));
|
|
|
|
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() && qstrcmp(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) {
|
|
|
|
qWarning("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(rv)->len;
|
|
|
|
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(rv)->len;
|
|
|
|
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 TTQTextCodec *codec = 0;
|
|
|
|
|
|
|
|
static void
|
|
|
|
init_codec() {
|
|
|
|
VALUE temp = rb_gv_get("$KCODE");
|
|
|
|
KCODE = StringValuePtr(temp);
|
|
|
|
if (qstrcmp(KCODE, "EUC") == 0) {
|
|
|
|
codec = TTQTextCodec::codecForName("eucJP");
|
|
|
|
} else if (qstrcmp(KCODE, "SJIS") == 0) {
|
|
|
|
codec = TTQTextCodec::codecForName("Shift-JIS");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TTQString*
|
|
|
|
qstringFromRString(VALUE rstring) {
|
|
|
|
if (KCODE == 0) {
|
|
|
|
init_codec();
|
|
|
|
}
|
|
|
|
|
|
|
|
TTQString * s;
|
|
|
|
if (qstrcmp(KCODE, "UTF8") == 0)
|
|
|
|
s = new TTQString(TTQString::fromUtf8(StringValuePtr(rstring), RSTRING(rstring)->len));
|
|
|
|
else if (qstrcmp(KCODE, "EUC") == 0)
|
|
|
|
s = new TTQString(codec->toUnicode(StringValuePtr(rstring)));
|
|
|
|
else if (qstrcmp(KCODE, "SJIS") == 0)
|
|
|
|
s = new TTQString(codec->toUnicode(StringValuePtr(rstring)));
|
|
|
|
else if(qstrcmp(KCODE, "NONE") == 0)
|
|
|
|
s = new TTQString(TTQString::fromLatin1(StringValuePtr(rstring)));
|
|
|
|
else
|
|
|
|
s = new TTQString(TTQString::fromLocal8Bit(StringValuePtr(rstring), RSTRING(rstring)->len));
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
VALUE
|
|
|
|
rstringFromTQString(TTQString * s) {
|
|
|
|
if (KCODE == 0) {
|
|
|
|
init_codec();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (qstrcmp(KCODE, "UTF8") == 0)
|
|
|
|
return rb_str_new2(s->utf8());
|
|
|
|
else if (qstrcmp(KCODE, "EUC") == 0)
|
|
|
|
return rb_str_new2(codec->fromUnicode(*s));
|
|
|
|
else if (qstrcmp(KCODE, "SJIS") == 0)
|
|
|
|
return rb_str_new2(codec->fromUnicode(*s));
|
|
|
|
else if (qstrcmp(KCODE, "NONE") == 0)
|
|
|
|
return rb_str_new2(s->latin1());
|
|
|
|
else
|
|
|
|
return rb_str_new2(s->local8Bit());
|
|
|
|
}
|
|
|
|
|
|
|
|
static void marshall_QString(Marshall *m) {
|
|
|
|
switch(m->action()) {
|
|
|
|
case Marshall::FromVALUE:
|
|
|
|
{
|
|
|
|
TTQString* s = 0;
|
|
|
|
if ( *(m->var()) != Qnil) {
|
|
|
|
s = qstringFromRString(*(m->var()));
|
|
|
|
} else {
|
|
|
|
s = new TTQString(TTQString::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:
|
|
|
|
{
|
|
|
|
TTQString *s = (TTQString*)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 TTQChar to a TTQString is to
|
|
|
|
// pass a TTQChar to a TTQString 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;
|
|
|
|
}
|
|
|
|
|
|
|
|
TTQChar * qchar = (TTQChar*) o->ptr;
|
|
|
|
TTQString 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_QCString(Marshall *m) {
|
|
|
|
switch(m->action()) {
|
|
|
|
case Marshall::FromVALUE:
|
|
|
|
{
|
|
|
|
TTQCString *s = 0;
|
|
|
|
VALUE rv = *(m->var());
|
|
|
|
if (rv == Qnil) {
|
|
|
|
s = new TTQCString();
|
|
|
|
} else {
|
|
|
|
// Add 1 to the ruby string length to allow for a TTQCString '\0' terminator
|
|
|
|
s = new TTQCString(StringValuePtr(*(m->var())), RSTRING(*(m->var()))->len + 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:
|
|
|
|
{
|
|
|
|
TTQCString *s = (TTQCString*)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
|
|
|
|
// TTQTextCodec* c = TTQTextCodec::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_QCOORD_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(av)->len;
|
|
|
|
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(arglist)->len == 0 )
|
|
|
|
{
|
|
|
|
m->item().s_voidp = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
char **argv = new char *[RARRAY(arglist)->len + 1];
|
|
|
|
long i;
|
|
|
|
for(i = 0; i < RARRAY(arglist)->len; 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_QStringList(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(list)->len;
|
|
|
|
TTQStringList *stringlist = new TQStringList;
|
|
|
|
|
|
|
|
for(long i = 0; i < count; i++) {
|
|
|
|
VALUE item = rb_ary_entry(list, i);
|
|
|
|
if(TYPE(item) != T_STRING) {
|
|
|
|
stringlist->append(TTQString());
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
stringlist->append(*(qstringFromRString(item)));
|
|
|
|
}
|
|
|
|
|
|
|
|
m->item().s_voidp = stringlist;
|
|
|
|
m->next();
|
|
|
|
|
|
|
|
|
|
|
|
if (stringlist != 0 && !m->type().isConst()) {
|
|
|
|
rb_ary_clear(list);
|
|
|
|
for(TTQStringList::Iterator it = stringlist->begin(); it != stringlist->end(); ++it)
|
|
|
|
rb_ary_push(list, rstringFromTQString(&(*it)));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m->cleanup())
|
|
|
|
delete stringlist;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case Marshall::ToVALUE:
|
|
|
|
{
|
|
|
|
TTQStringList *stringlist = static_cast<TTQStringList *>(m->item().s_voidp);
|
|
|
|
if(!stringlist) {
|
|
|
|
*(m->var()) = Qnil;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
VALUE av = rb_ary_new();
|
|
|
|
for(TTQStringList::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_QStrList(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(list)->len;
|
|
|
|
TTQStrList *stringlist = new TQStrList;
|
|
|
|
|
|
|
|
for(long i = 0; i < count; i++) {
|
|
|
|
VALUE item = rb_ary_entry(list, i);
|
|
|
|
if(TYPE(item) != T_STRING) {
|
|
|
|
stringlist->append(TTQString());
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
stringlist->append(TTQString::fromUtf8(StringValuePtr(item), RSTRING(item)->len));
|
|
|
|
}
|
|
|
|
|
|
|
|
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:
|
|
|
|
{
|
|
|
|
TTQStrList *stringlist = static_cast<TTQStrList *>(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(list)->len;
|
|
|
|
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_QValueListInt(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(list)->len;
|
|
|
|
TTQValueList<int> *valuelist = new TTQValueList<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(TTQValueListIterator<int> it = valuelist->begin();
|
|
|
|
it != valuelist->end();
|
|
|
|
++it)
|
|
|
|
rb_ary_push(list, INT2NUM((int)*it));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m->cleanup()) {
|
|
|
|
delete valuelist;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case Marshall::ToVALUE:
|
|
|
|
{
|
|
|
|
TTQValueList<int> *valuelist = (TTQValueList<int>*)m->item().s_voidp;
|
|
|
|
if(!valuelist) {
|
|
|
|
*(m->var()) = Qnil;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
VALUE av = rb_ary_new();
|
|
|
|
|
|
|
|
for(TTQValueListIterator<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_QMapTQStringTQString(Marshall *m) {
|
|
|
|
switch(m->action()) {
|
|
|
|
case Marshall::FromVALUE:
|
|
|
|
{
|
|
|
|
VALUE hash = *(m->var());
|
|
|
|
if (TYPE(hash) != T_HASH) {
|
|
|
|
m->item().s_voidp = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
TTQMap<TTQString,TTQString> * map = new TTQMap<TTQString,TTQString>;
|
|
|
|
|
|
|
|
// 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(temp)->len; i++) {
|
|
|
|
VALUE key = rb_ary_entry(rb_ary_entry(temp, i), 0);
|
|
|
|
VALUE value = rb_ary_entry(rb_ary_entry(temp, i), 1);
|
|
|
|
(*map)[TTQString(StringValuePtr(key))] = TTQString(StringValuePtr(value));
|
|
|
|
}
|
|
|
|
|
|
|
|
m->item().s_voidp = map;
|
|
|
|
m->next();
|
|
|
|
|
|
|
|
if(m->cleanup())
|
|
|
|
delete map;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case Marshall::ToVALUE:
|
|
|
|
{
|
|
|
|
TTQMap<TTQString,TTQString> *map = (TTQMap<TTQString,TTQString>*)m->item().s_voidp;
|
|
|
|
if(!map) {
|
|
|
|
*(m->var()) = Qnil;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
VALUE hv = rb_hash_new();
|
|
|
|
|
|
|
|
TTQMap<TTQString,TTQString>::Iterator it;
|
|
|
|
for (it = map->begin(); it != map->end(); ++it) {
|
|
|
|
rb_hash_aset(hv, rstringFromTQString((TTQString*)&(it.key())), rstringFromTQString((TTQString*) &(it.data())));
|
|
|
|
}
|
|
|
|
|
|
|
|
*(m->var()) = hv;
|
|
|
|
m->next();
|
|
|
|
|
|
|
|
if(m->cleanup())
|
|
|
|
delete map;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
m->unsupported();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void marshall_QMapTQStringTQVariant(Marshall *m) {
|
|
|
|
switch(m->action()) {
|
|
|
|
case Marshall::FromVALUE:
|
|
|
|
{
|
|
|
|
VALUE hash = *(m->var());
|
|
|
|
if (TYPE(hash) != T_HASH) {
|
|
|
|
m->item().s_voidp = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
TTQMap<TTQString,TTQVariant> * map = new TTQMap<TTQString,TTQVariant>;
|
|
|
|
|
|
|
|
// 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(temp)->len; 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("TTQVariant")) {
|
|
|
|
// 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("TTQVariant"));
|
|
|
|
|
|
|
|
(*map)[TTQString(StringValuePtr(key))] = (TTQVariant)*(TTQVariant*)ptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
m->item().s_voidp = map;
|
|
|
|
m->next();
|
|
|
|
|
|
|
|
if(m->cleanup())
|
|
|
|
delete map;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case Marshall::ToVALUE:
|
|
|
|
{
|
|
|
|
TTQMap<TTQString,TTQVariant> *map = (TTQMap<TTQString,TTQVariant>*)m->item().s_voidp;
|
|
|
|
if(!map) {
|
|
|
|
*(m->var()) = Qnil;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
VALUE hv = rb_hash_new();
|
|
|
|
|
|
|
|
TTQMap<TTQString,TTQVariant>::Iterator it;
|
|
|
|
for (it = map->begin(); it != map->end(); ++it) {
|
|
|
|
void *p = new TTQVariant(it.data());
|
|
|
|
VALUE obj = getPointerObject(p);
|
|
|
|
|
|
|
|
if (obj == Qnil) {
|
|
|
|
smokeruby_object * o = ALLOC(smokeruby_object);
|
|
|
|
o->classId = m->smoke()->idClass("TTQVariant");
|
|
|
|
o->smoke = m->smoke();
|
|
|
|
o->ptr = p;
|
|
|
|
o->allocated = true;
|
|
|
|
obj = set_obj_info("TQt::Variant", o);
|
|
|
|
}
|
|
|
|
|
|
|
|
rb_hash_aset(hv, rstringFromTQString((TTQString*)&(it.key())), obj);
|
|
|
|
}
|
|
|
|
|
|
|
|
*(m->var()) = hv;
|
|
|
|
m->next();
|
|
|
|
|
|
|
|
if(m->cleanup())
|
|
|
|
delete map;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
m->unsupported();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void marshall_QUObject(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_QRgb_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(list)->len;
|
|
|
|
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_QPairintint(Marshall *m) {
|
|
|
|
switch(m->action()) {
|
|
|
|
case Marshall::FromVALUE:
|
|
|
|
{
|
|
|
|
VALUE list = *(m->var());
|
|
|
|
if (TYPE(list) != T_ARRAY || RARRAY(list)->len != 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 QT_VERSION >= 0x030200
|
|
|
|
DEF_LIST_MARSHALLER( TQPtrListTQNetworkOperation, TTQPtrList<TTQNetworkOperation>, TTQNetworkOperation, TTQPtrListStdIterator<TTQNetworkOperation> )
|
|
|
|
DEF_LIST_MARSHALLER( TQPtrListTQToolBar, TTQPtrList<TTQToolBar>, TTQToolBar, TTQPtrListStdIterator<TTQToolBar> )
|
|
|
|
DEF_LIST_MARSHALLER( TQPtrListTQTab, TTQPtrList<TTQTab>, TTQTab, TTQPtrListStdIterator<TTQTab> )
|
|
|
|
DEF_LIST_MARSHALLER( TQPtrListTQDockWindow, TTQPtrList<TTQDockWindow>, TTQDockWindow, TTQPtrListStdIterator<TTQDockWindow> )
|
|
|
|
DEF_LIST_MARSHALLER( TQFileInfoList, TQFileInfoList, TTQFileInfo, TQFileInfoList::Iterator )
|
|
|
|
DEF_LIST_MARSHALLER( TTQObjectList, TTQObjectList, TTQObject, TTQPtrListStdIterator<TTQObject> )
|
|
|
|
DEF_LIST_MARSHALLER( TTQWidgetList, TTQWidgetList, TTQWidget, TTQPtrListStdIterator<TTQWidget> )
|
|
|
|
#endif
|
|
|
|
|
|
|
|
DEF_LIST_MARSHALLER( TTQCanvasItemList, TTQCanvasItemList, TTQCanvasItem, TTQValueListIterator<TTQCanvasItem*> )
|
|
|
|
|
|
|
|
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(list)->len;
|
|
|
|
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 TTQValueList<TTQVariant> type
|
|
|
|
if ( qstrcmp(ItemSTR, "TTQVariant") == 0
|
|
|
|
&& (!o || !o->ptr || o->classId != o->smoke->idClass("TTQVariant")) )
|
|
|
|
{
|
|
|
|
// 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, TTQValueList<TTQVariant>, TTQVariant, TTQValueList<TTQVariant>::Iterator )
|
|
|
|
DEF_VALUELIST_MARSHALLER( TQPixmapList, TTQValueList<TTQPixmap>, TTQPixmap, TTQValueList<TTQPixmap>::Iterator )
|
|
|
|
DEF_VALUELIST_MARSHALLER( TQIconDragItemList, TTQValueList<TTQIconDragItem>, TTQIconDragItem, TTQValueList<TTQIconDragItem>::Iterator )
|
|
|
|
DEF_VALUELIST_MARSHALLER( TQImageTextKeyLangList, TTQValueList<TTQImageTextKeyLang>, TTQImageTextKeyLang, TTQValueList<TTQImageTextKeyLang>::Iterator )
|
|
|
|
DEF_VALUELIST_MARSHALLER( TQUrlInfoList, TTQValueList<TTQUrlInfo>, TTQUrlInfo, TTQValueList<TTQUrlInfo>::Iterator )
|
|
|
|
DEF_VALUELIST_MARSHALLER( TQTranslatorMessageList, TTQValueList<TQTranslatorMessage>, TQTranslatorMessage, TTQValueList<TQTranslatorMessage>::Iterator )
|
|
|
|
DEF_VALUELIST_MARSHALLER( TQHostAddressList, TTQValueList<TTQHostAddress>, TTQHostAddress, TTQValueList<TTQHostAddress>::Iterator )
|
|
|
|
|
|
|
|
TypeHandler Qt_handlers[] = {
|
|
|
|
{ "TTQString", marshall_QString },
|
|
|
|
{ "TTQString&", marshall_QString },
|
|
|
|
{ "TTQString*", marshall_QString },
|
|
|
|
{ "TTQCString", marshall_QCString },
|
|
|
|
{ "TTQCString&", marshall_QCString },
|
|
|
|
{ "TTQCString*", marshall_QCString },
|
|
|
|
{ "TTQStringList", marshall_QStringList },
|
|
|
|
{ "TTQStringList&", marshall_QStringList },
|
|
|
|
{ "TTQStringList*", marshall_QStringList },
|
|
|
|
{ "TTQStrList", marshall_QStrList },
|
|
|
|
{ "TTQStrList&", marshall_QStrList },
|
|
|
|
{ "TTQStrList*", marshall_QStrList },
|
|
|
|
{ "long long int", marshall_longlong },
|
|
|
|
{ "long long int&", marshall_longlong },
|
|
|
|
{ "Q_INT64", marshall_longlong },
|
|
|
|
{ "Q_INT64&", marshall_longlong },
|
|
|
|
{ "Q_LLONG", marshall_longlong },
|
|
|
|
{ "Q_LLONG&", marshall_longlong },
|
|
|
|
{ "KIO::filesize_t", marshall_longlong },
|
|
|
|
{ "DOM::DOMTimeStamp", marshall_ulonglong },
|
|
|
|
{ "unsigned long long int", marshall_ulonglong },
|
|
|
|
{ "unsigned long long int&", marshall_ulonglong },
|
|
|
|
{ "Q_UINT64", marshall_ulonglong },
|
|
|
|
{ "Q_UINT64&", marshall_ulonglong },
|
|
|
|
{ "Q_ULLONG", marshall_ulonglong },
|
|
|
|
{ "Q_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_QRgb_array },
|
|
|
|
{ "TQPair<int,int>&", marshall_QPairintint },
|
|
|
|
{ "TQUObject*", marshall_QUObject },
|
|
|
|
{ "const TQCOORD*", marshall_QCOORD_array },
|
|
|
|
{ "void", marshall_void },
|
|
|
|
{ "TTQValueList<int>", marshall_QValueListInt },
|
|
|
|
{ "TTQValueList<int>&", marshall_QValueListInt },
|
|
|
|
{ "TTQValueList<TTQVariant>", marshall_QVariantList },
|
|
|
|
{ "TTQValueList<TTQVariant>&", marshall_QVariantList },
|
|
|
|
{ "TTQValueList<TTQPixmap>", marshall_QPixmapList },
|
|
|
|
{ "TTQValueList<TTQIconDragItem>&", marshall_QIconDragItemList },
|
|
|
|
{ "TTQValueList<TTQImageTextKeyLang>", marshall_QImageTextKeyLangList },
|
|
|
|
{ "TTQValueList<TTQUrlInfo>&", marshall_QUrlInfoList },
|
|
|
|
{ "TTQValueList<TQTranslatorMessage>", marshall_QTranslatorMessageList },
|
|
|
|
{ "TTQValueList<TTQHostAddress>", marshall_QHostAddressList },
|
|
|
|
{ "TTQCanvasItemList", marshall_TTQCanvasItemList },
|
|
|
|
{ "TTQMap<TTQString,TTQString>", marshall_QMapTQStringTQString },
|
|
|
|
{ "TTQMap<TTQString,TTQString>&", marshall_QMapTQStringTQString },
|
|
|
|
{ "TTQMap<TTQString,TTQVariant>", marshall_QMapTQStringTQVariant },
|
|
|
|
{ "TTQMap<TTQString,TTQVariant>&", marshall_QMapTQStringTQVariant },
|
|
|
|
#if QT_VERSION >= 0x030200
|
|
|
|
{ "TTQWidgetList", marshall_TTQWidgetList },
|
|
|
|
{ "TTQWidgetList*", marshall_TTQWidgetList },
|
|
|
|
{ "TTQWidgetList&", marshall_TTQWidgetList },
|
|
|
|
{ "TTQObjectList*", marshall_TTQObjectList },
|
|
|
|
{ "TTQObjectList&", marshall_TTQObjectList },
|
|
|
|
{ "TQFileInfoList*", marshall_QFileInfoList },
|
|
|
|
{ "TTQPtrList<TTQToolBar>", marshall_QPtrListTQToolBar },
|
|
|
|
{ "TTQPtrList<TTQTab>*", marshall_QPtrListTQTab },
|
|
|
|
{ "TTQPtrList<TTQDockWindow>", marshall_QPtrListTQDockWindow },
|
|
|
|
{ "TTQPtrList<TTQDockWindow>*", marshall_QPtrListTQDockWindow },
|
|
|
|
{ "TTQPtrList<TTQNetworkOperation>", marshall_QPtrListTQNetworkOperation },
|
|
|
|
{ "TTQPtrList<TTQNetworkOperation>&", marshall_QPtrListTQNetworkOperation },
|
|
|
|
#endif
|
|
|
|
{ 0, 0 }
|
|
|
|
};
|
|
|
|
|
|
|
|
TTQAsciiDict<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;
|
|
|
|
}
|