diff options
Diffstat (limited to 'dcopperl/DCOP.xs')
-rw-r--r-- | dcopperl/DCOP.xs | 492 |
1 files changed, 492 insertions, 0 deletions
diff --git a/dcopperl/DCOP.xs b/dcopperl/DCOP.xs new file mode 100644 index 00000000..509366af --- /dev/null +++ b/dcopperl/DCOP.xs @@ -0,0 +1,492 @@ + +#include "EXTERN.h" +#include "perl.h" +#include "XSUB.h" + +#ifdef METHOD +#undef METHOD +#endif + +#ifdef ref +#undef ref +#endif +#ifdef list +#undef list +#endif +#ifdef do_open +#undef do_open +#endif +#ifdef do_close +#undef do_close +#endif +#ifdef assert +#undef assert +#endif +#ifdef vform +#undef vform +#endif + +#include <qpoint.h> +#include <qrect.h> +#include <qregexp.h> +#include <qsize.h> +#include <qstringlist.h> + +#include <dcopclient.h> +#include <dcopref.h> +#include <kdatastream.h> +#include <kurl.h> + +int intFromSV(SV *data) +{ + if (!SvOK(data)) + return 0; + if (!SvIOK(data)) + croak("DCOP: Cannot convert to integer"); + return SvIV(data); +} + +SV *intToSV(int data, SV * self = 0) +{ + return newSViv(data); +} + +uint uintFromSV(SV *data) +{ + if (!SvOK(data)) + return 0; + if (!SvIOK(data)) + croak("DCOP: Cannot convert to integer"); + return SvIV(data); +} + +SV *uintToSV(uint data, SV * self = 0) +{ + return newSViv(data); +} + + +bool boolFromSV(SV *data) +{ + if (!SvOK(data)) + return false; + if (SvIOK(data)) + return SvIV(data); + if (SvPOK(data)) + return QCString(SvPV(data, PL_na)).lower() == "true"; + croak("DCOP: Cannot convert to bool"); +} + +SV *boolToSV(bool data, SV *self = 0) +{ + return newSViv(data ? 1 : 0); +} + +QCString QCStringFromSV(SV *data) +{ + if (!SvOK(data)) + return QCString(); + if (!SvPOK(data)) + croak("DCOP: Cannot convert to QCString"); + return SvPV(data, PL_na); +} + +SV *QCStringToSV(const QCString &data, SV * self = 0) +{ + return data.isNull() ? &PL_sv_undef : newSVpv(data.data(), 0); +} + +QString QStringFromSV(SV *data) +{ + if (!SvOK(data)) + return QString::null; + if (!SvPOK(data)) + croak("DCOP: Cannot convert to QString"); + return SvPV(data, PL_na); +} + +SV *QStringToSV(const QString &data, SV * self = 0) +{ + return data.isNull() ? &PL_sv_undef : newSVpv((char *)data.latin1(), 0); +} + +QCStringList QCStringListFromSV(SV *data) +{ + if (!SvROK(data)) + croak("DCOP: Not reference"); + if (SvTYPE(SvRV(data)) != SVt_PVAV) + croak("DCOP: Not an array reference"); + QCStringList result; + for (int i = 0; i <= av_len((AV*)SvRV(data)); i++) + result.append(QCStringFromSV(av_fetch((AV*)SvRV(data), i, 0)[0])); + return result; +} + +SV *QCStringListToSV(const QCStringList &data, SV * self = 0) +{ + AV *result = newAV(); + for (QCStringList::ConstIterator i = data.begin(); i != data.end(); i++) + av_push(result, QCStringToSV(*i)); + return newRV((SV*)result); +} + +QStringList QStringListFromSV(SV *data) +{ + if (!SvROK(data)) + croak("DCOP: Not reference"); + if (SvTYPE(SvRV(data)) != SVt_PVAV) + croak("DCOP: Not an array reference"); + QStringList result; + for (int i = 0; i <= av_len((AV*)SvRV(data)); i++) + result.append(QCStringFromSV(av_fetch((AV*)SvRV(data), i, 0)[0])); + return result; +} + +SV *QStringListToSV(const QStringList &data, SV * self = 0) +{ + AV *result = newAV(); + for (QStringList::ConstIterator i = data.begin(); i != data.end(); i++) + av_push(result, QStringToSV(*i)); + return newRV((SV*)result); +} + +QPoint QPointFromSV(SV *data) +{ + if (!SvROK(data)) + croak("DCOP: Not reference"); + if (SvTYPE(SvRV(data)) != SVt_PVAV) + croak("DCOP: Not an array reference"); + if (av_len((AV*)SvRV(data)) != 1) + croak("DCOP: A QPoint must have exactly 2 components"); + SV **pts = av_fetch((AV*)SvRV(data), 0, 0); + return QPoint(intFromSV(pts[0]), intFromSV(pts[1])); +} + +SV *QPointToSV(const QPoint &data, SV * self = 0) +{ + SV *pts[2] = { + intToSV(data.x()), + intToSV(data.y()) + }; + return newRV((SV*)av_make(2, pts)); +} + +QSize QSizeFromSV(SV *data) +{ + if (!SvROK(data)) + croak("DCOP: Not reference"); + if (SvTYPE(SvRV(data)) != SVt_PVAV) + croak("DCOP: Not an array reference"); + if (av_len((AV*)SvRV(data)) != 1) + croak("DCOP: A QSize must have exactly 2 components"); + SV **ext = av_fetch((AV*)SvRV(data), 0, 0); + return QSize(intFromSV(ext[0]), intFromSV(ext[1])); +} + +SV *QSizeToSV(const QSize &data, SV * self = 0) +{ + SV *ext[2] = { + intToSV(data.width()), + intToSV(data.height()) + }; + return newRV((SV*)av_make(2, ext)); +} + +QRect QRectFromSV(SV *data) +{ + if (!SvROK(data)) + croak("DCOP: Not a reference"); + if (SvTYPE(SvRV(data)) != SVt_PVAV) + croak("DCOP: Not an array reference"); + if (av_len((AV*)SvRV(data)) != 1) + croak("DCOP: A QRect must have exactly 4 components"); + SV **rc = av_fetch((AV*)SvRV(data), 0, 0); + return QRect(intFromSV(rc[0]), intFromSV(rc[1]), intFromSV(rc[2]), intFromSV(rc[3])); +} + +SV *QRectToSV(const QRect &data, SV * self = 0) +{ + SV *rc[4] = { + intToSV(data.left()), + intToSV(data.top()), + intToSV(data.width()), + intToSV(data.height()) + }; + return newRV((SV*)av_make(4, rc)); +} + +KURL KURLFromSV(SV *data) +{ + return KURL(QStringFromSV(data)); +} + +SV *KURLToSV(const KURL &data, SV * self = 0) +{ + return QStringToSV(data.url()); +} + +DCOPRef DCOPRefFromSV(SV *data) +{ + if (!sv_isa(data, "DCOP::Object")) + croak("DCOP: Not a DCOP::Object"); + SV **app = hv_fetch((HV*)SvRV(data), "APP", 3, 0); + SV **obj = hv_fetch((HV*)SvRV(data), "OBJ", 3, 0); + return DCOPRef(QCStringFromSV(app[0]), QCStringFromSV(obj[0])); +} + +SV *DCOPRefToSV(const DCOPRef &data, SV * self) +{ + SV *ref = newRV((SV*)newHV()); + hv_store((HV*)SvRV(ref), "CLIENT", 6, SvREFCNT_inc(self), 0); + hv_store((HV*)SvRV(ref), "APP", 3, QCStringToSV(data.app()), 0); + hv_store((HV*)SvRV(ref), "OBJ", 3, QCStringToSV(data.object()), 0); + return sv_bless(ref, gv_stashpv("DCOP::Object", 0)); +} + +# // Yes, defines *are* ugly... +#define CHECK_ARG(t) \ + if ((*it) == #t) \ + s << t##FromSV(data[i]); + +#define CHECK_REPLY(t) \ + if (replyType == #t) \ + { \ + t r; \ + s >> r; \ + return t##ToSV(r, self); \ + } + +#define DATA(func, argn) mapArgs(func, &ST(argn), items - argn) + +QByteArray mapArgs(const QCString &func, SV **data, int n) +{ + int p = func.find('('), + q = func.find(')'); + if (p == -1 || q == -1 || q < p) + croak("DCOP: Invalid function signature \"%s\"", func.data()); + QStringList types = QStringList::split(',', func.mid(p + 1, q - p - 1)); + QByteArray result; + QDataStream s(result, IO_WriteOnly); + QStringList::ConstIterator it = types.begin(); + for (int i = 0; i < n; ++i, ++it) + { + if (it == types.end()) + croak("DCOP: Too many (%d) arguments to function \"%s\"", n, func.data()); + CHECK_ARG(int) + else CHECK_ARG(uint) + else CHECK_ARG(bool) + else CHECK_ARG(QCString) + else CHECK_ARG(QString) + else CHECK_ARG(QCStringList) + else CHECK_ARG(QStringList) + else CHECK_ARG(QPoint) + else CHECK_ARG(QSize) + else CHECK_ARG(QRect) + else CHECK_ARG(KURL) + else CHECK_ARG(DCOPRef) + else + croak("DCOP: Sorry, passing a %s is not implemented", (*it).latin1()); + } + if (it != types.end()) + croak("DCOP: Too few (%d) arguments to function \"%s\"", n, func.data()); + return result; +} + +SV* mapReply(const QCString &replyType, const QByteArray &replyData, SV *self) +{ + if (replyType == "void") + return sv_newmortal(); + QDataStream s(replyData, IO_ReadOnly); + CHECK_REPLY(int) + else CHECK_REPLY(uint) + else CHECK_REPLY(bool) + else CHECK_REPLY(QCString) + else CHECK_REPLY(QString) + else CHECK_REPLY(QCStringList) + else CHECK_REPLY(QStringList) + else CHECK_REPLY(QPoint) + else CHECK_REPLY(QSize) + else CHECK_REPLY(QRect) + else CHECK_REPLY(KURL) + else CHECK_REPLY(DCOPRef) + else croak("Sorry, receiving a %s is not implemented", replyType.data()); +} + +bool isMultiWordType(const QString &type) +{ + return type == "unsigned" || type == "signed" || type == "long"; +} + +QCString canonicalizeSignature(const QCString &sig) +{ + QCString normal = DCOPClient::normalizeFunctionSignature(sig); + int p = normal.find('('), q = normal.find(')'); + QCString result = normal.left(p + 1); + result.remove(0, result.findRev(' ') + 1); + + QStringList params = QStringList::split(',', normal.mid(p + 1, q - p - 1)); + for (QStringList::ConstIterator it = params.begin(); it != params.end(); ++it) + { + QStringList words = QStringList::split(' ', (*it).simplifyWhiteSpace()); + for (QStringList::ConstIterator wi = words.begin(); wi != words.end(); ++wi) + if (!isMultiWordType(*wi)) + { + result += *wi; + break; + } + if (it != params.fromLast()) + result += ','; + } + result += ')'; + + return result; +} + +MODULE = DCOP PACKAGE = DCOP + +PROTOTYPES: ENABLE + +DCOPClient * +DCOPClient::new() + OUTPUT: + RETVAL + +void +DCOPClient::DESTROY() + +bool +DCOPClient::attach() + OUTPUT: + RETVAL + +bool +DCOPClient::detach() + OUTPUT: + RETVAL + +bool +DCOPClient::isAttached() + OUTPUT: + RETVAL + +#if 0 +QCString +DCOPClient::registerAs(appId, ...) + QCString appId + PREINIT: + bool addPID = true; + CODE: + if (items > 3) + croak("Usage: DCOP::registerAs(THIS, appId [, addPID])"); + if (items == 3) + addPID = SvIV(ST(2)); + RETVAL = THIS->registerAs(appId, addPID); + OUTPUT: + RETVAL + +bool +DCOPClient::isRegistered() + OUTPUT: + RETVAL + +#endif + +QCString +DCOPClient::appId() + OUTPUT: + RETVAL + +bool +DCOPClient::send(app, obj, func, ...) + QCString app + QCString obj + QCString func + CODE: + func = canonicalizeSignature(func); + RETVAL = THIS->send(app, obj, func, DATA(func, 4)); + OUTPUT: + RETVAL + +SV* +DCOPClient::call(app, obj, func, ...) + QCString app + QCString obj + QCString func + PPCODE: + func = canonicalizeSignature(func); + QCString replyType; + QByteArray replyData; + bool success; + if ((success = THIS->call(app, obj, func, DATA(func, 4), replyType, replyData))) + PUSHs(mapReply(replyType, replyData, ST(0))); + else + PUSHs(&PL_sv_undef); + if (GIMME_V == G_ARRAY) + PUSHs(success ? &PL_sv_yes : &PL_sv_no); + +SV* +DCOPClient::findObject(app, obj, func, ...) + QCString app + QCString obj + QCString func + PPCODE: + func = canonicalizeSignature(func); + QCString foundApp; + QCString foundObj; + if (!THIS->findObject(app, obj, func, DATA(func, 4), foundApp, foundObj)) + XSRETURN_UNDEF; + PUSHs(QCStringToSV(foundApp)); + PUSHs(QCStringToSV(foundObj)); + +void +DCOPClient::emitDCOPSignal(obj, signal, ...) + QCString obj + QCString signal + CODE: + signal = canonicalizeSignature(signal); + THIS->emitDCOPSignal(obj, signal, DATA(signal, 3)); + +bool +DCOPClient::isApplicationRegistered(app) + QCString app + OUTPUT: + RETVAL + +QCStringList +DCOPClient::registeredApplications() + OUTPUT: + RETVAL + +QCStringList +DCOPClient::remoteObjects(app) + QCString app + OUTPUT: + RETVAL + +QCStringList +DCOPClient::remoteInterfaces(app, obj) + QCString app + QCString obj + OUTPUT: + RETVAL + +QCStringList +DCOPClient::remoteFunctions(app, obj) + QCString app + QCString obj + OUTPUT: + RETVAL + +static QCString +DCOPClient::normalizeFunctionSignature(sig) + QCString sig + OUTPUT: + RETVAL + +QCString +canonicalizeSignature(sig) + QCString sig + CODE: + RETVAL = canonicalizeSignature(sig); + OUTPUT: + RETVAL |