From a912f987cc4a42b842e46d5ba8953533bd39c115 Mon Sep 17 00:00:00 2001 From: stanton Date: Sat, 22 May 1999 01:59:21 +0000 Subject: Merged changes from scriptics-tclpro-1-3-b2 branch --- ChangeLog | 17 ++++ generic/tk.h | 18 +++- library/console.tcl | 5 +- tests/winClipboard.test | 7 +- win/tkWinClipboard.c | 240 ++++++++++++++++++++++++++++++++++++++---------- 5 files changed, 236 insertions(+), 51 deletions(-) diff --git a/ChangeLog b/ChangeLog index f874388..257d937 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,20 @@ +1999-05-20 + + * library/console.tcl: Changed copyright string to read 1999 + Scriptics Corp. in wish console about box. + +1999-05-19 + + * generic/tk.h: Add extern "C" block around entire header file for + C++ compilers to fix linkage issues. Submitted by Don Porter and + Paul Duffin. + +1999-05-18 + + * tests/winClipboard.test: + * win/tkWinClipboard.c: Fixed clipboard code so it handles Unicode + data properly on Windows NT and 95. [Bug: 1791] + 1999-05-07 * library/menu.tcl: Fixed bug where tk_popup fails when called too diff --git a/generic/tk.h b/generic/tk.h index c5ea528..45ef472 100644 --- a/generic/tk.h +++ b/generic/tk.h @@ -12,13 +12,21 @@ * 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.24 1999/04/30 23:40:44 stanton Exp $ + * RCS: @(#) $Id: tk.h,v 1.25 1999/05/22 01:59:21 stanton Exp $ */ #ifndef _TK #define _TK /* + * For C++ compilers, use extern "C" + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* * When version numbers change here, you must also go into the following files * and update the version numbers: * @@ -1210,4 +1218,12 @@ typedef int (Tk_SelectionProc) _ANSI_ARGS_((ClientData clientData, #undef TCL_STORAGE_CLASS #define TCL_STORAGE_CLASS DLLIMPORT +/* + * end block for C++ + */ + +#ifdef __cplusplus +} +#endif + #endif /* _TK */ diff --git a/library/console.tcl b/library/console.tcl index 602f32d..0ea7716 100644 --- a/library/console.tcl +++ b/library/console.tcl @@ -4,8 +4,9 @@ # can be used by non-unix systems that do not have built-in support # for shells. # -# RCS: @(#) $Id: console.tcl,v 1.4 1999/04/16 01:51:26 stanton Exp $ +# RCS: @(#) $Id: console.tcl,v 1.5 1999/05/22 01:59:21 stanton Exp $ # +# Copyright (c) 1998-1999 Scriptics Corp. # Copyright (c) 1995-1997 Sun Microsystems, Inc. # # See the file "license.terms" for information on usage and redistribution @@ -470,7 +471,7 @@ proc tkConsoleExit {} { proc tkConsoleAbout {} { global tk_patchLevel tk_messageBox -type ok -message "Tcl for Windows -Copyright \251 1996 Sun Microsystems, Inc. +Copyright \251 1999 Scriptics Corporation Tcl [info patchlevel] Tk $tk_patchLevel" diff --git a/tests/winClipboard.test b/tests/winClipboard.test index 446dbd1..492ced9 100644 --- a/tests/winClipboard.test +++ b/tests/winClipboard.test @@ -10,7 +10,7 @@ # Copyright (c) 1998-1999 by Scriptics Corporation. # All rights reserved. # -# RCS: @(#) $Id: winClipboard.test,v 1.4 1999/04/16 01:51:43 stanton Exp $ +# RCS: @(#) $Id: winClipboard.test,v 1.5 1999/05/22 01:59:22 stanton Exp $ if {[lsearch [namespace children] ::tcltest] == -1} { source [file join [pwd] [file dirname [info script]] defs.tcl] @@ -39,6 +39,11 @@ test winClipboard-1.4 {TkSelGetSelection & TkWinClipboardRender} {pcOnly} { clipboard append "line 1\nline 2" list [selection get -selection CLIPBOARD] [testclipboard] } [list "line 1\nline 2" "line 1\r\nline 2"] +test winClipboard-1.5 {TkSelGetSelection & TkWinClipboardRender} {pcOnly} { + clipboard clear + clipboard append "line 1\u00c7\nline 2" + list [selection get -selection CLIPBOARD] [testclipboard] +} [list "line 1\u00c7\nline 2" [bytestring "line 1\u00c7\r\nline 2"]] # cleanup ::tcltest::cleanupTests diff --git a/win/tkWinClipboard.c b/win/tkWinClipboard.c index de0b40c..cb7d1a8 100644 --- a/win/tkWinClipboard.c +++ b/win/tkWinClipboard.c @@ -8,12 +8,13 @@ * 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.3 1999/04/16 01:51:49 stanton Exp $ + * RCS: @(#) $Id: tkWinClipboard.c,v 1.4 1999/05/22 01:59:22 stanton Exp $ */ #include "tkWinInt.h" #include "tkSelect.h" +static void UpdateClipboard _ANSI_ARGS_((HWND hwnd)); /* *---------------------------------------------------------------------- @@ -49,43 +50,123 @@ TkSelGetSelection(interp, tkwin, selection, target, proc, clientData) * selection, once it has been retrieved. */ ClientData clientData; /* Arbitrary value to pass to proc. */ { - char *data, *buffer, *destPtr; + char *data, *destPtr; Tcl_DString ds; HGLOBAL handle; - int result, length; - - if ((selection == Tk_InternAtom(tkwin, "CLIPBOARD")) - && (target == XA_STRING)) { - if (OpenClipboard(NULL)) { - handle = GetClipboardData(CF_TEXT); - if (handle != NULL) { - data = GlobalLock(handle); - length = strlen(data); - buffer = ckalloc(length+1); - destPtr = buffer; - while (*data != '\0') { - if (*data != '\r') { - *destPtr = *data; - destPtr++; - } - data++; - } - *destPtr = '\0'; - GlobalUnlock(handle); - CloseClipboard(); - Tcl_ExternalToUtfDString(NULL, buffer, -1, &ds); - ckfree(buffer); - result = (*proc)(clientData, interp, Tcl_DStringValue(&ds)); - Tcl_DStringFree(&ds); - return result; - } + Tcl_Encoding encoding; + int result, locale; + + if ((selection != Tk_InternAtom(tkwin, "CLIPBOARD")) + || (target != XA_STRING) + || !OpenClipboard(NULL)) { + goto error; + } + + /* + * Attempt to get the data in Unicode form if available as this is + * less work that CF_TEXT. + */ + + result = TCL_ERROR; + if (IsClipboardFormatAvailable(CF_UNICODETEXT)) { + handle = GetClipboardData(CF_UNICODETEXT); + if (!handle) { CloseClipboard(); + goto error; + } + data = GlobalLock(handle); + Tcl_DStringInit(&ds); + Tcl_UniCharToUtfDString((Tcl_UniChar *)data, + Tcl_UniCharLen((Tcl_UniChar *)data), &ds); + GlobalUnlock(handle); + } else if (IsClipboardFormatAvailable(CF_TEXT) + && IsClipboardFormatAvailable(CF_LOCALE)) { + /* + * Determine the encoding to use to convert this text. + */ + + handle = GetClipboardData(CF_LOCALE); + if (!handle) { + CloseClipboard(); + goto error; + } + + /* + * Get the locale identifier, determine the proper code page to use, + * and find the corresponding encoding. + */ + + Tcl_DStringInit(&ds); + Tcl_DStringAppend(&ds, "cp######", -1); + data = GlobalLock(handle); + + + /* + * Even though the documentation claims that GetLocaleInfo expects an + * LCID, on Windows 9x it really seems to expect a LanguageID. + */ + + locale = LANGIDFROMLCID(*((int*)data)); + GetLocaleInfo(locale, LOCALE_IDEFAULTANSICODEPAGE, + Tcl_DStringValue(&ds)+2, Tcl_DStringLength(&ds)-2); + GlobalUnlock(handle); + + encoding = Tcl_GetEncoding(NULL, Tcl_DStringValue(&ds)); + Tcl_DStringFree(&ds); + + if (!encoding) { + CloseClipboard(); + goto error; + } + + /* + * Fetch the text and convert it to UTF. + */ + + handle = GetClipboardData(CF_TEXT); + if (!handle) { + Tcl_FreeEncoding(encoding); + CloseClipboard(); + goto error; + } + data = GlobalLock(handle); + Tcl_ExternalToUtfDString(encoding, data, -1, &ds); + GlobalUnlock(handle); + Tcl_FreeEncoding(encoding); + + } else { + CloseClipboard(); + goto error; + } + + /* + * Translate CR/LF to LF. + */ + + data = destPtr = Tcl_DStringValue(&ds); + while (*data) { + if (data[0] == '\r' && data[1] == '\n') { + data++; + } else { + *destPtr++ = *data++; } } + *destPtr = '\0'; + + /* + * Pass the data off to the selection procedure. + */ + result = (*proc)(clientData, interp, Tcl_DStringValue(&ds)); + Tcl_DStringFree(&ds); + CloseClipboard(); + return result; + +error: Tcl_AppendResult(interp, Tk_GetAtomName(tkwin, selection), - " selection doesn't exist or form \"", Tk_GetAtomName(tkwin, target), - "\" not defined", (char *) NULL); + " selection doesn't exist or form \"", + Tk_GetAtomName(tkwin, target), + "\" not defined", (char *) NULL); return TCL_ERROR; } @@ -132,10 +213,7 @@ XSetSelectionOwner(display, selection, owner, time) */ if (GetClipboardOwner() != hwnd) { - OpenClipboard(hwnd); - EmptyClipboard(); - SetClipboardData(CF_TEXT, NULL); - CloseClipboard(); + UpdateClipboard(hwnd); } } } @@ -174,6 +252,12 @@ TkWinClipboardRender(dispPtr, format) if (targetPtr->type == XA_STRING) break; } + + /* + * Count the number of newlines so we can add space for them in + * the resulting string. + */ + length = 0; if (targetPtr != NULL) { for (cbPtr = targetPtr->firstBufferPtr; cbPtr != NULL; @@ -187,6 +271,11 @@ TkWinClipboardRender(dispPtr, format) } } } + + /* + * Copy the data and change EOL characters. + */ + buffer = rawText = ckalloc(length + 1); if (targetPtr != NULL) { for (cbPtr = targetPtr->firstBufferPtr; cbPtr != NULL; @@ -201,19 +290,43 @@ TkWinClipboardRender(dispPtr, format) } } *buffer = '\0'; - Tcl_UtfToExternalDString(NULL, rawText, -1, &ds); - ckfree(rawText); - handle = GlobalAlloc(GMEM_MOVEABLE|GMEM_DDESHARE, - Tcl_DStringLength(&ds)+1); - if (!handle) { + + /* + * Depending on the platform, turn the data into Unicode or the + * system encoding before placing it on the clipboard. + */ + + if (TkWinGetPlatformId() == VER_PLATFORM_WIN32_NT) { + Tcl_DStringInit(&ds); + Tcl_UtfToUniCharDString(rawText, -1, &ds); + ckfree(rawText); + handle = GlobalAlloc(GMEM_MOVEABLE|GMEM_DDESHARE, + Tcl_DStringLength(&ds)+2); + if (!handle) { + Tcl_DStringFree(&ds); + return; + } + buffer = GlobalLock(handle); + memcpy(buffer, Tcl_DStringValue(&ds), Tcl_DStringLength(&ds) + 2); + GlobalUnlock(handle); Tcl_DStringFree(&ds); - return; + SetClipboardData(CF_UNICODETEXT, handle); + } else { + Tcl_UtfToExternalDString(NULL, rawText, -1, &ds); + ckfree(rawText); + handle = GlobalAlloc(GMEM_MOVEABLE|GMEM_DDESHARE, + Tcl_DStringLength(&ds)+1); + if (!handle) { + Tcl_DStringFree(&ds); + return; + } + buffer = GlobalLock(handle); + memcpy(buffer, Tcl_DStringValue(&ds), Tcl_DStringLength(&ds) + 1); + GlobalUnlock(handle); + Tcl_DStringFree(&ds); + SetClipboardData(CF_TEXT, handle); } - buffer = GlobalLock(handle); - memcpy(buffer, Tcl_DStringValue(&ds), Tcl_DStringLength(&ds) + 1); - GlobalUnlock(handle); - Tcl_DStringFree(&ds); - SetClipboardData(CF_TEXT, handle); + return; } @@ -240,10 +353,43 @@ TkSelUpdateClipboard(winPtr, targetPtr) TkClipboardTarget *targetPtr; { HWND hwnd = TkWinGetHWND(winPtr->window); + UpdateClipboard(hwnd); +} + +/* + *---------------------------------------------------------------------- + * + * UpdateClipboard -- + * + * Take ownership of the clipboard, clear it, and indicate to the + * system the supported formats. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ +static void +UpdateClipboard(hwnd) + HWND hwnd; +{ OpenClipboard(hwnd); EmptyClipboard(); - SetClipboardData(CF_TEXT, NULL); + + /* + * CF_UNICODETEXT is only supported on NT, but it it is preffered + * when possible. + */ + + if (TkWinGetPlatformId() == VER_PLATFORM_WIN32_NT) { + SetClipboardData(CF_UNICODETEXT, NULL); + } else { + SetClipboardData(CF_TEXT, NULL); + } CloseClipboard(); } -- cgit v0.12