summaryrefslogtreecommitdiffstats
path: root/win
diff options
context:
space:
mode:
Diffstat (limited to 'win')
-rw-r--r--win/tkWinClipboard.c240
1 files changed, 193 insertions, 47 deletions
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();
}