mirror of
https://github.com/gnustep/libs-gui.git
synced 2025-04-29 11:21:05 +00:00
Partial implementation of filtering services
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@17046 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
11fd5099ac
commit
f9f1b64f5d
1 changed files with 159 additions and 114 deletions
|
@ -55,6 +55,98 @@
|
||||||
#include "gnustep/gui/GSServicesManager.h"
|
#include "gnustep/gui/GSServicesManager.h"
|
||||||
#include "gnustep/gui/GSPasteboardServer.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)
|
@interface NSPasteboard (Private)
|
||||||
+ (id<GSPasteboardSvr>) _pbs;
|
+ (id<GSPasteboardSvr>) _pbs;
|
||||||
+ (NSPasteboard*) _pasteboardWithTarget: (id<GSPasteboardObj>)aTarget
|
+ (NSPasteboard*) _pasteboardWithTarget: (id<GSPasteboardObj>)aTarget
|
||||||
|
@ -234,7 +326,7 @@ static NSMapTable *mimeMap = NULL;
|
||||||
|
|
||||||
[dictionary_lock lock];
|
[dictionary_lock lock];
|
||||||
p = [pasteboards objectForKey: aName];
|
p = [pasteboards objectForKey: aName];
|
||||||
if (p)
|
if (p != nil)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* It is conceivable that the following may have occurred -
|
* 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
|
* For a newly created NSPasteboard object, we must make an entry
|
||||||
* in the dictionary so we can look it up safely.
|
* in the dictionary so we can look it up safely.
|
||||||
*/
|
*/
|
||||||
p = [NSPasteboard alloc];
|
p = [self alloc];
|
||||||
if (p)
|
if (p != nil)
|
||||||
{
|
{
|
||||||
p->target = RETAIN((id)aTarget);
|
p->target = RETAIN((id)aTarget);
|
||||||
p->name = RETAIN(aName);
|
p->name = RETAIN(aName);
|
||||||
|
@ -288,10 +380,10 @@ static NSMapTable *mimeMap = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>Returns the pastebaord for the specified name. Creates a new pasreboard
|
* <p>Returns the pasteboard for the specified name. Creates a new pasreboard
|
||||||
* if (and only if) one with the given name does not exist.
|
* if (and only if) one with the given name does not exist.
|
||||||
* </p>
|
* </p>
|
||||||
* Standard pastebaord names are -
|
* Standard pasteboard names are -
|
||||||
* <list>
|
* <list>
|
||||||
* <item>NSGeneralPboard</item>
|
* <item>NSGeneralPboard</item>
|
||||||
* <item>NSFontPboard</item>
|
* <item>NSFontPboard</item>
|
||||||
|
@ -372,35 +464,17 @@ static NSMapTable *mimeMap = NULL;
|
||||||
+ (NSPasteboard*) pasteboardByFilteringData: (NSData*)data
|
+ (NSPasteboard*) pasteboardByFilteringData: (NSData*)data
|
||||||
ofType: (NSString*)type
|
ofType: (NSString*)type
|
||||||
{
|
{
|
||||||
NS_DURING
|
FilteredPasteboard *p;
|
||||||
{
|
NSArray *types;
|
||||||
id<GSPasteboardObj> anObj;
|
NSArray *originalTypes;
|
||||||
|
|
||||||
anObj = [[self _pbs] pasteboardByFilteringData: data
|
originalTypes = [NSArray arrayWithObject: type];
|
||||||
ofType: type
|
types = [FilteredPasteboard _typesFilterableFrom: originalTypes];
|
||||||
isFile: NO];
|
p = (FilteredPasteboard*)[FilteredPasteboard pasteboardWithUniqueName];
|
||||||
if (anObj)
|
p->originalTypes = [originalTypes copy];
|
||||||
{
|
p->data = [data copy];
|
||||||
NSString *aName;
|
[p declareTypes: types owner: p];
|
||||||
|
return p;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -412,92 +486,63 @@ static NSMapTable *mimeMap = NULL;
|
||||||
*/
|
*/
|
||||||
+ (NSPasteboard*) pasteboardByFilteringFile: (NSString*)filename
|
+ (NSPasteboard*) pasteboardByFilteringFile: (NSString*)filename
|
||||||
{
|
{
|
||||||
NSData *data;
|
FilteredPasteboard *p;
|
||||||
NSString *type;
|
NSString *ext = [filename pathExtension];
|
||||||
|
NSArray *types;
|
||||||
|
NSArray *originalTypes;
|
||||||
|
|
||||||
data = [NSData dataWithContentsOfFile: filename];
|
if ([ext length] > 0)
|
||||||
type = NSCreateFileContentsPboardType([filename pathExtension]);
|
|
||||||
NS_DURING
|
|
||||||
{
|
{
|
||||||
id<GSPasteboardObj> anObj;
|
originalTypes = [NSArray arrayWithObjects:
|
||||||
|
NSCreateFileContentsPboardType(ext),
|
||||||
anObj = [[self _pbs] pasteboardByFilteringData: data
|
NSFileContentsPboardType,
|
||||||
ofType: type
|
nil];
|
||||||
isFile: YES];
|
}
|
||||||
if (anObj)
|
else
|
||||||
{
|
{
|
||||||
NSString *aName;
|
originalTypes = [NSArray arrayWithObject: NSFileContentsPboardType];
|
||||||
|
|
||||||
aName = [anObj name];
|
|
||||||
if (aName)
|
|
||||||
{
|
|
||||||
NSPasteboard *ret;
|
|
||||||
|
|
||||||
ret = [self _pasteboardWithTarget: anObj name: aName];
|
|
||||||
NS_VALRETURN(ret);
|
|
||||||
}
|
}
|
||||||
}
|
types = [FilteredPasteboard _typesFilterableFrom: originalTypes];
|
||||||
}
|
p = (FilteredPasteboard*)[FilteredPasteboard pasteboardWithUniqueName];
|
||||||
NS_HANDLER
|
p->originalTypes = [originalTypes copy];
|
||||||
{
|
p->file = [filename copy];
|
||||||
[NSException raise: NSPasteboardCommunicationException
|
[p declareTypes: types owner: p];
|
||||||
format: @"%@", [localException reason]];
|
return p;
|
||||||
}
|
|
||||||
NS_ENDHANDLER
|
|
||||||
|
|
||||||
return nil;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>Creates and returns a pasteboard in where the data contained in pboard
|
* <p>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
|
* 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 filter services. This normally expands on the range of types
|
||||||
* available in pboard.
|
* available in pboard.
|
||||||
* </p>
|
* </p>
|
||||||
* <p>NB. This only permits a singlke level of filtering ... if pboard was
|
* <p>NB. This only permits a single level of filtering ... if pboard was
|
||||||
* previously returned by another filtering method, it is returned instead
|
* previously returned by another filtering method, it is returned instead
|
||||||
* of a new pastebaord.
|
* of a new pasteboard.
|
||||||
* </p>
|
* </p>
|
||||||
*/
|
*/
|
||||||
+ (NSPasteboard*) pasteboardByFilteringTypesInPasteboard: (NSPasteboard*)pboard
|
+ (NSPasteboard*) pasteboardByFilteringTypesInPasteboard: (NSPasteboard*)pboard
|
||||||
{
|
{
|
||||||
NS_DURING
|
FilteredPasteboard *p;
|
||||||
{
|
NSArray *types;
|
||||||
id<GSPasteboardObj> anObj;
|
NSArray *originalTypes;
|
||||||
|
|
||||||
anObj = [pboard _target];
|
if ([pboard isKindOfClass: [FilteredPasteboard class]] == YES)
|
||||||
if (anObj)
|
|
||||||
{
|
{
|
||||||
anObj = [[self _pbs] pasteboardByFilteringTypesInPasteboard: anObj];
|
return pboard;
|
||||||
if (anObj)
|
|
||||||
{
|
|
||||||
NSString *aName;
|
|
||||||
|
|
||||||
aName = [anObj name];
|
|
||||||
if (aName)
|
|
||||||
{
|
|
||||||
NSPasteboard *ret;
|
|
||||||
|
|
||||||
ret = [self _pasteboardWithTarget: anObj
|
|
||||||
name: (NSString*)aName];
|
|
||||||
NS_VALRETURN(ret);
|
|
||||||
}
|
}
|
||||||
}
|
originalTypes = [pboard types];
|
||||||
}
|
types = [FilteredPasteboard _typesFilterableFrom: originalTypes];
|
||||||
}
|
p = (FilteredPasteboard*)[FilteredPasteboard pasteboardWithUniqueName];
|
||||||
NS_HANDLER
|
p->originalTypes = [originalTypes copy];
|
||||||
{
|
p->pboard = RETAIN(pboard);
|
||||||
[NSException raise: NSPasteboardCommunicationException
|
[p declareTypes: types owner: p];
|
||||||
format: @"%@", [localException reason]];
|
return p;
|
||||||
}
|
|
||||||
NS_ENDHANDLER
|
|
||||||
|
|
||||||
return nil;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an array of the types to which data of the specified type
|
* Returns an array of the types from which data of the specified type
|
||||||
* can be converted by registered filter services.<br />
|
* can be produced by registered filter services.<br />
|
||||||
* The original type is always present in this array.<br />
|
* The original type is always present in this array.<br />
|
||||||
* Raises an exception if type is nil.
|
* Raises an exception if type is nil.
|
||||||
*/
|
*/
|
||||||
|
@ -513,14 +558,14 @@ static NSMapTable *mimeMap = NULL;
|
||||||
* Step through the filters looking for those which handle the type
|
* Step through the filters looking for those which handle the type
|
||||||
*/
|
*/
|
||||||
while ((info = [enumerator nextObject]) != nil)
|
while ((info = [enumerator nextObject]) != nil)
|
||||||
{
|
|
||||||
NSArray *sendTypes = [info objectForKey: @"NSSendTypes"];
|
|
||||||
|
|
||||||
if ([sendTypes containsObject: type] == YES)
|
|
||||||
{
|
{
|
||||||
NSArray *returnTypes = [info objectForKey: @"NSReturnTypes"];
|
NSArray *returnTypes = [info objectForKey: @"NSReturnTypes"];
|
||||||
|
|
||||||
[types addObjectsFromArray: returnTypes];
|
if ([returnTypes containsObject: type] == YES)
|
||||||
|
{
|
||||||
|
NSArray *sendTypes = [info objectForKey: @"NSSendTypes"];
|
||||||
|
|
||||||
|
[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
|
* can use the pasteboard. This should not be called for any of the standard
|
||||||
* pasteboards, only for temporary ones.
|
* 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
|
* for the same owner, because the new owner may not support all the types
|
||||||
* declared by a previous owner.
|
* declared by a previous owner.
|
||||||
* </p>
|
* </p>
|
||||||
* <p>Returns the new change count for the pastebaord, or zero if an error
|
* <p>Returns the new change count for the pasteboard, or zero if an error
|
||||||
* occurs.
|
* occurs.
|
||||||
* </p>
|
* </p>
|
||||||
*/
|
*/
|
||||||
|
@ -612,10 +657,10 @@ static NSMapTable *mimeMap = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>Sets the owner of the pastebaord to be newOwner and declares newTypes
|
* <p>Sets the owner of the pasteboard to be newOwner and declares newTypes
|
||||||
* as the types of data supported by it.
|
* as the types of data supported by it.
|
||||||
* </p>
|
* </p>
|
||||||
* <p>Returns the new change count for the pastebaord, or zero if an error
|
* <p>Returns the new change count for the pasteboard, or zero if an error
|
||||||
* occurs.
|
* occurs.
|
||||||
* </p>
|
* </p>
|
||||||
*/
|
*/
|
||||||
|
@ -659,7 +704,7 @@ static NSMapTable *mimeMap = NULL;
|
||||||
/**
|
/**
|
||||||
* <p>Writes data of type dataType to the pasteboard server so that other
|
* <p>Writes data of type dataType to the pasteboard server so that other
|
||||||
* applications can read it. The dataType must be one of the types
|
* applications can read it. The dataType must be one of the types
|
||||||
* previously declared for the pastebaord.
|
* previously declared for the pasteboard.
|
||||||
* </p>
|
* </p>
|
||||||
* <p>Returns YES on success, NO if the data could not be written for some
|
* <p>Returns YES on success, NO if the data could not be written for some
|
||||||
* reason.
|
* reason.
|
||||||
|
@ -689,7 +734,7 @@ static NSMapTable *mimeMap = NULL;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serialises the data in the supplied property list and writes it to the
|
* 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
|
- (BOOL) setPropertyList: (id)propertyList
|
||||||
forType: (NSString*)dataType
|
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.
|
* -setPropertyList:forType: method.
|
||||||
*/
|
*/
|
||||||
- (BOOL) setString: (NSString*)string
|
- (BOOL) setString: (NSString*)string
|
||||||
|
@ -860,8 +905,8 @@ static NSMapTable *mimeMap = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the change count for the receiving pastebaord. This count
|
* Returns the change count for the receiving pasteboard. This count
|
||||||
* is incremented whenever the owner of the pastebaord is changed.
|
* is incremented whenever the owner of the pasteboard is changed.
|
||||||
*/
|
*/
|
||||||
- (int) changeCount
|
- (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).
|
* it to the specified filename and returns the file name (or nil on failure).
|
||||||
*/
|
*/
|
||||||
- (NSString*) readFileContentsType: (NSString*)type
|
- (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).
|
* it and returns the resulting file wrapper (or nil).
|
||||||
*/
|
*/
|
||||||
- (NSFileWrapper*) readFileWrapper
|
- (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).
|
* it and returns the resulting string (or nil).
|
||||||
*/
|
*/
|
||||||
- (NSString*) stringForType: (NSString*)dataType
|
- (NSString*) stringForType: (NSString*)dataType
|
||||||
|
|
Loading…
Reference in a new issue