From a1336268a7601dbb3197bc4cde5d5ffddcd2ad38 Mon Sep 17 00:00:00 2001 From: Richard Frith-Macdonald Date: Fri, 27 Jun 2003 16:42:27 +0000 Subject: [PATCH] More documentation updates and initial implementation of some filtering code git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@17051 72102866-910b-0410-8b05-ffd578937521 --- ChangeLog | 3 +- Headers/gnustep/gui/NSPasteboard.h | 192 +++++++++++++++++--------- Source/NSPasteboard.m | 209 +++++++++++++++++++++++++---- 3 files changed, 317 insertions(+), 87 deletions(-) diff --git a/ChangeLog b/ChangeLog index 420da1d72..89903f6ac 100644 --- a/ChangeLog +++ b/ChangeLog @@ -4,7 +4,8 @@ writing fiels to pastebaords, implemented ([+typesFilterableTo:]) wrote (partial implementation ...) the unimplemented filters stuff. * Source/GSServicesManager.m: helpers for filters. - * Headers/AppKit/GSPasteboard.h: Removed unused methods. + * Headers/AppKit/GSPasteboard.h: Removed unused methods, added + documentation. 2003-06-26 Ludovic Marcotte diff --git a/Headers/gnustep/gui/NSPasteboard.h b/Headers/gnustep/gui/NSPasteboard.h index e1a5f15b3..f8ae10c61 100644 --- a/Headers/gnustep/gui/NSPasteboard.h +++ b/Headers/gnustep/gui/NSPasteboard.h @@ -7,6 +7,7 @@ Author: Scott Christley Date: 1996 + Author: Richard Frith-Macdonald This file is part of the GNUstep GUI Library. @@ -38,137 +39,204 @@ @class NSData; @class NSFileWrapper; -// -// Pasteboard Type Globals -// +/** + * Pasteboard contains string data as written by + * [NSPasteboard-setString:forType:] or [NSPasteboard-setPropertyList:forType:] + */ APPKIT_EXPORT NSString *NSStringPboardType; + +/** + * Pasteboard contains string color information + */ APPKIT_EXPORT NSString *NSColorPboardType; APPKIT_EXPORT NSString *NSFileContentsPboardType; APPKIT_EXPORT NSString *NSFilenamesPboardType; + +/** + * Pasteboard contains font color information + */ APPKIT_EXPORT NSString *NSFontPboardType; + +/** + * Pasteboard contains ruler color information + */ APPKIT_EXPORT NSString *NSRulerPboardType; + +/** + * Pasteboard contains postscript code + */ APPKIT_EXPORT NSString *NSPostScriptPboardType; + +/** + * Pasteboard contains tabular text. + */ APPKIT_EXPORT NSString *NSTabularTextPboardType; + +/** + * Pasteboard contains text in rich text format. + */ APPKIT_EXPORT NSString *NSRTFPboardType; + +/** + * Pasteboard contains text in rich text format with additional info + */ APPKIT_EXPORT NSString *NSRTFDPboardType; + +/** + * Pasteboard contains a TIFF image + */ APPKIT_EXPORT NSString *NSTIFFPboardType; + +/** + * Pasteboard contains a link to data in some document + */ APPKIT_EXPORT NSString *NSDataLinkPboardType; + +/** + * Pasteboard contains general binary data + */ APPKIT_EXPORT NSString *NSGeneralPboardType; #ifndef STRICT_OPENSTEP +/** + * Pasteboard contains a PDF document + */ APPKIT_EXPORT NSString *NSPDFPboardType; + +/** + * Pasteboard contains a PICT diagram document + */ APPKIT_EXPORT NSString *NSPICTPboardType; + +/** + * Pasteboard contains a URL + */ APPKIT_EXPORT NSString *NSURLPboardType; + +/** + * Pasteboard contains HTML data + */ APPKIT_EXPORT NSString *NSHTMLPboardType; #endif -// -// Pasteboard Name Globals -// +/** + * The pasteboard used for drag and drop information. + */ APPKIT_EXPORT NSString *NSDragPboard; + +/** + * The pasteboard used search and replace editing operations. + */ APPKIT_EXPORT NSString *NSFindPboard; + +/** + * The pasteboard used for cutting and pasting font information. + */ APPKIT_EXPORT NSString *NSFontPboard; + +/** + * The general purpose pasteboard (mostly used for sut and paste) + */ APPKIT_EXPORT NSString *NSGeneralPboard; + +/** + * The pasteboard used for cutting and pasting ruler information. + */ APPKIT_EXPORT NSString *NSRulerPboard; -// -// Pasteboard Exceptions -// +/** + * Exception raised when communication with the pasteboard server fails. + */ APPKIT_EXPORT NSString *NSPasteboardCommunicationException; @interface NSPasteboard : NSObject { - NSString* name; // The name of this pasteboard. - int changeCount; // What we think the current count is. - id target; // Proxy to the object in the server. - id owner; // Local pasteboard owner. - BOOL useHistory; // Want strict OPENSTEP? + NSString *name; // The name of this pasteboard. + int changeCount; // What we think the current count is. + id target; // Proxy to the object in the server. + id owner; // Local pasteboard owner. + BOOL useHistory; // Want strict OPENSTEP? } // // Creating and Releasing an NSPasteboard Object // -+ (NSPasteboard *)generalPasteboard; -+ (NSPasteboard *)pasteboardWithName:(NSString *)aName; -+ (NSPasteboard *)pasteboardWithUniqueName; -- (void)releaseGlobally; ++ (NSPasteboard*) generalPasteboard; ++ (NSPasteboard*) pasteboardWithName: (NSString*)aName; ++ (NSPasteboard*) pasteboardWithUniqueName; +- (void) releaseGlobally; // // Getting Data in Different Formats // -+ (NSPasteboard *)pasteboardByFilteringData:(NSData *)data - ofType:(NSString *)type; -+ (NSPasteboard *)pasteboardByFilteringFile:(NSString *)filename; -+ (NSPasteboard *)pasteboardByFilteringTypesInPasteboard:(NSPasteboard *)pboard; -+ (NSArray *)typesFilterableTo:(NSString *)type; ++ (NSPasteboard*) pasteboardByFilteringData: (NSData*)data + ofType: (NSString*)type; ++ (NSPasteboard*) pasteboardByFilteringFile: (NSString*)filename; ++ (NSPasteboard*) pasteboardByFilteringTypesInPasteboard: (NSPasteboard*)pboard; ++ (NSArray*) typesFilterableTo: (NSString*)type; // // Referring to a Pasteboard by Name // -- (NSString *)name; +- (NSString*) name; // // Writing Data // -- (int)addTypes:(NSArray *)newTypes - owner:(id)newOwner; -- (int)declareTypes:(NSArray *)newTypes - owner:(id)newOwner; -- (BOOL)setData:(NSData *)data - forType:(NSString *)dataType; -- (BOOL)setPropertyList:(id)propertyList - forType:(NSString *)dataType; -- (BOOL)setString:(NSString *)string - forType:(NSString *)dataType; -- (BOOL)writeFileContents:(NSString *)filename; -- (BOOL)writeFileWrapper:(NSFileWrapper *)wrapper; +- (int) addTypes: (NSArray*)newTypes + owner: (id)newOwner; +- (int) declareTypes: (NSArray*)newTypes + owner: (id)newOwner; +- (BOOL) setData: (NSData*)data + forType: (NSString*)dataType; +- (BOOL) setPropertyList: (id)propertyList + forType: (NSString*)dataType; +- (BOOL) setString: (NSString*)string + forType: (NSString*)dataType; +- (BOOL) writeFileContents: (NSString*)filename; +- (BOOL) writeFileWrapper: (NSFileWrapper*)wrapper; // // Determining Types // -- (NSString *)availableTypeFromArray:(NSArray *)types; -- (NSArray *)types; +- (NSString*) availableTypeFromArray: (NSArray*)types; +- (NSArray*) types; // // Reading Data // -- (int)changeCount; -- (NSData *)dataForType:(NSString *)dataType; -- (id)propertyListForType:(NSString *)dataType; -- (NSString *)readFileContentsType:(NSString *)type - toFile:(NSString *)filename; -- (NSFileWrapper *)readFileWrapper; -- (NSString *)stringForType:(NSString *)dataType; +- (int) changeCount; +- (NSData*) dataForType: (NSString*)dataType; +- (id) propertyListForType: (NSString*)dataType; +- (NSString*) readFileContentsType: (NSString*)type + toFile: (NSString*)filename; +- (NSFileWrapper*) readFileWrapper; +- (NSString*) stringForType: (NSString*)dataType; @end @interface NSObject (NSPasteboardOwner) -// -// Methods Implemented by the Owner -// -- (void)pasteboard:(NSPasteboard *)sender -provideDataForType:(NSString *)type; -- (void)pasteboard:(NSPasteboard *)sender -provideDataForType:(NSString *)type - andVersion:(int)ver; -- (void)pasteboardChangedOwner:(NSPasteboard *)sender; - +- (void) pasteboard: (NSPasteboard*)sender + provideDataForType: (NSString*)type; +- (void) pasteboard: (NSPasteboard*)sender + provideDataForType: (NSString*)type + andVersion: (int)version; +- (void) pasteboardChangedOwner: (NSPasteboard*)sender; @end @interface NSPasteboard (GNUstepExtensions) -+ (NSString *) mimeTypeForPasteboardType: (NSString *)type; -+ (NSString *) pasteboardTypeForMimeType: (NSString *)mimeType; - -- (void)setChangeCount: (int)count; ++ (NSString*) mimeTypeForPasteboardType: (NSString*)type; ++ (NSString*) pasteboardTypeForMimeType: (NSString*)mimeType; +- (void) setChangeCount: (int)count; @end #ifndef STRICT_OPENSTEP #include @interface NSURL (NSPasteboard) -+ (NSURL *) URLFromPasteboard: (NSPasteboard *)pasteBoard; -- (void) writeToPasteboard: (NSPasteboard *)pasteBoard; ++ (NSURL*) URLFromPasteboard: (NSPasteboard*)pasteBoard; +- (void) writeToPasteboard: (NSPasteboard*)pasteBoard; @end #endif @@ -176,7 +244,7 @@ provideDataForType:(NSString *)type // Return File-related Pasteboard Types // APPKIT_EXPORT NSString *NSCreateFileContentsPboardType(NSString *fileType); -APPKIT_EXPORT NSString *NSCreateFilenamePboardType(NSString *filename); +APPKIT_EXPORT NSString *NSCreateFilenamePboardType(NSString *fileType); APPKIT_EXPORT NSString *NSGetFileType(NSString *pboardType); APPKIT_EXPORT NSArray *NSGetFileTypes(NSArray *pboardTypes); diff --git a/Source/NSPasteboard.m b/Source/NSPasteboard.m index f52bfd7bb..8b8f271d4 100644 --- a/Source/NSPasteboard.m +++ b/Source/NSPasteboard.m @@ -55,6 +55,9 @@ #include "gnustep/gui/GSServicesManager.h" #include "gnustep/gui/GSPasteboardServer.h" +static NSString *contentsPrefix = @"NSTypedFileContentsPboardType:"; +static NSString *namePrefix = @"NSTypedFilenamesPboardType:"; + /* * A pasteboard class for lazily filtering data */ @@ -62,8 +65,8 @@ { @public NSArray *originalTypes; - NSData *data; NSString *file; + NSData *data; NSPasteboard *pboard; } @end @@ -136,7 +139,6 @@ { DESTROY(originalTypes); DESTROY(data); - DESTROY(file); DESTROY(pboard); [super dealloc]; } @@ -205,13 +207,80 @@ if ([mechanism isEqualToString: @"NSUnixStdio"] == YES) { -// FIXME + NSMutableData *m = [NSMutableData dataWithCapacity: 1023]; + NSString *filename; + NSData *d; + NSPipe *p; + NSTask *t; + id o; + + /* + * The data for an NSUnixStdio filter must be one or more filenames + */ + if ([type isEqualToString: NSFilenamesPboardType] == NO + && [type hasPrefix: namePrefix] == NO) + { + [sender setData: [NSData data] forType: type]; + return; // Not the name of a file to filter. + } + if (data != nil) + { + d = data; + } + else if (file != nil) + { + d = [NSData dataWithContentsOfFile: file]; + } + else + { + d = [pboard dataForType: fromType]; + } + + o = [NSDeserializer deserializePropertyListFromData: d + mutableContainers: NO]; + if ([o isKindOfClass: [NSString class]] == YES) + { + filename = o; + } + else if ([o isKindOfClass: [NSArray class]] == YES + && [o count] > 0 + && [[o objectAtIndex: 0] isKindOfClass: [NSString class]] == YES) + { + filename = [o objectAtIndex: 0]; + } + else + { + [sender setData: [NSData data] forType: type]; + return; // Not the name of a file to filter. + } + + /* + * Set up and launch task to filter the named file. + */ + t = [NSTask new]; + [t setLaunchPath: [info objectForKey: @"NSPortName"]]; + [t setArguments: [NSArray arrayWithObject: filename]]; + p = [NSPipe pipe]; + [t setStandardOutput: p]; + [t launch]; + + /* + * Read all the data that the task writes. + */ + while ((d = [[p fileHandleForReading] availableData]) != nil) + { + [m appendData: d]; + } + [t waitUntilExit]; + RELEASE(t); + + /* + * And send it on. + */ + [sender setData: m forType: type]; } - else if ([mechanism isEqualToString: @"NSMapFile"] == YES) - { -// FIXME - } - else if ([mechanism isEqualToString: @"NSIdentity"] == YES) + else if ([mechanism isEqualToString: @"NSIdentity"] == YES + || [mechanism isEqualToString: @"NSMapFile"] == YES) { /* * An 'identity' filter simply places the required data on the @@ -278,6 +347,38 @@ - (id) _target; @end +/** + *

