From f9f1b64f5d61a7c01ecab66a23f6ac424aea468f Mon Sep 17 00:00:00 2001
From: CaS
Date: Fri, 27 Jun 2003 12:08:13 +0000
Subject: [PATCH] Partial implementation of filtering services
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@17046 72102866-910b-0410-8b05-ffd578937521
---
Source/NSPasteboard.m | 273 ++++++++++++++++++++++++------------------
1 file changed, 159 insertions(+), 114 deletions(-)
diff --git a/Source/NSPasteboard.m b/Source/NSPasteboard.m
index c31468773..accc77347 100644
--- a/Source/NSPasteboard.m
+++ b/Source/NSPasteboard.m
@@ -55,6 +55,98 @@
#include "gnustep/gui/GSServicesManager.h"
#include "gnustep/gui/GSPasteboardServer.h"
+/*
+ * A pasteboard class for lazily filtering data
+ */
+@interface FilteredPasteboard : NSPasteboard
+{
+@public
+ NSArray *originalTypes;
+ NSData *data;
+ NSString *file;
+ NSPasteboard *pboard;
+}
+@end
+
+@implementation FilteredPasteboard
+/**
+ * Given an array of types, produce an array of all the types we can
+ * make from that using a single filter.
+ */
++ (NSArray*) _typesFilterableFrom: (NSArray*)from
+{
+ NSMutableSet *types = [NSMutableSet setWithCapacity: 8];
+ NSDictionary *info = [[GSServicesManager manager] filters];
+ unsigned i;
+
+ for (i = 0; i < [from count]; i++)
+ {
+ NSString *type = [from objectAtIndex: i];
+ NSEnumerator *enumerator = [info objectEnumerator];
+
+ [types addObject: type]; // Always include original type
+
+ while ((info = [enumerator nextObject]) != nil)
+ {
+ NSArray *sendTypes = [info objectForKey: @"NSSendTypes"];
+
+ if ([sendTypes containsObject: type] == YES)
+ {
+ NSArray *returnTypes = [info objectForKey: @"NSReturnTypes"];
+
+ [types addObjectsFromArray: returnTypes];
+ }
+ }
+ }
+ return [types allObjects];
+}
+
+- (void) dealloc
+{
+ DESTROY(originalTypes);
+ DESTROY(data);
+ DESTROY(file);
+ DESTROY(pboard);
+ [super dealloc];
+}
+
+/**
+ * This method actually performs any filtering required.
+ */
+- (void) pasteboard: (NSPasteboard*)sender
+ provideDataForType: (NSString*)type
+{
+ /*
+ * If the requested type is the same as one of the original types,
+ * no filtering is required ... and we can just write what we have.
+ */
+ if ([originalTypes containsObject: type] == YES)
+ {
+ if (data != nil)
+ {
+ [sender setData: data forType: type];
+ }
+ else if (file != nil)
+ {
+ [sender writeFileContents: file];
+ }
+ else
+ {
+ NSData *d = [pboard dataForType: type];
+
+ [sender setData: d forType: type];
+ }
+ }
+ else
+ {
+// FIXME
+ }
+}
+
+@end
+
+
+
@interface NSPasteboard (Private)
+ (id) _pbs;
+ (NSPasteboard*) _pasteboardWithTarget: (id)aTarget
@@ -230,11 +322,11 @@ static NSMapTable *mimeMap = NULL;
+ (NSPasteboard*) _pasteboardWithTarget: (id)aTarget
name: (NSString*)aName
{
- NSPasteboard* p = nil;
+ NSPasteboard *p = nil;
[dictionary_lock lock];
p = [pasteboards objectForKey: aName];
- if (p)
+ if (p != nil)
{
/*
* It is conceivable that the following may have occurred -
@@ -258,8 +350,8 @@ static NSMapTable *mimeMap = NULL;
* For a newly created NSPasteboard object, we must make an entry
* in the dictionary so we can look it up safely.
*/
- p = [NSPasteboard alloc];
- if (p)
+ p = [self alloc];
+ if (p != nil)
{
p->target = RETAIN((id)aTarget);
p->name = RETAIN(aName);
@@ -288,10 +380,10 @@ static NSMapTable *mimeMap = NULL;
}
/**
- * Returns the pastebaord for the specified name. Creates a new pasreboard
+ *
Returns the pasteboard for the specified name. Creates a new pasreboard
* if (and only if) one with the given name does not exist.
*
- * Standard pastebaord names are -
+ * Standard pasteboard names are -
*
* - NSGeneralPboard
* - NSFontPboard
@@ -372,35 +464,17 @@ static NSMapTable *mimeMap = NULL;
+ (NSPasteboard*) pasteboardByFilteringData: (NSData*)data
ofType: (NSString*)type
{
- NS_DURING
- {
- id anObj;
+ FilteredPasteboard *p;
+ NSArray *types;
+ NSArray *originalTypes;
- anObj = [[self _pbs] pasteboardByFilteringData: data
- ofType: type
- isFile: NO];
- if (anObj)
- {
- NSString *aName;
-
- aName = [anObj name];
- if (aName)
- {
- NSPasteboard *ret;
-
- ret = [self _pasteboardWithTarget: anObj name: aName];
- NS_VALRETURN(ret);
- }
- }
- }
- NS_HANDLER
- {
- [NSException raise: NSPasteboardCommunicationException
- format: @"%@", [localException reason]];
- }
- NS_ENDHANDLER
-
- return nil;
+ originalTypes = [NSArray arrayWithObject: type];
+ types = [FilteredPasteboard _typesFilterableFrom: originalTypes];
+ p = (FilteredPasteboard*)[FilteredPasteboard pasteboardWithUniqueName];
+ p->originalTypes = [originalTypes copy];
+ p->data = [data copy];
+ [p declareTypes: types owner: p];
+ return p;
}
/**
@@ -412,92 +486,63 @@ static NSMapTable *mimeMap = NULL;
*/
+ (NSPasteboard*) pasteboardByFilteringFile: (NSString*)filename
{
- NSData *data;
- NSString *type;
+ FilteredPasteboard *p;
+ NSString *ext = [filename pathExtension];
+ NSArray *types;
+ NSArray *originalTypes;
- data = [NSData dataWithContentsOfFile: filename];
- type = NSCreateFileContentsPboardType([filename pathExtension]);
- NS_DURING
+ if ([ext length] > 0)
{
- id anObj;
-
- anObj = [[self _pbs] pasteboardByFilteringData: data
- ofType: type
- isFile: YES];
- if (anObj)
- {
- NSString *aName;
-
- aName = [anObj name];
- if (aName)
- {
- NSPasteboard *ret;
-
- ret = [self _pasteboardWithTarget: anObj name: aName];
- NS_VALRETURN(ret);
- }
- }
+ originalTypes = [NSArray arrayWithObjects:
+ NSCreateFileContentsPboardType(ext),
+ NSFileContentsPboardType,
+ nil];
}
- NS_HANDLER
+ else
{
- [NSException raise: NSPasteboardCommunicationException
- format: @"%@", [localException reason]];
+ originalTypes = [NSArray arrayWithObject: NSFileContentsPboardType];
}
- NS_ENDHANDLER
-
- return nil;
+ types = [FilteredPasteboard _typesFilterableFrom: originalTypes];
+ p = (FilteredPasteboard*)[FilteredPasteboard pasteboardWithUniqueName];
+ p->originalTypes = [originalTypes copy];
+ p->file = [filename copy];
+ [p declareTypes: types owner: p];
+ return p;
}
/**
- * Creates and returns a pasteboard in where the data contained in pboard
+ *
Creates and returns a pasteboard 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
+ *
NB. This only permits a single level of filtering ... if pboard was
* previously returned by another filtering method, it is returned instead
- * of a new pastebaord.
+ * of a new pasteboard.
*
*/
+ (NSPasteboard*) pasteboardByFilteringTypesInPasteboard: (NSPasteboard*)pboard
{
- NS_DURING
+ FilteredPasteboard *p;
+ NSArray *types;
+ NSArray *originalTypes;
+
+ if ([pboard isKindOfClass: [FilteredPasteboard class]] == YES)
{
- id anObj;
-
- anObj = [pboard _target];
- if (anObj)
- {
- anObj = [[self _pbs] pasteboardByFilteringTypesInPasteboard: anObj];
- if (anObj)
- {
- NSString *aName;
-
- aName = [anObj name];
- if (aName)
- {
- NSPasteboard *ret;
-
- ret = [self _pasteboardWithTarget: anObj
- name: (NSString*)aName];
- NS_VALRETURN(ret);
- }
- }
- }
+ return pboard;
}
- NS_HANDLER
- {
- [NSException raise: NSPasteboardCommunicationException
- format: @"%@", [localException reason]];
- }
- NS_ENDHANDLER
-
- return nil;
+ originalTypes = [pboard types];
+ types = [FilteredPasteboard _typesFilterableFrom: originalTypes];
+ p = (FilteredPasteboard*)[FilteredPasteboard pasteboardWithUniqueName];
+ p->originalTypes = [originalTypes copy];
+ p->pboard = RETAIN(pboard);
+ [p declareTypes: types owner: p];
+ return p;
}
/**
- * Returns an array of the types to which data of the specified type
- * can be converted by registered filter services.
+ * Returns an array of the types from which data of the specified type
+ * can be produced by registered filter services.
* The original type is always present in this array.
* Raises an exception if type is nil.
*/
@@ -514,13 +559,13 @@ static NSMapTable *mimeMap = NULL;
*/
while ((info = [enumerator nextObject]) != nil)
{
- NSArray *sendTypes = [info objectForKey: @"NSSendTypes"];
+ NSArray *returnTypes = [info objectForKey: @"NSReturnTypes"];
- if ([sendTypes containsObject: type] == YES)
+ if ([returnTypes containsObject: type] == YES)
{
- NSArray *returnTypes = [info objectForKey: @"NSReturnTypes"];
+ NSArray *sendTypes = [info objectForKey: @"NSSendTypes"];
- [types addObjectsFromArray: returnTypes];
+ [types addObjectsFromArray: sendTypes];
}
}
@@ -548,7 +593,7 @@ static NSMapTable *mimeMap = NULL;
}
/**
- * Releases the receiver in the pastebaord server so that no other application
+ * Releases the receiver in the pasteboard 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.
*/
@@ -581,7 +626,7 @@ static NSMapTable *mimeMap = NULL;
* 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
+ *
Returns the new change count for the pasteboard, or zero if an error
* occurs.
*
*/
@@ -612,10 +657,10 @@ static NSMapTable *mimeMap = NULL;
}
/**
- * Sets the owner of the pastebaord to be newOwner and declares newTypes
+ *
Sets the owner of the pasteboard 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
+ *
Returns the new change count for the pasteboard, or zero if an error
* occurs.
*
*/
@@ -659,7 +704,7 @@ static NSMapTable *mimeMap = NULL;
/**
* 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.
+ * previously declared for the pasteboard.
*
* Returns YES on success, NO if the data could not be written for some
* reason.
@@ -689,7 +734,7 @@ static NSMapTable *mimeMap = NULL;
/**
* Serialises the data in the supplied property list and writes it to the
- * pastebaord server using the -setData:forType: method.
+ * pasteboard server using the -setData:forType: method.
*/
- (BOOL) setPropertyList: (id)propertyList
forType: (NSString*)dataType
@@ -700,7 +745,7 @@ static NSMapTable *mimeMap = NULL;
}
/**
- * Writes string it to the pastebaord server using the
+ * Writes string it to the pasteboard server using the
* -setPropertyList:forType: method.
*/
- (BOOL) setString: (NSString*)string
@@ -860,8 +905,8 @@ static NSMapTable *mimeMap = NULL;
}
/**
- * Returns the change count for the receiving pastebaord. This count
- * is incremented whenever the owner of the pastebaord is changed.
+ * Returns the change count for the receiving pasteboard. This count
+ * is incremented whenever the owner of the pasteboard is changed.
*/
- (int) changeCount
{
@@ -922,7 +967,7 @@ static NSMapTable *mimeMap = NULL;
}
/**
- * Obtains data of the specified dataType from the pastebaord, deserializes
+ * Obtains data of the specified dataType from the pasteboard, deserializes
* it to the specified filename and returns the file name (or nil on failure).
*/
- (NSString*) readFileContentsType: (NSString*)type
@@ -954,7 +999,7 @@ static NSMapTable *mimeMap = NULL;
}
/**
- * Obtains data of the specified dataType from the pastebaord, deserializes
+ * Obtains data of the specified dataType from the pasteboard, deserializes
* it and returns the resulting file wrapper (or nil).
*/
- (NSFileWrapper*) readFileWrapper
@@ -969,7 +1014,7 @@ static NSMapTable *mimeMap = NULL;
}
/**
- * Obtains data of the specified dataType from the pastebaord, deserializes
+ * Obtains data of the specified dataType from the pasteboard, deserializes
* it and returns the resulting string (or nil).
*/
- (NSString*) stringForType: (NSString*)dataType