From 1c06a203ecbe741c83687742b659ab73514a0b00 Mon Sep 17 00:00:00 2001 From: hobbs Date: Wed, 12 Apr 2000 18:51:11 +0000 Subject: * test/winClipboard.test: * win/tkWinInt.h: * win/tkWinClipboard.c (UpdateClipboard): * win/tkWinX.c (GenerateXEvent): added updatingClipboard tsd and TkWinUpdatingClipboard accessor function to allow us to flag ourselves when we are the ones updating the clipboard. This corrected inability to create our own clipboard types within a Tk application. [Bug: 2338 4318] * win/tkWinTest.c (TestclipboardCmd): improved TestclipboardCmd with better error handling and obj'ification --- tests/winClipboard.test | 20 ++++++++++++++++++-- win/Makefile.in | 7 ++++--- win/tkWinClipboard.c | 5 ++++- win/tkWinInt.h | 19 +++++++++++++------ win/tkWinTest.c | 34 ++++++++++++++++++++++++++-------- win/tkWinX.c | 45 ++++++++++++++++++++++++++++++++++++++++----- 6 files changed, 105 insertions(+), 25 deletions(-) diff --git a/tests/winClipboard.test b/tests/winClipboard.test index e693c6a..fca13eb 100644 --- a/tests/winClipboard.test +++ b/tests/winClipboard.test @@ -7,10 +7,10 @@ # generates output for errors. No output means no errors were found. # # Copyright (c) 1997 by Sun Microsystems, Inc. -# Copyright (c) 1998-1999 by Scriptics Corporation. +# Copyright (c) 1998-2000 by Scriptics Corporation. # All rights reserved. # -# RCS: @(#) $Id: winClipboard.test,v 1.6 1999/12/14 06:53:15 hobbs Exp $ +# RCS: @(#) $Id: winClipboard.test,v 1.7 2000/04/12 18:52:14 hobbs Exp $ if {[lsearch [namespace children] ::tcltest] == -1} { source [file join [pwd] [file dirname [info script]] defs.tcl] @@ -38,6 +38,7 @@ test winClipboard-1.2 {TkSelGetSelection} {pcOnly} { test winClipboard-1.3 {TkSelGetSelection & TkWinClipboardRender} {pcOnly} { clipboard clear clipboard append abcd + update list [selection get -selection CLIPBOARD] [testclipboard] } {abcd abcd} test winClipboard-1.4 {TkSelGetSelection & TkWinClipboardRender} {pcOnly} { @@ -51,6 +52,21 @@ test winClipboard-1.5 {TkSelGetSelection & TkWinClipboardRender} {pcOnly} { list [selection get -selection CLIPBOARD] [testclipboard] } [list "line 1\u00c7\nline 2" [bytestring "line 1\u00c7\r\nline 2"]] +test winClipboard-2.1 {TkSelUpdateClipboard reentrancy problem} {pcOnly} { + clipboard clear + clipboard append -type OUR_ACTION "action data" + clipboard append "string data" + update + list [selection get -selection CLIPBOARD -type OUR_ACTION] [testclipboard] +} [list "action data" "string data"] +test winClipboard-2.2 {TkSelUpdateClipboard reentrancy problem} {pcOnly} { + clipboard clear + clipboard append -type OUR_ACTION "new data" + clipboard append "more data in string" + update + list [testclipboard] [selection get -selection CLIPBOARD -type OUR_ACTION] +} [list "more data in string" "new data"] + # cleanup ::tcltest::cleanupTests return diff --git a/win/Makefile.in b/win/Makefile.in index 1af4b34..3b91f52 100644 --- a/win/Makefile.in +++ b/win/Makefile.in @@ -4,7 +4,7 @@ # "autoconf" program (constructs like "@foo@" will get replaced in the # actual Makefile. # -# RCS: @(#) $Id: Makefile.in,v 1.19 2000/04/08 06:59:09 hobbs Exp $ +# RCS: @(#) $Id: Makefile.in,v 1.20 2000/04/12 18:51:11 hobbs Exp $ TCLVERSION = @TCL_VERSION@ VERSION = @TK_VERSION@ @@ -132,9 +132,10 @@ DEPARG = "$(shell cygpath $(PATHTYPE) $<)" # Setting the VPATH variable to a list of paths will cause the # makefile to look into these paths when resolving .c to .obj -# dependencies. +# dependencies. Note the ':' to avoid autoconf's habit of deleting +# all VPATH lines without an explicit ':' in it. -VPATH = $(GENERIC_DIR);$(WIN_DIR);$(UNIX_DIR);$(XLIB_DIR);$(RC_DIR) +VPATH = $(GENERIC_DIR);$(WIN_DIR);$(UNIX_DIR);$(XLIB_DIR);$(RC_DIR) # : # warning flags CFLAGS_WARNING = @CFLAGS_WARNING@ diff --git a/win/tkWinClipboard.c b/win/tkWinClipboard.c index c5a6cd8..b08147a 100644 --- a/win/tkWinClipboard.c +++ b/win/tkWinClipboard.c @@ -4,11 +4,12 @@ * This file contains functions for managing the clipboard. * * Copyright (c) 1995-1997 Sun Microsystems, Inc. + * Copyright (c) 1998-2000 by Scriptics Corporation. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkWinClipboard.c,v 1.6 1999/09/21 06:43:06 hobbs Exp $ + * RCS: @(#) $Id: tkWinClipboard.c,v 1.7 2000/04/12 18:51:11 hobbs Exp $ */ #include "tkWinInt.h" @@ -380,6 +381,7 @@ static void UpdateClipboard(hwnd) HWND hwnd; { + TkWinUpdatingClipboard(TRUE); OpenClipboard(hwnd); EmptyClipboard(); @@ -394,6 +396,7 @@ UpdateClipboard(hwnd) SetClipboardData(CF_TEXT, NULL); } CloseClipboard(); + TkWinUpdatingClipboard(FALSE); } /* diff --git a/win/tkWinInt.h b/win/tkWinInt.h index 339b164..710779a 100644 --- a/win/tkWinInt.h +++ b/win/tkWinInt.h @@ -6,11 +6,12 @@ * Tk. * * Copyright (c) 1995-1997 Sun Microsystems, Inc. + * Copyright (c) 1998-2000 by Scriptics Corporation. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkWinInt.h,v 1.9 2000/03/31 09:24:27 hobbs Exp $ + * RCS: @(#) $Id: tkWinInt.h,v 1.10 2000/04/12 18:51:11 hobbs Exp $ */ #ifndef _TKWININT @@ -90,11 +91,11 @@ typedef union { * The following macros are used to retrieve internal values from a Drawable. */ -#define TkWinGetHWND(w) (((TkWinDrawable *) w)->window.handle) -#define TkWinGetWinPtr(w) (((TkWinDrawable*)w)->window.winPtr) -#define TkWinGetHBITMAP(w) (((TkWinDrawable*)w)->bitmap.handle) -#define TkWinGetColormap(w) (((TkWinDrawable*)w)->bitmap.colormap) -#define TkWinGetHDC(w) (((TkWinDrawable *) w)->winDC.hdc) +#define TkWinGetHWND(w) (((TkWinDrawable *) w)->window.handle) +#define TkWinGetWinPtr(w) (((TkWinDrawable *) w)->window.winPtr) +#define TkWinGetHBITMAP(w) (((TkWinDrawable *) w)->bitmap.handle) +#define TkWinGetColormap(w) (((TkWinDrawable *) w)->bitmap.colormap) +#define TkWinGetHDC(w) (((TkWinDrawable *) w)->winDC.hdc) /* * The following structure is used to encapsulate palette information. @@ -157,6 +158,12 @@ extern int tkpWinRopModes[]; EXTERN LRESULT CALLBACK TkWinChildProc _ANSI_ARGS_((HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)); +/* + * Special proc needed as tsd accessor function between + * tkWinX.c:GenerateXEvent and tkWinClipboard.c:UpdateClipboard + */ +EXTERN void TkWinUpdatingClipboard(int mode); + #undef TCL_STORAGE_CLASS #define TCL_STORAGE_CLASS DLLIMPORT diff --git a/win/tkWinTest.c b/win/tkWinTest.c index 00553eb..6f7ee7e 100644 --- a/win/tkWinTest.c +++ b/win/tkWinTest.c @@ -5,11 +5,12 @@ * the Windows platform. * * Copyright (c) 1997 Sun Microsystems, Inc. + * Copyright (c) 2000 by Scriptics Corporation. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkWinTest.c,v 1.2 1999/04/16 01:51:53 stanton Exp $ + * RCS: @(#) $Id: tkWinTest.c,v 1.3 2000/04/12 18:51:11 hobbs Exp $ */ #include "tkWinInt.h" @@ -21,8 +22,9 @@ HWND tkWinCurrentDialog; */ int TkplatformtestInit(Tcl_Interp *interp); -static int TestclipboardCmd(ClientData clientData, - Tcl_Interp *interp, int argc, char **argv); +static int TestclipboardObjCmd(ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[]); static int TestwineventCmd(ClientData clientData, Tcl_Interp *interp, int argc, char **argv); @@ -52,7 +54,7 @@ TkplatformtestInit( * Add commands for platform specific tests on MacOS here. */ - Tcl_CreateCommand(interp, "testclipboard", TestclipboardCmd, + Tcl_CreateObjCommand(interp, "testclipboard", TestclipboardObjCmd, (ClientData) Tk_MainWindow(interp), (Tcl_CmdDeleteProc *) NULL); Tcl_CreateCommand(interp, "testwinevent", TestwineventCmd, (ClientData) Tk_MainWindow(interp), (Tcl_CmdDeleteProc *) NULL); @@ -63,7 +65,7 @@ TkplatformtestInit( /* *---------------------------------------------------------------------- * - * TestclipboardCmd -- + * TestclipboardObjCmd -- * * This procedure implements the testclipboard command. It provides * a way to determine the actual contents of the Windows clipboard. @@ -78,24 +80,40 @@ TkplatformtestInit( */ static int -TestclipboardCmd(clientData, interp, argc, argv) +TestclipboardObjCmd(clientData, interp, objc, objv) ClientData clientData; /* Main window for application. */ Tcl_Interp *interp; /* Current interpreter. */ - int argc; /* Number of arguments. */ - char **argv; /* Argument strings. */ + int objc; /* Number of arguments. */ + Tcl_Obj *CONST objv[]; /* Argument values. */ { TkWindow *winPtr = (TkWindow *) clientData; HGLOBAL handle; char *data; + if (objc != 1) { + Tcl_WrongNumArgs(interp, 1, objv, (char *) NULL); + return TCL_ERROR; + } if (OpenClipboard(NULL)) { + /* + * We could consider using CF_UNICODETEXT on NT, but then we + * would have to convert it from External. Instead we'll just + * take this and do "bytestring" at the Tcl level for Unicode + * inclusive text + */ handle = GetClipboardData(CF_TEXT); if (handle != NULL) { data = GlobalLock(handle); Tcl_AppendResult(interp, data, (char *) NULL); GlobalUnlock(handle); + } else { + Tcl_AppendResult(interp, "null clipboard handle", (char *) NULL); + return TCL_ERROR; } CloseClipboard(); + } else { + Tcl_AppendResult(interp, "couldn't open clipboard", (char *) NULL); + return TCL_ERROR; } return TCL_OK; } diff --git a/win/tkWinX.c b/win/tkWinX.c index d537a7f..0ccf07a 100644 --- a/win/tkWinX.c +++ b/win/tkWinX.c @@ -5,12 +5,12 @@ * * Copyright (c) 1995-1996 Sun Microsystems, Inc. * Copyright (c) 1994 Software Research Associates, Inc. - * Copyright (c) 1998 by Scriptics Corporation. + * Copyright (c) 1998-2000 by Scriptics Corporation. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkWinX.c,v 1.8 2000/03/31 09:24:27 hobbs Exp $ + * RCS: @(#) $Id: tkWinX.c,v 1.9 2000/04/12 18:51:11 hobbs Exp $ */ #include "tkWinInt.h" @@ -41,6 +41,7 @@ TCL_DECLARE_MUTEX(winXMutex) typedef struct ThreadSpecificData { TkDisplay *winDisplay; /* TkDisplay structure that * * represents Windows screen. */ + int updatingClipboard; /* If 1, we are updating the clipboard */ } ThreadSpecificData; static Tcl_ThreadDataKey dataKey; @@ -397,13 +398,14 @@ TkpOpenDisplay(display_name) screen->white_pixel = RGB(255, 255, 255); screen->black_pixel = RGB(0, 0, 0); - display->screens = screen; - display->nscreens = 1; - display->default_screen = 0; + display->screens = screen; + display->nscreens = 1; + display->default_screen = 0; screen->cmap = XCreateColormap(display, None, screen->root_visual, AllocNone); tsdPtr->winDisplay = (TkDisplay *) ckalloc(sizeof(TkDisplay)); tsdPtr->winDisplay->display = display; + tsdPtr->updatingClipboard = FALSE; return tsdPtr->winDisplay; } @@ -682,6 +684,8 @@ GenerateXEvent(hwnd, message, wParam, lParam) { XEvent event; TkWindow *winPtr = (TkWindow *)Tk_HWNDToWindow(hwnd); + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); if (!winPtr || winPtr->window == None) { return; @@ -746,6 +750,13 @@ GenerateXEvent(hwnd, message, wParam, lParam) } case WM_DESTROYCLIPBOARD: + if (tsdPtr->updatingClipboard == TRUE) { + /* + * We want to avoid this event if we are the ones that caused + * this event. + */ + return; + } event.type = SelectionClear; event.xselectionclear.selection = Tk_InternAtom((Tk_Window)winPtr, "CLIPBOARD"); @@ -1149,3 +1160,27 @@ TkpGetMS() { return GetTickCount(); } + +/* + *---------------------------------------------------------------------- + * + * TkWinUpdatingClipboard -- + * + * + * Results: + * Number of milliseconds. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +TkWinUpdatingClipboard(int mode) +{ + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + + tsdPtr->updatingClipboard = mode; +} -- cgit v0.12