summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorredman <redman>1999-04-01 21:58:48 (GMT)
committerredman <redman>1999-04-01 21:58:48 (GMT)
commit5f1a88adc8d3daa1d9bcc15196c12b056e8aae7b (patch)
tree40d4f02cecc0c57f7407bd4a0844b860a62f8712
parent91bd30b4de4717f3c9dd8a9958a3a8d2e304955e (diff)
downloadtk-5f1a88adc8d3daa1d9bcc15196c12b056e8aae7b.zip
tk-5f1a88adc8d3daa1d9bcc15196c12b056e8aae7b.tar.gz
tk-5f1a88adc8d3daa1d9bcc15196c12b056e8aae7b.tar.bz2
Remove the DDE code.
Modified stubs based on Jan's patch.
-rw-r--r--ChangeLog22
-rw-r--r--generic/tk.decls9
-rw-r--r--generic/tk.h11
-rw-r--r--generic/tkPlatDecls.h11
-rw-r--r--generic/tkStubInit.c13
-rw-r--r--generic/tkWindow.c13
-rw-r--r--tests/winSend.test8
-rw-r--r--unix/Makefile.in8
-rw-r--r--win/makefile.vc3
-rw-r--r--win/tkWinSend.c1240
10 files changed, 65 insertions, 1273 deletions
diff --git a/ChangeLog b/ChangeLog
index dfe4066..6184b68 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,25 @@
+1999-04-01 <redman@scriptics.com>
+
+ * generic/tk.decls:
+ * generic/tk.h:
+ * generic/tkStubInit.c:
+ * generic/tkWindow.c:
+ * unix/Makefile.in:
+ * win/makefile.vc: Tk now uses its own stub library to store
+ pointers to its own stubs table.
+
+ * generic/tk.decls:
+ * tests/winSend.test:
+ * generic/tkPlatDecls.h:
+ * win/tkWinSend.c: Removed the DDE-based send and dde commands,
+ they were causing Tk to lock up when any window on the system was
+ not processing its message queue (more importantly, windows in Tcl
+ and Tk). The send command needs to be rewritten to prevent the
+ deadlock situation (soon). The dde command is being pushed into
+ its own package and will provide almost all of the capabilities
+ that send did before (using a "dde eval" command), not yet
+ completed.
+
1999-03-31 <redman@scriptics.com>
* win/tkWinSend.c: Modified dde/send code to work properly on
diff --git a/generic/tk.decls b/generic/tk.decls
index 9c9630a..8dd49eb 100644
--- a/generic/tk.decls
+++ b/generic/tk.decls
@@ -10,7 +10,7 @@
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
-# RCS: @(#) $Id: tk.decls,v 1.2.2.2 1999/03/30 04:12:55 stanton Exp $
+# RCS: @(#) $Id: tk.decls,v 1.2.2.3 1999/04/01 21:58:49 redman Exp $
library tk
@@ -1068,13 +1068,6 @@ declare 5 win {
UINT message, WPARAM wParam, LPARAM lParam, LRESULT *result)
}
-# new for 8.1
-
-declare 6 win {
- int Tk_DdeObjCmd (ClientData clientData, Tcl_Interp *interp, \
- int objc, Tcl_Obj *CONST objv[])
-}
-
# Mac specific functions
declare 0 mac {
diff --git a/generic/tk.h b/generic/tk.h
index f1ef086..5ae3562 100644
--- a/generic/tk.h
+++ b/generic/tk.h
@@ -12,7 +12,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tk.h,v 1.1.4.14 1999/03/18 00:43:01 stanton Exp $
+ * RCS: @(#) $Id: tk.h,v 1.1.4.15 1999/04/01 21:58:49 redman Exp $
*/
#ifndef _TK
@@ -1159,6 +1159,15 @@ struct Tk_PhotoImageFormat {
#define Tk_Main(argc, argv, proc) \
Tk_MainEx(argc, argv, proc, Tcl_CreateInterp())
+char *Tk_InitStubs _ANSI_ARGS_((Tcl_Interp *interp, char *version, int exact));
+
+#ifndef USE_TK_STUBS
+
+#define Tk_InitStubs(interp, version, exact) \
+ Tcl_PkgRequire(interp, "Tk", version, exact)
+
+#endif
+
/*
*--------------------------------------------------------------
diff --git a/generic/tkPlatDecls.h b/generic/tkPlatDecls.h
index d02c888..268a037 100644
--- a/generic/tkPlatDecls.h
+++ b/generic/tkPlatDecls.h
@@ -8,7 +8,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkPlatDecls.h,v 1.2.2.2 1999/03/30 02:08:02 redman Exp $
+ * RCS: @(#) $Id: tkPlatDecls.h,v 1.2.2.3 1999/04/01 21:58:49 redman Exp $
*/
#ifndef _TKPLATDECLS
@@ -48,10 +48,6 @@ EXTERN void Tk_PointerEvent _ANSI_ARGS_((HWND hwnd, int x, int y));
EXTERN int Tk_TranslateWinEvent _ANSI_ARGS_((HWND hwnd,
UINT message, WPARAM wParam, LPARAM lParam,
LRESULT * result));
-/* 6 */
-EXTERN int Tk_DdeObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp * interp, int objc,
- Tcl_Obj *CONST objv[]));
#endif /* __WIN32__ */
#ifdef MAC_TCL
/* 0 */
@@ -99,7 +95,6 @@ typedef struct TkPlatStubs {
Tk_Window (*tk_HWNDToWindow) _ANSI_ARGS_((HWND hwnd)); /* 3 */
void (*tk_PointerEvent) _ANSI_ARGS_((HWND hwnd, int x, int y)); /* 4 */
int (*tk_TranslateWinEvent) _ANSI_ARGS_((HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam, LRESULT * result)); /* 5 */
- int (*tk_DdeObjCmd) _ANSI_ARGS_((ClientData clientData, Tcl_Interp * interp, int objc, Tcl_Obj *CONST objv[])); /* 6 */
#endif /* __WIN32__ */
#ifdef MAC_TCL
void (*tk_MacSetEmbedHandler) _ANSI_ARGS_((Tk_MacEmbedRegisterWinProc * registerWinProcPtr, Tk_MacEmbedGetGrafPortProc * getPortProcPtr, Tk_MacEmbedMakeContainerExistProc * containerExistProcPtr, Tk_MacEmbedGetClipProc * getClipProc, Tk_MacEmbedGetOffsetInParentProc * getOffsetProc)); /* 0 */
@@ -149,10 +144,6 @@ extern TkPlatStubs *tkPlatStubsPtr;
#define Tk_TranslateWinEvent \
(tkPlatStubsPtr->tk_TranslateWinEvent) /* 5 */
#endif
-#ifndef Tk_DdeObjCmd
-#define Tk_DdeObjCmd \
- (tkPlatStubsPtr->tk_DdeObjCmd) /* 6 */
-#endif
#endif /* __WIN32__ */
#ifdef MAC_TCL
#ifndef Tk_MacSetEmbedHandler
diff --git a/generic/tkStubInit.c b/generic/tkStubInit.c
index 5428263..01c4799 100644
--- a/generic/tkStubInit.c
+++ b/generic/tkStubInit.c
@@ -8,7 +8,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkStubInit.c,v 1.2.2.3 1999/03/30 04:12:58 stanton Exp $
+ * RCS: @(#) $Id: tkStubInit.c,v 1.2.2.4 1999/04/01 21:58:50 redman Exp $
*/
#include "tkInt.h"
@@ -258,8 +258,6 @@ TkStubs tkStubs = {
Tk_SetOptions, /* 214 */
};
-TkStubs *tkStubsPtr = &tkStubs;
-
TkIntStubs tkIntStubs = {
TCL_STUB_MAGIC,
NULL,
@@ -378,8 +376,6 @@ TkIntStubs tkIntStubs = {
TkpMenuThreadInit, /* 112 */
};
-TkIntStubs *tkIntStubsPtr = &tkIntStubs;
-
TkIntPlatStubs tkIntPlatStubs = {
TCL_STUB_MAGIC,
NULL,
@@ -511,8 +507,6 @@ TkIntPlatStubs tkIntPlatStubs = {
#endif /* MAC_TCL */
};
-TkIntPlatStubs *tkIntPlatStubsPtr = &tkIntPlatStubs;
-
TkIntXlibStubs tkIntXlibStubs = {
TCL_STUB_MAGIC,
NULL,
@@ -664,8 +658,6 @@ TkIntXlibStubs tkIntXlibStubs = {
#endif /* MAC_TCL */
};
-TkIntXlibStubs *tkIntXlibStubsPtr = &tkIntXlibStubs;
-
TkPlatStubs tkPlatStubs = {
TCL_STUB_MAGIC,
NULL,
@@ -676,7 +668,6 @@ TkPlatStubs tkPlatStubs = {
Tk_HWNDToWindow, /* 3 */
Tk_PointerEvent, /* 4 */
Tk_TranslateWinEvent, /* 5 */
- Tk_DdeObjCmd, /* 6 */
#endif /* __WIN32__ */
#ifdef MAC_TCL
Tk_MacSetEmbedHandler, /* 0 */
@@ -693,8 +684,6 @@ TkPlatStubs tkPlatStubs = {
#endif /* MAC_TCL */
};
-TkPlatStubs *tkPlatStubsPtr = &tkPlatStubs;
-
static TkStubHooks tkStubHooks = {
&tkPlatStubs,
&tkIntStubs,
diff --git a/generic/tkWindow.c b/generic/tkWindow.c
index 2f33e8a..ab01dc7 100644
--- a/generic/tkWindow.c
+++ b/generic/tkWindow.c
@@ -12,7 +12,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkWindow.c,v 1.1.4.10 1999/03/30 22:32:02 stanton Exp $
+ * RCS: @(#) $Id: tkWindow.c,v 1.1.4.11 1999/04/01 21:58:50 redman Exp $
*/
#include "tkPort.h"
@@ -2680,6 +2680,9 @@ Tk_SafeInit(interp)
return Initialize(interp);
}
+
+extern TkStubs tkStubs;
+
/*
*----------------------------------------------------------------------
*
@@ -2937,11 +2940,17 @@ Initialize(interp)
* Provide Tk and its stub table.
*/
- code = Tcl_PkgProvideEx(interp, "Tk", TK_VERSION, (ClientData) tkStubsPtr);
+ code = Tcl_PkgProvideEx(interp, "Tk", TK_VERSION, (ClientData) &tkStubs);
if (code != TCL_OK) {
goto done;
}
+#ifdef Tk_InitStubs
+#undef Tk_InitStubs
+#endif
+
+ Tk_InitStubs(interp, TK_VERSION, 1);
+
/*
* Invoke platform-specific initialization.
*/
diff --git a/tests/winSend.test b/tests/winSend.test
index ce1a9a6..6edbca5 100644
--- a/tests/winSend.test
+++ b/tests/winSend.test
@@ -7,7 +7,7 @@
# Copyright (c) 1998-1999 by Scriptics Corporation.
# All rights reserved.
#
-# RCS: @(#) $Id: winSend.test,v 1.1.2.6 1999/03/26 00:08:12 hershey Exp $
+# RCS: @(#) $Id: winSend.test,v 1.1.2.7 1999/04/01 21:58:51 redman Exp $
if {[lsearch [namespace children] ::tcltest] == -1} {
source [file join [pwd] [file dirname [info script]] defs.tcl]
@@ -19,6 +19,12 @@ if {$tcl_platform(platform) != "windows"} {
return
}
+if {[info commands send] != "send"} {
+ puts "skipping: Unimplemented send command"
+ ::tcltest::cleanupTests
+ return
+}
+
foreach i [winfo children .] {
destroy $i
}
diff --git a/unix/Makefile.in b/unix/Makefile.in
index 7e40d63..f40e354 100644
--- a/unix/Makefile.in
+++ b/unix/Makefile.in
@@ -5,7 +5,7 @@
# "autoconf" program (constructs like "@foo@" will get replaced in the
# actual Makefile.
#
-# RCS: @(#) $Id: Makefile.in,v 1.1.4.10 1999/03/30 02:08:03 redman Exp $
+# RCS: @(#) $Id: Makefile.in,v 1.1.4.11 1999/04/01 21:58:51 redman Exp $
# Current Tk version; used in various names.
@@ -265,7 +265,7 @@ UNIXOBJS = tkUnix.o tkUnix3d.o tkUnixButton.o tkUnixColor.o tkUnixConfig.o \
tkUnixCursor.o tkUnixDraw.o tkUnixEmbed.o tkUnixEvent.o \
tkUnixFocus.o tkUnixFont.o tkUnixInit.o tkUnixKey.o tkUnixMenu.o \
tkUnixMenubu.o tkUnixScale.o tkUnixScrlbr.o tkUnixSelect.o \
- tkUnixSend.o tkUnixWm.o tkUnixXId.o tkStubInit.o
+ tkUnixSend.o tkUnixWm.o tkUnixXId.o tkStubInit.o tkStubLib.o
STUB_LIB_OBJS = tkStubLib.o
@@ -317,6 +317,7 @@ SRCS = \
$(GENERIC_DIR)/tkTextTag.c $(GENERIC_DIR)/tkTextWind.c \
$(GENERIC_DIR)/tkOldConfig.c \
$(GENERIC_DIR)/tkSquare.c $(GENERIC_DIR)/tkTest.c \
+ $(GENERIC_DIR)/tkStubInit.c $(GENERIC_DIR)/tkStubLib.c \
$(UNIX_DIR)/tkAppInit.c $(UNIX_DIR)/tkUnix.c \
$(UNIX_DIR)/tkUnix3d.c \
$(UNIX_DIR)/tkUnixButton.c $(UNIX_DIR)/tkUnixColor.c \
@@ -775,8 +776,7 @@ tkStubInit.o: $(GENERIC_DIR)/tkStubInit.c
# even though they will be placed in a static archive
tkStubLib.o: $(GENERIC_DIR)/tkStubLib.c
- $(CC) -c $(CC_SWITCHES_NO_STUBS) $(GENERIC_DIR)/tkStubLib.c
-
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkStubLib.c
tkUnix.o: $(UNIX_DIR)/tkUnix.c
$(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tkUnix.c
diff --git a/win/makefile.vc b/win/makefile.vc
index 44e34cf..e28586e 100644
--- a/win/makefile.vc
+++ b/win/makefile.vc
@@ -4,7 +4,7 @@
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# Copyright (c) 1995-1997 Sun Microsystems, Inc.
-# RCS: @(#) $Id: makefile.vc,v 1.1.4.20 1999/03/30 02:30:19 redman Exp $
+# RCS: @(#) $Id: makefile.vc,v 1.1.4.21 1999/04/01 21:58:52 redman Exp $
# Does not depend on the presence of any environment variables in
# order to compile tcl; all needed information is derived from
@@ -208,6 +208,7 @@ TKOBJS = \
$(TMPDIR)\tkUtil.obj \
$(TMPDIR)\tkVisual.obj \
$(TMPDIR)\tkStubInit.obj \
+ $(TMPDIR)\tkStubLib.obj \
$(TMPDIR)\tkWindow.obj
TKSTUBOBJS = $(TMPDIR)\tkStubLib.obj \
diff --git a/win/tkWinSend.c b/win/tkWinSend.c
index 2aee404..acad720 100644
--- a/win/tkWinSend.c
+++ b/win/tkWinSend.c
@@ -10,71 +10,11 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkWinSend.c,v 1.1.4.6 1999/03/31 22:37:26 redman Exp $
+ * RCS: @(#) $Id: tkWinSend.c,v 1.1.4.7 1999/04/01 21:58:52 redman Exp $
*/
-#include "tkWinInt.h"
-#include <ddeml.h>
-
-/*
- * The following structure is used to keep track of the interpreters
- * registered by this process.
- */
-
-typedef struct RegisteredInterp {
- struct RegisteredInterp *nextPtr;
- /* The next interp this application knows
- * about. */
- char *name; /* Interpreter's name (malloc-ed). */
- Tcl_Interp *interp; /* The interpreter attached to this name. */
-} RegisteredInterp;
-
-/*
- * Used to keep track of conversations.
- */
-
-typedef struct Conversation {
- struct Conversation *nextPtr;
- /* The next conversation in the list. */
- RegisteredInterp *riPtr; /* The info we know about the conversation. */
- HCONV hConv; /* The DDE handle for this conversation. */
- Tcl_Obj *returnPackagePtr; /* The result package for this conversation. */
-} Conversation;
-
-typedef struct ThreadSpecificData {
- Conversation *currentConversations;
- /* A list of conversations currently
- * being processed. */
- RegisteredInterp *interpListPtr;
- /* List of all interpreters registered
- * in the current process. */
-} ThreadSpecificData;
-static Tcl_ThreadDataKey dataKey;
-
-/*
- * The following variables cannot be placed in thread-local storage.
- * The Mutex ddeMutex guards access to the ddeInstance.
- */
-static DWORD ddeInstance; /* The application instance handle given
- * to us by DdeInitialize. */
-TCL_DECLARE_MUTEX(ddeMutex)
-
-/*
- * Forward declarations for procedures defined later in this file.
- */
-
-static void RemoveDdeServerExitProc _ANSI_ARGS_((ClientData clientData));
-static void DeleteProc _ANSI_ARGS_((ClientData clientData));
-static Tcl_Obj * ExecuteRemoteObject _ANSI_ARGS_((
- RegisteredInterp *riPtr,
- Tcl_Obj *ddeObjectPtr));
-static int MakeDdeConnection _ANSI_ARGS_((Tcl_Interp *interp,
- char *name, HCONV *ddeConvPtr));
-static HDDEDATA CALLBACK TkDdeServerProc _ANSI_ARGS_((UINT uType,
- UINT uFmt, HCONV hConv, HSZ ddeTopic,
- HSZ ddeItem, HDDEDATA hData, DWORD dwData1,
- DWORD dwData2));
-static void SetDdeError _ANSI_ARGS_((Tcl_Interp *interp));
+#include "tkPort.h"
+#include "tkInt.h"
/*
@@ -112,395 +52,7 @@ Tk_SetAppName(tkwin, name)
* "send" commands. Must be globally
* unique. */
{
- TkWindow *winPtr = (TkWindow *) tkwin;
- Tcl_Interp *interp = winPtr->mainPtr->interp;
- int i, suffix, offset;
- RegisteredInterp *riPtr, *prevPtr;
- char *actualName;
- Tcl_DString dString;
- Tcl_Obj *resultObjPtr, *interpNamePtr;
- char *interpName;
- ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
- Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
- TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;
-
- /*
- * Make sure that the DDE server is there. This is done only once,
- * add an exit handler tear it down.
- */
-
- if (ddeInstance == 0) {
- Tcl_MutexLock(&ddeMutex);
- if (ddeInstance == 0) {
- HSZ ddeService;
-
- if (DdeInitialize(&ddeInstance, TkDdeServerProc,
- CBF_SKIP_REGISTRATIONS|CBF_SKIP_UNREGISTRATIONS
- |CBF_FAIL_POKES, 0)
- != DMLERR_NO_ERROR) {
- DdeUninitialize(ddeInstance);
- return NULL;
- }
- Tcl_CreateExitHandler(RemoveDdeServerExitProc, NULL);
- ddeService = DdeCreateStringHandle(ddeInstance, "Tk", 0);
- DdeNameService(ddeInstance, ddeService, 0L, DNS_REGISTER);
- }
- Tcl_MutexUnlock(&ddeMutex);
- }
-
- /*
- * See if the application is already registered; if so, remove its
- * current name from the registry. The deletion of the command
- * will take care of disposing of this entry.
- */
-
- for (riPtr = tsdPtr->interpListPtr, prevPtr = NULL; riPtr != NULL;
- prevPtr = riPtr, riPtr = riPtr->nextPtr) {
- if (riPtr->interp == interp) {
- if (prevPtr == NULL) {
- tsdPtr->interpListPtr = tsdPtr->interpListPtr->nextPtr;
- } else {
- prevPtr->nextPtr = riPtr->nextPtr;
- }
- break;
- }
- }
-
- /*
- * Pick a name to use for the application. Use "name" if it's not
- * already in use. Otherwise add a suffix such as " #2", trying
- * larger and larger numbers until we eventually find one that is
- * unique.
- */
-
- actualName = name;
- suffix = 1;
- offset = 0;
- Tcl_DStringInit(&dString);
-
- TkGetInterpNames(interp, tkwin);
- resultObjPtr = Tcl_GetObjResult(interp);
- Tcl_IncrRefCount(resultObjPtr);
- for (i = 0; ; ) {
- (void) Tcl_ListObjIndex(NULL, resultObjPtr, i, &interpNamePtr);
- if (interpNamePtr == NULL) {
- break;
- }
- interpName = Tcl_GetString(interpNamePtr);
- if (stricmp(actualName, interpName) == 0) {
- if (suffix == 1) {
- Tcl_DStringAppend(&dString, name, -1);
- Tcl_DStringAppend(&dString, " #", 2);
- offset = Tcl_DStringLength(&dString);
- Tcl_DStringSetLength(&dString, offset + 10);
- actualName = Tcl_DStringValue(&dString);
- }
- suffix++;
- sprintf(actualName + offset, "%d", suffix);
- i = 0;
- } else {
- i++;
- }
- }
-
- Tcl_DecrRefCount(resultObjPtr);
- Tcl_ResetResult(interp);
-
- /*
- * We have found a unique name. Now add it to the registry.
- */
-
- riPtr = (RegisteredInterp *) ckalloc(sizeof(RegisteredInterp));
- riPtr->interp = interp;
- riPtr->name = ckalloc(strlen(actualName) + 1);
- riPtr->nextPtr = tsdPtr->interpListPtr;
- tsdPtr->interpListPtr = riPtr;
- strcpy(riPtr->name, actualName);
-
- Tcl_CreateObjCommand(interp, "send", Tk_SendObjCmd,
- (ClientData) riPtr, DeleteProc);
- Tcl_CreateObjCommand(interp, "dde", Tk_DdeObjCmd,
- (ClientData) NULL, NULL);
- if (Tcl_IsSafe(interp)) {
- Tcl_HideCommand(interp, "send", "send");
- Tcl_HideCommand(interp, "dde", "dde");
- }
- Tcl_DStringFree(&dString);
-
- return riPtr->name;
-}
-
-/*
- *--------------------------------------------------------------
- *
- * Tk_SendObjCmd --
- *
- * This procedure is invoked to process the "send" Tcl command.
- * See the user documentation for details on what it does.
- *
- * Results:
- * A standard Tcl result.
- *
- * Side effects:
- * See the user documentation.
- *
- *--------------------------------------------------------------
- */
-
-int
-Tk_SendObjCmd(
- ClientData clientData, /* Used only for deletion */
- Tcl_Interp *interp, /* The interp we are sending from */
- int objc, /* Number of arguments */
- Tcl_Obj *CONST objv[]) /* The arguments */
-{
- ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
- Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
- char *string, *sendName;
- int async, i, result, length;
- RegisteredInterp *riPtr;
- Tcl_Interp *sendInterp;
- Tcl_Obj *objPtr;
- static char *options[] = {
- "-async", "-displayof", "--", (char *) NULL
- };
- enum options {
- SEND_ASYNC, SEND_DISPLAYOF, SEND_LAST
- };
-
- async = 0;
- for (i = 1; i < objc; i++) {
- int index;
-
- string = Tcl_GetString(objv[i]);
- if (string[0] != '-') {
- break;
- }
- if (Tcl_GetIndexFromObj(interp, objv[i], options, "option", TCL_EXACT,
- &index) != TCL_OK) {
- return TCL_ERROR;
- }
- switch ((enum options) index) {
- case SEND_ASYNC: {
- async = 1;
- break;
- }
- case SEND_DISPLAYOF: {
- /*
- * Don't care about -displayof option. Skip the
- * (ignored) window argument.
- */
-
- i++;
- break;
- }
- case SEND_LAST: {
- i++;
- /* break 2; */
- goto endOfOptionLoop;
- }
- }
- }
-
- endOfOptionLoop:
- if (objc - i < 2) {
- Tcl_WrongNumArgs(interp, 1, objv,
- "?options? interpName arg ?arg ...?");
- return TCL_ERROR;
- }
-
- sendName = Tcl_GetString(objv[i]);
- objc -= i + 1;
- ((Tcl_Obj **)objv) += i + 1;
-
- /*
- * See if the target interpreter is local. If so, execute
- * the command directly without going through the DDE server.
- * Don't exchange objects between interps. The target interp could
- * compile an object, producing a bytecode structure that refers to
- * other objects owned by the target interp. If the target interp
- * is then deleted, the bytecode structure would be referring to
- * deallocated objects.
- */
-
- for (riPtr = tsdPtr->interpListPtr; riPtr != NULL; riPtr
- = riPtr->nextPtr) {
- if (stricmp(sendName, riPtr->name) == 0) {
- break;
- }
- }
-
- if (riPtr != NULL) {
- /*
- * This command is to a local interp. No need to go through
- * the server.
- */
-
- Tcl_Preserve((ClientData) riPtr);
- sendInterp = riPtr->interp;
- Tcl_Preserve((ClientData) sendInterp);
-
- /*
- * Don't exchange objects between interps. The target interp would
- * compile an object, producing a bytecode structure that refers to
- * other objects owned by the target interp. If the target interp
- * is then deleted, the bytecode structure would be referring to
- * deallocated objects.
- */
-
- if (objc == 1) {
- result = Tcl_EvalObjEx(sendInterp, objv[0], TCL_EVAL_GLOBAL);
- } else {
- objPtr = Tcl_ConcatObj(objc, objv);
- Tcl_IncrRefCount(objPtr);
- result = Tcl_EvalObjEx(sendInterp, objPtr, TCL_EVAL_GLOBAL);
- Tcl_DecrRefCount(objPtr);
- }
- if (interp != sendInterp) {
- if (result == TCL_ERROR) {
- /*
- * An error occurred, so transfer error information from the
- * destination interpreter back to our interpreter.
- */
-
- Tcl_ResetResult(interp);
- objPtr = Tcl_GetVar2Ex(sendInterp, "errorInfo", NULL,
- TCL_GLOBAL_ONLY);
- string = Tcl_GetStringFromObj(objPtr, &length);
- Tcl_AddObjErrorInfo(interp, string, length);
-
- objPtr = Tcl_GetVar2Ex(sendInterp, "errorCode", NULL,
- TCL_GLOBAL_ONLY);
- Tcl_SetObjErrorCode(interp, objPtr);
- }
- Tcl_SetObjResult(interp, Tcl_GetObjResult(sendInterp));
- }
- Tcl_Release((ClientData) riPtr);
- Tcl_Release((ClientData) sendInterp);
- } else {
- /*
- * This is a non-local request. Send the script to the server and poll
- * it for a result.
- */
-
- HCONV hConv = 0;
- HDDEDATA ddeItem = 0;
- HDDEDATA ddeData = 0;
- HSZ ddeCookie = 0;
- DWORD ddeResult;
-
- if (MakeDdeConnection(interp, sendName, &hConv) != TCL_OK) {
- return TCL_ERROR;
- }
-
- objPtr = Tcl_ConcatObj(objc, objv);
- string = Tcl_GetStringFromObj(objPtr, &length);
- ddeItem = DdeCreateDataHandle(ddeInstance, string, length+1, 0, 0,
- CF_TEXT, 0);
-
- if (async) {
- ddeData = DdeClientTransaction((LPBYTE) ddeItem, 0xFFFFFFFF, hConv, 0,
- CF_TEXT, XTYP_EXECUTE, TIMEOUT_ASYNC, &ddeResult);
- DdeAbandonTransaction(ddeInstance, hConv, ddeResult);
- } else {
- ddeData = DdeClientTransaction((LPBYTE) ddeItem, 0xFFFFFFFF, hConv, 0,
- CF_TEXT, XTYP_EXECUTE, 7200000, NULL);
- if (ddeData != 0) {
-
- ddeCookie = DdeCreateStringHandle(ddeInstance,
- "$TK$EXECUTE$RESULT", CP_WINANSI);
- ddeData = DdeClientTransaction(NULL, 0, hConv, ddeCookie,
- CF_TEXT, XTYP_REQUEST, 7200000, NULL);
- }
- }
-
-
- Tcl_DecrRefCount(objPtr);
-
- if (ddeData == 0) {
- SetDdeError(interp);
- DdeFreeDataHandle(ddeItem);
- DdeDisconnect(hConv);
- return TCL_ERROR;
- }
-
- if (async == 0) {
- Tcl_Obj *resultPtr;
-
- /*
- * The return handle has a two or four element list in it. The first
- * element is the return code (TCL_OK, TCL_ERROR, etc.). The
- * second is the result of the script. If the return code is TCL_ERROR,
- * then the third element is the value of the variable "errorCode",
- * and the fourth is the value of the variable "errorInfo".
- */
-
- resultPtr = Tcl_NewObj();
- length = DdeGetData(ddeData, NULL, 0, 0);
- Tcl_SetObjLength(resultPtr, length);
- string = Tcl_GetString(resultPtr);
- DdeGetData(ddeData, string, length, 0);
- Tcl_SetObjLength(resultPtr, strlen(string));
-
- if (Tcl_ListObjIndex(NULL, resultPtr, 0, &objPtr) != TCL_OK) {
- goto error;
- }
- if (Tcl_GetIntFromObj(NULL, objPtr, &result) != TCL_OK) {
- goto error;
- }
- if (result == TCL_ERROR) {
- Tcl_ResetResult(interp);
-
- if (Tcl_ListObjIndex(NULL, resultPtr, 3, &objPtr) != TCL_OK) {
- goto error;
- }
- length = -1;
- string = Tcl_GetStringFromObj(objPtr, &length);
- Tcl_AddObjErrorInfo(interp, string, length);
-
- Tcl_ListObjIndex(NULL, resultPtr, 2, &objPtr);
- Tcl_SetObjErrorCode(interp, objPtr);
- }
- if (Tcl_ListObjIndex(NULL, resultPtr, 1, &objPtr) != TCL_OK) {
- goto error;
- }
- Tcl_SetObjResult(interp, objPtr);
- Tcl_DecrRefCount(resultPtr);
- return result;
-
- error:
- Tcl_SetStringObj(Tcl_GetObjResult(interp),
- "invalid data returned from server", -1);
- Tcl_DecrRefCount(resultPtr);
- if (ddeCookie != NULL) {
- DdeFreeStringHandle(ddeInstance, ddeCookie);
- }
- if (ddeItem != NULL) {
- DdeFreeDataHandle(ddeItem);
- }
- if (ddeData != NULL) {
- DdeFreeDataHandle(ddeData);
- }
- if (hConv != NULL) {
- DdeDisconnect(hConv);
- }
- return TCL_ERROR;
- }
- if (ddeCookie != NULL) {
- DdeFreeStringHandle(ddeInstance, ddeCookie);
- }
- if (ddeItem != NULL) {
- DdeFreeDataHandle(ddeItem);
- }
- if (ddeData != NULL) {
- DdeFreeDataHandle(ddeData);
- }
- if (hConv != NULL) {
- DdeDisconnect(hConv);
- }
- }
-
- return result;
+ return name;
}
/*
@@ -513,10 +65,10 @@ Tk_SendObjCmd(
* of a particular window.
*
* Results:
- * A standard Tcl return value. The interp's result will be set
+ * A standard Tcl return value. Interp->result will be set
* to hold a list of all the interpreter names defined for
* tkwin's display. If an error occurs, then TCL_ERROR
- * is returned and the interp's result will hold an error message.
+ * is returned and interp->result will hold an error message.
*
* Side effects:
* None.
@@ -530,785 +82,5 @@ TkGetInterpNames(interp, tkwin)
Tk_Window tkwin; /* Window whose display is to be used
* for the lookup. */
{
- Tcl_Obj *listObjPtr;
- HCONVLIST hConvList;
- HCONV hConv;
- HSZ ddeService;
- CONVINFO convInfo;
- Tcl_DString dString;
- char *topicName;
- int len;
- ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
- Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
-
- convInfo.cb = sizeof(CONVINFO);
- ddeService = DdeCreateStringHandle(ddeInstance, "Tk", CP_WINANSI);
- hConvList = DdeConnectList(ddeInstance, ddeService, NULL,
- 0, NULL);
- hConv = 0;
-
- Tcl_DStringInit(&dString);
- listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL);
- while (hConv = DdeQueryNextServer(hConvList, hConv), hConv != 0) {
- DdeQueryConvInfo(hConv, QID_SYNC, &convInfo);
- len = DdeQueryString(ddeInstance, convInfo.hszTopic,
- NULL, 0, CP_WINANSI);
- Tcl_DStringSetLength(&dString, len);
- topicName = Tcl_DStringValue(&dString);
- DdeQueryString(ddeInstance, convInfo.hszTopic, topicName,
- len + 1, CP_WINANSI);
- Tcl_ListObjAppendElement(interp, listObjPtr,
- Tcl_NewStringObj(topicName, len));
- }
-
- DdeDisconnectList(hConvList);
- Tcl_SetObjResult(interp, listObjPtr);
- Tcl_DStringFree(&dString);
return TCL_OK;
}
-
-/*
- *--------------------------------------------------------------
- *
- * DeleteProc --
- *
- * This procedure is invoked by Tcl when the "send" command
- * is deleted in an interpreter. It unregisters the interpreter.
- *
- * Results:
- * None.
- *
- * Side effects:
- * The interpreter given by riPtr is unregistered.
- *
- *--------------------------------------------------------------
- */
-
-static void
-DeleteProc(clientData)
- ClientData clientData; /* The interp we are deleting passed
- * as ClientData. */
-{
- RegisteredInterp *riPtr = (RegisteredInterp *) clientData;
- RegisteredInterp *searchPtr, *prevPtr;
- ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
- Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
-
- for (searchPtr = tsdPtr->interpListPtr, prevPtr = NULL;
- (searchPtr != NULL) && (searchPtr != riPtr);
- prevPtr = searchPtr, searchPtr = searchPtr->nextPtr) {
- /*
- * Empty loop body.
- */
- }
-
- Tcl_DeleteCommand(riPtr->interp, "dde");
-
- if (searchPtr != NULL) {
- if (prevPtr == NULL) {
- tsdPtr->interpListPtr = tsdPtr->interpListPtr->nextPtr;
- } else {
- prevPtr->nextPtr = searchPtr->nextPtr;
- }
- }
- ckfree(riPtr->name);
- Tcl_EventuallyFree(clientData, TCL_DYNAMIC);
-}
-
-/*
- *--------------------------------------------------------------
- *
- * ExecuteRemoteObject --
- *
- * Takes the package delivered by DDE and executes it in
- * the server's interpreter.
- *
- * Results:
- * A list Tcl_Obj * that describes what happened. The first
- * element is the numerical return code (TCL_ERROR, etc.).
- * The second element is the result of the script. If the
- * return result was TCL_ERROR, then the third element
- * will be the value of the global "errorCode", and the
- * fourth will be the value of the global "errorInfo".
- * The return result will have a refCount of 0.
- *
- * Side effects:
- * A Tcl script is run, which can cause all kinds of other
- * things to happen.
- *
- *--------------------------------------------------------------
- */
-
-static Tcl_Obj *
-ExecuteRemoteObject(
- RegisteredInterp *riPtr, /* Info about this server. */
- Tcl_Obj *ddeObjectPtr) /* The object to execute. */
-{
- Tcl_Obj *errorObjPtr;
- Tcl_Obj *returnPackagePtr;
- int result;
-
- result = Tcl_EvalObjEx(riPtr->interp, ddeObjectPtr, TCL_EVAL_GLOBAL);
- returnPackagePtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL);
- Tcl_ListObjAppendElement(NULL, returnPackagePtr,
- Tcl_NewIntObj(result));
- Tcl_ListObjAppendElement(NULL, returnPackagePtr,
- Tcl_GetObjResult(riPtr->interp));
- if (result == TCL_ERROR) {
- errorObjPtr = Tcl_GetVar2Ex(riPtr->interp, "errorCode", NULL,
- TCL_GLOBAL_ONLY);
- Tcl_ListObjAppendElement(NULL, returnPackagePtr, errorObjPtr);
- errorObjPtr = Tcl_GetVar2Ex(riPtr->interp, "errorInfo", NULL,
- TCL_GLOBAL_ONLY);
- Tcl_ListObjAppendElement(NULL, returnPackagePtr, errorObjPtr);
- }
-
- return returnPackagePtr;
-}
-
-/*
- *--------------------------------------------------------------
- *
- * TkDdeServerProc --
- *
- * Handles all transactions for this server. Can handle
- * execute, request, and connect protocols. Dde will
- * call this routine when a client attempts to run a dde
- * command using this server.
- *
- * Results:
- * A DDE Handle with the result of the dde command.
- *
- * Side effects:
- * Depending on which command is executed, arbitrary
- * Tcl scripts can be run.
- *
- *--------------------------------------------------------------
- */
-
-static HDDEDATA CALLBACK
-TkDdeServerProc (
- UINT uType, /* The type of DDE transaction we
- * are performing. */
- UINT uFmt, /* The format that data is sent or
- * received. */
- HCONV hConv, /* The conversation associated with the
- * current transaction. */
- HSZ ddeTopic, /* A string handle. Transaction-type
- * dependent. */
- HSZ ddeItem, /* A string handle. Transaction-type
- * dependent. */
- HDDEDATA hData, /* DDE data. Transaction-type dependent. */
- DWORD dwData1, /* Transaction-dependent data. */
- DWORD dwData2) /* Transaction-dependent data. */
-{
- Tcl_DString dString;
- int len;
- char *utilString;
- Tcl_Obj *ddeObjectPtr;
- HDDEDATA ddeReturn = NULL;
- RegisteredInterp *riPtr;
- Conversation *convPtr, *prevConvPtr;
- ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
- Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
-
- switch(uType) {
- case XTYP_CONNECT:
-
- /*
- * Dde is trying to initialize a conversation with us. Check
- * and make sure we have a valid topic.
- */
-
- len = DdeQueryString(ddeInstance, ddeTopic, NULL, 0, 0);
- Tcl_DStringInit(&dString);
- Tcl_DStringSetLength(&dString, len);
- utilString = Tcl_DStringValue(&dString);
- DdeQueryString(ddeInstance, ddeTopic, utilString, len + 1,
- CP_WINANSI);
-
- for (riPtr = tsdPtr->interpListPtr; riPtr != NULL;
- riPtr = riPtr->nextPtr) {
- if (stricmp(utilString, riPtr->name) == 0) {
- Tcl_DStringFree(&dString);
- return (HDDEDATA) TRUE;
- }
- }
-
- Tcl_DStringFree(&dString);
- return (HDDEDATA) FALSE;
-
- case XTYP_CONNECT_CONFIRM:
-
- /*
- * Dde has decided that we can connect, so it gives us a
- * conversation handle. We need to keep track of it
- * so we know which execution result to return in an
- * XTYP_REQUEST.
- */
-
- len = DdeQueryString(ddeInstance, ddeTopic, NULL, 0, 0);
- Tcl_DStringInit(&dString);
- Tcl_DStringSetLength(&dString, len);
- utilString = Tcl_DStringValue(&dString);
- DdeQueryString(ddeInstance, ddeTopic, utilString, len + 1,
- CP_WINANSI);
- for (riPtr = tsdPtr->interpListPtr; riPtr != NULL;
- riPtr = riPtr->nextPtr) {
- if (stricmp(riPtr->name, utilString) == 0) {
- convPtr = (Conversation *) ckalloc(sizeof(Conversation));
- convPtr->nextPtr = tsdPtr->currentConversations;
- convPtr->returnPackagePtr = NULL;
- convPtr->hConv = hConv;
- convPtr->riPtr = riPtr;
- tsdPtr->currentConversations = convPtr;
- break;
- }
- }
- Tcl_DStringFree(&dString);
- return (HDDEDATA) TRUE;
-
- case XTYP_DISCONNECT:
-
- /*
- * The client has disconnected from our server. Forget this
- * conversation.
- */
-
- for (convPtr = tsdPtr->currentConversations, prevConvPtr = NULL;
- convPtr != NULL;
- prevConvPtr = convPtr, convPtr = convPtr->nextPtr) {
- if (hConv == convPtr->hConv) {
- if (prevConvPtr == NULL) {
- tsdPtr->currentConversations = convPtr->nextPtr;
- } else {
- prevConvPtr->nextPtr = convPtr->nextPtr;
- }
- if (convPtr->returnPackagePtr != NULL) {
- Tcl_DecrRefCount(convPtr->returnPackagePtr);
- }
- ckfree((char *) convPtr);
- break;
- }
- }
- return (HDDEDATA) TRUE;
-
- case XTYP_REQUEST:
-
- /*
- * This could be either a request for a value of a Tcl variable,
- * or it could be the send command requesting the results of the
- * last execute.
- */
-
- if (uFmt != CF_TEXT) {
- return (HDDEDATA) FALSE;
- }
-
- ddeReturn = (HDDEDATA) FALSE;
- for (convPtr = tsdPtr->currentConversations; (convPtr != NULL)
- && (convPtr->hConv != hConv); convPtr = convPtr->nextPtr) {
- /*
- * Empty loop body.
- */
- }
-
- if (convPtr != NULL) {
- char *returnString;
-
- len = DdeQueryString(ddeInstance, ddeItem, NULL, 0,
- CP_WINANSI);
- Tcl_DStringInit(&dString);
- Tcl_DStringSetLength(&dString, len);
- utilString = Tcl_DStringValue(&dString);
- DdeQueryString(ddeInstance, ddeItem, utilString,
- len + 1, CP_WINANSI);
- if (stricmp(utilString, "$TK$EXECUTE$RESULT") == 0) {
- returnString =
- Tcl_GetStringFromObj(convPtr->returnPackagePtr, &len);
- ddeReturn = DdeCreateDataHandle(ddeInstance,
- returnString, len+1, 0, ddeItem, CF_TEXT,
- 0);
- } else {
- Tcl_Obj *variableObjPtr = Tcl_GetVar2Ex(
- convPtr->riPtr->interp, utilString, NULL,
- TCL_GLOBAL_ONLY);
- if (variableObjPtr != NULL) {
- returnString = Tcl_GetStringFromObj(variableObjPtr,
- &len);
- ddeReturn = DdeCreateDataHandle(ddeInstance,
- returnString, len+1, 0, ddeItem, CF_TEXT, 0);
- } else {
- ddeReturn = NULL;
- }
- }
- Tcl_DStringFree(&dString);
- }
- return ddeReturn;
-
- case XTYP_EXECUTE: {
-
- /*
- * Execute this script. The results will be saved into
- * a list object which will be retreived later. See
- * ExecuteRemoteObject.
- */
-
- Tcl_Obj *returnPackagePtr;
-
- for (convPtr = tsdPtr->currentConversations; (convPtr != NULL)
- && (convPtr->hConv != hConv); convPtr = convPtr->nextPtr) {
- /*
- * Empty loop body.
- */
-
- }
-
- if (convPtr == NULL) {
- return (HDDEDATA) DDE_FNOTPROCESSED;
- }
-
- utilString = (char *) DdeAccessData(hData, &len);
- ddeObjectPtr = Tcl_NewStringObj(utilString, -1);
- Tcl_IncrRefCount(ddeObjectPtr);
- DdeUnaccessData(hData);
- if (convPtr->returnPackagePtr != NULL) {
- Tcl_DecrRefCount(convPtr->returnPackagePtr);
- }
- convPtr->returnPackagePtr = NULL;
- returnPackagePtr =
- ExecuteRemoteObject(convPtr->riPtr, ddeObjectPtr);
- for (convPtr = tsdPtr->currentConversations; (convPtr != NULL)
- && (convPtr->hConv != hConv); convPtr = convPtr->nextPtr) {
- /*
- * Empty loop body.
- */
-
- }
- if (convPtr != NULL) {
- Tcl_IncrRefCount(returnPackagePtr);
- convPtr->returnPackagePtr = returnPackagePtr;
- }
- Tcl_DecrRefCount(ddeObjectPtr);
- if (returnPackagePtr == NULL) {
- return (HDDEDATA) DDE_FNOTPROCESSED;
- } else {
- return (HDDEDATA) DDE_FACK;
- }
- }
-
- case XTYP_WILDCONNECT: {
-
- /*
- * Dde wants a list of services and topics that we support.
- */
-
- HSZPAIR *returnPtr;
- int i;
- int numItems;
-
- for (i = 0, riPtr = tsdPtr->interpListPtr; riPtr != NULL;
- i++, riPtr = riPtr->nextPtr) {
- /*
- * Empty loop body.
- */
-
- }
-
- numItems = i;
- ddeReturn = DdeCreateDataHandle(ddeInstance, NULL,
- (numItems + 1) * sizeof(HSZPAIR), 0, 0, 0, 0);
- returnPtr = (HSZPAIR *) DdeAccessData(ddeReturn, &len);
- for (i = 0, riPtr = tsdPtr->interpListPtr; i < numItems;
- i++, riPtr = riPtr->nextPtr) {
- returnPtr[i].hszSvc = DdeCreateStringHandle(
- ddeInstance, "Tk", CP_WINANSI);
- returnPtr[i].hszTopic = DdeCreateStringHandle(
- ddeInstance, riPtr->name, CP_WINANSI);
- }
- returnPtr[i].hszSvc = NULL;
- returnPtr[i].hszTopic = NULL;
- DdeUnaccessData(ddeReturn);
- return ddeReturn;
- }
-
- }
- return NULL;
-}
-
-
-/*
- *--------------------------------------------------------------
- *
- * RemoveDdeServerExitProc --
- *
- * Gets rid of our DDE server when we go away.
- *
- * Results:
- * None.
- *
- * Side effects:
- * The DDE server is deleted.
- *
- *--------------------------------------------------------------
- */
-
-static void
-RemoveDdeServerExitProc(
- ClientData clientData) /* Not used in this handler. */
-{
- ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
- Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
-
- DdeNameService(ddeInstance, NULL, 0, DNS_UNREGISTER);
- DdeUninitialize(ddeInstance);
- ddeInstance = 0;
-}
-
-/*
- *--------------------------------------------------------------
- *
- * MakeDdeConnection --
- *
- * This procedure is a utility used to connect to a DDE
- * server when given a server name and a topic name.
- *
- * Results:
- * A standard Tcl result.
- *
- *
- * Side effects:
- * Passes back a conversation through ddeConvPtr
- *
- *--------------------------------------------------------------
- */
-
-static int
-MakeDdeConnection(
- Tcl_Interp *interp, /* Used to report errors. */
- char *name, /* The connection to use. */
- HCONV *ddeConvPtr)
-{
- HSZ ddeTopic, ddeService;
- HCONV ddeConv;
- ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
- Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
-
- ddeService = DdeCreateStringHandle(ddeInstance, "Tk", 0);
- ddeTopic = DdeCreateStringHandle(ddeInstance, name, 0);
-
- ddeConv = DdeConnect(ddeInstance, ddeService, ddeTopic, NULL);
- DdeFreeStringHandle(ddeInstance, ddeService);
- DdeFreeStringHandle(ddeInstance, ddeTopic);
-
- if (ddeConv == (HCONV) NULL) {
- if (interp != NULL) {
- Tcl_AppendResult(interp, "no registered server named \"",
- name, "\"", (char *) NULL);
- }
- return TCL_ERROR;
- }
-
- *ddeConvPtr = ddeConv;
- return TCL_OK;
-}
-
-/*
- *--------------------------------------------------------------
- *
- * SetDdeError --
- *
- * Sets the interp result to a cogent error message
- * describing the last DDE error.
- *
- * Results:
- * None.
- *
- *
- * Side effects:
- * The interp's result object is changed.
- *
- *--------------------------------------------------------------
- */
-
-static void
-SetDdeError(
- Tcl_Interp *interp) /* The interp to put the message in.*/
-{
- Tcl_Obj *resultPtr = Tcl_GetObjResult(interp);
- int err;
- ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
- Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
-
- err = DdeGetLastError(ddeInstance);
- switch (err) {
- case DMLERR_DATAACKTIMEOUT:
- case DMLERR_EXECACKTIMEOUT:
- case DMLERR_POKEACKTIMEOUT:
- Tcl_SetStringObj(resultPtr,
- "remote interpreter did not respond", -1);
- break;
-
- case DMLERR_BUSY:
- Tcl_SetStringObj(resultPtr, "remote server is busy", -1);
- break;
-
- case DMLERR_NOTPROCESSED:
- Tcl_SetStringObj(resultPtr,
- "remote server cannot handle this command", -1);
- break;
-
- default:
- Tcl_SetStringObj(resultPtr, "dde command failed", -1);
- }
-}
-
-/*
- *--------------------------------------------------------------
- *
- * Tk_DdeObjCmd --
- *
- * This procedure is invoked to process the "dde" Tcl command.
- * See the user documentation for details on what it does.
- *
- * Results:
- * A standard Tcl result.
- *
- * Side effects:
- * See the user documentation.
- *
- *--------------------------------------------------------------
- */
-
-int
-Tk_DdeObjCmd(
- ClientData clientData, /* Used only for deletion */
- Tcl_Interp *interp, /* The interp we are sending from */
- int objc, /* Number of arguments */
- Tcl_Obj *CONST objv[]) /* The arguments */
-{
- enum {
- DDE_EXECUTE,
- DDE_REQUEST,
- DDE_SERVICES
- };
-
- static char *ddeCommands[] = {"execute", "request", "services",
- (char *) NULL};
- static char *ddeOptions[] = {"-async", (char *) NULL};
- int index, argIndex;
- int async = 0;
- int result = TCL_OK;
- HSZ ddeService = NULL;
- HSZ ddeTopic = NULL;
- HSZ ddeItem = NULL;
- HDDEDATA ddeData = NULL;
- HCONV hConv;
- char *serviceName, *topicName, *itemString, *dataString;
- int firstArg, length, dataLength;
- DWORD ddeResult;
- HDDEDATA ddeReturn;
- ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
- Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
-
- if (objc < 2) {
- Tcl_WrongNumArgs(interp, 1, objv,
- "?-async? serviceName topicName value");
- return TCL_ERROR;
- }
-
- if (Tcl_GetIndexFromObj(interp, objv[1], ddeCommands, "command", 0,
- &index) != TCL_OK) {
- return TCL_ERROR;
- }
-
- switch (index) {
- case DDE_EXECUTE:
- if ((objc < 5) || (objc > 6)) {
- Tcl_WrongNumArgs(interp, 1, objv,
- "execute ?-async? serviceName topicName value");
- return TCL_ERROR;
- }
- if (Tcl_GetIndexFromObj(NULL, objv[2], ddeOptions, "option", 0,
- &argIndex) != TCL_OK) {
- if (objc != 5) {
- Tcl_WrongNumArgs(interp, 1, objv,
- "execute ?-async? serviceName topicName value");
- return TCL_ERROR;
- }
- async = 0;
- firstArg = 2;
- } else {
- if (objc != 6) {
- Tcl_WrongNumArgs(interp, 1, objv,
- "execute ?-async? serviceName topicName value");
- return TCL_ERROR;
- }
- async = 1;
- firstArg = 3;
- }
- break;
- case DDE_REQUEST:
- if (objc != 5) {
- Tcl_WrongNumArgs(interp, 1, objv,
- "request serviceName topicName value");
- return TCL_ERROR;
- }
- firstArg = 2;
- break;
- case DDE_SERVICES:
- if (objc != 4) {
- Tcl_WrongNumArgs(interp, 1, objv,
- "services serviceName topicName");
- return TCL_ERROR;
- }
- firstArg = 2;
- break;
- }
-
- serviceName = Tcl_GetStringFromObj(objv[firstArg], &length);
- if (length == 0) {
- serviceName = NULL;
- } else {
- ddeService = DdeCreateStringHandle(ddeInstance, serviceName,
- CP_WINANSI);
- }
- topicName = Tcl_GetStringFromObj(objv[firstArg + 1], &length);
- if (length == 0) {
- topicName = NULL;
- } else {
- ddeTopic = DdeCreateStringHandle(ddeInstance,
- topicName, CP_WINANSI);
- }
-
- switch (index) {
- case DDE_EXECUTE: {
- dataString = Tcl_GetStringFromObj(objv[firstArg + 2], &dataLength);
- if (dataLength == 0) {
- Tcl_SetStringObj(Tcl_GetObjResult(interp),
- "cannot execute null data", -1);
- result = TCL_ERROR;
- break;
- }
- hConv = DdeConnect(ddeInstance, ddeService, ddeTopic,
- NULL);
-
- if (hConv == NULL) {
- SetDdeError(interp);
- result = TCL_ERROR;
- break;
- }
-
- ddeData = DdeCreateDataHandle(ddeInstance, dataString,
- dataLength+1, 0, 0, CF_TEXT, 0);
- if (ddeData != NULL) {
- if (async) {
- DdeClientTransaction((LPBYTE) ddeData, 0xFFFFFFFF, hConv, 0,
- CF_TEXT, XTYP_EXECUTE, TIMEOUT_ASYNC, &ddeResult);
- DdeAbandonTransaction(ddeInstance, hConv,
- ddeResult);
- } else {
- ddeReturn = DdeClientTransaction((LPBYTE) ddeData, 0xFFFFFFFF,
- hConv, 0, CF_TEXT, XTYP_EXECUTE, 7200000, NULL);
- if (ddeReturn == 0) {
- SetDdeError(interp);
- result = TCL_ERROR;
- }
- }
- DdeFreeDataHandle(ddeData);
- } else {
- SetDdeError(interp);
- result = TCL_ERROR;
- }
- DdeDisconnect(hConv);
- break;
- }
- case DDE_REQUEST: {
- itemString = Tcl_GetStringFromObj(objv[firstArg + 2], &length);
- if (length == 0) {
- Tcl_SetStringObj(Tcl_GetObjResult(interp),
- "cannot request value of null data", -1);
- return TCL_ERROR;
- }
- hConv = DdeConnect(ddeInstance, ddeService, ddeTopic,
- NULL);
-
- if (hConv == NULL) {
- SetDdeError(interp);
- result = TCL_ERROR;
- } else {
- Tcl_Obj *returnObjPtr;
- ddeItem = DdeCreateStringHandle(ddeInstance,
- itemString, CP_WINANSI);
- if (ddeItem != NULL) {
- ddeData = DdeClientTransaction(NULL, 0, hConv, ddeItem,
- CF_TEXT, XTYP_REQUEST, 5000, NULL);
- if (ddeData == NULL) {
- SetDdeError(interp);
- result = TCL_ERROR;
- } else {
- dataString = DdeAccessData(ddeData, &dataLength);
- returnObjPtr = Tcl_NewStringObj(dataString, -1);
- DdeUnaccessData(ddeData);
- DdeFreeDataHandle(ddeData);
- Tcl_SetObjResult(interp, returnObjPtr);
- }
- } else {
- SetDdeError(interp);
- result = TCL_ERROR;
- }
- DdeDisconnect(hConv);
- }
-
- break;
- }
- case DDE_SERVICES: {
- HCONVLIST hConvList;
- CONVINFO convInfo;
- Tcl_Obj *convListObjPtr, *elementObjPtr;
- Tcl_DString dString;
- char *name;
-
- convInfo.cb = sizeof(CONVINFO);
- hConvList = DdeConnectList(ddeInstance, ddeService,
- ddeTopic, 0, NULL);
- hConv = 0;
- convListObjPtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL);
- Tcl_DStringInit(&dString);
-
- while (hConv = DdeQueryNextServer(hConvList, hConv), hConv != 0) {
- elementObjPtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL);
- DdeQueryConvInfo(hConv, QID_SYNC, &convInfo);
- length = DdeQueryString(ddeInstance,
- convInfo.hszSvcPartner, NULL, 0, CP_WINANSI);
- Tcl_DStringSetLength(&dString, length);
- name = Tcl_DStringValue(&dString);
- DdeQueryString(ddeInstance, convInfo.hszSvcPartner,
- name, length + 1, CP_WINANSI);
- Tcl_ListObjAppendElement(interp, elementObjPtr,
- Tcl_NewStringObj(name, length));
- length = DdeQueryString(ddeInstance, convInfo.hszTopic,
- NULL, 0, CP_WINANSI);
- Tcl_DStringSetLength(&dString, length);
- name = Tcl_DStringValue(&dString);
- DdeQueryString(ddeInstance, convInfo.hszTopic, name,
- length + 1, CP_WINANSI);
- Tcl_ListObjAppendElement(interp, elementObjPtr,
- Tcl_NewStringObj(name, length));
- Tcl_ListObjAppendElement(interp, convListObjPtr, elementObjPtr);
- }
- DdeDisconnectList(hConvList);
- Tcl_SetObjResult(interp, convListObjPtr);
- Tcl_DStringFree(&dString);
- break;
- }
- }
- if (ddeService != NULL) {
- DdeFreeStringHandle(ddeInstance, ddeService);
- }
- if (ddeTopic != NULL) {
- DdeFreeStringHandle(ddeInstance, ddeTopic);
- }
-
- return result;
-}