diff options
Diffstat (limited to 'carbon/tkMacOSXClipboard.c')
-rw-r--r-- | carbon/tkMacOSXClipboard.c | 371 |
1 files changed, 371 insertions, 0 deletions
diff --git a/carbon/tkMacOSXClipboard.c b/carbon/tkMacOSXClipboard.c new file mode 100644 index 0000000..07fc925 --- /dev/null +++ b/carbon/tkMacOSXClipboard.c @@ -0,0 +1,371 @@ +/* + * tkMacOSXClipboard.c -- + * + * This file manages the clipboard for the Tk toolkit. + * + * Copyright (c) 1995-1997 Sun Microsystems, Inc. + * Copyright 2001, Apple Computer, Inc. + * Copyright (c) 2006-2007 Daniel A. Steffen <das@users.sourceforge.net> + * + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. + */ + +#include "tkMacOSXPrivate.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( + 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. */ +{ + int result; + OSStatus err; + long length; + ScrapRef scrapRef; + char *buf; + + if ((selection == Tk_InternAtom(tkwin, "CLIPBOARD")) + && (target == XA_STRING)) { + /* + * Get the scrap from the Macintosh global clipboard. + */ + + err = ChkErr(GetCurrentScrap, &scrapRef); + if (err != noErr) { + Tcl_AppendResult(interp, Tk_GetAtomName(tkwin, selection), + " GetCurrentScrap failed.", NULL); + return TCL_ERROR; + } + + /* + * Try UNICODE first + */ + + err = ChkErr(GetScrapFlavorSize, scrapRef, kScrapFlavorTypeUnicode, + &length); + if (err == noErr && length > 0) { + Tcl_DString ds; + char *data; + + buf = ckalloc(length + 2); + buf[length] = 0; + buf[length+1] = 0; /* 2-byte unicode null */ + err = ChkErr(GetScrapFlavorData, scrapRef, kScrapFlavorTypeUnicode, + &length, buf); + if (err == noErr) { + Tcl_DStringInit(&ds); + Tcl_UniCharToUtfDString((Tcl_UniChar *) buf, + Tcl_UniCharLen((Tcl_UniChar *) buf), &ds); + for (data = Tcl_DStringValue(&ds); *data != '\0'; data++) { + if (*data == '\r') { + *data = '\n'; + } + } + result = proc(clientData, interp, Tcl_DStringValue(&ds)); + Tcl_DStringFree(&ds); + ckfree(buf); + return result; + } + } + + err = ChkErr(GetScrapFlavorSize, scrapRef, 'TEXT', &length); + if (err != noErr) { + Tcl_AppendResult(interp, Tk_GetAtomName(tkwin, selection), + " GetScrapFlavorSize failed.", NULL); + return TCL_ERROR; + } + if (length > 0) { + Tcl_DString encodedText; + char *data; + + buf = ckalloc(length + 1); + buf[length] = 0; + err = ChkErr(GetScrapFlavorData, scrapRef, 'TEXT', &length, buf); + if (err != noErr) { + Tcl_AppendResult(interp, Tk_GetAtomName(tkwin, selection), + " GetScrapFlavorData failed.", NULL); + return TCL_ERROR; + } + + /* + * Tcl expects '\n' not '\r' as the line break character. + */ + + for (data = buf; *data != '\0'; data++) { + if (*data == '\r') { + *data = '\n'; + } + } + + Tcl_ExternalToUtfDString(TkMacOSXCarbonEncoding, buf, length, + &encodedText); + result = proc(clientData, interp, Tcl_DStringValue(&encodedText)); + Tcl_DStringFree(&encodedText); + + ckfree(buf); + return result; + } + } + + Tcl_AppendResult(interp, Tk_GetAtomName(tkwin, selection), + " selection doesn't exist or form \"", + Tk_GetAtomName(tkwin, target), "\" not defined", 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: + * None. + * + *---------------------------------------------------------------------- + */ + +void +XSetSelectionOwner( + Display *display, /* X Display. */ + Atom selection, /* What selection to own. */ + Window owner, /* Window to be the owner. */ + Time time) /* The current time? */ +{ + Tk_Window tkwin; + TkDisplay *dispPtr; + + /* + * 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. + */ + + dispPtr = TkGetMainInfoList()->winPtr->dispPtr; + if (dispPtr->clipboardActive) { + return; + } + ClearCurrentScrap(); + } +} + +/* + *---------------------------------------------------------------------- + * + * TkSelUpdateClipboard -- + * + * This function is called to force the clipboard to be updated after new + * data is added. On the Mac we don't need to do anything. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +TkSelUpdateClipboard( + TkWindow *winPtr, /* Window associated with clipboard. */ + TkClipboardTarget *targetPtr) + /* Info about the content. */ +{ +} + +/* + *-------------------------------------------------------------- + * + * 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. */ + 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( + register XEvent *eventPtr) /* X PropertyChange event. */ +{ +} + +/* + *---------------------------------------------------------------------- + * + * TkSuspendClipboard -- + * + * Handle clipboard conversion as required by the suppend event. This + * function is also called on exit. + * + * Results: + * None. + * + * Side effects: + * The local scrap is moved to the global scrap. + * + *---------------------------------------------------------------------- + */ + +void +TkSuspendClipboard(void) +{ + TkClipboardTarget *targetPtr; + TkClipboardBuffer *cbPtr; + TkDisplay *dispPtr; + char *buffer, *p, *endPtr, *buffPtr; + long length; + ScrapRef scrapRef; + + dispPtr = TkGetDisplayList(); + if ((dispPtr == NULL) || !dispPtr->clipboardActive) { + return; + } + + for (targetPtr = dispPtr->clipTargetPtr; targetPtr != NULL; + targetPtr = targetPtr->nextPtr) { + if (targetPtr->type == XA_STRING) { + break; + } + } + if (targetPtr != NULL) { + Tcl_DString encodedText, unicodedText; + + length = 0; + for (cbPtr = targetPtr->firstBufferPtr; cbPtr != NULL; + cbPtr = cbPtr->nextPtr) { + length += cbPtr->length; + } + + buffer = ckalloc(length); + buffPtr = buffer; + for (cbPtr = targetPtr->firstBufferPtr; cbPtr != NULL; + cbPtr = cbPtr->nextPtr) { + for (p = cbPtr->buffer, endPtr = p + cbPtr->length; + p < endPtr; p++) { + if (*p == '\n') { + *buffPtr++ = '\r'; + } else { + *buffPtr++ = *p; + } + } + } + + ClearCurrentScrap(); + GetCurrentScrap(&scrapRef); + Tcl_UtfToExternalDString(TkMacOSXCarbonEncoding, buffer, length, + &encodedText); + PutScrapFlavor(scrapRef, 'TEXT', 0, Tcl_DStringLength(&encodedText), + Tcl_DStringValue(&encodedText)); + Tcl_DStringFree(&encodedText); + + /* + * Also put unicode data on scrap. + */ + + Tcl_DStringInit(&unicodedText); + Tcl_UtfToUniCharDString(buffer, length, &unicodedText); + PutScrapFlavor(scrapRef, kScrapFlavorTypeUnicode, 0, + Tcl_DStringLength(&unicodedText), + Tcl_DStringValue(&unicodedText)); + Tcl_DStringFree(&unicodedText); + + ckfree(buffer); + } + + /* + * The system now owns the scrap. We tell Tk that it has lost the + * selection so that it will look for it the next time it needs it. + * (Window list NULL if quiting.) + */ + + if (TkGetMainInfoList() != NULL) { + Tk_ClearSelection((Tk_Window) TkGetMainInfoList()->winPtr, + Tk_InternAtom((Tk_Window) TkGetMainInfoList()->winPtr, + "CLIPBOARD")); + } + + return; +} + +/* + * Local Variables: + * fill-column: 78 + * c-basic-offset: 4 + * End: + */ |