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.
tdebindings/dcopperl/DCOP.xs

493 lines
11 KiB

#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