summaryrefslogtreecommitdiffstats
path: root/dcopperl/DCOP.xs
diff options
context:
space:
mode:
Diffstat (limited to 'dcopperl/DCOP.xs')
-rw-r--r--dcopperl/DCOP.xs492
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