309 lines
7.9 KiB
C
309 lines
7.9 KiB
C
/*
|
||
* 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 <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"
|
||
|
||
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 ? (char*)[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.
|
||
*
|
||
*----------------------------------------------------------------------
|
||
*/
|
||
|
||
int
|
||
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];
|
||
}
|
||
}
|
||
return Success;
|
||
}
|
||
|
||
/*
|
||
*----------------------------------------------------------------------
|
||
*
|
||
* 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: objc
|
||
* c-basic-offset: 4
|
||
* fill-column: 79
|
||
* coding: utf-8
|
||
* End:
|
||
*/
|