summaryrefslogtreecommitdiffstats
path: root/dcopc
diff options
context:
space:
mode:
authortoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
committertoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
commit90825e2392b2d70e43c7a25b8a3752299a933894 (patch)
treee33aa27f02b74604afbfd0ea4f1cfca8833d882a /dcopc
downloadtdebindings-90825e2392b2d70e43c7a25b8a3752299a933894.tar.gz
tdebindings-90825e2392b2d70e43c7a25b8a3752299a933894.zip
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923 git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdebindings@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'dcopc')
-rw-r--r--dcopc/Makefile.am20
-rw-r--r--dcopc/configure.in.in5
-rw-r--r--dcopc/dcopc.c1579
-rw-r--r--dcopc/dcopc.h143
-rw-r--r--dcopc/dcopobject.c301
-rw-r--r--dcopc/dcopobject.h93
-rw-r--r--dcopc/glib.m4196
-rw-r--r--dcopc/glibtest.c133
-rw-r--r--dcopc/global.h75
-rw-r--r--dcopc/gtk.m4197
-rw-r--r--dcopc/marshal.c420
-rw-r--r--dcopc/marshal.h93
-rw-r--r--dcopc/util.c137
-rw-r--r--dcopc/util.h73
14 files changed, 3465 insertions, 0 deletions
diff --git a/dcopc/Makefile.am b/dcopc/Makefile.am
new file mode 100644
index 00000000..362994b5
--- /dev/null
+++ b/dcopc/Makefile.am
@@ -0,0 +1,20 @@
+AM_CFLAGS = $(GLIB_CFLAGS) $(GTK_CFLAGS)
+AM_CXXFLAGS = $(GLIB_CFLAGS) $(GTK_CFLAGS)
+
+INCLUDES = -I$(top_srcdir)/ $(X_INCLUDES)
+
+lib_LTLIBRARIES = libdcopc.la
+
+libdcopc_la_SOURCES = dcopc.c marshal.c dcopobject.c
+libdcopc_la_LIBADD = -lSM -lICE $(GTK_LIBS) $(GLIB_LIBS)
+libdcopc_la_LDFLAGS = -version-info 1:0 $(X_LDFLAGS) -lICE -no-undefined
+
+include_HEADERS = dcopc.h marshal.h dcopobject.h util.h
+includedir = $(prefix)/include/dcopc
+
+noinst_HEADERS = global.h
+
+check_PROGRAMS = glibtest
+
+glibtest_SOURCES = glibtest.c
+glibtest_LDADD = libdcopc.la
diff --git a/dcopc/configure.in.in b/dcopc/configure.in.in
new file mode 100644
index 00000000..9c1458ee
--- /dev/null
+++ b/dcopc/configure.in.in
@@ -0,0 +1,5 @@
+dnl if test "$GTK_CONFIG" = "no"; then
+ DO_NOT_COMPILE="$DO_NOT_COMPILE dcopc"
+dnl fi
+dnl
+dnl AC_CHECK_GETHOSTNAME
diff --git a/dcopc/dcopc.c b/dcopc/dcopc.c
new file mode 100644
index 00000000..fcb51e2b
--- /dev/null
+++ b/dcopc/dcopc.c
@@ -0,0 +1,1579 @@
+/*
+Copyright (c) 2000 Simon Hausmann <hausmann@kde.org>
+Copyright (c) 2000 Lars Knoll <knoll@kde.org>
+Copyright (c) 1999 Preston Brown <pbrown@kde.org>
+Copyright (c) 1999, 2000 Matthias Ettrich <ettrich@kde.org>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include <config.h>
+
+#include "global.h"
+#include "dcopc.h"
+#include "dcopobject.h"
+
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <ctype.h>
+
+typedef struct _DcopClientMessage DcopClientMessage;
+
+struct _DcopClientMessage
+{
+ int opcode;
+ CARD32 key;
+ dcop_data *data;
+};
+
+typedef struct _DcopClientPrivate DcopClientPrivate;
+
+struct _DcopClientPrivate
+{
+ gchar *app_id;
+ IceConn ice_conn;
+ gint major_opcode;
+ gint major_version, minor_version;
+ gchar *vendor, *release;
+ gboolean registered;
+ gchar *sender_id;
+
+ gchar *default_object;
+
+ CARD32 key;
+ CARD32 current_key;
+
+ GList *transaction_list;
+ gboolean transaction;
+ gint32 transaction_id;
+
+ int opcode;
+
+ guint post_message_timer;
+ GList *messages;
+};
+
+struct _DcopClientTransaction
+{
+ gint32 id;
+ CARD32 key;
+ gchar *sender_id;
+};
+
+int DCOPAuthCount = 1;
+const char *DCOPAuthNames[] = {"MIT-MAGIC-COOKIE-1"};
+
+extern IcePoAuthStatus _IcePoMagicCookie1Proc (IceConn, void **, int, int, int, void *, int *, void **, char **);
+extern IcePaAuthStatus _IcePaMagicCookie1Proc (IceConn, void **, int, int, void *, int *, void **, char **);
+
+IcePoAuthProc DCOPClientAuthProcs[] = {_IcePoMagicCookie1Proc};
+IcePaAuthProc DCOPServerAuthProcs[] = {_IcePaMagicCookie1Proc};
+
+enum reply_status
+{ Pending, Ok, Rejected, Failed };
+
+typedef struct _reply_struct reply_struct;
+
+struct _reply_struct
+{
+ gint status;
+ gchar **reply_type;
+ dcop_data **reply_data;
+ guint reply_id;
+};
+
+static void reply_struct_init( reply_struct *s )
+{
+ s->status = Pending;
+ s->reply_type = 0;
+ s->reply_data = 0;
+ s->reply_id = 0;
+}
+
+#define P ((DcopClientPrivate *)(client->priv))
+#define ERR( emsg ) \
+ { \
+ if ( dcop_client_free_error_msg ) \
+ g_free( dcop_client_error_msg ); \
+ dcop_client_error_msg = (gchar *)emsg; \
+ dcop_client_free_error_msg = FALSE; \
+ }
+
+#define CLIENT_CLASS(obj) DCOP_CLIENT_CLASS(GTK_OBJECT(obj)->klass)
+
+static gchar *dcop_client_server_address = 0;
+static gchar *dcop_client_error_msg = 0;
+static gboolean dcop_client_free_error_msg;
+
+/* don't use the glib types for args here, as this is an ICE callback (Simon)*/
+void dcop_process_message( IceConn ice_conn, IcePointer client_object,
+ int opcode, unsigned long length, Bool swap,
+ IceReplyWaitInfo *replyWait,
+ Bool *replyWaitRet );
+
+gchar *dcop_client_normalize_function_signature( const gchar *fun );
+
+static IcePoVersionRec DCOPVersions[] = {
+ { DCOPVersionMajor, DCOPVersionMinor, dcop_process_message
+ }
+};
+
+static unsigned int dcop_client_count = 0;
+static GtkObjectClass *parent_class = 0;
+
+static void dcop_client_class_init(DcopClientClass *klass);
+static void dcop_client_init(DcopClient *client);
+
+static gboolean dcop_client_real_process ( DcopClient *client, const char *fun, dcop_data *data,
+ char **reply_type, dcop_data **reply_data );
+
+GtkType
+dcop_client_get_type(void)
+{
+ static GtkType dcop_client_type = 0;
+ if (!dcop_client_type)
+ {
+ static const GtkTypeInfo dcop_client_info =
+ {
+ (gchar *)"DcopClient",
+ sizeof(DcopClient),
+ sizeof(DcopClientClass),
+ (GtkClassInitFunc)dcop_client_class_init,
+ (GtkObjectInitFunc)dcop_client_init,
+ 0,
+ 0,
+ 0
+ };
+ dcop_client_type = gtk_type_unique(GTK_TYPE_OBJECT, &dcop_client_info);
+ }
+ return dcop_client_type;
+}
+
+static void dcop_client_destroy( GtkObject *obj );
+static void dcop_init(void);
+static void dcop_shutdown(void);
+
+void
+dcop_client_class_init(DcopClientClass *klass)
+{
+ GtkObjectClass *object_class;
+ object_class = (GtkObjectClass *)klass;
+
+ parent_class = (GtkObjectClass *)gtk_type_class(gtk_object_get_type());
+
+ object_class->destroy = dcop_client_destroy;
+ klass->process = dcop_client_real_process;
+}
+
+void
+dcop_client_init(DcopClient *client)
+{
+ DcopClientPrivate *p;
+/* tststs :-) C++ hackers :-) (Simon)*/
+/* p = new GtkDcopClientPrivate;*/
+ p = g_new( DcopClientPrivate, 1 );
+
+ p->app_id = 0;
+ p->ice_conn = 0;
+ p->major_opcode = p->major_version = p->minor_version = 0;
+ p->vendor = p->release = 0;
+ p->registered = FALSE;
+ p->sender_id = 0;
+ p->key = 0;
+ p->current_key = 0;
+ p->post_message_timer = 0;
+ p->messages = 0;
+ p->default_object = 0;
+ p->transaction_list = 0;
+ p->transaction = FALSE;
+ p->transaction_id = 0;
+ p->opcode = 0;
+
+ client->priv = p;
+
+ if ( dcop_client_count == 0 )
+ dcop_init();
+
+ dcop_client_count++;
+}
+
+void dcop_client_destroy( GtkObject *obj )
+{
+ DcopClient *client = DCOP_CLIENT(obj);
+
+ g_message( "dcop_client_destructor()\n" );
+
+ if ( P->ice_conn && IceConnectionStatus( P->ice_conn ) == IceConnectAccepted )
+ dcop_client_detach( client );
+
+ if ( P->post_message_timer != 0 )
+ g_source_remove( P->post_message_timer );
+
+ {
+ GList *it = g_list_first( P->messages );
+ while ( it )
+ {
+ DcopClientMessage *msg = (DcopClientMessage *)it->data;
+ dcop_data_deref( msg->data );
+ g_free( msg );
+ it = g_list_next( it );
+ }
+ g_list_free( P->messages );
+ }
+
+ {
+ GList *it = g_list_first( P->transaction_list );
+ while ( it )
+ {
+ g_free( ((DcopClientTransaction *)it->data)->sender_id );
+ g_free( (DcopClientTransaction *)it );
+ it = g_list_next( it );
+ }
+
+ g_list_free( P->transaction_list );
+ }
+
+ g_free( P->app_id );
+ g_free( P->vendor );
+ g_free( P->release );
+ g_free( P->sender_id );
+
+ g_free( P );
+
+ if ( !--dcop_client_count )
+ dcop_shutdown();
+
+ parent_class->destroy(GTK_OBJECT(client));
+}
+
+
+void dcop_init()
+{
+ g_message( "dcop_init\n" );
+ dcop_client_free_error_msg = FALSE;
+}
+
+void dcop_shutdown()
+{
+ g_message( "dcop_shutdown\n" );
+ dcop_free( dcop_client_server_address );
+
+ if ( dcop_client_free_error_msg )
+ dcop_free( dcop_client_error_msg );
+}
+
+DcopClient *dcop_client_new()
+{
+ return (DcopClient *) gtk_type_new(dcop_client_get_type());
+}
+
+void dcop_client_set_server_address( const gchar *addr )
+{
+ dcop_string_copy( dcop_client_server_address, addr );
+}
+
+/* SM DUMMY */
+#include <X11/SM/SMlib.h>
+static gboolean HostBasedAuthProc ( char* hostname)
+{
+ /* we don't need any security here, as this is only a hack to
+ * get the protocol number we want for DCOP. We don't use the SM
+ * connection in any way */
+ return True;
+}
+
+static Status NewClientProc ( SmsConn c, SmPointer p, unsigned long*l, SmsCallbacks*cb, char**s )
+{
+ return 0;
+}
+
+static void dcop_client_registerXSM()
+{
+ char errormsg[256];
+ if (!SmsInitialize ((char *)("SAMPLE-SM"), (char *)("1.0"),
+ NewClientProc, NULL,
+ HostBasedAuthProc, 256, errormsg))
+ {
+ g_error( "register xsm failed");
+ exit( 1 );
+ }
+}
+
+/* hack*/
+extern int _IceLastMajorOpcode;
+
+static void dcop_client_xsm_check()
+{
+ if ( _IceLastMajorOpcode < 1 )
+ /* hack to enforce the correct ICE major opcode for DCOP*/
+ dcop_client_registerXSM();
+}
+
+static gboolean dcop_client_attach_internal( DcopClient *client, gboolean anonymous )
+{
+ gboolean bClearServerAddr = FALSE;
+ gchar *fname = 0;
+ const gchar *dcopSrvEnv = 0;
+ gchar *dcopSrv = 0;
+ gchar *dcopServerFileContent = 0;
+ glong dcopServerFileContentSize = 0;
+ ssize_t bytesRead = 0;
+ gchar *newLine = 0;
+ FILE *f = 0;
+ gchar errBuf[1024];
+ gint setupstat;
+
+ g_message( "dcop_client_attach\n" );
+
+ if ( dcop_client_is_attached( client ) )
+ dcop_client_detach( client );
+
+ dcop_client_xsm_check();
+
+ if ( ( P->major_opcode = IceRegisterForProtocolSetup( (char *)("DCOP"),
+ (char *)(DCOPVendorString),
+ (char *)(DCOPReleaseString),
+ 1, DCOPVersions,
+ DCOPAuthCount,
+ (char **)(DCOPAuthNames),
+ DCOPClientAuthProcs, 0 ) ) < 0 )
+ {
+ ERR( "Communications could not be established." );
+ return FALSE;
+ }
+ else
+ {
+ g_message( "dcop: major opcode is %d\n", P->major_opcode );
+ }
+
+ if ( !dcop_client_server_address )
+ {
+ dcopSrvEnv = getenv( "DCOPSERVER" );
+ if ( !dcopSrvEnv || strlen( dcopSrvEnv ) == 0 )
+ {
+ char hostName[255];
+
+ fname = g_strdup( getenv( "HOME" ) );
+ fname = (gchar *)g_realloc( fname, strlen( fname ) + 1 + 13 );
+ strcat( fname, "/.DCOPserver_" );
+
+ if ( gethostname( hostName, 255 ) == 0 )
+ {
+ fname = (gchar *)g_realloc( fname, strlen( fname ) + 1 + strlen( hostName ) );
+ strcat( fname, hostName );
+ }
+ else
+ {
+ fname = (gchar *)g_realloc( fname, strlen( fname ) + 1 + 9 );
+ strcat( fname, "localhost" );
+ }
+
+ f = fopen( fname, "r" );
+
+ if ( f == NULL ) /* try .DCOPServer_hostname_display (for KDE > 2.0) */
+ {
+ char *i;
+ char *display = getenv( "DISPLAY" );
+ gchar *display_real = g_strdup( display );
+ gchar *disppos;
+
+ /* dcopserver per display, not per screen */
+ if ( ( disppos = strchr( display_real, '.' ) ) > strchr( display_real, ':' ) && disppos != NULL )
+ (*disppos) = '\0';
+
+ while((i = strchr(display_real, ':')) != NULL)
+ *i = '_';
+
+ fname = (gchar *)g_realloc( fname, strlen( fname ) + 1 + 1 + strlen( display_real ) );
+ strcat( fname, "_" );
+ strcat( fname, display_real );
+
+ g_free( display_real );
+
+ f = fopen( fname, "r" );
+
+ if ( f == NULL )
+ {
+ g_free( fname );
+ ERR( "Cannot open ~/.DCOPserver" );
+ return FALSE;
+ }
+ }
+
+ fseek( f, 0L, SEEK_END );
+
+ dcopServerFileContentSize = ftell( f );
+
+ if ( dcopServerFileContentSize == 0L )
+ {
+ g_free( fname );
+ ERR( "Invalid ~/.DCOPserver" );
+ return FALSE;
+ }
+
+ fseek( f, 0L, SEEK_SET );
+
+ dcopServerFileContent = (gchar *)g_malloc( dcopServerFileContentSize );
+
+ bytesRead = fread( (void *)dcopServerFileContent, sizeof(gchar), dcopServerFileContentSize, f );
+
+ if ( bytesRead != dcopServerFileContentSize )
+ {
+ g_free( fname );
+ g_free( dcopServerFileContent );
+ fclose( f );
+ ERR( "Cannot read ~/.DCOPserver" );
+ return FALSE;
+ }
+
+ newLine = strchr( dcopServerFileContent, '\n' );
+
+ if ( newLine == NULL )
+ {
+ g_free( fname );
+ g_free( dcopServerFileContent );
+ fclose( f );
+ ERR( "Invalid ~/.DCOPserver" );
+ return FALSE;
+ }
+
+ *newLine = '\0';
+
+ fclose( f );
+ g_free( fname );
+
+ dcopSrv = g_strdup( dcopServerFileContent );
+
+ g_free( dcopServerFileContent );
+ }
+ else
+ dcopSrv = g_strdup( dcopSrvEnv );
+
+ if ( dcopSrv == NULL )
+ {
+ ERR( "Cannot determine dcop server address." );
+ return FALSE;
+ }
+
+ g_message( "dcop server address is : %s\n", dcopSrv );
+
+ dcop_client_server_address = dcopSrv;
+
+ bClearServerAddr = TRUE;
+
+ }
+
+ if ( ( P->ice_conn = IceOpenConnection( (char *)( dcop_client_server_address ),
+ (IcePointer)( client ), False, P->major_opcode,
+ sizeof( errBuf ), errBuf ) ) == NULL )
+ {
+ if ( bClearServerAddr )
+ dcop_free( dcop_client_server_address );
+ ERR( g_strdup( errBuf ) );
+ dcop_client_free_error_msg = TRUE;
+ return FALSE;
+
+ }
+
+ IceSetShutdownNegotiation( P->ice_conn, False );
+
+ setupstat = IceProtocolSetup( P->ice_conn, P->major_opcode, (IcePointer *)client, False,
+ &(P->major_version), &(P->minor_version),
+ &(P->vendor), &(P->release), sizeof( errBuf ), errBuf );
+
+ if ( setupstat == IceProtocolSetupFailure ||
+ setupstat == IceProtocolSetupIOError )
+ {
+ IceCloseConnection( P->ice_conn );
+
+ if ( bClearServerAddr )
+ dcop_free( dcop_client_server_address );
+
+ ERR( g_strdup( errBuf ) );
+ dcop_client_free_error_msg = TRUE;
+ return FALSE;
+ }
+ else if ( setupstat == IceProtocolAlreadyActive )
+ {
+ if ( bClearServerAddr )
+ dcop_free( dcop_client_server_address );
+
+ ERR( "Internal error in IceOpenConnection" );
+ return FALSE;
+ }
+
+ if ( IceConnectionStatus( P->ice_conn ) != IceConnectAccepted )
+ {
+ if ( bClearServerAddr )
+ dcop_free( dcop_client_server_address );
+
+ ERR( "DCOP server did not accept the connection" );
+ return FALSE;
+ }
+
+ if ( anonymous )
+ dcop_client_register_as( client, "anonymous", TRUE );
+
+ return TRUE;
+}
+
+gboolean dcop_client_attach( DcopClient *client )
+{
+ if ( !dcop_client_attach_internal( client, TRUE ) )
+ if ( !dcop_client_attach_internal( client, TRUE ) )
+ return FALSE; /* try two times!*/
+
+ return TRUE;
+}
+
+gboolean dcop_client_detach( DcopClient *client )
+{
+ int status;
+
+ g_message( "dcop_client_detach\n" );
+
+ if ( P->ice_conn )
+ {
+ IceProtocolShutdown( P->ice_conn, P->major_opcode );
+ status = IceCloseConnection( P->ice_conn );
+ if ( status != IceClosedNow )
+ {
+ ERR( "error detaching from DCOP server" );
+ return FALSE;
+ }
+ else
+ P->ice_conn = 0L;
+ }
+
+ P->registered = FALSE;
+
+ return TRUE;
+}
+
+gboolean dcop_client_is_attached( DcopClient *client )
+{
+ if ( !P->ice_conn )
+ return FALSE;
+
+ return (IceConnectionStatus( P->ice_conn ) == IceConnectAccepted );
+}
+
+const gchar *dcop_client_register_as( DcopClient *client, const gchar *app_id, gboolean add_pid /* = TRUE */ )
+{
+ gchar *result = 0;
+
+ gchar *id = g_strdup( app_id );
+ gchar pid[64];
+ gint pid_len = 0;
+
+ dcop_data *data = 0;
+ gchar *reply_type = 0;
+ dcop_data *reply_data = 0;
+
+ g_message( "dcop_client_register_as %s\n", app_id );
+
+ if ( dcop_client_is_registered( client ) )
+ dcop_client_detach( client );
+
+ if ( !dcop_client_is_attached( client ) )
+ if ( !dcop_client_attach_internal( client, FALSE ) )
+ return result; /*try two times*/
+
+ if ( add_pid )
+ {
+ pid_len = g_snprintf( pid, sizeof( pid ), "-%d", getpid() );
+ id = (gchar *)g_realloc( id, strlen( id ) + 1 + pid_len );
+ strcat( id, pid );
+ }
+
+
+ g_message( "trying to register as %s\n", id );
+
+ data = dcop_data_ref( dcop_data_new() );
+
+ dcop_marshal_string( data, id );
+
+ if ( dcop_client_call( client, "DCOPServer", "", "registerAs(QCString)", data,
+ &reply_type,
+ &reply_data ) )
+ {
+ dcop_data_reset( reply_data );
+ dcop_demarshal_string( reply_data, &result );
+
+ dcop_data_deref( reply_data );
+ g_free( reply_type );
+ }
+
+ dcop_string_assign( P->app_id, result );
+
+ P->registered = ( P->app_id != NULL && strlen( P->app_id ) > 0 );
+
+ if ( P->registered )
+ g_message( "we are registered as %s\n", P->app_id );
+ else
+ g_message( "registration failed\n" );
+
+ dcop_data_deref( data );
+
+ g_free( id );
+
+ return result;
+}
+
+gboolean dcop_client_is_registered( DcopClient *client )
+{
+ return P->registered;
+}
+
+const gchar *dcop_client_app_id( DcopClient *client )
+{
+ return P->app_id;
+}
+
+int dcop_client_socket( DcopClient *client )
+{
+ if ( P->ice_conn )
+ return IceConnectionNumber( P->ice_conn );
+ else
+ return 0;
+}
+
+gboolean dcop_client_send( DcopClient *client,
+ const gchar *rem_app, const gchar *rem_obj, const gchar *rem_fun,
+ dcop_data *data )
+{
+ struct DCOPMsg *pMsg = 0;
+ dcop_data *hdata = 0;
+ gchar *func = 0;
+ gboolean res = TRUE;
+
+ g_message( "dcop_client_send( %s, %s, %s )\n", rem_app, rem_obj, rem_fun);
+
+ if ( !dcop_client_is_attached( client ) )
+ return FALSE;
+
+ if ( strcmp( P->app_id, rem_app ) == 0 )
+ {
+ gchar *reply_type = 0;
+ dcop_data *reply_data = 0;
+
+ if ( !dcop_client_receive( client, rem_app, rem_obj, rem_fun, data, &reply_type, &reply_data ) )
+ g_warning( "dcop failure in app %s:\n object '%s' has no function '%s'", rem_app, rem_obj, rem_fun );
+
+ return TRUE;
+ }
+
+ hdata = dcop_data_ref( dcop_data_new() );
+
+ dcop_marshal_string( hdata, P->app_id );
+ dcop_marshal_string( hdata, rem_app );
+ dcop_marshal_string( hdata, rem_obj );
+
+ func = dcop_client_normalize_function_signature( rem_fun );
+ dcop_marshal_string( hdata, func );
+
+ dcop_marshal_uint32( hdata, data->size );
+
+ IceGetHeader( P->ice_conn, P->major_opcode, DCOPSend, sizeof(struct DCOPMsg), struct DCOPMsg, pMsg );
+
+ pMsg->key = 1; /* DCOPSend always uses the magic key 1*/
+ pMsg->length += hdata->size + data->size;
+
+ IceSendData( P->ice_conn, hdata->size, hdata->ptr );
+ IceSendData( P->ice_conn, data->size, data->ptr );
+
+ /* IceFlush( P->ice_conn );
+ */
+ if ( IceConnectionStatus( P->ice_conn ) != IceConnectAccepted )
+ res = FALSE;
+
+ g_free( func );
+
+ return res;
+}
+
+static gboolean dcop_client_call_internal( DcopClient *client,
+ const gchar *rem_app, const gchar *rem_obj, const gchar *rem_fun,
+ dcop_data *data,
+ gchar **reply_type, dcop_data **reply_data,
+ gint minor_opcode )
+{
+ gboolean success = FALSE;
+ struct DCOPMsg *pMsg = 0;
+ dcop_data *hdata = 0;
+ gchar *func = 0;
+ IceReplyWaitInfo waitInfo;
+ reply_struct reply;
+ gboolean readyRet;
+ IceProcessMessagesStatus status;
+ CARD32 old_current_key = 0;
+
+ reply_struct_init( &reply );
+
+ if ( !dcop_client_is_attached( client ) )
+ return FALSE;
+
+ old_current_key = P->current_key;
+ if ( !P->current_key )
+ P->current_key = P->key; /* no key, yet, initiate new call*/
+
+ hdata = dcop_data_ref( dcop_data_new() );
+
+ dcop_marshal_string( hdata, P->app_id );
+ dcop_marshal_string( hdata, rem_app );
+ dcop_marshal_string( hdata, rem_obj );
+
+ func = dcop_client_normalize_function_signature( rem_fun );
+ dcop_marshal_string( hdata, func );
+
+ dcop_marshal_uint32( hdata, data->size );
+
+ IceGetHeader( P->ice_conn, P->major_opcode, minor_opcode,
+ sizeof(struct DCOPMsg), struct DCOPMsg, pMsg );
+
+ pMsg->key = P->current_key;
+ pMsg->length += hdata->size + data->size;
+
+ IceSendData( P->ice_conn, hdata->size, hdata->ptr );
+ IceSendData( P->ice_conn, data->size, data->ptr );
+
+ if ( IceConnectionStatus( P->ice_conn ) != IceConnectAccepted )
+ {
+ dcop_data_deref( hdata );
+ g_free( func );
+ P->current_key = old_current_key;
+ return FALSE;
+ }
+
+ IceFlush( P->ice_conn );
+
+ waitInfo.sequence_of_request = IceLastSentSequenceNumber( P->ice_conn );
+ waitInfo.major_opcode_of_request = P->major_opcode;
+ waitInfo.minor_opcode_of_request = minor_opcode;
+ reply.reply_type = reply_type;
+ reply.reply_data = reply_data;
+ waitInfo.reply = (IcePointer)&reply;
+
+ readyRet = False;
+
+ do
+ {
+ status = IceProcessMessages( P->ice_conn, &waitInfo, &readyRet );
+ if ( status == IceProcessMessagesIOError )
+ {
+ IceCloseConnection( P->ice_conn );
+ dcop_data_deref( hdata );
+ g_free( func );
+ P->current_key = old_current_key;
+ return FALSE;
+ }
+ } while ( !readyRet );
+
+ dcop_data_deref( hdata );
+
+ success = reply.status == Ok;
+
+ g_free( func );
+
+ P->current_key = old_current_key;
+ return success;
+}
+
+gboolean dcop_client_call( DcopClient *client,
+ const gchar *rem_app, const gchar *rem_obj, const gchar *rem_fun,
+ dcop_data *data,
+ gchar **reply_type, dcop_data **reply_data )
+{
+ return dcop_client_call_internal( client, rem_app, rem_obj, rem_fun, data,
+ reply_type, reply_data, DCOPCall );
+}
+
+gboolean dcop_client_is_application_registered( DcopClient *client, const gchar *app )
+{
+ gchar *reply_type = 0;
+ dcop_data *reply_data = 0;
+ dcop_data *data = dcop_data_ref( dcop_data_new() );
+ gboolean res = FALSE;
+
+ dcop_marshal_string( data, app );
+
+ if ( dcop_client_call( client, "DCOPServer", "", "isApplicationRegistered(QCString)", data, &reply_type, &reply_data ) )
+ {
+ dcop_data_reset( reply_data );
+ dcop_demarshal_boolean( reply_data, &res );
+ }
+
+ g_free( reply_type );
+ if ( reply_data )
+ dcop_data_deref( reply_data );
+ dcop_data_deref( data );
+
+ return res;
+}
+
+GList *dcop_client_registered_applications( DcopClient *client )
+{
+ GList *res = 0;
+ dcop_data *data = 0;
+ dcop_data *reply_data = 0;
+ gchar *reply_type = 0;
+
+ data = dcop_data_ref( dcop_data_new() );
+
+ if ( dcop_client_call( client, "DCOPServer", "", "registeredApplications()", data,
+ &reply_type, &reply_data ) )
+ {
+ fprintf( stderr, "reply type is %s\n", reply_type );
+ dcop_data_reset( reply_data );
+ dcop_demarshal_stringlist( reply_data, &res );
+ dcop_data_deref( reply_data );
+ }
+
+ g_free( reply_type );
+ dcop_data_deref( data );
+ return res;
+}
+
+extern GHashTable *object_dict;
+
+GList *g_temp_object_list = 0;
+
+static void dcop_client_receive_list_objects_internal( gpointer key, gpointer val, gpointer user_data )
+{
+ gchar *nam = (gchar *)key;
+ DcopObject *obj = (DcopObject *)val;
+ DcopClient *client = (DcopClient *)user_data;
+ const gchar *id = DCOP_ID( obj );
+
+ if ( id && strlen( id ) > 0 )
+ {
+ if ( P->default_object &&
+ strcmp( id, P->default_object ) == 0 )
+ g_temp_object_list = g_list_append( g_temp_object_list, (gchar *)"default" );
+
+ g_temp_object_list = g_list_append( g_temp_object_list, (gchar *)id );
+ }
+}
+
+gboolean dcop_client_receive( DcopClient *client,
+ const gchar *app, const gchar *obj, const gchar *fun,
+ dcop_data *data,
+ gchar **reply_type, dcop_data **reply_data )
+{
+ DcopObject *o;
+
+ g_message( "dcop_client_receive app=%s obj=%s fun=%s\n", app, obj, fun);
+
+ if ( obj && strcmp( obj, "DCOPClient" ) == 0 )
+ {
+ if ( strcmp( fun, "objects()" ) == 0 )
+ {
+ GList *list = 0;
+
+ *reply_type = strdup( "QCStringList" );
+ *reply_data = dcop_data_ref( dcop_data_new() );
+
+ if ( object_dict )
+ {
+ /*
+ GList *it = g_list_first( object_list );
+
+ while ( it )
+ {
+ if ( it->data )
+ {
+ const gchar *id;
+ o = (DcopObject *)it->data;
+ id = DCOP_ID(o);
+ if ( id && strlen( id ) > 0 )
+ {
+ if ( P->default_object &&
+ strcmp( id, P->default_object ) == 0 )
+ list = g_list_append( list, (gchar *)"default" );
+
+ list = g_list_append( list, (gchar *)id );
+ }
+ }
+ it = g_list_next( it );
+ }
+ */
+ g_temp_object_list = 0;
+
+ g_hash_table_foreach( object_dict, dcop_client_receive_list_objects_internal, client );
+
+ list = g_temp_object_list;
+ }
+
+ dcop_marshal_stringlist( *reply_data, list );
+ /* important: only "free" (return to internal allocator) the list*/
+ /* itself, not it's data, as that data are either static strings*/
+ /* or strings already owned by someone else*/
+ g_list_free( list );
+ return TRUE;
+ }
+
+ if ( CLIENT_CLASS(client)->process( client, fun, data, reply_type, reply_data ) )
+ return TRUE;
+ }
+
+ if ( !obj || strlen( obj ) == 0 || strcmp( obj, "default" ) == 0 )
+ if ( P->default_object && strlen( P->default_object ) != 0 )
+ {
+ o = dcop_object_lookup( P->default_object );
+ if ( o && DCOP_OBJECT_CLASS(GTK_OBJECT(o)->klass)->process( o, fun, data, reply_type, reply_data ) )
+ return TRUE;
+ }
+
+ if ( obj && obj[ strlen( obj ) - 1 ] == '*' )
+ {
+ gchar *partial_id = (gchar *)g_malloc( strlen( obj ) - 1 );
+ GList *match_list = 0;
+
+ strncpy( partial_id, obj, strlen( obj ) - 1 );
+
+ match_list = dcop_object_match( partial_id );
+
+ if ( match_list )
+ {
+ GList *it = g_list_first( match_list );
+
+ while ( it )
+ {
+ o = (DcopObject *)it->data;
+
+ if ( !DCOP_OBJECT_CLASS(GTK_OBJECT(o)->klass)->process( o, fun, data, reply_type, reply_data ) )
+ {
+ g_list_free( match_list );
+ g_free( partial_id );
+ return FALSE;
+ }
+
+ it = g_list_next( it );
+ }
+
+ g_list_free( match_list );
+ }
+
+ g_free( partial_id );
+ return TRUE;
+ }
+
+ /* ### proxy support
+ */
+ o = dcop_object_lookup( obj );
+ if ( !o )
+ return FALSE;
+ return DCOP_OBJECT_CLASS(GTK_OBJECT(o)->klass)->process( o, fun, data, reply_type, reply_data );
+}
+
+static inline gboolean is_ident_char( gchar x )
+{ /* Avoid bug in isalnum */
+ return x == '_' || (x >= '0' && x <= '9') ||
+ (x >= 'a' && x <= 'z') || (x >= 'A' && x <= 'Z');
+}
+
+gchar *dcop_client_normalize_function_signature( const gchar *fun )
+{
+ gchar *result;
+ size_t len = strlen( fun );
+ const gchar *from;
+ gchar *to, *first;
+ gchar last;
+
+ if ( len == 0 )
+ return g_strdup( fun );
+
+ result = (gchar *)g_malloc( len + 1 );
+
+ from = fun;
+ first = to = result;
+ last = 0;
+
+ while ( 42 )
+ {
+ while ( *from && isspace( *from ) )
+ from++;
+ if ( last && is_ident_char( last ) && is_ident_char( *from ) )
+ *to++ = 0x20;
+ while ( *from && !isspace( *from ) )
+ {
+ last = *from++;
+ *to++ = last;
+ }
+ if ( !*from )
+ break;
+ }
+ if ( to > first && *(to-1) == 0x20 )
+ to--;
+ *to = '\0';
+ result = (gchar *)g_realloc( result, (int)((long)to - (long)result) + 1 );
+ return result;
+}
+
+const gchar *dcop_client_sender_id( DcopClient *client )
+{
+ return P->sender_id;
+}
+
+gboolean dcop_client_process( DcopClient *client, const gchar *fun, dcop_data *data,
+ gchar **reply_type, dcop_data **reply_data )
+{
+ return CLIENT_CLASS( client )->process( client, fun, data, reply_type, reply_data );
+}
+
+gboolean dcop_client_real_process( DcopClient *client, const gchar *fun, dcop_data *data,
+ gchar **reply_type, dcop_data **reply_data )
+{
+ /* empty default implementation*/
+ return FALSE;
+}
+
+void dcop_client_process_socket_data( DcopClient *client )
+{
+ IceProcessMessagesStatus status;
+
+ g_message( "dcop_client_process_socket_data\n" );
+
+ status = IceProcessMessages( P->ice_conn, 0, 0 );
+
+ g_message( "dcop_client_process_socket_data : messages processed\n" );
+
+ if ( status == IceProcessMessagesIOError )
+ {
+ IceCloseConnection( P->ice_conn );
+ g_message( "error receiving data from the DCOP server.\n" );
+ return;
+ }
+}
+
+const gchar *dcop_client_error_message()
+{
+ return dcop_client_error_msg;
+}
+
+void dcop_process_internal( DcopClient *client, int opcode, CARD32 key, dcop_data *data_received, gboolean can_post );
+
+/* don't use the glib types for args here, as this is an ICE callback (Simon)*/
+void dcop_process_message( IceConn ice_conn, IcePointer client_object,
+ int opcode, unsigned long length, Bool swap,
+ IceReplyWaitInfo *replyWait,
+ Bool *replyWaitRet )
+{
+ struct DCOPMsg *pMsg = 0;
+ DcopClient *client = (DcopClient *)client_object;
+ void *data_received;
+ dcop_data *tmp_stream = 0;
+ unsigned int id;
+ char *called_app = 0;
+ char *app = 0;
+ char *obj = 0;
+ char *fun = 0;
+ CARD32 key;
+
+ IceReadMessageHeader( ice_conn, sizeof( struct DCOPMsg ), struct DCOPMsg, pMsg );
+
+ key = pMsg->key;
+ if ( P->key == 0 )
+ P->key = key; /* received a key from the server*/
+
+ data_received = g_malloc( length );
+ IceReadData( ice_conn, length, data_received );
+
+ tmp_stream = dcop_data_ref( dcop_data_new() );
+ dcop_data_assign( tmp_stream, (char *)data_received, length );
+
+ P->opcode = opcode;
+
+ switch ( opcode )
+ {
+ case DCOPReplyFailed:
+ if ( replyWait )
+ {
+ ((reply_struct *)replyWait->reply)->status = Failed;
+ *replyWaitRet = True;
+ break;
+ }
+ else
+ {
+ g_warning( "dcop error: received an unexpected DCOPReplyFailed opcode.\n" );
+ break;
+ }
+ case DCOPReply:
+ if ( replyWait )
+ {
+ ((reply_struct *)replyWait->reply)->status = Ok;
+
+ dcop_demarshal_string( tmp_stream, &called_app );
+ dcop_demarshal_string( tmp_stream, &app );
+ dcop_demarshal_string( tmp_stream, ((reply_struct *)replyWait->reply)->reply_type );
+ dcop_demarshal_data( tmp_stream, ((reply_struct *)replyWait->reply)->reply_data );
+
+ *replyWaitRet = True;
+ break;
+ }
+ else
+ {
+ g_warning( "dcop error: received an unexpected DCOPReply.\n" );
+ break;
+ }
+ case DCOPReplyWait:
+ if ( replyWait )
+ {
+ dcop_demarshal_string( tmp_stream, &called_app );
+ dcop_demarshal_string( tmp_stream, &app );
+ dcop_demarshal_uint32( tmp_stream, &id );
+
+ ((reply_struct *)replyWait->reply)->reply_id = id;
+
+ break;
+ }
+ else
+ {
+ g_warning( "dcop error: received an unexpected DCOPReplyWait.\n" );
+ break;
+ }
+ case DCOPReplyDelayed:
+ if ( replyWait )
+ {
+ ((reply_struct *)replyWait->reply)->status = Ok;
+
+ dcop_demarshal_string( tmp_stream, &called_app );
+ dcop_demarshal_string( tmp_stream, &app );
+ dcop_demarshal_uint32( tmp_stream, &id );
+ dcop_demarshal_string( tmp_stream, ((reply_struct *)replyWait->reply)->reply_type );
+ dcop_demarshal_data( tmp_stream, ((reply_struct *)replyWait->reply)->reply_data );
+
+ if ( id != ((reply_struct *)replyWait->reply)->reply_id )
+ {
+ ((reply_struct *)replyWait->reply)->status = Failed;
+ g_warning( "dcop error: received a wrong sequence id for DCOPReplyDelayed.\n" );
+ }
+
+ *replyWaitRet = True;
+
+ break;
+ }
+ else
+ {
+ g_message( "dcop error: received an unexpeced DCOPReplyDelayed.\n" );
+ break;
+ }
+ case DCOPCall:
+ case DCOPFind:
+ case DCOPSend:
+ dcop_process_internal( client, opcode, key, tmp_stream, TRUE );
+ break;
+ }
+
+ dcop_data_deref( tmp_stream );
+
+ g_free( called_app );
+ g_free( app );
+}
+
+static gboolean dcop_client_process_post_messages_internal( gpointer data )
+{
+ DcopClient *client = DCOP_CLIENT( data );
+ GList *it = 0;
+
+ g_message( "dcop_client_process_post_messages_internal" );
+
+ if ( g_list_length( P->messages ) == 0 )
+ return FALSE;
+
+ it = g_list_first( P->messages );
+ while ( it )
+ {
+ DcopClientMessage *msg = (DcopClientMessage *)it->data;
+ it = g_list_next( it );
+
+ g_assert( msg );
+
+ if ( P->current_key && msg->key != P->current_key )
+ continue;
+
+ P->messages = g_list_remove( P->messages, msg );
+ dcop_process_internal( client, msg->opcode, msg->key, msg->data, FALSE );
+ dcop_data_deref( msg->data );
+ g_free( msg );
+ }
+
+ if ( g_list_length( P->messages ) == 0 )
+ return FALSE;
+
+ return TRUE;
+}
+
+void dcop_process_internal( DcopClient *client, int opcode, CARD32 key, dcop_data *data_received, gboolean can_post )
+{
+ gchar *app = 0;
+ gchar *obj = 0;
+ gchar *fun = 0;
+ char *reply_type = 0;
+ dcop_data *reply_data = 0;
+ gboolean b = FALSE;
+ CARD32 old_current_key = 0;
+ dcop_data *data = 0;
+ dcop_data *reply = 0;
+ struct DCOPMsg *pMsg = 0;
+
+ dcop_free( P->sender_id );
+ dcop_demarshal_string( data_received, &P->sender_id );
+ dcop_demarshal_string( data_received, &app );
+ dcop_demarshal_string( data_received, &obj );
+ dcop_demarshal_string( data_received, &fun );
+ dcop_demarshal_data( data_received, &data );
+
+ if ( can_post && P->current_key && key != P->current_key )
+ {
+ DcopClientMessage *msg = g_new( DcopClientMessage, 1 );
+ g_message( "posting message with key %i", key );
+ msg->opcode = opcode;
+ msg->key = key;
+ msg->data = dcop_data_ref( data_received );
+ P->messages = g_list_append( P->messages, msg );
+ if ( P->post_message_timer != 0 )
+ g_source_remove( P->post_message_timer );
+ P->post_message_timer = g_timeout_add( 0, dcop_client_process_post_messages_internal, client );
+ return;
+ }
+
+ old_current_key = P->current_key;
+ if ( opcode != DCOPSend ) /* DCOPSend doesn't change the current key*/
+ P->current_key = key;
+
+ if ( opcode == DCOPFind )
+ {
+ /* #### b = dcop_client_find( app, obj, fun, data, &reply_type, &reply_data ); */
+ }
+ else
+ b = dcop_client_receive( client, app, obj, fun, data, &reply_type, &reply_data );
+
+ if ( opcode == DCOPSend )
+ {
+ g_free( app );
+ g_free( obj );
+ g_free( fun );
+ if ( data )
+ dcop_data_deref( data );
+ g_free( reply_type );
+ if ( reply_data )
+ dcop_data_deref( reply_data );
+ return;
+ }
+
+ P->current_key = old_current_key;
+
+ reply = dcop_data_ref( dcop_data_new() );
+
+ if ( P->transaction_id )
+ {
+ dcop_marshal_string( reply, P->app_id );
+ dcop_marshal_string( reply, P->sender_id );
+ dcop_marshal_uint32( reply, (guint32)P->transaction_id );
+
+ IceGetHeader( P->ice_conn, P->major_opcode, DCOPReplyWait,
+ sizeof( struct DCOPMsg ), struct DCOPMsg, pMsg );
+
+ pMsg->key = key;
+ pMsg->length += reply->size;
+
+ IceSendData( P->ice_conn, reply->size, reply->ptr );
+
+ dcop_data_deref( reply );
+ g_free( app );
+ g_free( obj );
+ g_free( fun );
+ dcop_data_deref( data );
+ return;
+ }
+
+ if ( !b )
+ {
+ g_warning( "dcop failure in app %s:\n object '%s' has no function '%s'", app, obj, fun );
+
+ dcop_marshal_string( reply, P->app_id );
+ dcop_marshal_string( reply, P->sender_id );
+
+ IceGetHeader( P->ice_conn, P->major_opcode, DCOPReplyFailed,
+ sizeof( struct DCOPMsg ), struct DCOPMsg, pMsg );
+ pMsg->key = key;
+ pMsg->length += reply->size;
+ IceSendData( P->ice_conn, reply->size, reply->ptr );
+
+ dcop_data_deref( reply );
+ g_free( app );
+ g_free( obj );
+ g_free( fun );
+ dcop_data_deref( data );
+ return;
+ }
+
+ if ( !reply_data )
+ reply_data = dcop_data_ref( dcop_data_new() );
+
+ dcop_marshal_string( reply, P->app_id );
+ dcop_marshal_string( reply, P->sender_id );
+ dcop_marshal_string( reply, reply_type );
+ dcop_marshal_uint32( reply, reply_data->size );
+
+ IceGetHeader( P->ice_conn, P->major_opcode, DCOPReply,
+ sizeof( struct DCOPMsg ), struct DCOPMsg, pMsg );
+
+ pMsg->key = key;
+ pMsg->length += reply->size + reply_data->size;
+ /* use IceSendData not IceWriteData to avoid a copy. Output buffer
+ shouldn't need to be flushed. */
+ IceSendData( P->ice_conn, reply->size, reply->ptr );
+ IceSendData( P->ice_conn, reply_data->size, reply_data->ptr );
+
+ dcop_data_deref( reply );
+ g_free( app );
+ g_free( obj );
+ g_free( fun );
+ dcop_data_deref( data );
+ dcop_data_deref( reply_data );
+}
+
+void dcop_client_set_default_object( DcopClient *client, const gchar *obj_id )
+{
+ dcop_string_copy( P->default_object, obj_id );
+}
+
+const gchar *dcop_client_default_object( DcopClient *client )
+{
+ return P->default_object;
+}
+
+DcopClientTransaction *dcop_client_begin_transaction( DcopClient *client )
+{
+ DcopClientTransaction *transaction = 0;
+
+ if ( P->opcode == DCOPSend )
+ return 0;
+
+ P->transaction = TRUE;
+ transaction = g_new( DcopClientTransaction, 1 );
+ transaction->sender_id = g_strdup( P->sender_id );
+
+ if ( !P->transaction_id )
+ P->transaction_id++;
+
+ transaction->id = ++(P->transaction_id);
+ transaction->key = P->current_key;
+
+ P->transaction_list = g_list_append( P->transaction_list, transaction );
+
+ return transaction;
+}
+
+gint32 dcop_client_transaction_id( DcopClient *client )
+{
+ if ( P->transaction )
+ return P->transaction_id;
+ else
+ return 0;
+}
+
+void dcop_client_end_transaction( DcopClient *client, DcopClientTransaction *trans, gchar *reply_type, dcop_data *reply_data )
+{
+ struct DCOPMsg *pMsg = 0;
+ dcop_data *data = 0;
+
+ if ( !trans )
+ return;
+
+ if ( !dcop_client_is_attached( client ) )
+ return;
+
+ if ( !P->transaction_list )
+ {
+ g_warning( "dcop_client_end_transaction: no pending transactions!" );
+ return;
+ }
+
+ if ( !g_list_find( P->transaction_list, trans ) )
+ {
+ g_warning( "dcop_client_end_transaction: unknown transaction!" );
+ return;
+ }
+
+ P->transaction_list = g_list_remove( P->transaction_list, trans );
+
+ data = dcop_data_ref( dcop_data_new() );
+
+ dcop_data_ref( reply_data );
+
+ dcop_marshal_string( data, P->app_id );
+ dcop_marshal_string( data, trans->sender_id );
+ dcop_marshal_uint32( data, (guint32)trans->id );
+ dcop_marshal_string( data, reply_type );
+ dcop_marshal_data( data, reply_data );
+
+ IceGetHeader( P->ice_conn, P->major_opcode, DCOPReplyDelayed, sizeof( struct DCOPMsg ), struct DCOPMsg, pMsg );
+
+ pMsg->key = trans->key;
+ pMsg->length += data->size;
+
+ IceSendData( P->ice_conn, data->size, data->ptr );
+
+ dcop_data_deref( data );
+ dcop_data_deref( reply_data );
+
+ g_free( trans->sender_id );
+ g_free( trans );
+}
+
+void dcop_client_emit_dcop_signal( DcopClient *client,
+ const gchar *object, const gchar *signal, dcop_data *data )
+{
+ gchar *normalized_signal_name = dcop_client_normalize_function_signature( signal );
+ gchar *signame = g_strdup( object );
+
+ signame = (gchar *)g_realloc( signame, strlen( object ) + 1 + 1 + strlen( normalized_signal_name ) );
+ strcat( signame, "#" );
+ strcat( signame, normalized_signal_name );
+
+ dcop_client_send( client, "DCOPServer", "emit", signame, data );
+
+ g_free( signame );
+}
+
+gboolean dcop_client_connect_dcop_signal( DcopClient *client,
+ const gchar *sender, const gchar *sender_obj,
+ const gchar *signal,
+ const gchar *receiver_obj, const gchar *slot,
+ gboolean _volatile )
+{
+ gchar *reply_type = 0;
+ dcop_data *reply_data = 0;
+ dcop_data *data = dcop_data_ref( dcop_data_new() );
+ guint8 ivolatile = _volatile ? 1 : 0;
+ gchar *normalized_signame = dcop_client_normalize_function_signature( signal );
+ gchar *normalized_slotname = dcop_client_normalize_function_signature( slot );
+ guint8 result = 0;
+
+ dcop_marshal_string( data, sender );
+ dcop_marshal_string( data, sender_obj );
+ dcop_marshal_string( data, normalized_signame );
+ dcop_marshal_string( data, receiver_obj );
+ dcop_marshal_string( data, normalized_slotname );
+ dcop_marshal_uint8( data, ivolatile );
+
+ if ( dcop_client_call( client, "DCOPServer", "", "connectSignal(QCString,QCString,QCString,QCString,QCString,bool)", data, &reply_type, &reply_data ) == FALSE )
+ {
+ g_free( normalized_signame );
+ g_free( normalized_slotname );
+ dcop_data_deref( data );
+ return FALSE;
+ }
+
+ if ( reply_type == NULL || strcmp( reply_type, "bool" ) != 0 ||
+ reply_data == NULL )
+ {
+ g_free( normalized_signame );
+ g_free( normalized_slotname );
+ dcop_data_deref( data );
+ if ( reply_data != NULL )
+ dcop_data_deref( reply_data );
+ return FALSE;
+ }
+
+ dcop_data_reset( reply_data );
+ dcop_demarshal_uint8( reply_data, &result );
+
+ g_free( normalized_signame );
+ g_free( normalized_slotname );
+ dcop_data_deref( data );
+ dcop_data_deref( reply_data );
+
+ if ( result == 0 )
+ return FALSE;
+
+ return TRUE;
+}
+
+gboolean dcop_client_disconnect_dcop_signal( DcopClient *client,
+ const gchar *sender, const gchar *sender_obj,
+ const gchar *signal,
+ const gchar *receiver_obj, const gchar *slot )
+{
+ gchar *reply_type = 0;
+ dcop_data *reply_data = 0;
+ dcop_data *data = dcop_data_ref( dcop_data_new() );
+ gchar *normalized_signame = dcop_client_normalize_function_signature( signal );
+ gchar *normalized_slotname = dcop_client_normalize_function_signature( slot );
+ guint8 result = 0;
+
+ dcop_marshal_string( data, sender );
+ dcop_marshal_string( data, sender_obj );
+ dcop_marshal_string( data, normalized_signame );
+ dcop_marshal_string( data, receiver_obj );
+ dcop_marshal_string( data, normalized_slotname );
+
+ if ( dcop_client_call( client, "DCOPServer", "", "disconnectSignal(QCString,QCString,QCString,QCString,QCString)", data, &reply_type, &reply_data ) == FALSE )
+ {
+ g_free( normalized_signame );
+ g_free( normalized_slotname );
+ dcop_data_deref( data );
+ return FALSE;
+ }
+
+ if ( reply_type == NULL || strcmp( reply_type, "bool" ) != 0 ||
+ reply_data == NULL )
+ {
+ g_free( normalized_signame );
+ g_free( normalized_slotname );
+ dcop_data_deref( data );
+ if ( reply_data != NULL )
+ dcop_data_deref( reply_data );
+ return FALSE;
+ }
+
+ dcop_data_reset( reply_data );
+ dcop_demarshal_uint8( reply_data, &result );
+
+ g_free( normalized_signame );
+ g_free( normalized_slotname );
+ dcop_data_deref( data );
+ dcop_data_deref( reply_data );
+
+ if ( result == 0 )
+ return FALSE;
+
+ return TRUE;
+}
+
+void dcop_client_set_daemon_mode( DcopClient *client, gboolean daemon )
+{
+ gchar *reply_type = 0;
+ dcop_data *reply_data = 0;
+ dcop_data *data = dcop_data_ref( dcop_data_new() );
+ guint8 idaemon = daemon ? 1 : 0;
+ dcop_marshal_uint8( data, idaemon );
+
+ dcop_client_call( client, "DCOPServer", "", "setDaemonMode(bool)", data, &reply_type, &reply_data );
+
+ if ( reply_data != NULL )
+ dcop_data_deref( reply_data );
+
+ dcop_data_deref( data );
+
+ dcop_free( reply_type );
+}
diff --git a/dcopc/dcopc.h b/dcopc/dcopc.h
new file mode 100644
index 00000000..beda5ec0
--- /dev/null
+++ b/dcopc/dcopc.h
@@ -0,0 +1,143 @@
+/*
+Copyright (c) 2000 Simon Hausmann <hausmann@kde.org>
+Copyright (c) 2000 Lars Knoll <knoll@kde.org>
+Copyright (c) 1999 Preston Brown <pbrown@kde.org>
+Copyright (c) 1999, 2000 Matthias Ettrich <ettrich@kde.org>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef __dcopc_h__
+#define __dcopc_h__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <X11/ICE/ICElib.h>
+
+#include <dcopc/marshal.h>
+#include <dcopc/util.h>
+
+#include <gtk/gtk.h>
+
+#define DCOP_TYPE_CLIENT (dcop_client_get_type())
+#define DCOP_CLIENT(obj) GTK_CHECK_CAST((obj), DCOP_TYPE_CLIENT, DcopClient)
+#define DCOP_CLIENT_CLASS(klass) GTK_CHECK_CLASS_CAST((klass), DCOP_TYPE_CLIENT, DcopClientClass)
+#define DCOP_IS_CLIENT(obj) GTK_CHECK_TYPE((obj), DCOP_TYPE_CLIENT)
+#define DCOP_IS_CLIENT_CLASS(klass) GTK_CHECK_CLASS_TYPE((klass), DCOP_TYPE_CLIENT)
+
+typedef struct _DcopClient DcopClient;
+typedef struct _DcopClientClass DcopClientClass;
+
+struct _DcopClient
+{
+ GtkObject obj;
+ void *priv;
+};
+
+struct _DcopClientClass
+{
+ GtkObjectClass parent_class;
+
+ gboolean (*process) ( DcopClient *client, const gchar *fun, dcop_data *data,
+ gchar **reply_type, dcop_data **reply_data );
+};
+
+typedef struct _DcopClientTransaction DcopClientTransaction;
+
+extern GtkType dcop_client_get_type( void );
+
+extern DcopClient *dcop_client_new( void );
+
+void dcop_client_set_server_address( const gchar *addr );
+
+gboolean dcop_client_attach( DcopClient *client );
+
+gboolean dcop_client_detach( DcopClient *client );
+
+gboolean dcop_client_is_attached( DcopClient *client );
+
+const char *dcop_client_register_as( DcopClient *client, const gchar *app_id, gboolean add_pid /* = TRUE */ );
+
+gboolean dcop_client_is_registered( DcopClient *client );
+
+const gchar *dcop_client_app_id( DcopClient *client );
+
+int dcop_client_socket( DcopClient *client );
+
+gboolean dcop_client_send( DcopClient *client,
+ const gchar *rem_app, const gchar *rem_obj, const gchar *rem_fun,
+ dcop_data *data );
+
+gboolean dcop_client_call( DcopClient *client,
+ const gchar *rem_app, const gchar *rem_obj, const gchar *rem_fun,
+ dcop_data *data,
+ gchar **reply_type, dcop_data **reply_data );
+
+DcopClientTransaction *dcop_client_begin_transaction( DcopClient *client );
+
+void dcop_client_end_transaction( DcopClient *client, DcopClientTransaction *transaction, gchar *reply_type, dcop_data *reply_data );
+
+gint32 dcop_client_transaction_id( DcopClient *client );
+
+gboolean dcop_client_is_application_registered( DcopClient *client, const gchar *rem_app );
+
+GList *dcop_client_registered_applications( DcopClient *client );
+
+gboolean dcop_client_receive( DcopClient *client,
+ const gchar *app, const gchar *obj, const gchar *fun,
+ dcop_data *data,
+ gchar **reply_type, dcop_data **reply_data );
+
+gchar *dcop_client_normalize_function_signature( const gchar *fun );
+
+const gchar *dcop_client_sender_id( DcopClient *client );
+
+void dcop_client_set_default_object( DcopClient *client, const gchar *obj_id );
+
+const gchar *dcop_client_default_object( DcopClient *client );
+
+gboolean dcop_client_process ( DcopClient *client, const char *gfun, dcop_data *data,
+ gchar **reply_type, dcop_data **reply_data );
+
+void dcop_client_process_socket_data( DcopClient *client );
+
+const gchar *dcop_client_error_message();
+
+void dcop_client_emit_dcop_signal( DcopClient *client,
+ const gchar *object, const gchar *signal, dcop_data *data );
+
+gboolean dcop_client_connect_dcop_signal( DcopClient *client,
+ const gchar *sender, const gchar *sender_obj,
+ const gchar *signal,
+ const gchar *receiver_obj, const gchar *slot,
+ gboolean _volatile );
+
+gboolean dcop_client_disconnect_dcop_signal( DcopClient *client,
+ const gchar *sender, const gchar *sender_obj,
+ const gchar *signal,
+ const gchar *receiver_obj, const gchar *slot );
+
+void dcop_client_set_daemon_mode( DcopClient *client, gboolean daemon );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/dcopc/dcopobject.c b/dcopc/dcopobject.c
new file mode 100644
index 00000000..ff9d5309
--- /dev/null
+++ b/dcopc/dcopobject.c
@@ -0,0 +1,301 @@
+/*
+Copyright (c) 2000 Simon Hausmann <hausmann@kde.org>
+Copyright (c) 2000 Lars Knoll <knoll@kde.org>
+Copyright (c) 1999 Preston Brown <pbrown@kde.org>
+Copyright (c) 1999, 2000 Matthias Ettrich <ettrich@kde.org>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include "dcopobject.h"
+#include "global.h"
+#include "dcopc.h"
+
+#include <string.h>
+#include <stdlib.h>
+
+#define OBJECT_CLASS(obj) DCOP_OBJECT_CLASS(GTK_OBJECT(obj)->klass)
+
+typedef struct _DcopObjectPrivate DcopObjectPrivate;
+
+struct _DcopObjectPrivate
+{
+ gchar *id;
+};
+
+/* initialization */
+static void dcop_object_class_init(DcopObjectClass *klass);
+
+static void dcop_object_init(DcopObject *part);
+
+/* GtkObject methods */
+static void dcop_object_destroy(GtkObject *object);
+
+static GtkObjectClass *parent_class = 0;
+
+GHashTable *object_dict = 0;
+
+GtkType dcop_object_get_type(void)
+{
+ static GtkType dcop_object_type = 0;
+ if (!dcop_object_type)
+ {
+ static const GtkTypeInfo dcop_object_info =
+ {
+ (gchar *)"DcopObject",
+ sizeof(DcopObject),
+ sizeof(DcopObjectClass),
+ (GtkClassInitFunc)dcop_object_class_init,
+ (GtkObjectInitFunc)dcop_object_init,
+ 0,
+ 0,
+ 0
+ };
+ dcop_object_type = gtk_type_unique(GTK_TYPE_OBJECT, &dcop_object_info);
+ }
+ return dcop_object_type;
+}
+
+gboolean dcop_object_real_process( DcopObject *obj, const gchar *fun, dcop_data *data,
+ gchar **reply_type, dcop_data **reply_data );
+
+gboolean dcop_object_real_process_dynamic( DcopObject *obj, const gchar *fun, dcop_data *data,
+ gchar **reply_type, dcop_data **reply_data );
+
+GList *dcop_object_real_functions( DcopObject *obj );
+
+GList *dcop_object_real_interfaces( DcopObject *obj );
+
+void dcop_object_class_init(DcopObjectClass *klass)
+{
+ GtkObjectClass *object_class;
+ object_class = (GtkObjectClass *)klass;
+
+ parent_class = (GtkObjectClass *)gtk_type_class(gtk_object_get_type());
+
+ object_class->destroy = dcop_object_destroy;
+
+ klass->process = dcop_object_real_process;
+ klass->process_dynamic = dcop_object_real_process_dynamic;
+ klass->functions = dcop_object_real_functions;
+ klass->interfaces = dcop_object_real_interfaces;
+
+ g_message( "dcop_object_class_init(DcopObjectClass *klass)\n");
+}
+
+void dcop_object_init(DcopObject *obj)
+{
+ DcopObjectPrivate *d;
+ /* eheh :-) (Simon)*/
+/* d = new DcopObjectPrivate();*/
+ d = g_new( DcopObjectPrivate, 1 );
+ d->id = 0;
+ obj->data = d;
+
+ /* register a unique id*/
+ {
+ gchar n[1024];
+ g_snprintf( n, sizeof( n ), "%p", obj );
+ dcop_object_set_id( obj, n ); /* also registers the object at the object_dict*/
+ }
+
+ g_message( "dcop_object_init(DcopObject *obj)\n");
+}
+
+DcopObject *dcop_object_new (void)
+{
+ DcopObject *obj = DCOP_OBJECT( gtk_type_new(dcop_object_get_type()) );
+
+ return obj;
+}
+
+void dcop_object_destroy( GtkObject *obj )
+{
+ DcopObject *o = DCOP_OBJECT(obj);
+ DcopObjectPrivate *d = (DcopObjectPrivate *)o->data;
+
+ g_message( "dcop_object_destructor %s\n", DCOP_ID(o) );
+
+ g_assert( object_dict );
+ g_assert( d->id );
+
+ g_hash_table_remove( object_dict, d->id );
+
+ if ( g_hash_table_size( object_dict ) == 0 )
+ {
+ g_hash_table_destroy( object_dict );
+ object_dict = 0;
+ }
+
+ g_free(d->id);
+ /* Lars, you hack to much C++ :-))) (Simon)*/
+/* delete d;*/
+ g_free( d );
+
+ parent_class->destroy(obj);
+}
+
+void dcop_object_set_id( DcopObject *obj, const gchar *id )
+{
+ DcopObjectPrivate *d = (DcopObjectPrivate *) obj->data;
+
+ if ( !object_dict )
+ object_dict = g_hash_table_new( g_str_hash, g_str_equal );
+
+ if ( d->id )
+ g_hash_table_remove( object_dict, d->id );
+
+ dcop_string_copy( d->id, id );
+
+ g_assert( d->id );
+
+ g_hash_table_insert( object_dict, d->id, obj );
+}
+
+const gchar *dcop_object_get_id( DcopObject *obj)
+{
+ return ((DcopObjectPrivate *) obj->data)->id;
+}
+
+gboolean dcop_object_process( DcopObject *obj, const gchar *fun, dcop_data *data,
+ gchar **reply_type, dcop_data **reply_data )
+{
+ return OBJECT_CLASS(obj)->process( obj, fun, data, reply_type, reply_data );
+}
+
+gboolean dcop_object_process_dynamic( DcopObject *obj, const gchar *fun, dcop_data *data,
+ gchar **reply_type, dcop_data **reply_data )
+{
+ return OBJECT_CLASS(obj)->process_dynamic( obj, fun, data, reply_type, reply_data );
+}
+
+gboolean dcop_object_real_process( DcopObject *obj, const gchar *fun, dcop_data *data,
+ gchar **reply_type, dcop_data **reply_data )
+{
+ GList *strlist = 0;
+ DcopObjectClass *klass = OBJECT_CLASS(obj);
+
+ if ( strcmp( fun, "interfaces()" ) == 0 )
+ {
+ *reply_type = g_strdup( "QCStringList" );
+ *reply_data = dcop_data_ref( dcop_data_new() );
+ strlist = klass->interfaces( obj );
+
+ dcop_marshal_stringlist( *reply_data, strlist );
+
+ dcop_list_free( strlist );
+ return TRUE;
+ }
+ else if ( strcmp( fun, "functions()" ) == 0 )
+ {
+ *reply_type = strdup( "QCStringList" );
+ *reply_data = dcop_data_ref( dcop_data_new() );
+ strlist = klass->functions( obj );
+
+ dcop_marshal_stringlist( *reply_data, strlist );
+
+ dcop_list_free( strlist );
+ return TRUE;
+ }
+ return klass->process_dynamic( obj, fun, data, reply_type, reply_data );
+}
+
+gboolean dcop_object_real_process_dynamic( DcopObject *client, const gchar *fun, dcop_data *data,
+ gchar **reply_type, dcop_data **reply_data )
+{
+ /* empty default implementation*/
+ return FALSE;
+}
+
+GList *dcop_object_functions( DcopObject *obj )
+{
+ return OBJECT_CLASS(obj)->functions( obj );
+}
+
+GList *dcop_object_interfaces( DcopObject *obj )
+{
+ return OBJECT_CLASS(obj)->interfaces( obj );
+}
+
+GList *dcop_object_real_functions( DcopObject *client )
+{
+ GList *res = 0;
+ res = g_list_append( res, g_strdup( "QCStringList interfaces()" ) );
+ res = g_list_append( res, g_strdup( "QCStringList functions()" ) );
+ return res;
+}
+
+GList *dcop_object_real_interfaces( DcopObject *client )
+{
+ GList *res = 0;
+ res = g_list_append( res, g_strdup( "DCOPObject" ) );
+ return res;
+}
+
+DcopObject *dcop_object_lookup( const gchar *name )
+{
+ DcopObject *res = 0;
+
+ if ( !object_dict || !name )
+ return NULL;
+
+ return (DcopObject *)g_hash_table_lookup( object_dict, name );
+}
+
+gchar *g_partial_id = 0;
+size_t g_id_len = 0;
+
+static void dcop_object_match_internal( gpointer key, gpointer val, gpointer user_data )
+{
+ GList **lst = (GList **)user_data;
+ gchar *nam = (gchar *)key;
+ DcopObjectPrivate *d = ((DcopObject *)val)->data;
+
+ if ( strncmp( d->id, g_partial_id, g_id_len ) == 0 )
+ *lst = g_list_append( *lst, (DcopObject *)val );
+}
+
+GList *dcop_object_match( const gchar *partial_id )
+{
+ GList *res = 0;
+ GList *it = 0;
+ size_t id_len = strlen( partial_id );
+
+ if ( !object_dict )
+ return res;
+
+ g_hash_table_foreach( object_dict, dcop_object_match_internal, &res );
+
+ /*
+ if ( !object_list)
+ return res;
+
+ it = g_list_first( object_list );
+
+ while ( it )
+ {
+ DcopObjectPrivate *d = (DcopObjectPrivate *)((DcopObject *)it->data)->data;
+
+ if ( strncmp( d->id, partial_id, id_len ) == 0 )
+ res = g_list_append( res, (DcopObject *)it->data );
+
+ it = g_list_next( it );
+ }
+ */
+ return res;
+}
diff --git a/dcopc/dcopobject.h b/dcopc/dcopobject.h
new file mode 100644
index 00000000..fff64bdc
--- /dev/null
+++ b/dcopc/dcopobject.h
@@ -0,0 +1,93 @@
+/*
+Copyright (c) 2000 Simon Hausmann <hausmann@kde.org>
+Copyright (c) 2000 Lars Knoll <knoll@kde.org>
+Copyright (c) 1999 Preston Brown <pbrown@kde.org>
+Copyright (c) 1999, 2000 Matthias Ettrich <ettrich@kde.org>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef __dcopc_dcopobject_h__
+#define __dcopc_dcopobject_h__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <X11/ICE/ICElib.h>
+
+#include <dcopc/marshal.h>
+#include <dcopc/util.h>
+
+#include <gtk/gtk.h>
+
+#define DCOP_TYPE_OBJECT (dcop_object_get_type())
+#define DCOP_OBJECT(obj) GTK_CHECK_CAST((obj), DCOP_TYPE_OBJECT, DcopObject)
+#define DCOP_OBJECT_CLASS(klass) GTK_CHECK_CLASS_CAST((klass), DCOP_TYPE_OBJECT, DcopObjectClass)
+#define DCOP_IS_OBJECT(obj) GTK_CHECK_TYPE((obj), DCOP_TYPE_OBJECT)
+#define DCOP_IS_OBJECT_CLASS(klass) GTK_CHECK_CLASS_TYPE((klass), DCOP_TYPE_OBJECT)
+#define DCOP_ID(obj) (dcop_object_get_id(obj))
+
+typedef struct _DcopObject DcopObject;
+typedef struct _DcopObjectClass DcopObjectClass;
+
+struct _DcopObject
+{
+ GtkObject obj;
+ void *data;
+};
+
+struct _DcopObjectClass
+{
+ GtkObjectClass parent_class;
+
+ gboolean (*process) ( DcopObject *obj, const gchar *fun, dcop_data *data,
+ gchar **reply_type, dcop_data **reply_data );
+ gboolean (*process_dynamic) ( DcopObject *obj, const gchar *fun, dcop_data *data,
+ gchar **reply_type, dcop_data **reply_data );
+
+ GList *(*functions) ( DcopObject *obj );
+ GList *(*interfaces) ( DcopObject *obj );
+};
+
+GtkType dcop_object_get_type(void);
+
+DcopObject *dcop_object_new( void );
+
+void dcop_object_set_id( DcopObject *obj, const gchar *id );
+const gchar *dcop_object_get_id( DcopObject *obj);
+
+gboolean dcop_object_process( DcopObject *obj, const gchar *fun, dcop_data *data,
+ gchar **reply_type, dcop_data **reply_data );
+
+gboolean dcop_object_process_dynamic( DcopObject *obj, const gchar *fun, dcop_data *data,
+ gchar **reply_type, dcop_data **reply_data );
+
+GList *dcop_object_functions( DcopObject *obj );
+
+GList *dcop_object_interfaces( DcopObject *obj );
+
+DcopObject *dcop_object_lookup( const gchar *name );
+
+GList *dcop_object_match( const gchar *partial_id );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/dcopc/glib.m4 b/dcopc/glib.m4
new file mode 100644
index 00000000..b8094bbf
--- /dev/null
+++ b/dcopc/glib.m4
@@ -0,0 +1,196 @@
+# Configure paths for GLIB
+# Owen Taylor 97-11-3
+
+dnl AM_PATH_GLIB([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND [, MODULES]]]])
+dnl Test for GLIB, and define GLIB_CFLAGS and GLIB_LIBS, if "gmodule" or
+dnl gthread is specified in MODULES, pass to glib-config
+dnl
+AC_DEFUN(AM_PATH_GLIB,
+[dnl
+dnl Get the cflags and libraries from the glib-config script
+dnl
+AC_ARG_WITH(glib-prefix,[ --with-glib-prefix=PFX Prefix where GLIB is installed (optional)],
+ glib_config_prefix="$withval", glib_config_prefix="")
+AC_ARG_WITH(glib-exec-prefix,[ --with-glib-exec-prefix=PFX Exec prefix where GLIB is installed (optional)],
+ glib_config_exec_prefix="$withval", glib_config_exec_prefix="")
+AC_ARG_ENABLE(glibtest, [ --disable-glibtest Do not try to compile and run a test GLIB program],
+ , enable_glibtest=yes)
+
+ if test x$glib_config_exec_prefix != x ; then
+ glib_config_args="$glib_config_args --exec-prefix=$glib_config_exec_prefix"
+ if test x${GLIB_CONFIG+set} != xset ; then
+ GLIB_CONFIG=$glib_config_exec_prefix/bin/glib-config
+ fi
+ fi
+ if test x$glib_config_prefix != x ; then
+ glib_config_args="$glib_config_args --prefix=$glib_config_prefix"
+ if test x${GLIB_CONFIG+set} != xset ; then
+ GLIB_CONFIG=$glib_config_prefix/bin/glib-config
+ fi
+ fi
+
+ for module in . $4
+ do
+ case "$module" in
+ gmodule)
+ glib_config_args="$glib_config_args gmodule"
+ ;;
+ gthread)
+ glib_config_args="$glib_config_args gthread"
+ ;;
+ esac
+ done
+
+ AC_PATH_PROG(GLIB_CONFIG, glib-config, no)
+ min_glib_version=ifelse([$1], ,0.99.7,$1)
+ AC_MSG_CHECKING(for GLIB - version >= $min_glib_version)
+ no_glib=""
+ if test "$GLIB_CONFIG" = "no" ; then
+ no_glib=yes
+ else
+ GLIB_CFLAGS=`$GLIB_CONFIG $glib_config_args --cflags`
+ GLIB_LIBS=`$GLIB_CONFIG $glib_config_args --libs`
+ glib_config_major_version=`$GLIB_CONFIG $glib_config_args --version | \
+ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'`
+ glib_config_minor_version=`$GLIB_CONFIG $glib_config_args --version | \
+ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'`
+ glib_config_micro_version=`$GLIB_CONFIG $glib_config_args --version | \
+ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'`
+ if test "x$enable_glibtest" = "xyes" ; then
+ ac_save_CFLAGS="$CFLAGS"
+ ac_save_LIBS="$LIBS"
+ CFLAGS="$CFLAGS $GLIB_CFLAGS"
+ LIBS="$GLIB_LIBS $LIBS"
+dnl
+dnl Now check if the installed GLIB is sufficiently new. (Also sanity
+dnl checks the results of glib-config to some extent
+dnl
+ rm -f conf.glibtest
+ AC_TRY_RUN([
+#include <glib.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+int
+main ()
+{
+ int major, minor, micro;
+ char *tmp_version;
+
+ system ("touch conf.glibtest");
+
+ /* HP/UX 9 (%@#!) writes to sscanf strings */
+ tmp_version = g_strdup("$min_glib_version");
+ if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, &micro) != 3) {
+ printf("%s, bad version string\n", "$min_glib_version");
+ exit(1);
+ }
+
+ if ((glib_major_version != $glib_config_major_version) ||
+ (glib_minor_version != $glib_config_minor_version) ||
+ (glib_micro_version != $glib_config_micro_version))
+ {
+ printf("\n*** 'glib-config --version' returned %d.%d.%d, but GLIB (%d.%d.%d)\n",
+ $glib_config_major_version, $glib_config_minor_version, $glib_config_micro_version,
+ glib_major_version, glib_minor_version, glib_micro_version);
+ printf ("*** was found! If glib-config was correct, then it is best\n");
+ printf ("*** to remove the old version of GLIB. You may also be able to fix the error\n");
+ printf("*** by modifying your LD_LIBRARY_PATH enviroment variable, or by editing\n");
+ printf("*** /etc/ld.so.conf. Make sure you have run ldconfig if that is\n");
+ printf("*** required on your system.\n");
+ printf("*** If glib-config was wrong, set the environment variable GLIB_CONFIG\n");
+ printf("*** to point to the correct copy of glib-config, and remove the file config.cache\n");
+ printf("*** before re-running configure\n");
+ }
+ else if ((glib_major_version != GLIB_MAJOR_VERSION) ||
+ (glib_minor_version != GLIB_MINOR_VERSION) ||
+ (glib_micro_version != GLIB_MICRO_VERSION))
+ {
+ printf("*** GLIB header files (version %d.%d.%d) do not match\n",
+ GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION, GLIB_MICRO_VERSION);
+ printf("*** library (version %d.%d.%d)\n",
+ glib_major_version, glib_minor_version, glib_micro_version);
+ }
+ else
+ {
+ if ((glib_major_version > major) ||
+ ((glib_major_version == major) && (glib_minor_version > minor)) ||
+ ((glib_major_version == major) && (glib_minor_version == minor) && (glib_micro_version >= micro)))
+ {
+ return 0;
+ }
+ else
+ {
+ printf("\n*** An old version of GLIB (%d.%d.%d) was found.\n",
+ glib_major_version, glib_minor_version, glib_micro_version);
+ printf("*** You need a version of GLIB newer than %d.%d.%d. The latest version of\n",
+ major, minor, micro);
+ printf("*** GLIB is always available from ftp://ftp.gtk.org.\n");
+ printf("***\n");
+ printf("*** If you have already installed a sufficiently new version, this error\n");
+ printf("*** probably means that the wrong copy of the glib-config shell script is\n");
+ printf("*** being found. The easiest way to fix this is to remove the old version\n");
+ printf("*** of GLIB, but you can also set the GLIB_CONFIG environment to point to the\n");
+ printf("*** correct copy of glib-config. (In this case, you will have to\n");
+ printf("*** modify your LD_LIBRARY_PATH enviroment variable, or edit /etc/ld.so.conf\n");
+ printf("*** so that the correct libraries are found at run-time))\n");
+ }
+ }
+ return 1;
+}
+],, no_glib=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"])
+ CFLAGS="$ac_save_CFLAGS"
+ LIBS="$ac_save_LIBS"
+ fi
+ fi
+ if test "x$no_glib" = x ; then
+ AC_MSG_RESULT(yes)
+ ifelse([$2], , :, [$2])
+ else
+ AC_MSG_RESULT(no)
+ if test "$GLIB_CONFIG" = "no" ; then
+ echo "*** The glib-config script installed by GLIB could not be found"
+ echo "*** If GLIB was installed in PREFIX, make sure PREFIX/bin is in"
+ echo "*** your path, or set the GLIB_CONFIG environment variable to the"
+ echo "*** full path to glib-config."
+ else
+ if test -f conf.glibtest ; then
+ :
+ else
+ echo "*** Could not run GLIB test program, checking why..."
+ CFLAGS="$CFLAGS $GLIB_CFLAGS"
+ LIBS="$LIBS $GLIB_LIBS"
+ AC_TRY_LINK([
+#include <glib.h>
+#include <stdio.h>
+], [ return ((glib_major_version) || (glib_minor_version) || (glib_micro_version)); ],
+ [ echo "*** The test program compiled, but did not run. This usually means"
+ echo "*** that the run-time linker is not finding GLIB or finding the wrong"
+ echo "*** version of GLIB. If it is not finding GLIB, you'll need to set your"
+ echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point"
+ echo "*** to the installed location Also, make sure you have run ldconfig if that"
+ echo "*** is required on your system"
+ echo "***"
+ echo "*** If you have an old version installed, it is best to remove it, although"
+ echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"
+ echo "***"
+ echo "*** If you have a RedHat 5.0 system, you should remove the GTK package that"
+ echo "*** came with the system with the command"
+ echo "***"
+ echo "*** rpm --erase --nodeps gtk gtk-devel" ],
+ [ echo "*** The test program failed to compile or link. See the file config.log for the"
+ echo "*** exact error that occured. This usually means GLIB was incorrectly installed"
+ echo "*** or that you have moved GLIB since it was installed. In the latter case, you"
+ echo "*** may want to edit the glib-config script: $GLIB_CONFIG" ])
+ CFLAGS="$ac_save_CFLAGS"
+ LIBS="$ac_save_LIBS"
+ fi
+ fi
+ GLIB_CFLAGS=""
+ GLIB_LIBS=""
+ ifelse([$3], , :, [$3])
+ fi
+ AC_SUBST(GLIB_CFLAGS)
+ AC_SUBST(GLIB_LIBS)
+ rm -f conf.glibtest
+])
diff --git a/dcopc/glibtest.c b/dcopc/glibtest.c
new file mode 100644
index 00000000..b2473e66
--- /dev/null
+++ b/dcopc/glibtest.c
@@ -0,0 +1,133 @@
+/*
+Copyright (c) 2000 Simon Hausmann <hausmann@kde.org>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include <dcopc/dcopc.h>
+#include <dcopc/dcopobject.h>
+#include <stdio.h>
+#include <glib.h>
+
+#define C( call ) \
+ if ( !call ) \
+ { \
+ fprintf( stderr, "dcop error: %s\n", dcop_client_error_message() ); \
+ return 1; \
+ }
+
+gboolean dcop_socket_notify( GIOChannel *chan, GIOCondition condition, gpointer data )
+{
+ DcopClient *client = (DcopClient *)data;
+ fprintf( stderr, "dcop_socket_notify\n" );
+ dcop_client_process_socket_data( client );
+}
+
+gboolean (*old_process_func) ( DcopObject *obj, const gchar *fun, dcop_data *data,
+ gchar **reply_type, dcop_data **reply_data );
+
+gboolean my_obj_process( DcopObject *obj, const gchar *fun, dcop_data *data,
+ gchar **reply_type, dcop_data **reply_data )
+{
+ if ( strcmp( fun, "doExit()" ) == 0 )
+ {
+ gtk_main_quit();
+ return TRUE;
+ }
+ if ( strcmp( fun, "mySlot()" ) == 0 )
+ {
+ g_message( "mySlot called!" );
+ return TRUE;
+ }
+
+ return old_process_func( obj, fun, data, reply_type, reply_data );
+}
+
+GList *(*old_functions_func)( DcopObject *obj ) = 0;
+
+GList *my_obj_functions( DcopObject *obj )
+{
+ GList *res = old_functions_func( obj );
+ res = g_list_append( res, g_strdup( "doExit()" ) );
+ res = g_list_append( res, g_strdup( "mySlot()" ) );
+ return res;
+}
+
+GList *(*old_interfaces_func)( DcopObject *obj ) = 0;
+
+GList *my_obj_interfaces( DcopObject *obj )
+{
+ GList *res = old_interfaces_func( obj );
+ res = g_list_append( res, g_strdup( "MyObj" ) );
+ return res;
+}
+
+int main( int argc, char **argv )
+{
+ DcopClient *c;
+ dcop_data *d;
+ dcop_data *reply;
+ char *reply_type;
+ GIOChannel *chan;
+ DcopObject *obj;
+
+ gtk_init( &argc, &argv );
+
+ c = dcop_client_new();
+
+ C( dcop_client_register_as( c, "dcoptest", False ) );
+
+ chan = g_io_channel_unix_new( dcop_client_socket( c ) );
+ g_io_channel_ref( chan );
+
+ g_io_add_watch( chan, G_IO_IN, dcop_socket_notify, c );
+
+ obj = dcop_object_new();
+ dcop_object_set_id( obj, "myServer" );
+
+ old_process_func = DCOP_OBJECT_CLASS( GTK_OBJECT( obj )->klass )->process;
+ old_functions_func = DCOP_OBJECT_CLASS( GTK_OBJECT( obj )->klass )->functions;
+ old_interfaces_func = DCOP_OBJECT_CLASS( GTK_OBJECT( obj )->klass )->interfaces;
+
+ DCOP_OBJECT_CLASS( GTK_OBJECT( obj )->klass )->process = my_obj_process;
+ DCOP_OBJECT_CLASS( GTK_OBJECT( obj )->klass )->functions = my_obj_functions;
+ DCOP_OBJECT_CLASS( GTK_OBJECT( obj )->klass )->interfaces = my_obj_interfaces;
+
+ if ( dcop_client_connect_dcop_signal( c, dcop_client_app_id( c ), "myServer",
+ "mySignal()",
+ "myServer", "mySlot()", FALSE ) == FALSE )
+ g_message( "error connecting dcop signal :-(" );
+
+ d = dcop_data_ref( dcop_data_new() );
+
+ dcop_client_emit_dcop_signal( c, "myServer", "mySignal()", d );
+
+ dcop_data_deref( d );
+
+ dcop_client_set_daemon_mode( c, TRUE );
+
+ gtk_main();
+
+ g_io_channel_unref( chan );
+
+ C( dcop_client_detach( c ) );
+
+ gtk_object_unref( GTK_OBJECT( c ) );
+
+ return 0;
+}
diff --git a/dcopc/global.h b/dcopc/global.h
new file mode 100644
index 00000000..387a4945
--- /dev/null
+++ b/dcopc/global.h
@@ -0,0 +1,75 @@
+/*
+Copyright (c) 1999 Preston Brown <pbrown@kde.org>
+Copyright (c) 1999, 2000 Matthias Ettrich <ettrich@kde.org>
+Copyright (c) 2000 Simon Hausmann <hausmann@kde.org>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+#ifndef __global_h__
+#define __global_h__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "util.h"
+
+/* sometimes __STDC__ is defined, but to 0. The hateful X headers
+ ask for '#if __STDC__', so they become confused. */
+#if defined(__STDC__)
+#if !__STDC__
+#undef __STDC__
+#define __STDC__ 1
+#endif
+#endif
+
+#include <X11/Xlib.h>
+#include <X11/Xmd.h>
+#include <X11/ICE/ICElib.h>
+
+#include <X11/ICE/ICEutil.h>
+#include <X11/ICE/ICEmsg.h>
+#include <X11/ICE/ICEproto.h>
+
+
+#define DCOPVendorString "KDE"
+#define DCOPReleaseString "2.0"
+#define DCOPVersionMajor 2
+#define DCOPVersionMinor 0
+
+#define DCOPSend 1
+#define DCOPCall 2
+#define DCOPReply 3
+#define DCOPReplyFailed 4
+#define DCOPReplyWait 5
+#define DCOPReplyDelayed 6
+#define DCOPFind 7
+
+struct DCOPMsg {
+ CARD8 majorOpcode;
+ CARD8 minorOpcode;
+ CARD8 data[2];
+ CARD32 length B32;
+ CARD32 key;
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/dcopc/gtk.m4 b/dcopc/gtk.m4
new file mode 100644
index 00000000..af4c0855
--- /dev/null
+++ b/dcopc/gtk.m4
@@ -0,0 +1,197 @@
+# Configure paths for GTK+
+# Owen Taylor 97-11-3
+
+dnl AM_PATH_GTK([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND [, MODULES]]]])
+dnl Test for GTK, and define GTK_CFLAGS and GTK_LIBS
+dnl
+AC_DEFUN(AM_PATH_GTK,
+[dnl
+dnl Get the cflags and libraries from the gtk-config script
+dnl
+AC_ARG_WITH(gtk-prefix,[ --with-gtk-prefix=PFX Prefix where GTK is installed (optional)],
+ gtk_config_prefix="$withval", gtk_config_prefix="")
+AC_ARG_WITH(gtk-exec-prefix,[ --with-gtk-exec-prefix=PFX Exec prefix where GTK is installed (optional)],
+ gtk_config_exec_prefix="$withval", gtk_config_exec_prefix="")
+AC_ARG_ENABLE(gtktest, [ --disable-gtktest Do not try to compile and run a test GTK program],
+ , enable_gtktest=yes)
+
+ for module in . $4
+ do
+ case "$module" in
+ gthread)
+ gtk_config_args="$gtk_config_args gthread"
+ ;;
+ esac
+ done
+
+ if test x$gtk_config_exec_prefix != x ; then
+ gtk_config_args="$gtk_config_args --exec-prefix=$gtk_config_exec_prefix"
+ if test x${GTK_CONFIG+set} != xset ; then
+ GTK_CONFIG=$gtk_config_exec_prefix/bin/gtk-config
+ fi
+ fi
+ if test x$gtk_config_prefix != x ; then
+ gtk_config_args="$gtk_config_args --prefix=$gtk_config_prefix"
+ if test x${GTK_CONFIG+set} != xset ; then
+ GTK_CONFIG=$gtk_config_prefix/bin/gtk-config
+ fi
+ fi
+
+ AC_PATH_PROG(GTK_CONFIG, gtk-config, no)
+ min_gtk_version=ifelse([$1], ,0.99.7,$1)
+ AC_MSG_CHECKING(for GTK - version >= $min_gtk_version)
+ no_gtk=""
+ if test "$GTK_CONFIG" = "no" ; then
+ no_gtk=yes
+ else
+ GTK_CFLAGS=`$GTK_CONFIG $gtk_config_args --cflags`
+ GTK_LIBS=`$GTK_CONFIG $gtk_config_args --libs`
+ gtk_config_major_version=`$GTK_CONFIG $gtk_config_args --version | \
+ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'`
+ gtk_config_minor_version=`$GTK_CONFIG $gtk_config_args --version | \
+ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'`
+ gtk_config_micro_version=`$GTK_CONFIG $gtk_config_args --version | \
+ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'`
+ if test "x$enable_gtktest" = "xyes" ; then
+ ac_save_CFLAGS="$CFLAGS"
+ ac_save_LIBS="$LIBS"
+ CFLAGS="$CFLAGS $GTK_CFLAGS"
+ LIBS="$GTK_LIBS $LIBS"
+ AC_LANG_SAVE
+ AC_LANG_C
+dnl
+dnl Now check if the installed GTK is sufficiently new. (Also sanity
+dnl checks the results of gtk-config to some extent
+dnl
+ rm -f conf.gtktest
+ AC_TRY_RUN([
+#include <gtk/gtk.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+int
+main ()
+{
+ int major, minor, micro;
+ char *tmp_version;
+
+ system ("touch conf.gtktest");
+
+ /* HP/UX 9 (%@#!) writes to sscanf strings */
+ tmp_version = g_strdup("$min_gtk_version");
+ if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, &micro) != 3) {
+ printf("%s, bad version string\n", "$min_gtk_version");
+ exit(1);
+ }
+
+ if ((gtk_major_version != $gtk_config_major_version) ||
+ (gtk_minor_version != $gtk_config_minor_version) ||
+ (gtk_micro_version != $gtk_config_micro_version))
+ {
+ printf("\n*** 'gtk-config --version' returned %d.%d.%d, but GTK+ (%d.%d.%d)\n",
+ $gtk_config_major_version, $gtk_config_minor_version, $gtk_config_micro_version,
+ gtk_major_version, gtk_minor_version, gtk_micro_version);
+ printf ("*** was found! If gtk-config was correct, then it is best\n");
+ printf ("*** to remove the old version of GTK+. You may also be able to fix the error\n");
+ printf("*** by modifying your LD_LIBRARY_PATH enviroment variable, or by editing\n");
+ printf("*** /etc/ld.so.conf. Make sure you have run ldconfig if that is\n");
+ printf("*** required on your system.\n");
+ printf("*** If gtk-config was wrong, set the environment variable GTK_CONFIG\n");
+ printf("*** to point to the correct copy of gtk-config, and remove the file config.cache\n");
+ printf("*** before re-running configure\n");
+ }
+#if defined (GTK_MAJOR_VERSION) && defined (GTK_MINOR_VERSION) && defined (GTK_MICRO_VERSION)
+ else if ((gtk_major_version != GTK_MAJOR_VERSION) ||
+ (gtk_minor_version != GTK_MINOR_VERSION) ||
+ (gtk_micro_version != GTK_MICRO_VERSION))
+ {
+ printf("*** GTK+ header files (version %d.%d.%d) do not match\n",
+ GTK_MAJOR_VERSION, GTK_MINOR_VERSION, GTK_MICRO_VERSION);
+ printf("*** library (version %d.%d.%d)\n",
+ gtk_major_version, gtk_minor_version, gtk_micro_version);
+ }
+#endif /* defined (GTK_MAJOR_VERSION) ... */
+ else
+ {
+ if ((gtk_major_version > major) ||
+ ((gtk_major_version == major) && (gtk_minor_version > minor)) ||
+ ((gtk_major_version == major) && (gtk_minor_version == minor) && (gtk_micro_version >= micro)))
+ {
+ return 0;
+ }
+ else
+ {
+ printf("\n*** An old version of GTK+ (%d.%d.%d) was found.\n",
+ gtk_major_version, gtk_minor_version, gtk_micro_version);
+ printf("*** You need a version of GTK+ newer than %d.%d.%d. The latest version of\n",
+ major, minor, micro);
+ printf("*** GTK+ is always available from ftp://ftp.gtk.org.\n");
+ printf("***\n");
+ printf("*** If you have already installed a sufficiently new version, this error\n");
+ printf("*** probably means that the wrong copy of the gtk-config shell script is\n");
+ printf("*** being found. The easiest way to fix this is to remove the old version\n");
+ printf("*** of GTK+, but you can also set the GTK_CONFIG environment to point to the\n");
+ printf("*** correct copy of gtk-config. (In this case, you will have to\n");
+ printf("*** modify your LD_LIBRARY_PATH enviroment variable, or edit /etc/ld.so.conf\n");
+ printf("*** so that the correct libraries are found at run-time))\n");
+ }
+ }
+ return 1;
+}
+],, no_gtk=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"])
+ CFLAGS="$ac_save_CFLAGS"
+ LIBS="$ac_save_LIBS"
+ AC_LANG_RESTORE
+ fi
+ fi
+ if test "x$no_gtk" = x ; then
+ AC_MSG_RESULT(yes)
+ ifelse([$2], , :, [$2])
+ else
+ AC_MSG_RESULT(no)
+ if test "$GTK_CONFIG" = "no" ; then
+ echo "*** The gtk-config script installed by GTK could not be found"
+ echo "*** If GTK was installed in PREFIX, make sure PREFIX/bin is in"
+ echo "*** your path, or set the GTK_CONFIG environment variable to the"
+ echo "*** full path to gtk-config."
+ else
+ if test -f conf.gtktest ; then
+ :
+ else
+ echo "*** Could not run GTK test program, checking why..."
+ CFLAGS="$CFLAGS $GTK_CFLAGS"
+ LIBS="$LIBS $GTK_LIBS"
+ AC_TRY_LINK([
+#include <gtk/gtk.h>
+#include <stdio.h>
+], [ return ((gtk_major_version) || (gtk_minor_version) || (gtk_micro_version)); ],
+ [ echo "*** The test program compiled, but did not run. This usually means"
+ echo "*** that the run-time linker is not finding GTK or finding the wrong"
+ echo "*** version of GTK. If it is not finding GTK, you'll need to set your"
+ echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point"
+ echo "*** to the installed location Also, make sure you have run ldconfig if that"
+ echo "*** is required on your system"
+ echo "***"
+ echo "*** If you have an old version installed, it is best to remove it, although"
+ echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"
+ echo "***"
+ echo "*** If you have a RedHat 5.0 system, you should remove the GTK package that"
+ echo "*** came with the system with the command"
+ echo "***"
+ echo "*** rpm --erase --nodeps gtk gtk-devel" ],
+ [ echo "*** The test program failed to compile or link. See the file config.log for the"
+ echo "*** exact error that occured. This usually means GTK was incorrectly installed"
+ echo "*** or that you have moved GTK since it was installed. In the latter case, you"
+ echo "*** may want to edit the gtk-config script: $GTK_CONFIG" ])
+ CFLAGS="$ac_save_CFLAGS"
+ LIBS="$ac_save_LIBS"
+ fi
+ fi
+ GTK_CFLAGS=""
+ GTK_LIBS=""
+ ifelse([$3], , :, [$3])
+ fi
+ AC_SUBST(GTK_CFLAGS)
+ AC_SUBST(GTK_LIBS)
+ rm -f conf.gtktest
+])
diff --git a/dcopc/marshal.c b/dcopc/marshal.c
new file mode 100644
index 00000000..e0de9296
--- /dev/null
+++ b/dcopc/marshal.c
@@ -0,0 +1,420 @@
+/*
+Copyright (c) 2000 Simon Hausmann <hausmann@kde.org>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include "marshal.h"
+
+#include <glib.h>
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+dcop_data *dcop_data_new()
+{
+ dcop_data *res = g_new( dcop_data, 1 );
+
+ res->ptr = 0;
+ res->size = 0;
+ res->cur = 0;
+ res->ref = 0;
+
+ return res;
+}
+
+void dcop_data_destroy( dcop_data *data )
+{
+ g_assert( data->ref == 0 );
+
+ g_free( data->ptr );
+
+ g_free( data );
+}
+
+dcop_data *dcop_data_copy( dcop_data *data )
+{
+ dcop_data *res = dcop_data_new();
+ res->ptr = (char *)g_malloc( data->size );
+ res->size = data->size;
+ dcop_data_reset( res );
+ memcpy( res->ptr, data->ptr, data->size );
+ return res;
+}
+
+static gboolean dcop_data_check_size( dcop_data *data, unsigned int size )
+{
+ if ( data->size - ( data->cur - data->ptr ) < size )
+ return FALSE;
+ return TRUE;
+}
+
+gboolean dcop_marshal_raw( dcop_data *data, const void *ptr, unsigned int size )
+{
+ unsigned int relptr = data->cur - data->ptr;
+
+ data->ptr = (char *)g_realloc( data->ptr, data->size + size );
+
+ if ( data->ptr == 0 )
+ return FALSE;
+
+ data->cur = data->ptr + relptr;
+
+ memcpy( data->cur, ptr, size );
+
+ data->cur += size;
+ data->size += size;
+
+ return TRUE;
+}
+
+gboolean dcop_marshal_uint32( dcop_data *data, unsigned int val )
+{
+ unsigned char buf[4];
+
+ g_assert( sizeof( unsigned int ) == 4 );
+
+ buf[0] = val;
+ buf[1] = val >> 8;
+ buf[2] = val >> 16;
+ buf[3] = val >> 24;
+
+ return dcop_marshal_raw( data, buf, 4 );
+}
+
+gboolean dcop_demarshal_uint32( dcop_data *data, unsigned int *val )
+{
+ g_assert( sizeof( unsigned int ) == 4 );
+
+ if ( !dcop_data_check_size( data, 4 ) )
+ return FALSE;
+
+ *val = (data->cur[3] << 24) |
+ (data->cur[2] << 16) |
+ (data->cur[1] << 8) |
+ data->cur[0];
+ data->cur += 4;
+
+ return TRUE;
+}
+
+gboolean dcop_marshal_string( dcop_data *data, const gchar *str )
+{
+ size_t l = 0;
+
+ if ( str )
+ l = strlen( str ) + 1;
+
+ if( !dcop_marshal_uint32( data, l ) )
+ return FALSE;
+
+ if ( str )
+ return dcop_marshal_raw( data, str, l );
+ else
+ return TRUE;
+}
+
+gboolean dcop_demarshal_string( dcop_data *data, gchar **str )
+{
+ unsigned int l = 0;
+ gchar *res = 0;
+
+ g_assert( str );
+
+ if ( !dcop_demarshal_uint32( data, &l ) )
+ return FALSE;
+
+ if ( !dcop_data_check_size( data, l ) )
+ return FALSE;
+
+ res = (char *)g_malloc( l );
+ memcpy( res, data->cur, l );
+ data->cur += l;
+
+ *str = res;
+
+ return TRUE;
+}
+
+
+gboolean dcop_marshal_string16( dcop_data *data, const gchar *str )
+{
+ size_t l = 0;
+ size_t c = 0;
+ char *tmp = 0;
+ const char *src = str;
+ char *dst = 0;
+
+ if ( str )
+ l = strlen( str ) * 2;
+ else
+ {
+ /* null marker*/
+ guint32 s = 0xffffffff;
+ return dcop_marshal_uint32( data, s );
+ }
+
+ if( !dcop_marshal_uint32( data, l ) )
+ return FALSE;
+
+ if ( str )
+ {
+ dst = tmp = (char *)g_malloc( l );
+ c = strlen( str );
+
+ while ( c-- )
+ {
+ *dst++ = 0;
+ *dst++ = *src++;
+ }
+
+ dcop_marshal_raw( data, tmp, l );
+
+ g_free( tmp );
+ }
+ return TRUE;
+}
+
+gboolean dcop_demarshal_string16( dcop_data *data, gchar **str )
+{
+ unsigned int l = 0;
+ unsigned int size = 0;
+ char *res = 0;
+ char *p = 0;
+
+ assert( str );
+
+ if ( !dcop_demarshal_uint32( data, &l ) )
+ return FALSE;
+
+ /* null marker*/
+ if ( l == 0xffffffff )
+ {
+ *str = 0;
+ return TRUE;
+ }
+
+ if ( !dcop_data_check_size( data, l ) )
+ return FALSE;
+
+ size = ( l / 2 );
+
+ p = res = (char *)g_malloc( size + 1 );
+
+ while( size-- )
+ {
+ data->cur++;
+ *p++ = *data->cur++;
+ }
+
+ *p = '\0';
+
+ *str = res;
+
+ return TRUE;
+}
+
+gboolean dcop_marshal_bytearray( dcop_data *data, const gchar *str, size_t size )
+{
+ if( !dcop_marshal_uint32( data, size ) )
+ return FALSE;
+
+ if ( str )
+ return dcop_marshal_raw( data, str, size );
+ else
+ return TRUE;
+}
+
+gboolean dcop_demarshal_bytearray( dcop_data *data, gchar **str, size_t *size )
+{
+ unsigned int l = 0;
+ gchar *res = 0;
+
+ g_assert( str );
+
+ if ( !dcop_demarshal_uint32( data, &l ) )
+ return FALSE;
+
+ if ( !dcop_data_check_size( data, l ) )
+ return FALSE;
+
+ res = (char *)g_malloc( l );
+ memcpy( res, data->cur, l );
+ data->cur += l;
+
+ *str = res;
+ *size = l;
+
+ return TRUE;
+}
+
+
+
+gboolean dcop_marshal_data( dcop_data *data, dcop_data *other )
+{
+ if ( !dcop_marshal_uint32( data, other->size ) )
+ return FALSE;
+
+ return dcop_marshal_raw( data, other->ptr, other->size );
+}
+
+gboolean dcop_demarshal_data( dcop_data *data, dcop_data **other )
+{
+ dcop_data *res = dcop_data_new();
+ char *tmp = 0;
+ unsigned int l = 0;
+
+ if ( !dcop_demarshal_uint32( data, &l ) )
+ return FALSE;
+
+ if ( !dcop_data_check_size( data, l ) )
+ return FALSE;
+
+ tmp = (char *)malloc( l );
+
+ memcpy( tmp, data->cur, l );
+ data->cur += l;
+
+ dcop_data_assign( res, tmp, l );
+ dcop_data_ref( res );
+
+ *other = res;
+ return True;
+}
+
+gboolean dcop_marshal_stringlist( dcop_data *data, GList *list )
+{
+ GList *it = g_list_first( list );
+
+ if ( !dcop_marshal_uint32( data, g_list_length( list ) ) )
+ return FALSE;
+
+ while ( it )
+ {
+ if ( !dcop_marshal_string( data, (gchar *)it->data ) )
+ return FALSE;
+ it = g_list_next( it );
+ }
+ return TRUE;
+}
+
+gboolean dcop_demarshal_stringlist( dcop_data *data, GList**list )
+{
+ unsigned int count = 0;
+ GList *res = 0;
+ unsigned int i = 0;
+ gchar *str = 0;
+
+ *list = 0;
+
+ if ( !dcop_demarshal_uint32( data, &count ) )
+ return FALSE;
+
+ for ( i = 0; i < count; ++i )
+ {
+ if ( !dcop_demarshal_string( data, &str ) )
+ {
+ dcop_list_free( res );
+ return FALSE;
+ }
+ res = g_list_append( res, str );
+ }
+ *list = res;
+ return TRUE;
+}
+
+gboolean dcop_marshal_stringlist16( dcop_data *data, GList *list )
+{
+ GList *it = g_list_first( list );
+
+ if ( !dcop_marshal_uint32( data, g_list_length( list ) ) )
+ return False;
+
+ while ( it )
+ {
+ if ( !dcop_marshal_string16( data, (gchar *)it->data ) )
+ return FALSE;
+ it = g_list_next( it );
+ }
+ return TRUE;
+}
+
+gboolean dcop_demarshal_stringlist16( dcop_data *data, GList **list )
+{
+ unsigned int count = 0;
+ GList *res = 0;
+ unsigned int i = 0;
+ char *str = 0;
+
+ *list = 0;
+
+ if ( !dcop_demarshal_uint32( data, &count ) )
+ return FALSE;
+
+ for ( i = 0; i < count; ++i )
+ {
+ if ( !dcop_demarshal_string16( data, &str ) )
+ {
+ dcop_list_free( res );
+ return FALSE;
+ }
+ res = g_list_append( res, str );
+ }
+ *list = res;
+ return TRUE;
+}
+
+void dcop_data_assign( dcop_data *data, char *d, unsigned int size )
+{
+ data->ptr = data->cur = d;
+ data->size = size;
+}
+
+gboolean dcop_marshal_boolean( dcop_data *data, gboolean val )
+{
+ guint8 i = (guint8)val;
+ return dcop_marshal_uint8( data, i );
+}
+
+gboolean dcop_demarshal_boolean( dcop_data *data, gboolean *val )
+{
+ guint8 i;
+ if ( !dcop_demarshal_uint8( data, &i ) )
+ return FALSE;
+ *val = (gboolean)i;
+ return TRUE;
+}
+
+gboolean dcop_marshal_uint8( dcop_data *data, guint8 val )
+{
+ return dcop_marshal_raw( data, &val, 1 );
+}
+
+gboolean dcop_demarshal_uint8( dcop_data *data, guint8 *val )
+{
+ if ( !dcop_data_check_size( data, 1 ) )
+ return FALSE;
+
+ *val = *data->cur++;
+ return TRUE;
+}
+
+dcop_data *dcop_data_ref( dcop_data *data ) { data->ref++; return data; }
+void dcop_data_deref( dcop_data *data ) { if ( !--data->ref ) dcop_data_destroy( data ); }
+void dcop_data_reset( dcop_data *data ) { data->cur = data->ptr; }
diff --git a/dcopc/marshal.h b/dcopc/marshal.h
new file mode 100644
index 00000000..a5065627
--- /dev/null
+++ b/dcopc/marshal.h
@@ -0,0 +1,93 @@
+/*
+Copyright (c) 2000 Simon Hausmann <hausmann@kde.org>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+#ifndef __dcopc_marshal_h__
+#define __dcopc_marshal_h__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <X11/ICE/ICElib.h>
+
+#include <dcopc/util.h>
+#include <stdlib.h>
+
+typedef struct _dcop_data dcop_data;
+
+struct _dcop_data
+{
+ char *ptr;
+ unsigned int size;
+ char *cur;
+ unsigned int ref;
+};
+
+/* remember to call ref() after this one! */
+dcop_data *dcop_data_new();
+
+/* do not call directly! use deref! */
+void dcop_data_destroy( dcop_data *data );
+
+void dcop_data_assign( dcop_data *data, char *d, unsigned int size );
+
+dcop_data *dcop_data_ref( dcop_data *data );
+void dcop_data_deref( dcop_data *data );
+
+dcop_data *dcop_data_copy( dcop_data *data );
+
+void dcop_data_reset( dcop_data *data );
+
+gboolean dcop_marshal_raw( dcop_data *data, const void *ptr, unsigned int size );
+
+gboolean dcop_marshal_uint32( dcop_data *data, unsigned int val );
+gboolean dcop_demarshal_uint32( dcop_data *data, unsigned int *val );
+
+gboolean dcop_marshal_string( dcop_data *data, const gchar *str );
+gboolean dcop_demarshal_string( dcop_data *data, gchar **str );
+
+/* works only for ascii! */
+gboolean dcop_marshal_string16( dcop_data *data, const gchar *str );
+gboolean dcop_demarshal_string16( dcop_data *data, gchar **str );
+
+gboolean dcop_marshal_bytearray( dcop_data *data, const gchar *str, size_t size );
+gboolean dcop_demarshal_bytearray( dcop_data *data, gchar **str, size_t *size );
+
+gboolean dcop_marshal_data( dcop_data *data, dcop_data *other );
+gboolean dcop_demarshal_data( dcop_data *data, dcop_data **other );
+
+gboolean dcop_marshal_stringlist( dcop_data *data, GList *list );
+gboolean dcop_demarshal_stringlist( dcop_data *data, GList **list );
+
+gboolean dcop_marshal_stringlist16( dcop_data *data, GList *list );
+gboolean dcop_demarshal_stringlist16( dcop_data *data, GList **list );
+
+gboolean dcop_marshal_boolean( dcop_data *data, gboolean val );
+gboolean dcop_demarshal_boolean( dcop_data *data, gboolean *val );
+
+gboolean dcop_marshal_uint8( dcop_data *data, guint8 val );
+gboolean dcop_demarshal_uint8( dcop_data *data, guint8 *val );
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
diff --git a/dcopc/util.c b/dcopc/util.c
new file mode 100644
index 00000000..f69549c5
--- /dev/null
+++ b/dcopc/util.c
@@ -0,0 +1,137 @@
+/*
+Copyright (c) 2000 Simon Hausmann <hausmann@kde.org>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include "util.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <stdio.h>
+
+void dcop_stringlist_destroy( dcop_stringlist *list )
+{
+ dcop_list_item *it = list->root;
+ while ( it )
+ {
+ free( (char *)it->data );
+ it = it->next;
+ }
+ dcop_list_destroy( list );
+}
+
+void dcop_stringlist_append( dcop_stringlist *list, const char *str )
+{
+ dcop_list_append( list, strdup( str ) );
+}
+
+dcop_list *dcop_list_new()
+{
+ dcop_list *res = (dcop_list *)malloc( sizeof( dcop_list ) );
+ res->root = NULL;
+ return res;
+}
+
+void dcop_list_destroy( dcop_list *list )
+{
+ dcop_list_item *it = list->root;
+ while ( it )
+ {
+ dcop_list_item *tmp = it;
+ it = it->next;
+ free( tmp );
+ }
+ free( list );
+}
+
+dcop_list_item *dcop_list_item_new()
+{
+ dcop_list_item *res = malloc( sizeof( dcop_list ) );
+ res->prev = res->next = NULL;
+ return res;
+}
+
+dcop_list_item *dcop_list_append( dcop_list *list, void *data )
+{
+ dcop_list_item *it = list->root;
+ dcop_list_item *res = dcop_list_item_new();
+
+ if ( it == NULL )
+ list->root = res;
+ else
+ {
+ while ( it->next != NULL )
+ it = it->next;
+
+ it->next = res;
+ res->prev = it;
+ }
+
+ res->data = data;
+ return res;
+}
+
+gboolean dcop_list_remove( dcop_list *list, void *data )
+{
+ dcop_list_item *it = list->root;
+
+ if ( it == NULL )
+ return False;
+
+ if ( it->data == data )
+ {
+ list->root = it->next;
+ if ( list->root )
+ list->root->prev = NULL;
+
+ free( it );
+
+ return True;
+ }
+
+ it = it->next;
+
+ while ( it != NULL )
+ {
+ if ( it->data == data )
+ {
+ it->prev->next = it->next;
+ if ( it->next )
+ it->next->prev = it->prev;
+ free( it );
+ return True;
+ }
+ it = it->next;
+ }
+
+ return False;
+}
+
+unsigned int dcop_list_count( dcop_list *list )
+{
+ unsigned int res = 0;
+ dcop_list_item *it = list->root;
+ while ( it )
+ {
+ res++;
+ it = it->next;
+ }
+ return res;
+}
diff --git a/dcopc/util.h b/dcopc/util.h
new file mode 100644
index 00000000..38d89f0f
--- /dev/null
+++ b/dcopc/util.h
@@ -0,0 +1,73 @@
+/*
+Copyright (c) 2000 Simon Hausmann <hausmann@kde.org>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+#ifndef __dcopc_util_h__
+#define __dcopc_util_h__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <X11/ICE/ICElib.h>
+#include <gtk/gtk.h>
+
+#define dcop_free( o ) \
+ { \
+ g_free( o ); \
+ o = 0; \
+ }
+
+#define dcop_string_assign( s, val ) \
+ { \
+ dcop_free( s ); \
+ if ( val != NULL ) \
+ s = val; \
+ }
+
+#define dcop_string_copy( s, val ) \
+ { \
+ dcop_free( s ); \
+ if( val != NULL ) \
+ s = g_strdup( val ); \
+ }
+
+#define dcop_string_assing( s, val ) \
+ { \
+ dcop_free( s ); \
+ if ( val != NULL ) \
+ s = val; \
+ }
+
+#define dcop_list_free( lst ) \
+ { \
+ GList *it = g_list_first( lst ); \
+ while ( it ) \
+ { \
+ g_free( it->data ); \
+ it = g_list_next( it ); \
+ } \
+ g_list_free( lst ); \
+ }
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif