diff options
author | redman <redman> | 1999-04-01 21:58:48 (GMT) |
---|---|---|
committer | redman <redman> | 1999-04-01 21:58:48 (GMT) |
commit | 5f1a88adc8d3daa1d9bcc15196c12b056e8aae7b (patch) | |
tree | 40d4f02cecc0c57f7407bd4a0844b860a62f8712 | |
parent | 91bd30b4de4717f3c9dd8a9958a3a8d2e304955e (diff) | |
download | tk-5f1a88adc8d3daa1d9bcc15196c12b056e8aae7b.zip tk-5f1a88adc8d3daa1d9bcc15196c12b056e8aae7b.tar.gz tk-5f1a88adc8d3daa1d9bcc15196c12b056e8aae7b.tar.bz2 |
Remove the DDE code.
Modified stubs based on Jan's patch.
-rw-r--r-- | ChangeLog | 22 | ||||
-rw-r--r-- | generic/tk.decls | 9 | ||||
-rw-r--r-- | generic/tk.h | 11 | ||||
-rw-r--r-- | generic/tkPlatDecls.h | 11 | ||||
-rw-r--r-- | generic/tkStubInit.c | 13 | ||||
-rw-r--r-- | generic/tkWindow.c | 13 | ||||
-rw-r--r-- | tests/winSend.test | 8 | ||||
-rw-r--r-- | unix/Makefile.in | 8 | ||||
-rw-r--r-- | win/makefile.vc | 3 | ||||
-rw-r--r-- | win/tkWinSend.c | 1240 |
10 files changed, 65 insertions, 1273 deletions
@@ -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; -} |