The pasteboard system is the primary mechanism for data exchange + * between OpenStep applications. It is used for cut and paste of data, + * as the exchange mechanism for services (as listed on the + * services menu), for communicating with a spelling server in order to + * perform spell checking, and for filter services which convert + * data of one typ to another transparently. + *

+ *

Pasteboards are identified by names, some of which are standard + * and are intended to exist permenantly and be shared between all + * applications, others are temporary or private and are used to handle + * specific services. + *

+ *

All data transferred to/from pasteboards is typed. Mostly + * using one of several standard types for common data or using standardised + * names which identify particular kinds of files and their contents + * (see the NSCreateFileContentsPboardType() an + * NSCreateFilenamePboardType() functions for details). It is also possible + * for cooperating applications to use their own private types ... any string + * value will do. + *

+ *

Each pasteboard has an owner ... an object which declares the + * types of data it can provide. That object is responsible for producing + * the data for the pasteboard when it is called for (or it may send all + * formats of data it supports to the pastebaord system before any other + * application calls for it).
+ * The pasteboard owner needs to implement the + * -pasteboard:provideDataForType: and -pasteboardChangedOwner: methods, + * and for extended (GNUstep specific) pastebaord support may implement + * -pasteboard:provideDataForType:andVersion: too. + *

+ */ @implementation NSPasteboard static NSLock *dictionary_lock = nil; @@ -577,12 +678,13 @@ static NSMapTable *mimeMap = NULL; } /** - *

Returns a pasteboard from which the data (of the specified type) - * can be read in all the types to which it can be converted by - * filter services. + *

Creates and returns a pasteboard from which the data in the named + * file can be read in all the types to which it can be converted by + * filter services.
+ * The type of data in the file is inferred from the file extension. *

- *

Also registers the pasteboard as providing information of the - * specified type. + *

No filtering is actually performed until some object asks the + * pasteboard for the data, so calling this method is quite inexpensive. *

*/ + (NSPasteboard*) pasteboardByFilteringData: (NSData*)data @@ -1152,26 +1254,51 @@ static NSMapTable *mimeMap = NULL; return s; } -/* - * Methods Implemented by the Owner +@end + + + +/** + * Methods to be implemented by pastebaord owners. + */ +@implementation NSObject (NSPasteboardOwner) +/** + * This method is called by the pasteboard system when it does not have + * the data that has been asked for ... the pasteboard owner should + * supply the data to the pasteboard by calling -setData:forType: or one + * of the related methods. */ - (void) pasteboard: (NSPasteboard*)sender provideDataForType: (NSString*)type { } +/** + * Implemented where GNUstep pasteboard extensions are required.
+ * This method is called by the pasteboard system when it does not have + * the data that has been asked for ... the pasteboard owner should + * supply the data to the pasteboard by calling -setData:forType: or one + * of the related methods. + */ - (void) pasteboard: (NSPasteboard*)sender provideDataForType: (NSString*)type andVersion: (int)version { } +/** + * This method is called by the pasteboard system when another object + * takes ownership of the pasteboard ... it lets the previous owner + * know that it is no longer required to supply data. + */ - (void) pasteboardChangedOwner: (NSPasteboard*)sender { } @end + + @implementation NSPasteboard (GNUstepExtensions) /** @@ -1292,35 +1419,65 @@ static NSMapTable *mimeMap = NULL; - (void) writeToPasteboard: (NSPasteboard *)pasteBoard { [pasteBoard setString: [self absoluteString] - forType: NSURLPboardType]; + forType: NSURLPboardType]; } @end -static NSString* contentsPrefix = @"NSTypedFileContentsPboardType:"; -static NSString* namePrefix = @"NSTypedFilenamesPboardType:"; - /** - * Returns a standardised pasteboard type for file contents, + *

Returns a standardised pasteboard type for file contents, * formed from the supplied file extension. + *

+ *

Data written to a pastebaord with a file contents type should + * be written using the [NSPasteboard-writeFileContents:] or + * [NSPasteboard-writeFileWrapper:] method. Similarly, the data should + * be read using the [NSPasteboard-readFileContentsType:toFile:] or + * [NSPasteboard-readFileWrapper] method. */ NSString* NSCreateFileContentsPboardType(NSString *fileType) { - return [NSString stringWithFormat: @"%@%@", contentsPrefix, fileType]; + NSString *ext = [fileType pathExtension]; + + if ([ext length] == 0) + { + ext = fileType; + } + return [NSString stringWithFormat: @"%@%@", contentsPrefix, ext]; } /** - * Returns a standardised pasteboard type for file names, + *

Returns a standardised pasteboard type for file names, * formed from the supplied file extension. + *

+ *

Data written to a pastebaord with a file names type should + * be a single name writen using [NSPasteboard-setString:forType:] or + * an array of strings written using + * [NSPasteboard-setPropertyList:forType:].
+ * Similarly, the data should be read using + * the [NSPasteboard-stringForType:] or + * [NSPasteboard-propertyListForType:] method. + *

+ *

See also the NSGetFileType() and NSGetFileTypes() functions. */ NSString* -NSCreateFilenamePboardType(NSString *filename) +NSCreateFilenamePboardType(NSString *fileType) { - return [NSString stringWithFormat: @"%@%@", namePrefix, filename]; + NSString *ext = [fileType pathExtension]; + + if ([ext length] == 0) + { + ext = fileType; + } + return [NSString stringWithFormat: @"%@%@", namePrefix, ext]; } +/** + * Returns the file type (fileType extension) corresponding to the + * pasteboard type given.
+ * This is a counterpart to the NSCreateFilenamePboardType() function. + */ NSString* NSGetFileType(NSString *pboardType) { @@ -1335,6 +1492,10 @@ NSGetFileType(NSString *pboardType) return nil; } +/** + * Returns the file types (filename extensions) corresponding to the + * pasteboard types given. + */ NSArray* NSGetFileTypes(NSArray *pboardTypes) {