/* * tkMacOSXClipboard.c -- * * This file manages the clipboard for the Tk toolkit. * * Copyright (c) 1995-1997 Sun Microsystems, Inc. * Copyright 2001-2009, Apple Inc. * Copyright (c) 2006-2009 Daniel A. Steffen * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * * RCS: @(#) $Id: tkMacOSXClipboard.c,v 1.15 2009/06/29 14:35:01 das Exp $ */ #include "tkMacOSXPrivate.h" #include "tkSelect.h" static NSInteger changeCount = -1; static Tk_Window clipboardOwner = NULL; #pragma mark TKApplication(TKClipboard) @implementation TKApplication(TKClipboard) - (void)tkProvidePasteboard:(TkDisplay *)dispPtr pasteboard:(NSPasteboard *)sender provideDataForType:(NSString *)type { NSMutableString *string = [NSMutableString new]; if (dispPtr && dispPtr->clipboardActive && [type isEqualToString:NSStringPboardType]) { for (TkClipboardTarget *targetPtr = dispPtr->clipTargetPtr; targetPtr; targetPtr = targetPtr->nextPtr) { if (targetPtr->type == XA_STRING || targetPtr->type == dispPtr->utf8Atom) { for (TkClipboardBuffer *cbPtr = targetPtr->firstBufferPtr; cbPtr; cbPtr = cbPtr->nextPtr) { NSString *s = [[NSString alloc] initWithBytesNoCopy: cbPtr->buffer length:cbPtr->length encoding:NSUTF8StringEncoding freeWhenDone:NO]; [string appendString:s]; [s release]; } break; } } } [sender setString:string forType:type]; [string release]; } - (void)tkProvidePasteboard:(TkDisplay *)dispPtr { if (dispPtr && dispPtr->clipboardActive) { [self tkProvidePasteboard:dispPtr pasteboard:[NSPasteboard generalPasteboard] provideDataForType:NSStringPboardType]; } } - (void)pasteboard:(NSPasteboard *)sender provideDataForType:(NSString *)type { [self tkProvidePasteboard:TkGetDisplayList() pasteboard:sender provideDataForType:type]; } - (void)tkCheckPasteboard { if (clipboardOwner && [[NSPasteboard generalPasteboard] changeCount] != changeCount) { TkDisplay *dispPtr = TkGetDisplayList(); if (dispPtr) { XEvent event; event.xany.type = SelectionClear; event.xany.serial = NextRequest(Tk_Display(clipboardOwner)); event.xany.send_event = False; event.xany.window = Tk_WindowId(clipboardOwner); event.xany.display = Tk_Display(clipboardOwner); event.xselectionclear.selection = dispPtr->clipboardAtom; Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL); } clipboardOwner = NULL; } } @end #pragma mark - /* *---------------------------------------------------------------------- * * 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 = TCL_ERROR; TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr; if (dispPtr && selection == dispPtr->clipboardAtom && (target == XA_STRING || target == dispPtr->utf8Atom)) { NSString *string = nil; NSPasteboard *pb = [NSPasteboard generalPasteboard]; NSString *type = [pb availableTypeFromArray:[NSArray arrayWithObject: NSStringPboardType]]; if (type) { string = [pb stringForType:type]; } result = proc(clientData, interp, string ? [string UTF8String] : ""); } else { Tcl_AppendResult(interp, Tk_GetAtomName(tkwin, selection), " selection doesn't exist or form \"", Tk_GetAtomName(tkwin, target), "\" not defined", NULL); } return result; } /* *---------------------------------------------------------------------- * * XSetSelectionOwner -- * * 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? */ { TkDisplay *dispPtr = TkGetDisplayList(); if (dispPtr && selection == dispPtr->clipboardAtom) { clipboardOwner = owner ? Tk_IdToWindow(display, owner) : NULL; if (!dispPtr->clipboardActive) { NSPasteboard *pb = [NSPasteboard generalPasteboard]; changeCount = [pb declareTypes:[NSArray array] owner:NSApp]; } } } /* *---------------------------------------------------------------------- * * TkMacOSXSelDeadWindow -- * * This function is invoked just before a TkWindow is deleted. It * performs selection-related cleanup. * * Results: * None. * * Side effects: * clipboardOwner is cleared. * *---------------------------------------------------------------------- */ void TkMacOSXSelDeadWindow( TkWindow *winPtr) { if (winPtr && winPtr == (TkWindow *)clipboardOwner) { clipboardOwner = NULL; } } /* *---------------------------------------------------------------------- * * TkSelUpdateClipboard -- * * This function is called to force the clipboard to be updated after new * data is added. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ void TkSelUpdateClipboard( TkWindow *winPtr, /* Window associated with clipboard. */ TkClipboardTarget *targetPtr) /* Info about the content. */ { NSPasteboard *pb = [NSPasteboard generalPasteboard]; changeCount = [pb addTypes:[NSArray arrayWithObject:NSStringPboardType] owner:NSApp]; } /* *-------------------------------------------------------------- * * 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) { clipboardOwner = NULL; 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. * * Results: * None. * * Side effects: * The local scrap is moved to the global scrap. * *---------------------------------------------------------------------- */ void TkSuspendClipboard(void) { changeCount = [[NSPasteboard generalPasteboard] changeCount]; } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 79 * coding: utf-8 * End: */