/* NSPasteboard.m Manage cut/copy/paste operations. Copyright (C) 1997 Free Software Foundation, Inc. Author: Felipe A. Rodriguez Date: August 1998 This file is part of the mySTEP Library and is provided under the terms of the GNU Library General Public License. */ #import #import #import #import #import #import #import #import #import #import #import #import #import #import #import "NSAppKitPrivate.h" #import "NSBackendPrivate.h" // // Class variables // static NSMutableDictionary *__pasteboards = nil; static NSString *_contentsPrefix = @"NSTypedFileContentsPboardType:"; static NSString *_namePrefix = @"NSTypedFilenamesPboardType:"; @implementation NSPasteboard + (NSPasteboard *) generalPasteboard { return [self pasteboardWithName: NSGeneralPboard]; } + (NSPasteboard *) pasteboardWithName:(NSString *)aName { NSPasteboard *pb; if(!(pb = [__pasteboards objectForKey: aName])) { pb = [NSPasteboard new]; pb->_name = aName; if(!__pasteboards) __pasteboards = [[NSMutableDictionary alloc] initWithCapacity:8]; [__pasteboards setObject:pb forKey:aName]; [pb release]; } return pb; } + (NSPasteboard *) pasteboardWithUniqueName { NSProcessInfo *p = [NSProcessInfo processInfo]; return [self pasteboardWithName:[p globallyUniqueString]]; } // Filter contents + (NSPasteboard *) pasteboardByFilteringData:(NSData *)data ofType:(NSString *)type { // create a unique name from data and type NIMP; return nil; } + (NSPasteboard *) pasteboardByFilteringFile:(NSString *)filename { NSData *data = [NSData dataWithContentsOfFile:filename]; NSString *type = NSCreateFileContentsPboardType([filename pathExtension]); return [self pasteboardByFilteringData:data ofType:type]; } + (NSPasteboard *) pasteboardByFilteringTypesInPasteboard:(NSPasteboard *)pb { NIMP; return nil; } + (NSArray *) typesFilterableTo:(NSString *)type { NSArray *types = [NSMutableArray array]; return types; } - (void) dealloc { [_target release]; [_name release]; [_owner release]; [super dealloc]; } - (void) releaseGlobally { [_target releaseGlobally]; [__pasteboards removeObjectForKey: _name]; } - (NSString *) name { return _name; } - (NSArray *) types { return _types; } - (int) changeCount { return _changeCount; } - (int) addTypes:(NSArray *)newTypes owner:(id)newOwner { ASSIGN(_owner, newOwner); ASSIGN(_types, [_types arrayByAddingObjectsFromArray: newTypes]); [_typesProvided addObjectsFromArray: newTypes]; return _changeCount++; } - (int) declareTypes:(NSArray *)newTypes owner:(id)newOwner { ASSIGN(_types, newTypes); ASSIGN(_typesProvided, [_types mutableCopy]); ASSIGN(_owner, newOwner); return _changeCount++; } - (NSGraphicsContext *) _context { NSWindow *win=[NSApp keyWindow]; // try key window if(!win) win=[NSApp mainWindow]; // try main window if(!win) win=[NSApp _mainMenuWindow]; // try main menu window if(!win) { NSLog(@"NSPasteboard: there is no key/main/mainMenu window"); return nil; } return [win graphicsContext]; // get graphics context } - (BOOL) setData:(NSData *)data forType:(NSString *)dataType { // http://tronche.com/gui/x/xlib/window-information/XConvertSelection.html return [[self _context] _setPasteBoard:[self name] data:data forType:dataType]; } - (BOOL) setPropertyList:(id)propertyList forType:(NSString *)dataType { NSString *error; NSData *data=[NSPropertyListSerialization dataFromPropertyList:propertyList format:NSPropertyListBinaryFormat_v1_0 errorDescription:&error]; if(!data) return NO; return [self setData:data forType:dataType]; } - (BOOL) setString:(NSString *)string forType:(NSString *)dataType { return [self setPropertyList:string forType:dataType]; } - (NSString *) availableTypeFromArray:(NSArray *)types { if (!_types) // FIX ME hack for paste in app that did not copy/cut _types = [[NSArray arrayWithObjects: NSStringPboardType, nil] retain]; return [_types firstObjectCommonWithArray:types]; } - (NSData *) dataForType:(NSString *)dataType { return [[self _context] _pasteBoard:[self name] dataForType:dataType]; #if FRAGMENT if (!_owner) { NSMutableDictionary *d = [NSMutableDictionary new]; NSMutableArray *files = [NSMutableArray new]; NSString *s = [self stringForType:dt]; #if 1 NSLog(@"********* propertyListForType: %@\n",dt); #endif [files addObject:s]; [d setObject:s forKey:@"SourcePath"]; [d setObject:files forKey:@"SelectedFiles"]; return [d autorelease]; } [_owner pasteboard:self provideDataForType:dt]; #endif } - (id) propertyListForType:(NSString *)dt { NSPropertyListFormat format; NSString *error; NSData *data=[self dataForType:dt]; if(!data) return NO; return [NSPropertyListSerialization propertyListFromData:data mutabilityOption:0 format:&format errorDescription:&error]; } - (NSString *) stringForType:(NSString *)dataType { NSString *s=[self propertyListForType: dataType]; if(![s isKindOfClass:[NSString class]]) return NO; return s; } - (BOOL) writeFileContents:(NSString *)filename { NSData *data = [NSData dataWithContentsOfFile:filename]; NSString *type = NSCreateFileContentsPboardType([filename pathExtension]); if(type && ![self setData:data forType:type]) return NO; return [self setData:data forType:NSFileContentsPboardType]; } - (NSString *) readFileContentsType:(NSString *)type toFile:(NSString *)filename { NSData *d; if (type == nil) type = NSCreateFileContentsPboardType([filename pathExtension]); d = [self dataForType: type]; if(!d) d=[self dataForType:NSFileContentsPboardType]; if (![d writeToFile: filename atomically: NO]) return nil; return filename; } - (NSFileWrapper *) readFileWrapper; { NSData *data=[self dataForType:NSFileContentsPboardType]; if(data) return [[[NSFileWrapper alloc] initWithSerializedRepresentation:data] autorelease]; return nil; } - (BOOL) writeFileWrapper:(NSFileWrapper *) fileWrapper; { // FIXME: dies not exactly match description - which additionally saves a type based on the file extension and that it must have a file name return [self setData:[fileWrapper serializedRepresentation] forType:NSFileContentsPboardType]; } @end /* NSPasteboard */ NSString * NSCreateFileContentsPboardType(NSString *fileType) { return [NSString stringWithFormat:@"%@%@", _contentsPrefix, fileType]; } NSString * NSCreateFilenamePboardType(NSString *filename) { return [NSString stringWithFormat:@"%@%@", _namePrefix, filename]; } NSString * NSGetFileType(NSString *pboardType) { if ([pboardType hasPrefix: _contentsPrefix]) return [pboardType substringFromIndex: [_contentsPrefix length]]; if ([pboardType hasPrefix: _namePrefix]) return [pboardType substringFromIndex: [_namePrefix length]]; return nil; } NSArray * NSGetFileTypes(NSArray *pboardTypes) { NSMutableArray *a = [NSMutableArray arrayWithCapacity: [pboardTypes count]]; unsigned int i; for (i = 0; i < [pboardTypes count]; i++) { NSString *s = NSGetFileType([pboardTypes objectAtIndex:i]); if (s && ! [a containsObject:s]) [a addObject:s]; } if ([a count] > 0) return [[a copy] autorelease]; return nil; }