tkWinClipboard.c
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:10k
- /*
- * 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.
- *
- * RCS: @(#) $Id: tkWinClipboard.c,v 1.7 2000/04/12 18:51:11 hobbs Exp $
- */
- #include "tkWinInt.h"
- #include "tkSelect.h"
- static void UpdateClipboard _ANSI_ARGS_((HWND hwnd));
- /*
- *----------------------------------------------------------------------
- *
- * 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(interp, tkwin, selection, target, proc, clientData)
- 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;
- 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)) {
- /*
- * 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 = 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);
- } 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 = GlobalLock(handle);
- Tcl_ExternalToUtfDString(encoding, data, -1, &ds);
- GlobalUnlock(handle);
- if (encoding) {
- 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 = ' ';
- /*
- * 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);
- return TCL_ERROR;
- }
- /*
- *----------------------------------------------------------------------
- *
- * 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.
- *
- *----------------------------------------------------------------------
- */
- void
- XSetSelectionOwner(display, selection, owner, time)
- Display* display;
- Atom selection;
- Window owner;
- Time time;
- {
- HWND hwnd = owner ? TkWinGetHWND(owner) : NULL;
- Tk_Window tkwin;
- /*
- * 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);
- }
- }
- }
- /*
- *----------------------------------------------------------------------
- *
- * 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(dispPtr, format)
- TkDisplay *dispPtr;
- UINT format;
- {
- TkClipboardTarget *targetPtr;
- TkClipboardBuffer *cbPtr;
- HGLOBAL handle;
- char *buffer, *p, *rawText, *endPtr;
- int length;
- Tcl_DString ds;
- 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 = 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 = ' ';
- /*
- * 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);
- 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);
- }
- return;
- }
- /*
- *----------------------------------------------------------------------
- *
- * 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(winPtr, targetPtr)
- TkWindow *winPtr;
- 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;
- {
- TkWinUpdatingClipboard(TRUE);
- OpenClipboard(hwnd);
- EmptyClipboard();
- /*
- * CF_UNICODETEXT is only supported on NT, but it it is prefered
- * when possible.
- */
- if (TkWinGetPlatformId() == VER_PLATFORM_WIN32_NT) {
- SetClipboardData(CF_UNICODETEXT, NULL);
- } else {
- SetClipboardData(CF_TEXT, NULL);
- }
- CloseClipboard();
- TkWinUpdatingClipboard(FALSE);
- }
- /*
- *--------------------------------------------------------------
- *
- * TkSelEventProc --
- *
- * This procedure is invoked whenever a selection-related
- * event occurs.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Lots: depends on the type of event.
- *
- *--------------------------------------------------------------
- */
- void
- TkSelEventProc(tkwin, eventPtr)
- Tk_Window tkwin; /* Window for which event was
- * targeted. */
- register XEvent *eventPtr; /* X event: either SelectionClear,
- * SelectionRequest, or
- * SelectionNotify. */
- {
- if (eventPtr->type == SelectionClear) {
- TkSelClearSelection(tkwin, eventPtr);
- }
- }
- /*
- *----------------------------------------------------------------------
- *
- * 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(eventPtr)
- register XEvent *eventPtr; /* X PropertyChange event. */
- {
- }