/* * tkWinClipboard.c -- * * This file contains functions for managing the clipboard. * * Copyright (c) 1995-1997 Sun Microsystems, Inc. * * 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.1.4.4 1998/12/13 08:16:16 lfb Exp $ */ #include "tkWinInt.h" #include "tkSelect.h" /* *---------------------------------------------------------------------- * * 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, *buffer, *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; } CloseClipboard(); } } 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) { OpenClipboard(hwnd); EmptyClipboard(); SetClipboardData(CF_TEXT, NULL); CloseClipboard(); } } } /* *---------------------------------------------------------------------- * * 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; } 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++; } } } } 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 = '\0'; 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); OpenClipboard(hwnd); EmptyClipboard(); SetClipboardData(CF_TEXT, NULL); CloseClipboard(); } /* *-------------------------------------------------------------- * * 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. */ { }