OSDN Git Service

Please enter the commit message for your changes. Lines starting
[eos/base.git] / util / src / TclTk / tk8.6.12 / win / tkWinClipboard.c
diff --git a/util/src/TclTk/tk8.6.12/win/tkWinClipboard.c b/util/src/TclTk/tk8.6.12/win/tkWinClipboard.c
new file mode 100644 (file)
index 0000000..bcea1c1
--- /dev/null
@@ -0,0 +1,467 @@
+/*
+ * tkWinClipboard.c --
+ *
+ *     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.
+ */
+
+#include "tkWinInt.h"
+#include "tkSelect.h"
+#include <shlobj.h>    /* for DROPFILES */
+
+static void            UpdateClipboard(HWND hwnd);
+\f
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkSelGetSelection --
+ *
+ *     Retrieve the specified selection from another process. For now, only
+ *     fetching XA_STRING from CLIPBOARD is supported. Eventually other types
+ *     should be allowed.
+ *
+ * Results:
+ *     The return value is a standard Tcl return value. If an error occurs
+ *     (such as no selection exists) then an error message is left in the
+ *     interp's result.
+ *
+ * Side effects:
+ *     None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkSelGetSelection(
+    Tcl_Interp *interp,                /* Interpreter to use for reporting errors. */
+    Tk_Window tkwin,           /* Window on whose behalf to retrieve the
+                                * selection (determines display from which to
+                                * retrieve). */
+    Atom selection,            /* Selection to retrieve. */
+    Atom target,               /* Desired form in which selection is to be
+                                * returned. */
+    Tk_GetSelProc *proc,       /* Procedure to call to process the selection,
+                                * once it has been retrieved. */
+    ClientData clientData)     /* Arbitrary value to pass to proc. */
+{
+    char *data, *destPtr;
+    Tcl_DString ds;
+    HGLOBAL handle;
+    Tcl_Encoding encoding;
+    int result, locale, noBackslash = 0;
+
+    if (!OpenClipboard(NULL)) {
+        Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+               "clipboard cannot be opened, another application grabbed it"));
+        Tcl_SetErrorCode(interp, "TK", "CLIPBOARD", "BUSY", NULL);
+        return TCL_ERROR;
+    }
+    if ((selection != Tk_InternAtom(tkwin, "CLIPBOARD"))
+           || (target != XA_STRING)) {
+       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 = (char *)GlobalLock(handle);
+       Tcl_DStringInit(&ds);
+       Tcl_WCharToUtfDString((WCHAR *)data, wcslen((WCHAR *)data), &ds);
+       GlobalUnlock(handle);
+    } else if (IsClipboardFormatAvailable(CF_TEXT)) {
+       /*
+        * Determine the encoding to use to convert this text.
+        */
+
+       if (IsClipboardFormatAvailable(CF_LOCALE)) {
+           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 = (char *)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));
+           GetLocaleInfoA(locale, LOCALE_IDEFAULTANSICODEPAGE,
+                   Tcl_DStringValue(&ds)+2, Tcl_DStringLength(&ds)-2);
+           GlobalUnlock(handle);
+
+           encoding = Tcl_GetEncoding(NULL, Tcl_DStringValue(&ds));
+           Tcl_DStringFree(&ds);
+       } else {
+           encoding = NULL;
+       }
+
+       /*
+        * Fetch the text and convert it to UTF.
+        */
+
+       handle = GetClipboardData(CF_TEXT);
+       if (!handle) {
+           if (encoding) {
+               Tcl_FreeEncoding(encoding);
+           }
+           CloseClipboard();
+           goto error;
+       }
+       data = (char *)GlobalLock(handle);
+       Tcl_ExternalToUtfDString(encoding, data, -1, &ds);
+       GlobalUnlock(handle);
+       if (encoding) {
+           Tcl_FreeEncoding(encoding);
+       }
+    } else if (IsClipboardFormatAvailable(CF_HDROP)) {
+       DROPFILES *drop;
+
+       handle = GetClipboardData(CF_HDROP);
+       if (!handle) {
+           CloseClipboard();
+           goto error;
+       }
+       Tcl_DStringInit(&ds);
+       drop = (DROPFILES *) GlobalLock(handle);
+       if (drop->fWide) {
+           WCHAR *fname = (WCHAR *) ((char *) drop + drop->pFiles);
+           Tcl_DString dsTmp;
+           int count = 0;
+           size_t len;
+
+           while (*fname != 0) {
+               if (count) {
+                   Tcl_DStringAppend(&ds, "\n", 1);
+               }
+               len = wcslen(fname);
+               Tcl_DStringInit(&dsTmp);
+               Tcl_WCharToUtfDString(fname, len, &dsTmp);
+               Tcl_DStringAppend(&ds, Tcl_DStringValue(&dsTmp),
+                       Tcl_DStringLength(&dsTmp));
+               Tcl_DStringFree(&dsTmp);
+               fname += len + 1;
+               count++;
+           }
+           noBackslash = (count > 0);
+       }
+       GlobalUnlock(handle);
+    } 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 if (noBackslash && data[0] == '\\') {
+           data++;
+           *destPtr++ = '/';
+       } 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_SetObjResult(interp, Tcl_ObjPrintf(
+           "%s selection doesn't exist or form \"%s\" not defined",
+           Tk_GetAtomName(tkwin, selection), Tk_GetAtomName(tkwin, target)));
+    Tcl_SetErrorCode(interp, "TK", "SELECTION", "EXISTS", NULL);
+    return TCL_ERROR;
+}
+\f
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkSetSelectionOwner --
+ *
+ *     This function claims ownership of the specified selection. If the
+ *     selection is CLIPBOARD, then we empty the system clipboard.
+ *
+ * Results:
+ *     None.
+ *
+ * Side effects:
+ *     Empties the system clipboard, and claims ownership.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+XSetSelectionOwner(
+    Display *display,
+    Atom selection,
+    Window owner,
+    Time time)
+{
+    HWND hwnd = owner ? TkWinGetHWND(owner) : NULL;
+    Tk_Window tkwin;
+    (void)display;
+    (void)time;
+
+    /*
+     * This is a gross hack because the Tk_InternAtom interface is broken. It
+     * expects a Tk_Window, even though it only needs a Tk_Display.
+     */
+
+    tkwin = (Tk_Window) TkGetMainInfoList()->winPtr;
+
+    if (selection == Tk_InternAtom(tkwin, "CLIPBOARD")) {
+       /*
+        * Only claim and empty the clipboard if we aren't already the owner
+        * of the clipboard.
+        */
+
+       if (GetClipboardOwner() != hwnd) {
+           UpdateClipboard(hwnd);
+       }
+    }
+    return Success;
+}
+\f
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkWinClipboardRender --
+ *
+ *     This function supplies the contents of the clipboard in response to a
+ *     WM_RENDERFORMAT message.
+ *
+ * Results:
+ *     None.
+ *
+ * Side effects:
+ *     Sets the contents of the clipboard.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkWinClipboardRender(
+    TkDisplay *dispPtr,
+    UINT format)
+{
+    TkClipboardTarget *targetPtr;
+    TkClipboardBuffer *cbPtr;
+    HGLOBAL handle;
+    char *buffer, *p, *rawText, *endPtr;
+    int length;
+    Tcl_DString ds;
+    (void)format;
+
+    for (targetPtr = dispPtr->clipTargetPtr; targetPtr != NULL;
+           targetPtr = targetPtr->nextPtr) {
+       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;
+               cbPtr = cbPtr->nextPtr) {
+           length += cbPtr->length;
+           for (p = cbPtr->buffer, endPtr = p + cbPtr->length;
+                   p < endPtr; p++) {
+               if (*p == '\n') {
+                   length++;
+               }
+           }
+       }
+    }
+
+    /*
+     * Copy the data and change EOL characters.
+     */
+
+    buffer = rawText = (char *)ckalloc(length + 1);
+    if (targetPtr != NULL) {
+       for (cbPtr = targetPtr->firstBufferPtr; cbPtr != NULL;
+               cbPtr = cbPtr->nextPtr) {
+           for (p = cbPtr->buffer, endPtr = p + cbPtr->length;
+                   p < endPtr; p++) {
+               if (*p == '\n') {
+                   *buffer++ = '\r';
+               }
+               *buffer++ = *p;
+           }
+       }
+    }
+    *buffer = '\0';
+
+    Tcl_DStringInit(&ds);
+    Tcl_UtfToWCharDString(rawText, -1, &ds);
+    ckfree(rawText);
+    handle = GlobalAlloc(GMEM_MOVEABLE|GMEM_DDESHARE,
+           Tcl_DStringLength(&ds) + 2);
+    if (!handle) {
+       Tcl_DStringFree(&ds);
+       return;
+    }
+    buffer = (char *)GlobalLock(handle);
+    memcpy(buffer, Tcl_DStringValue(&ds),
+           Tcl_DStringLength(&ds) + 2);
+    GlobalUnlock(handle);
+    Tcl_DStringFree(&ds);
+    SetClipboardData(CF_UNICODETEXT, handle);
+}
+\f
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkSelUpdateClipboard --
+ *
+ *     This function is called to force the clipboard to be updated after new
+ *     data is added.
+ *
+ * Results:
+ *     None.
+ *
+ * Side effects:
+ *     Clears the current contents of the clipboard.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkSelUpdateClipboard(
+    TkWindow *winPtr,
+    TkClipboardTarget *targetPtr)
+{
+    HWND hwnd = TkWinGetHWND(winPtr->window);
+    (void)targetPtr;
+
+    UpdateClipboard(hwnd);
+}
+\f
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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)
+{
+    TkWinUpdatingClipboard(TRUE);
+    OpenClipboard(hwnd);
+    EmptyClipboard();
+
+    SetClipboardData(CF_UNICODETEXT, NULL);
+    CloseClipboard();
+    TkWinUpdatingClipboard(FALSE);
+}
+\f
+/*
+ *--------------------------------------------------------------
+ *
+ * TkSelEventProc --
+ *
+ *     This procedure is invoked whenever a selection-related event occurs.
+ *
+ * Results:
+ *     None.
+ *
+ * Side effects:
+ *     Lots: depends on the type of event.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+TkSelEventProc(
+    Tk_Window tkwin,           /* Window for which event was targeted. */
+    XEvent *eventPtr)  /* X event: either SelectionClear,
+                                * SelectionRequest, or SelectionNotify. */
+{
+    if (eventPtr->type == SelectionClear) {
+       TkSelClearSelection(tkwin, eventPtr);
+    }
+}
+\f
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkSelPropProc --
+ *
+ *     This procedure is invoked when property-change events occur on windows
+ *     not known to the toolkit. This is a stub function under Windows.
+ *
+ * Results:
+ *     None.
+ *
+ * Side effects:
+ *     None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkSelPropProc(
+    XEvent *eventPtr)  /* X PropertyChange event. */
+{
+    (void)eventPtr;
+}
+\f
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */