diff --git a/ChangeLog b/ChangeLog index 495c1587d..186b4f19f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2003-06-27 Richard Frith-Macdonald + + * Source/NSPasteboard.m: Documented all methods, fixed minor bugs + writign fiels to pastebaords, implemented ([+typesFilterableTo:]) + 2003-06-26 Ludovic Marcotte * Fixed the transparency of Images/common_ret.tiff diff --git a/Headers/gnustep/gui/GSServicesManager.h b/Headers/gnustep/gui/GSServicesManager.h index 01d5bc80b..ff7f3a6f8 100644 --- a/Headers/gnustep/gui/GSServicesManager.h +++ b/Headers/gnustep/gui/GSServicesManager.h @@ -66,6 +66,7 @@ - (BOOL) application: (NSApplication*)theApp printFile: (NSString*)file; - (void) doService: (NSMenuItem*)item; +- (NSDictionary*) filters; - (BOOL) hasRegisteredTypes: (NSDictionary*)service; - (NSString*) item2title: (NSMenuItem*)item; - (void) loadServices; diff --git a/Source/GSServicesManager.m b/Source/GSServicesManager.m index 4242b0df7..24a5dc8f3 100644 --- a/Source/GSServicesManager.m +++ b/Source/GSServicesManager.m @@ -545,6 +545,14 @@ static NSString *disabledName = @".GNUstepDisabled"; } } +/** + * Return a dictionary of information about registered filter services. + */ +- (NSDictionary*) filters +{ + return [_allServices objectForKey: @"ByFilter"]; +} + - (BOOL) hasRegisteredTypes: (NSDictionary*)service { NSArray *sendTypes = [service objectForKey: @"NSSendTypes"]; @@ -1438,7 +1446,10 @@ NSShowsServicesMenuItem(NSString *name) /** * A services providing application may use this to update the list of - * services it provides. + * services it provides.
+ * In order to update the services advertised, the application must + * create a .service bundle and place it in + * ~/Library/Services before invoking this function. */ void NSUpdateDynamicServices(void) diff --git a/Source/NSPasteboard.m b/Source/NSPasteboard.m index f2664e95a..c31468773 100644 --- a/Source/NSPasteboard.m +++ b/Source/NSPasteboard.m @@ -3,7 +3,7 @@ Implementation of class for communicating with the pasteboard server. - Copyright (C) 1997,1999 Free Software Foundation, Inc. + Copyright (C) 1997,1999,2003 Free Software Foundation, Inc. Author: Richard Frith-Macdonald Date: 1997 @@ -48,9 +48,11 @@ #include #include #include +#include #include #include +#include "gnustep/gui/GSServicesManager.h" #include "gnustep/gui/GSPasteboardServer.h" @interface NSPasteboard (Private) @@ -276,11 +278,28 @@ static NSMapTable *mimeMap = NULL; return p; } +/** + * Returns the general pasteboard found by calling +pasteboardWithName: + * with NSGeneralPboard as the name. + */ + (NSPasteboard*) generalPasteboard { return [self pasteboardWithName: NSGeneralPboard]; } +/** + *

Returns the pastebaord for the specified name. Creates a new pasreboard + * if (and only if) one with the given name does not exist. + *

+ * Standard pastebaord names are - + * + * NSGeneralPboard + * NSFontPboard + * NSRulerPboard + * NSFindPboard + * NSDragPboard + * + */ + (NSPasteboard*) pasteboardWithName: (NSString*)aName { NS_DURING @@ -306,6 +325,10 @@ static NSMapTable *mimeMap = NULL; return nil; } +/** + * Creates and returns a new pasteboard with a name guaranteed to be unique + * within the pasteboard server. + */ + (NSPasteboard*) pasteboardWithUniqueName { NS_DURING @@ -337,8 +360,14 @@ static NSMapTable *mimeMap = NULL; return nil; } -/* - * Getting Data in Different Formats +/** + *

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. + *

+ *

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

*/ + (NSPasteboard*) pasteboardByFilteringData: (NSData*)data ofType: (NSString*)type @@ -374,6 +403,13 @@ static NSMapTable *mimeMap = NULL; return nil; } +/** + *

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. + *

+ */ + (NSPasteboard*) pasteboardByFilteringFile: (NSString*)filename { NSData *data; @@ -412,6 +448,17 @@ static NSMapTable *mimeMap = NULL; return nil; } +/** + *

Creates and returns a pasteboard in where the data contained in pboard + * is available for reading in as many types as it can be converted to by + * available filter services. This normally expands on the range of types + * available in pboard. + *

+ *

NB. This only permits a singlke level of filtering ... if pboard was + * previously returned by another filtering method, it is returned instead + * of a new pastebaord. + *

+ */ + (NSPasteboard*) pasteboardByFilteringTypesInPasteboard: (NSPasteboard*)pboard { NS_DURING @@ -448,22 +495,36 @@ static NSMapTable *mimeMap = NULL; return nil; } +/** + * Returns an array of the types to which data of the specified type + * can be converted by registered filter services.
+ * The original type is always present in this array.
+ * Raises an exception if type is nil. + */ + (NSArray*) typesFilterableTo: (NSString*)type { - NSArray* types = nil; + NSMutableSet *types = [NSMutableSet setWithCapacity: 8]; + NSDictionary *info = [[GSServicesManager manager] filters]; + NSEnumerator *enumerator = [info objectEnumerator]; - NS_DURING + [types addObject: type]; // Always include original type + + /* + * Step through the filters looking for those which handle the type + */ + while ((info = [enumerator nextObject]) != nil) { - types = [[self _pbs] typesFilterableTo: type]; + NSArray *sendTypes = [info objectForKey: @"NSSendTypes"]; + + if ([sendTypes containsObject: type] == YES) + { + NSArray *returnTypes = [info objectForKey: @"NSReturnTypes"]; + + [types addObjectsFromArray: returnTypes]; + } } - NS_HANDLER - { - types = nil; - [NSException raise: NSPasteboardCommunicationException - format: @"%@", [localException reason]]; - } - NS_ENDHANDLER - return types; + + return [types allObjects]; } /* @@ -486,22 +547,43 @@ static NSMapTable *mimeMap = NULL; [super dealloc]; } +/** + * Releases the receiver in the pastebaord server so that no other application + * can use the pasteboard. This should not be called for any of the standard + * pasteboards, only for temporary ones. + */ - (void) releaseGlobally { + if ([name isEqualToString: NSGeneralPboard] == YES + || [name isEqualToString: NSFontPboard] == YES + || [name isEqualToString: NSRulerPboard] == YES + || [name isEqualToString: NSFindPboard] == YES + || [name isEqualToString: NSDragPboard] == YES) + { + [NSException raise: NSGenericException + format: @"Illegal attempt to globally release %@", name]; + } [target releaseGlobally]; [pasteboards removeObjectForKey: name]; } -/* - * Referring to a Pasteboard by Name +/** + * Returns the pasteboard name for the receiver. */ - (NSString*) name { return name; } -/* - * Writing Data +/** + *

Adds newTypes to the pasteboard and declares newOwner to be the owner + * of the pasteboard. Use only after -declareTypes:owner: has been called + * for the same owner, because the new owner may not support all the types + * declared by a previous owner. + *

+ *

Returns the new change count for the pastebaord, or zero if an error + * occurs. + *

*/ - (int) addTypes: (NSArray*)newTypes owner: (id)newOwner @@ -529,6 +611,14 @@ static NSMapTable *mimeMap = NULL; return count; } +/** + *

Sets the owner of the pastebaord to be newOwner and declares newTypes + * as the types of data supported by it. + *

+ *

Returns the new change count for the pastebaord, or zero if an error + * occurs. + *

+ */ - (int) declareTypes: (NSArray*)newTypes owner: (id)newOwner { @@ -566,6 +656,15 @@ static NSMapTable *mimeMap = NULL; RELEASE(super); } +/** + *

Writes data of type dataType to the pasteboard server so that other + * applications can read it. The dataType must be one of the types + * previously declared for the pastebaord. + *

+ *

Returns YES on success, NO if the data could not be written for some + * reason. + *

+ */ - (BOOL) setData: (NSData*)data forType: (NSString*)dataType { @@ -588,6 +687,10 @@ static NSMapTable *mimeMap = NULL; return ok; } +/** + * Serialises the data in the supplied property list and writes it to the + * pastebaord server using the -setData:forType: method. + */ - (BOOL) setPropertyList: (id)propertyList forType: (NSString*)dataType { @@ -596,27 +699,50 @@ static NSMapTable *mimeMap = NULL; return [self setData: d forType: dataType]; } +/** + * Writes string it to the pastebaord server using the + * -setPropertyList:forType: method. + */ - (BOOL) setString: (NSString*)string forType: (NSString*)dataType { return [self setPropertyList: string forType: dataType]; } +/** + * Writes the contents of the file filename to the pasteboard server + * after declaring the type NSFileContentsPboardType as well as a type + * based on the file extension (given by the NSCreateFileContentsPboardType() + * function) if there is one. + */ - (BOOL) writeFileContents: (NSString*)filename { NSFileWrapper *wrapper; NSData *data; - NSString *type; + NSArray *types; + NSString *ext = [filename pathExtension]; BOOL ok = NO; wrapper = [[NSFileWrapper alloc] initWithPath: filename]; data = [wrapper serializedRepresentation]; RELEASE(wrapper); - type = NSCreateFileContentsPboardType([filename pathExtension]); + if ([ext length] > 0) + { + types = [NSArray arrayWithObjects: NSFileContentsPboardType, + NSCreateFileContentsPboardType(ext), nil]; + } + else + { + types = [NSArray arrayWithObject: NSFileContentsPboardType]; + } + if ([self declareTypes: types owner: owner] == 0) + { + return NO; // Unable to declare types. + } NS_DURING { ok = [target setData: data - forType: type + forType: NSFileContentsPboardType isFile: YES oldCount: changeCount]; } @@ -630,11 +756,20 @@ static NSMapTable *mimeMap = NULL; return ok; } +/** + *

Writes the contents of the file wrapper to the pasteboard server + * after declaring the type NSFileContentsPboardType as well as a type + * based on the file extension of the wrappers preferred filename. + *

+ *

Raises an exception if there is no preferred filename. + *

+ */ - (BOOL) writeFileWrapper: (NSFileWrapper *)wrapper { NSString *filename = [wrapper preferredFilename]; NSData *data; - NSString *type; + NSArray *types; + NSString *ext = [filename pathExtension]; BOOL ok = NO; if (filename == nil) @@ -643,13 +778,24 @@ static NSMapTable *mimeMap = NULL; format: @"Cannot put file on pastboard with " @"no preferred filename"]; } - data = [wrapper serializedRepresentation]; - type = NSCreateFileContentsPboardType([filename pathExtension]); + if ([ext length] > 0) + { + types = [NSArray arrayWithObjects: NSFileContentsPboardType, + NSCreateFileContentsPboardType(ext), nil]; + } + else + { + types = [NSArray arrayWithObject: NSFileContentsPboardType]; + } + if ([self declareTypes: types owner: owner] == 0) + { + return NO; // Unable to declare types. + } NS_DURING { ok = [target setData: data - forType: type + forType: NSFileContentsPboardType isFile: YES oldCount: changeCount]; } @@ -663,8 +809,9 @@ static NSMapTable *mimeMap = NULL; return ok; } -/* - * Determining Types +/** + * Returns the first type listed in types which the receiver has been + * declared to support. */ - (NSString*) availableTypeFromArray: (NSArray*)types { @@ -688,6 +835,9 @@ static NSMapTable *mimeMap = NULL; return type; } +/** + * Returns all the types that the receiver has been declared to support. + */ - (NSArray*) types { NSArray *result = nil; @@ -709,8 +859,9 @@ static NSMapTable *mimeMap = NULL; return result; } -/* - * Reading Data +/** + * Returns the change count for the receiving pastebaord. This count + * is incremented whenever the owner of the pastebaord is changed. */ - (int) changeCount { @@ -730,6 +881,11 @@ static NSMapTable *mimeMap = NULL; return changeCount; } +/** + * Returns data from the pasteboard of the specified dataType, or nil + * if no such data is available.
+ * May raise an exception if communication with the pasteboard server fails. + */ - (NSData*) dataForType: (NSString*)dataType { NSData *d = nil; @@ -750,6 +906,10 @@ static NSMapTable *mimeMap = NULL; return d; } +/** + * Calls -dataForType: to obtain data (expected to be a serialized property + * list) and returns the object produced by deserializing it. + */ - (id) propertyListForType: (NSString*)dataType { NSData *d = [self dataForType: dataType]; @@ -761,6 +921,10 @@ static NSMapTable *mimeMap = NULL; return nil; } +/** + * Obtains data of the specified dataType from the pastebaord, deserializes + * it to the specified filename and returns the file name (or nil on failure). + */ - (NSString*) readFileContentsType: (NSString*)type toFile: (NSString*)filename { @@ -789,7 +953,11 @@ static NSMapTable *mimeMap = NULL; return filename; } -- (NSFileWrapper *)readFileWrapper +/** + * Obtains data of the specified dataType from the pastebaord, deserializes + * it and returns the resulting file wrapper (or nil). + */ +- (NSFileWrapper*) readFileWrapper { NSData *d = [self dataForType: NSFileContentsPboardType]; @@ -800,9 +968,19 @@ static NSMapTable *mimeMap = NULL; AUTORELEASE([[NSFileWrapper alloc] initWithSerializedRepresentation: d]); } +/** + * Obtains data of the specified dataType from the pastebaord, deserializes + * it and returns the resulting string (or nil). + */ - (NSString*) stringForType: (NSString*)dataType { - return [self propertyListForType: dataType]; + NSString *s = [self propertyListForType: dataType]; + + if ([s isKindOfClass: [NSString class]] == NO) + { + s = nil; + } + return s; } /* @@ -827,12 +1005,12 @@ static NSMapTable *mimeMap = NULL; @implementation NSPasteboard (GNUstepExtensions) -/* - * Once the '[-setChangeCount: ]' message has been sent to an NSPasteboard - * the object will gain an extra GNUstep behaviour - when geting data - * from the pasteboard, the data need no longer be from the latest - * version but may be a version from a previous representation with - * the specified change count. +/** + * Once the -setChangeCount: message has been sent to an NSPasteboard + * the object will gain an extra GNUstep behaviour - when geting data + * from the pasteboard, the data need no longer be from the latest + * version but may be a version from a previous representation with + * the specified change count. */ - (void) setChangeCount: (int)count { @@ -840,6 +1018,10 @@ static NSMapTable *mimeMap = NULL; changeCount = count; } +/** + * Sets the number of changes for which pasteboard data is kept.
+ * This is 1 by default. + */ - (void) setHistory: (unsigned)length { NS_DURING @@ -877,7 +1059,7 @@ static NSMapTable *mimeMap = NULL; (void *)@"text/plain"); } -/* +/** * Return the mapping for pasteboard->mime, or return the original pasteboard * type if no mapping is found */ @@ -897,7 +1079,7 @@ static NSMapTable *mimeMap = NULL; return mime; } -/* +/** * Return the mapping for mime->pasteboard, or return the original pasteboard * type if no mapping is found. This method may not have a one-to-one * mapping @@ -950,12 +1132,20 @@ static NSMapTable *mimeMap = NULL; static NSString* contentsPrefix = @"NSTypedFileContentsPboardType:"; static NSString* namePrefix = @"NSTypedFilenamesPboardType:"; +/** + * Returns a standardised pasteboard type for file contents, + * formed from the supplied file extension. + */ NSString* NSCreateFileContentsPboardType(NSString *fileType) { return [NSString stringWithFormat: @"%@%@", contentsPrefix, fileType]; } +/** + * Returns a standardised pasteboard type for file names, + * formed from the supplied file extension. + */ NSString* NSCreateFilenamePboardType(NSString *filename) {