Various partially completed works

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@4154 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
richard 1999-04-28 11:16:26 +00:00
parent d179d675db
commit 0e88a90011
4 changed files with 822 additions and 365 deletions

View file

@ -38,6 +38,18 @@
#include <AppKit/NSCachedImageRep.h> #include <AppKit/NSCachedImageRep.h>
#include <AppKit/NSWindow.h> #include <AppKit/NSWindow.h>
@interface GSCacheW : NSWindow
@end
@implementation GSCacheW
- (void) initDefaults
{
[super initDefaults];
menu_exclude = YES; // Don't show in windows menu.
}
@end
/* Backend protocol - methods that must be implemented by the backend to /* Backend protocol - methods that must be implemented by the backend to
complete the class */ complete the class */
@protocol NXCachedImageRepBackend @protocol NXCachedImageRepBackend
@ -48,17 +60,26 @@
// Initializing an NSCachedImageRep // Initializing an NSCachedImageRep
- (id) initWithSize: (NSSize)aSize - (id) initWithSize: (NSSize)aSize
depth: (NSWindowDepth)aDepth depth: (NSWindowDepth)aDepth
separate: (BOOL)separate separate: (BOOL)separate
alpha: (BOOL)alpha alpha: (BOOL)alpha
{ {
return nil; NSWindow *win;
NSRect frame;
frame.origin = NSMakePoint(0,0);
frame.size = aSize;
win = [[GSCacheW alloc] initWithContentRect: frame
styleMask: NSBorderlessWindowMask
backing: NSBackingStoreRetained
defer: NO];
self = [self initWithWindow: win rect: frame];
[win release];
return self;
} }
- initWithWindow: (NSWindow *)win rect: (NSRect)rect - (id) initWithWindow: (NSWindow *)win rect: (NSRect)rect
{ {
int style = NSClosableWindowMask;
[super init]; [super init];
_window = [win retain]; _window = [win retain];
@ -72,16 +93,17 @@
if (!_window) if (!_window)
{ {
[NSException raise: NSInvalidArgumentException [NSException raise: NSInvalidArgumentException
format: @"Must specify either window or rect when creating NSCachedImageRep"]; format: @"Must specify either window or rect when "
@"creating NSCachedImageRep"];
} }
_rect = [_window frame]; _rect = [_window frame];
} }
if (!_window) if (!_window)
_window = [[NSWindow alloc] initWithContentRect: _rect _window = [[GSCacheW alloc] initWithContentRect: _rect
styleMask: style styleMask: NSBorderlessWindowMask
backing: NSBackingStoreRetained backing: NSBackingStoreRetained
defer: NO]; defer: NO];
return self; return self;
} }
@ -104,6 +126,7 @@
- (BOOL)draw - (BOOL)draw
{ {
NSCopyBits([_window gState], _rect, _rect.origin);
return NO; return NO;
} }

View file

@ -43,6 +43,7 @@
#include <Foundation/NSString.h> #include <Foundation/NSString.h>
#include <AppKit/NSImage.h> #include <AppKit/NSImage.h>
#include <AppKit/AppKitExceptions.h>
#include <AppKit/NSBitmapImageRep.h> #include <AppKit/NSBitmapImageRep.h>
#include <AppKit/NSCachedImageRep.h> #include <AppKit/NSCachedImageRep.h>
#include <AppKit/NSView.h> #include <AppKit/NSView.h>
@ -50,6 +51,8 @@
#include <AppKit/NSScreen.h> #include <AppKit/NSScreen.h>
#include <AppKit/NSColor.h> #include <AppKit/NSColor.h>
BOOL doesCaching = NO;
// Resource directories // Resource directories
static NSString* gnustep_libdir = @GNUSTEP_INSTALL_LIBDIR; static NSString* gnustep_libdir = @GNUSTEP_INSTALL_LIBDIR;
static NSString* NSImage_PATH = @"Images"; static NSString* NSImage_PATH = @"Images";
@ -65,59 +68,62 @@ static NSString* NSImage_PATH = @"Images";
fraction: (float)aFloat; fraction: (float)aFloat;
@end @end
typedef struct _rep_data_t @interface GSRepData : NSObject
{ {
NSString* fileName; @public
id rep; NSString *fileName;
id cache; NSImageRep *rep;
id original; NSImageRep *original;
BOOL validCache; NSColor *bg;
} rep_data_t; }
@end
@implementation GSRepData
- (id) copyWithZone: (NSZone*)z
{
GSRepData *c = (GSRepData*)NSCopyObject(self, 0, z);
if (c->fileName)
c->fileName = [c->fileName copy];
if (c->rep)
c->rep = [c->rep copy];
if (c->bg)
c->bg = [c->bg copy];
return c;
}
- (void) dealloc
{
if (fileName)
[fileName release];
if (rep)
[rep release];
if (bg)
[bg release];
NSDeallocateObject(self);
}
@end
NSArray *iterate_reps_for_types(NSArray *imageReps, SEL method); NSArray *iterate_reps_for_types(NSArray *imageReps, SEL method);
/* Find the rep_data_t holding a representation */ /* Find the GSRepData object holding a representation */
rep_data_t GSRepData*
repd_for_rep(NSArray *_reps, NSImageRep *rep) repd_for_rep(NSArray *_reps, NSImageRep *rep)
{ {
int i, count; unsigned i, count;
rep_data_t repd; GSRepData *repd;
count = [_reps count]; count = [_reps count];
for (i = 0; i < count; i++) for (i = 0; i < count; i++)
{ {
[[_reps objectAtIndex: i] getValue: &repd]; repd = [_reps objectAtIndex: i];
if (repd.rep == rep) if (repd->rep == rep)
return repd; return repd;
} }
[NSException raise: NSInternalInconsistencyException [NSException raise: NSInternalInconsistencyException
format: @"Cannot find stored representation"]; format: @"Cannot find stored representation"];
/* NOT REACHED */ /* NOT REACHED */
return repd; return nil;
}
void
set_repd_for_rep(NSMutableArray *_reps, NSImageRep *rep, rep_data_t *new_repd)
{
int i, count;
rep_data_t repd;
BOOL found = NO;
count = [_reps count];
for (i = 0; i < count; i++)
{
[[_reps objectAtIndex: i] getValue: &repd];
if (repd.rep == rep && !found)
{
[_reps replaceObjectAtIndex: i withObject:
[NSValue value: new_repd withObjCType: @encode(rep_data_t)]];
found = YES;
break;
}
}
if (!found)
[_reps addObject:
[NSValue value: new_repd withObjCType: @encode(rep_data_t)]];
} }
@interface NSImage (Backend) <NSImageBackend> @interface NSImage (Backend) <NSImageBackend>
@ -140,10 +146,10 @@ static NSDictionary* nsmapping = nil;
{ {
if (self == [NSImage class]) if (self == [NSImage class])
{ {
NSBundle *system = [NSBundle bundleWithPath: gnustep_libdir]; NSBundle *system = [NSBundle bundleWithPath: gnustep_libdir];
NSString* path = [system pathForResource: @"nsmapping" NSString *path = [system pathForResource: @"nsmapping"
ofType: @"strings" ofType: @"strings"
inDirectory: NSImage_PATH]; inDirectory: NSImage_PATH];
// Initial version // Initial version
[self setVersion: 1]; [self setVersion: 1];
@ -158,7 +164,7 @@ static NSDictionary* nsmapping = nil;
+ imageNamed: (NSString *)aName + imageNamed: (NSString *)aName
{ {
NSString* realName = [nsmapping objectForKey: aName]; NSString *realName = [nsmapping objectForKey: aName];
if (realName) if (realName)
aName = realName; aName = realName;
@ -215,8 +221,8 @@ static NSDictionary* nsmapping = nil;
if (ext) if (ext)
path = [system pathForResource: the_name path = [system pathForResource: the_name
ofType: ext ofType: ext
inDirectory: NSImage_PATH]; inDirectory: NSImage_PATH];
else else
{ {
id o, e; id o, e;
@ -229,8 +235,8 @@ static NSDictionary* nsmapping = nil;
while ((o = [e nextObject])) while ((o = [e nextObject]))
{ {
path = [system pathForResource: the_name path = [system pathForResource: the_name
ofType: o ofType: o
inDirectory: NSImage_PATH]; inDirectory: NSImage_PATH];
if ([path length] != 0) if ([path length] != 0)
break; break;
} }
@ -242,7 +248,7 @@ static NSDictionary* nsmapping = nil;
NSImage *image; NSImage *image;
image = [[self allocWithZone: NSDefaultMallocZone()] image = [[self allocWithZone: NSDefaultMallocZone()]
initByReferencingFile: path]; initByReferencingFile: path];
if (image) if (image)
{ {
[image setName: aName]; [image setName: aName];
@ -463,8 +469,8 @@ static NSDictionary* nsmapping = nil;
// Determining How the Image is Drawn // Determining How the Image is Drawn
- (BOOL) isValid - (BOOL) isValid
{ {
BOOL valid = NO; BOOL valid = NO;
int i, count; unsigned i, count;
/* Go through all our representations and determine if at least one /* Go through all our representations and determine if at least one
is a valid cache */ is a valid cache */
@ -472,9 +478,11 @@ static NSDictionary* nsmapping = nil;
count = [_reps count]; count = [_reps count];
for (i = 0; i < count; i++) for (i = 0; i < count; i++)
{ {
rep_data_t repd; GSRepData *repd = (GSRepData*)[_reps objectAtIndex: i];
[[_reps objectAtIndex: i] getValue: &repd];
valid |= repd.validCache; if (repd->bg != nil
|| [repd->rep isKindOfClass: [NSCachedImageRep class]] == NO)
valid = YES;
} }
return valid; return valid;
} }
@ -486,11 +494,14 @@ static NSDictionary* nsmapping = nil;
count = [_reps count]; count = [_reps count];
for (i = 0; i < count; i++) for (i = 0; i < count; i++)
{ {
rep_data_t repd; GSRepData *repd;
[[_reps objectAtIndex: i] getValue: &repd];
repd.validCache = NO; repd = (GSRepData*)[_reps objectAtIndex: i];
[_reps replaceObjectAtIndex: i withObject: if (repd->bg != nil)
[NSValue value: &repd withObjCType: @encode(rep_data_t)]]; {
[repd->bg release];
repd->bg = nil;
}
} }
} }
@ -499,7 +510,7 @@ static NSDictionary* nsmapping = nil;
_flags.scalable = flag; _flags.scalable = flag;
} }
- (BOOL)scalesWhenResized - (BOOL) scalesWhenResized
{ {
return _flags.scalable; return _flags.scalable;
} }
@ -513,8 +524,10 @@ static NSDictionary* nsmapping = nil;
} }
} }
- (NSColor *)backgroundColor - (NSColor *) backgroundColor
{ {
if (_color == nil)
_color = [[NSColor clearColor] retain];
return _color; return _color;
} }
@ -522,25 +535,24 @@ static NSDictionary* nsmapping = nil;
in and added to the representation list. */ in and added to the representation list. */
- _loadImageFilenames - _loadImageFilenames
{ {
unsigned i, count; unsigned i, count;
rep_data_t repd; GSRepData *repd;
_syncLoad = NO; _syncLoad = NO;
count = [_reps count]; count = [_reps count];
for (i = 0; i < count; i++) for (i = 0; i < count; i++)
{ {
[[_reps objectAtIndex: i] getValue: &repd]; repd = (GSRepData*)[_reps objectAtIndex: i];
if (repd.fileName) if (repd->fileName)
[self loadFromFile: repd.fileName]; [self loadFromFile: repd->fileName];
} }
// Now get rid of them since they are already loaded // Now get rid of them since they are already loaded
count = [_reps count]; count = [_reps count];
while (count--) while (count--)
{ {
[[_reps objectAtIndex: count] getValue: &repd]; repd = (GSRepData*)[_reps objectAtIndex: count];
if (repd.fileName) if (repd->fileName)
{ {
[repd.fileName release];
[_reps removeObjectAtIndex: count]; [_reps removeObjectAtIndex: count];
} }
} }
@ -553,50 +565,65 @@ static NSDictionary* nsmapping = nil;
// image (if there is one). // image (if there is one).
- (NSImageRep *)_doImageCache - (NSImageRep *)_doImageCache
{ {
NSImageRep *rep = nil; NSImageRep *rep = nil;
rep_data_t repd; GSRepData *repd;
repd = repd_for_rep(_reps, [self bestRepresentationForDevice: nil]); repd = repd_for_rep(_reps, [self bestRepresentationForDevice: nil]);
rep = repd.rep; rep = repd->rep;
if (repd.cache)
rep = repd.cache;
if (![rep isKindOfClass: [NSCachedImageRep class]]) if (doesCaching)
{ {
#if 0 /*
[self lockFocus]; * If this is not a cached image rep - create a cache to be used to
* render the image rep into, and switch to the cached rep.
*/
if ([rep isKindOfClass: [NSCachedImageRep class]] == NO)
{ {
rep_data_t cached; NSScreen *cur = [NSScreen mainScreen];
NSRect bounds; NSCachedImageRep *cachedRep;
_lockedView = [NSView focusView]; NSSize imageSize;
bounds = [_lockedView bounds];
[self _displayEraseRect: bounds view: _lockedView color: _color]; imageSize = [self size];
[self unlockFocus]; if (imageSize.width == 0 || imageSize.height == 0)
[[_reps lastObject] getValue: &cached]; return nil;
cached.original = rep;
cached.validCache = YES; cachedRep = [[NSCachedImageRep alloc] initWithSize: _size
[_reps removeLastObject]; depth: [cur depth]
[_reps addObject: separate: NO
[NSValue value: &cached withObjCType: @encode(rep_data_t)]]; alpha: NO];
} [self addRepresentation: cachedRep];
#endif [cachedRep release]; /* Retained in _reps array. */
} repd = repd_for_rep(_reps, cachedRep);
else if (!repd.validCache) repd->original = rep;
{ rep = repd->rep;
#if 0 }
[self lockFocusOnRepresentation: rep];
/*
* if the cache is not valid, it's background color will not exist
* and we must draw the background then render from the original
* image rep into the cache.
*/
if (repd->bg == nil)
{ {
NSRect bounds; NSRect bounds;
[self lockFocusOnRepresentation: rep];
/*
* If this is not a cache - the lockFocus will have created a
* cache that we can use instead.
*/
if (repd->original == nil)
{
repd = repd_for_rep(_reps, [self lastRepresentation]);
}
bounds = [_lockedView bounds]; bounds = [_lockedView bounds];
[self _displayEraseRect: bounds view: _lockedView color: _color]; [_color set];
repd = repd_for_rep(_reps, rep); NSEraseRect(bounds);
[self drawRepresentation: repd.original [self drawRepresentation: repd->original
inRect: NSMakeRect(0, 0, _size.width, _size.height)]; inRect: NSMakeRect(0, 0, _size.width, _size.height)];
[self unlockFocus]; [self unlockFocus];
repd.validCache = YES; repd->bg = [_color copy];
set_repd_for_rep(_reps, repd.rep, &repd);
} }
#endif
} }
return rep; return rep;
@ -607,6 +634,7 @@ static NSDictionary* nsmapping = nil;
operation: (NSCompositingOperation)op; operation: (NSCompositingOperation)op;
{ {
NSRect rect; NSRect rect;
[self size]; [self size];
rect = NSMakeRect(0, 0, _size.width, _size.height); rect = NSMakeRect(0, 0, _size.width, _size.height);
[self compositeToPoint: aPoint fromRect: rect operation: op]; [self compositeToPoint: aPoint fromRect: rect operation: op];
@ -623,9 +651,7 @@ static NSDictionary* nsmapping = nil;
// then we need to construct a subimage to draw // then we need to construct a subimage to draw
rep = [self _doImageCache]; rep = [self _doImageCache];
[self lockFocusOnRepresentation: rep];
[self drawRepresentation: rep inRect: rect]; [self drawRepresentation: rep inRect: rect];
[self unlockFocus];
} }
- (void) dissolveToPoint: (NSPoint)aPoint fraction: (float)aFloat; - (void) dissolveToPoint: (NSPoint)aPoint fraction: (float)aFloat;
@ -647,9 +673,7 @@ static NSDictionary* nsmapping = nil;
// then we need to construct a subimage to draw // then we need to construct a subimage to draw
rep = [self _doImageCache]; rep = [self _doImageCache];
[self lockFocusOnRepresentation: rep];
[self drawRepresentation: rep inRect: rect]; [self drawRepresentation: rep inRect: rect];
[self unlockFocus];
} }
- (BOOL)drawRepresentation: (NSImageRep *)imageRep inRect: (NSRect)rect - (BOOL)drawRepresentation: (NSImageRep *)imageRep inRect: (NSRect)rect
@ -700,7 +724,7 @@ static NSDictionary* nsmapping = nil;
{ {
NSArray *array; NSArray *array;
NSString *ext; NSString *ext;
rep_data_t repd; GSRepData *repd;
NSFileManager *manager = [NSFileManager defaultManager]; NSFileManager *manager = [NSFileManager defaultManager];
if ([manager fileExistsAtPath: fileName] == NO) if ([manager fileExistsAtPath: fileName] == NO)
@ -714,8 +738,10 @@ static NSDictionary* nsmapping = nil;
array = [[self class] imageFileTypes]; array = [[self class] imageFileTypes];
if ([array indexOfObject: ext] == NSNotFound) if ([array indexOfObject: ext] == NSNotFound)
return NO; return NO;
repd.fileName = [fileName retain]; repd = [GSRepData new];
[_reps addObject: [NSValue value: &repd withObjCType: @encode(rep_data_t)]]; repd->fileName = [fileName retain];
[_reps addObject: repd];
[repd release];
_syncLoad = YES; _syncLoad = YES;
return YES; return YES;
} }
@ -727,8 +753,8 @@ static NSDictionary* nsmapping = nil;
- (void) addRepresentations: (NSArray *)imageRepArray - (void) addRepresentations: (NSArray *)imageRepArray
{ {
int i, count; unsigned i, count;
rep_data_t repd; GSRepData *repd;
if (!imageRepArray) if (!imageRepArray)
return; return;
@ -738,13 +764,10 @@ static NSDictionary* nsmapping = nil;
count = [imageRepArray count]; count = [imageRepArray count];
for (i = 0; i < count; i++) for (i = 0; i < count; i++)
{ {
repd.fileName = NULL; repd = [GSRepData new];
repd.rep = [[imageRepArray objectAtIndex: i] retain]; repd->rep = [[imageRepArray objectAtIndex: i] retain];
repd.cache = NULL; [_reps addObject: repd];
repd.original = NULL; [repd release];
repd.validCache = NO;
[_reps addObject:
[NSValue value: &repd withObjCType: @encode(rep_data_t)]];
} }
} }
@ -757,6 +780,7 @@ static NSDictionary* nsmapping = nil;
if (!imageSize.width || !imageSize.height) if (!imageSize.width || !imageSize.height)
return NO; return NO;
// FIXME: determine alpha? separate? // FIXME: determine alpha? separate?
rep = [[NSCachedImageRep alloc] initWithSize: _size rep = [[NSCachedImageRep alloc] initWithSize: _size
depth: depth depth: depth
@ -768,21 +792,28 @@ static NSDictionary* nsmapping = nil;
- (void) removeRepresentation: (NSImageRep *)imageRep - (void) removeRepresentation: (NSImageRep *)imageRep
{ {
int i, count; unsigned i;
rep_data_t repd; GSRepData *repd;
count = [_reps count];
for (i = 0; i < count; i++) i = [_reps count];
while (i-- > 0)
{ {
[[_reps objectAtIndex: i] getValue: &repd]; repd = (GSRepData*)[_reps objectAtIndex: i];
if (repd.rep == imageRep) if (repd->rep == imageRep)
[_reps removeObjectAtIndex: i]; {
[_reps removeObjectAtIndex: i];
}
else if (repd->original == imageRep)
{
repd->original = nil;
}
} }
} }
- (void) lockFocus - (void) lockFocus
{ {
NSScreen *cur = [NSScreen mainScreen]; NSScreen *cur = [NSScreen mainScreen];
NSImageRep *rep; NSImageRep *rep;
if (!(rep = [self bestRepresentationForDevice: nil])) if (!(rep = [self bestRepresentationForDevice: nil]))
{ {
@ -794,107 +825,159 @@ static NSDictionary* nsmapping = nil;
- (void) lockFocusOnRepresentation: (NSImageRep *)imageRep - (void) lockFocusOnRepresentation: (NSImageRep *)imageRep
{ {
#if 0 NSScreen *cur = [NSScreen mainScreen];
NSScreen *cur = [NSScreen mainScreen]; NSWindow *window;
NSWindow *window;
#endif
if (!imageRep) if (!imageRep)
[NSException raise: NSInvalidArgumentException [NSException raise: NSInvalidArgumentException
format: @"Cannot lock focus on nil rep"]; format: @"Cannot lock focus on nil rep"];
#if 0 if (doesCaching)
if (![imageRep isKindOfClass: [NSCachedImageRep class]])
{ {
rep_data_t repd, cached; if (![imageRep isKindOfClass: [NSCachedImageRep class]])
int depth;
if (_flags.unboundedCacheDepth)
depth = [cur depth]; // FIXME: get depth correctly
else
depth = [cur depth];
if (![self useCacheWithDepth: depth])
{ {
[NSException raise: NSImageCacheException GSRepData *repd, *cached;
format: @"Unable to create cache"]; int depth;
if (_flags.unboundedCacheDepth)
depth = [cur depth]; // FIXME: get depth correctly
else
depth = [cur depth];
if (![self useCacheWithDepth: depth])
{
[NSException raise: NSImageCacheException
format: @"Unable to create cache"];
}
cached = repd_for_rep(_reps, [self lastRepresentation]);
cached->original = imageRep;
imageRep = cached->rep;
} }
repd = repd_for_rep(_reps, imageRep); window = [(NSCachedImageRep *)imageRep window];
cached = repd_for_rep(_reps, [self lastRepresentation]); _lockedView = [window contentView];
repd.cache = cached.rep; [_lockedView lockFocus];
cached.original = repd.rep;
set_repd_for_rep(_reps, imageRep, &repd);
set_repd_for_rep(_reps, cached.rep, &cached);
imageRep = cached.rep;
} }
window = [(NSCachedImageRep *)imageRep window];
_lockedView = [window contentView];
[_lockedView lockFocus];
#endif
} }
- (void) unlockFocus - (void) unlockFocus
{ {
#if 0
if (_lockedView) if (_lockedView)
[_lockedView unlockFocus]; [_lockedView unlockFocus];
_lockedView = nil; _lockedView = nil;
#endif
} }
- (NSImageRep *) lastRepresentation - (NSImageRep *) lastRepresentation
{ {
// Reconstruct the repList if it has changed // Reconstruct the rep list if it has changed
[self representations]; [self representations];
return [_repList lastObject]; return [_repList lastObject];
} }
- (NSImageRep*) bestRepresentationForDevice: (NSDictionary*)deviceDescription - (NSImageRep*) bestRepresentationForDevice: (NSDictionary*)deviceDescription
{ {
id o, e; NSImageRep *rep = nil;
NSImageRep *rep = nil; unsigned count;
rep_data_t repd;
// Make sure we have the images loaded in /* Make sure we have the images loaded in. */
if (_syncLoad) if (_syncLoad)
[self _loadImageFilenames]; [self _loadImageFilenames];
if ([_reps count] == 0) count = [_reps count];
return nil;
// What's the best representation? FIXME
e = [_reps objectEnumerator];
o = [e nextObject];
while (o)
{
[o getValue: &repd];
if ([repd.rep isKindOfClass: [NSBitmapImageRep class]])
rep = repd.rep;
o = [e nextObject];
}
#if 0
[[_reps lastObject] getValue: &repd];
if (repd.cache)
rep = repd.cache;
else
rep = repd.rep;
#endif
if (count > 0)
{
GSRepData *reps[count];
unsigned i;
/*
* What's the best representation? FIXME
*/
[_reps getObjects: reps];
for (i = 0; i < count; i++)
{
GSRepData *repd = reps[i];
if ([repd->rep isKindOfClass: [NSBitmapImageRep class]])
{
rep = repd->rep;
}
}
/*
* If we got a representation - see if we already have it cached.
*/
if (doesCaching)
{
if (rep != nil)
{
GSRepData *invalidCache = nil;
GSRepData *validCache = nil;
/*
* Search the cached image reps for any whose original is our
* 'best' image rep. See if we can notice any invalidated
* cache as we go - if we don't find a valid cache, we want to
* re-use an invalidated one rather than createing a new one.
*/
for (i = 0; i < count; i++)
{
GSRepData *repd = reps[i];
if (repd->original == rep)
{
if (repd->bg == nil)
{
invalidCache = repd;
}
else if ([repd->bg isEqual: _color] == YES)
{
validCache = repd;
break;
}
}
}
if (validCache)
{
/*
* If the image rep has transparencey and we are drawing
* without a background (background is clear) then the
* cache can't really be valid 'cos we might be drawing
* transparency on top of anything. So we invalidate
* the cache by removing the background color information.
*/
if ([rep hasAlpha]
&& [validCache->bg isEqual: [NSColor clearColor]])
{
[validCache->bg release];
validCache->bg = nil;
}
rep = validCache->rep;
}
else if (invalidCache)
{
rep = invalidCache->rep;
}
}
}
}
return rep; return rep;
} }
- (NSArray *) representations - (NSArray *) representations
{ {
unsigned i, count; unsigned i, count;
if (!_repList) if (!_repList)
_repList = [[NSMutableArray alloc] init]; _repList = [[NSMutableArray alloc] init];
if (_syncLoad) if (_syncLoad)
[self _loadImageFilenames]; [self _loadImageFilenames];
count = [_reps count];
[_repList removeAllObjects]; [_repList removeAllObjects];
count = [_reps count];
for (i = 0; i < count; i++) for (i = 0; i < count; i++)
{ {
rep_data_t repd; GSRepData *repd = [_reps objectAtIndex: i];
[[_reps objectAtIndex: i] getValue: &repd];
[_repList addObject: repd.rep]; [_repList addObject: repd->rep];
} }
return _repList; return _repList;
} }
@ -1000,10 +1083,9 @@ static NSDictionary* nsmapping = nil;
NSArray * NSArray *
iterate_reps_for_types(NSArray* imageReps, SEL method) iterate_reps_for_types(NSArray* imageReps, SEL method)
{ {
NSImageRep *rep; NSImageRep *rep;
id e; NSEnumerator *e;
// int i, count; NSMutableArray *types;
NSMutableArray* types;
types = [NSMutableArray arrayWithCapacity: 2]; types = [NSMutableArray arrayWithCapacity: 2];

View file

@ -279,17 +279,27 @@ static NSMutableArray* imageReps = NULL;
// Drawing the Image // Drawing the Image
- (BOOL) draw - (BOOL) draw
{ {
[self subclassResponsibility: _cmd]; return YES; /* Subclass should implement this. */
return NO;
} }
- (BOOL) drawAtPoint: (NSPoint)aPoint - (BOOL) drawAtPoint: (NSPoint)aPoint
{ {
return NO; NSRect r;
if (aPoint.x == 0 && aPoint.y == 0)
return [self draw];
r.origin = aPoint;
r.size = size;
return [self drawInRect: r];
} }
- (BOOL) drawInRect: (NSRect)aRect - (BOOL) drawInRect: (NSRect)aRect
{ {
float x, y;
if (size.height == 0 || size.width == 0)
return NO;
/* FIXME - should scale and move as necessary. */
return NO; return NO;
} }

View file

@ -43,51 +43,29 @@
#include <Foundation/NSException.h> #include <Foundation/NSException.h>
#include <Foundation/NSProcessInfo.h> #include <Foundation/NSProcessInfo.h>
#include <Foundation/NSFileManager.h> #include <Foundation/NSFileManager.h>
#include <Foundation/NSNotificationQueue.h>
#define stringify_it(X) #X #define stringify_it(X) #X
#define mkpath(X) stringify_it(X) "/Tools" #define mkpath(X) stringify_it(X) "/Tools"
static NSDictionary *applications = nil;
@implementation NSWorkspace @implementation NSWorkspace
static NSWorkspace *sharedWorkspace = nil; static NSWorkspace *sharedWorkspace = nil;
static NSNotificationCenter *workspaceCenter = nil; static NSNotificationCenter *workspaceCenter = nil;
static NSMutableDictionary *iconMap = nil;
static BOOL userDefaultsChanged = NO; static BOOL userDefaultsChanged = NO;
static NSString *appListName = @".GNUstepAppList"; static NSString *appListName = @"Services/.GNUstepAppList";
static NSString *appListPath = nil; static NSString *appListPath = nil;
static NSDictionary *_suffixes = nil; static NSDictionary *applications = nil;
static NSString *defaultIconPath = nil;
static NSString *extPrefName = @".GNUstepExtPrefs";
static NSString *extPrefPath = nil;
static NSDictionary *extPreferences = nil;
static NSString *_rootPath = @"/"; static NSString *_rootPath = @"/";
static NSString* gnustep_target_dir =
#ifdef GNUSTEP_TARGET_DIR
@GNUSTEP_TARGET_DIR;
#else
nil;
#endif
static NSString* gnustep_target_cpu =
#ifdef GNUSTEP_TARGET_CPU
@GNUSTEP_TARGET_CPU;
#else
nil;
#endif
static NSString* gnustep_target_os =
#ifdef GNUSTEP_TARGET_OS
@GNUSTEP_TARGET_OS;
#else
nil;
#endif
static NSString* library_combo =
#ifdef LIBRARY_COMBO
@LIBRARY_COMBO;
#else
nil;
#endif
// //
// Class methods // Class methods
// //
@ -97,6 +75,9 @@ static NSString* library_combo =
{ {
static BOOL beenHere; static BOOL beenHere;
NSDictionary *env; NSDictionary *env;
NSString *home;
NSData *data;
NSDictionary *dict;
// Initial version // Initial version
[self setVersion: 1]; [self setVersion: 1];
@ -111,49 +92,44 @@ static NSString* library_combo =
beenHere = YES; beenHere = YES;
workspaceCenter = [NSNotificationCenter new]; workspaceCenter = [NSNotificationCenter new];
iconMap = [NSMutableDictionary new];
/*
* The home directory for per-user information is given by
* the GNUSTEP_USER_ROOT environment variable, or is assumed
* to be the 'GNUstep' subdirectory of the users home directory.
*/
env = [[NSProcessInfo processInfo] environment]; env = [[NSProcessInfo processInfo] environment];
if (env) if (!env || !(home = [env objectForKey: @"GNUSTEP_USER_ROOT"]))
{ {
NSString *str; home = [NSString stringWithFormat: @"%@/GNUstep", NSHomeDirectory()];
NSData *data;
NSDictionary *newApps;
str = [env objectForKey: @"GNUSTEP_USER_ROOT"];
if (str == nil)
str = [NSString stringWithFormat: @"%@/GNUstep",
NSHomeDirectory()];
str = [str stringByAppendingPathComponent: @"Services"];
str = [str stringByAppendingPathComponent: appListName];
appListPath = [str retain];
if ((str = [env objectForKey: @"GNUSTEP_TARGET_DIR"]) != nil)
gnustep_target_dir = [str retain];
else if ((str = [env objectForKey: @"GNUSTEP_HOST_DIR"]) != nil)
gnustep_target_dir = [str retain];
if ((str = [env objectForKey: @"GNUSTEP_TARGET_CPU"]) != nil)
gnustep_target_cpu = [str retain];
else if ((str = [env objectForKey: @"GNUSTEP_HOST_CPU"]) != nil)
gnustep_target_cpu = [str retain];
if ((str = [env objectForKey: @"GNUSTEP_TARGET_OS"]) != nil)
gnustep_target_os = [str retain];
else if ((str = [env objectForKey: @"GNUSTEP_HOST_OS"]) != nil)
gnustep_target_os = [str retain];
if ((str = [env objectForKey: @"LIBRARY_COMBO"]) != nil)
library_combo = [str retain];
data = [NSData dataWithContentsOfFile: appListPath];
if (data)
newApps = [NSDeserializer deserializePropertyListFromData: data
mutableContainers: NO];
applications = [newApps retain];
} }
_suffixes = [NSDictionary dictionaryWithContentsOfFile:@"Suffixes.plist"]; /*
_suffixes = [_suffixes retain]; * Load file extension preferences.
defaultIconPath = [_suffixes objectForKey: @"ICON_PATH"]; */
extPrefPath = [home stringByAppendingPathComponent: extPrefName];
[extPrefPath retain];
data = [NSData dataWithContentsOfFile: extPrefPath];
if (data)
{
dict = [NSDeserializer deserializePropertyListFromData: data
mutableContainers: NO];
extPreferences = [dict retain];
}
/*
* Load cached application information.
*/
appListPath = [home stringByAppendingPathComponent: appListName];
[appListPath retain];
data = [NSData dataWithContentsOfFile: appListPath];
if (data)
{
dict = [NSDeserializer deserializePropertyListFromData: data
mutableContainers: NO];
applications = [dict retain];
}
[gnustep_global_lock unlock]; [gnustep_global_lock unlock];
} }
@ -179,31 +155,46 @@ static NSString* library_combo =
sharedWorkspace = sharedWorkspace =
(NSWorkspace*)NSAllocateObject(self, 0, NSDefaultMallocZone()); (NSWorkspace*)NSAllocateObject(self, 0, NSDefaultMallocZone());
[NSNotificationCenter addObserver: sharedWorkspace
selector: @selector(noteUserDefaultsChanged)
name: NSUserDefaultsDidChangeNotification
object: nil];
} }
[gnustep_global_lock unlock]; [gnustep_global_lock unlock];
} }
return sharedWorkspace; return sharedWorkspace;
} }
static NSImage*
extIconForApp(NSWorkspace *ws, NSString *appName, NSDictionary *typeInfo)
{
NSString *file = [typeInfo objectForKey: @"NSIcon"];
if (file)
{
if ([file isAbsolutePath] == NO)
{
NSString *path;
path = [ws fullPathForApplication: appName];
file = [path stringByAppendingString: file];
}
if ([[NSFileManager defaultManager] isReadableFileAtPath: file] == YES)
{
return [[[NSImage alloc] initWithContentsOfFile: file] autorelease];
}
}
return nil;
}
- (NSImage*) _getImageWithName: (NSString *)name - (NSImage*) _getImageWithName: (NSString *)name
alternate: (NSString *)alternate alternate: (NSString *)alternate
{ {
NSString *iconName = nil;
NSImage *image = nil; NSImage *image = nil;
iconName = (NSString *)[_suffixes objectForKey: name]; image = [NSImage imageNamed: name];
if (iconName != nil) if (image == nil)
{ image = [NSImage imageNamed: alternate];
NSString *iconPath;
iconPath = [defaultIconPath stringByAppendingPathComponent: iconName];
image = [[NSImage alloc] initWithContentsOfFile: iconPath];
}
if ((image == nil) && (alternate != nil))
{
image = [[NSImage imageNamed: alternate] retain]; // !!! was retained
}
return image; return image;
} }
@ -214,8 +205,8 @@ static NSString* library_combo =
if (image == nil) if (image == nil)
{ {
image = [self _getImageWithName: @"FOLDER_ICON" image = [[self _getImageWithName: @"Folder.tiff"
alternate: @"Folder.tiff"]; alternate: @"common_Folder.tiff"] retain];
} }
return image; return image;
@ -228,8 +219,8 @@ static NSString* library_combo =
if (image == nil) if (image == nil)
{ {
image = [self _getImageWithName: @"UNKNOWN_ICON" image = [[self _getImageWithName: @"Unknown.tiff"
alternate: @"Unknown"]; alternate: @"common_Unknown.tiff"] retain];
} }
return image; return image;
@ -242,13 +233,222 @@ static NSString* library_combo =
if (image == nil) if (image == nil)
{ {
image = [self _getImageWithName: @"ROOT_ICON" image = [[self _getImageWithName: @"Root_PC.tiff"
alternate: @"Unknown"]; alternate: @"common_Root_PC.tiff"] retain];
} }
return image; return image;
} }
- (NSImage*) _iconForExtension: (NSString*)ext
{
NSImage *icon = nil;
if (ext == nil || [ext isEqualToString: @""])
return nil;
/*
* extensions are case-insensitive - convert to lowercase.
*/
ext = [ext lowercaseString];
if ((icon = [iconMap objectForKey: ext]) == nil)
{
NSDictionary *prefs;
NSDictionary *extInfo;
NSString *iconPath;
/*
* If there is a user-specified preference for an image -
* try to use that one.
*/
prefs = [extPreferences objectForKey: ext];
iconPath = [prefs objectForKey: @"Icon"];
if (iconPath)
{
icon = [[NSImage alloc] initWithContentsOfFile: iconPath];
[icon autorelease];
}
if (icon == nil && (extInfo = [self infoForExtension: ext]) != nil)
{
NSDictionary *typeInfo;
NSString *appName;
/*
* If there are any application preferences given, try to use the
* icon for this file that is used by the preferred app.
*/
if (prefs)
{
if ((appName = [extInfo objectForKey: @"Editor"]) != nil)
{
typeInfo = [extInfo objectForKey: appName];
icon = extIconForApp(self, appName, typeInfo);
}
if (icon == nil
&& (appName = [extInfo objectForKey: @"Viewer"]) != nil)
{
typeInfo = [extInfo objectForKey: appName];
icon = extIconForApp(self, appName, typeInfo);
}
}
if (icon == nil)
{
NSEnumerator *enumerator;
/*
* Still no icon - try all the apps that handle this file
* extension.
*/
enumerator = [extInfo keyEnumerator];
while (icon == nil && (appName = [enumerator nextObject]) != nil)
{
typeInfo = [extInfo objectForKey: appName];
icon = extIconForApp(self, appName, typeInfo);
}
}
}
if (icon == nil)
{
}
/*
* Nothing found at all - use the unknowntype icon.
*/
if (icon == nil)
{
icon = [self unknownFiletypeImage];
}
/*
* Set the icon in the cache for next time.
*/
if (icon != nil)
[iconMap setObject: icon forKey: ext];
}
return icon;
}
- (BOOL) _extension: (NSString*)ext
role: (NSString*)role
app: (NSString**)app
andInfo: (NSDictionary**)inf
{
NSEnumerator *enumerator;
NSString *appName = nil;
NSDictionary *apps;
NSDictionary *prefs;
NSDictionary *info;
ext = [ext lowercaseString];
apps = [self infoForExtension: ext];
if (apps == nil || [apps count] == 0)
return NO;
/*
* Look for the name of the preferred app in this role.
* A 'nil' roll is a wildcard - find the preferred Editor or Viewer.
*/
prefs = [extPreferences objectForKey: ext];
if (role == nil || [role isEqualToString: @"Editor"])
{
appName = [prefs objectForKey: @"Editor"];
if (appName)
{
info = [apps objectForKey: appName];
if (info)
{
if (app)
*app = appName;
if (inf)
*inf = info;
return YES;
}
}
}
if (role == nil || [role isEqualToString: @"Viewer"])
{
appName = [prefs objectForKey: @"Viewer"];
if (appName)
{
info = [apps objectForKey: appName];
if (info)
{
if (app)
*app = appName;
if (inf)
*inf = info;
return YES;
}
}
}
/*
* Go through the dictionary of apps that know about this file type and
* determine the best application to open the file by examining the
* type information for each app.
* The 'NSRole' field specifies what the app can do with the file - if it
* is missing, we assume an 'Editor' role.
*/
enumerator = [apps keyEnumerator];
if (role == nil)
{
BOOL found = NO;
/*
* If the requested role is 'nil', we can accept an app that is either
* an Editor (preferred) or a Viewer.
*/
while ((appName = [enumerator nextObject]) != nil)
{
NSString *str;
info = [apps objectForKey: appName];
str = [info objectForKey: @"NSRole"];
if (str == nil || [str isEqualToString: @"Editor"])
{
if (app)
*app = appName;
if (inf)
*inf = info;
return YES;
}
else if ([str isEqualToString: @"Viewer"])
{
if (app)
*app = appName;
if (inf)
*inf = info;
found = YES;
}
}
return found;
}
else
{
while ((appName = [enumerator nextObject]) != nil)
{
NSString *str;
info = [apps objectForKey: appName];
str = [info objectForKey: @"NSRole"];
if ((str == nil && [role isEqualToString: @"Editor"])
|| [str isEqualToString: role])
{
if (app)
*app = appName;
if (inf)
*inf = info;
return YES;
}
}
return NO;
}
}
// //
// Instance methods // Instance methods
@ -272,21 +472,9 @@ static NSString* library_combo =
- (BOOL) openFile: (NSString *)fullPath - (BOOL) openFile: (NSString *)fullPath
{ {
NSString *ext = [fullPath pathExtension]; NSString *ext = [fullPath pathExtension];
NSDictionary *map;
NSArray *apps;
NSString *appName; NSString *appName;
/* if ([self _extension: ext role: nil app: &appName andInfo: 0] == NO)
* Get the applications cache (generated by the make_services tool)
* and lookup the special entry that contains a dictionary of all
* file extensions recognised by GNUstep applications. Then find
* the array of applications that can handle our file.
*/
if (applications == nil)
[self findApplications];
map = [applications objectForKey: @"GSExtensionsMap"];
apps = [map objectForKey: ext];
if (apps == nil || [apps count] == 0)
{ {
NSRunAlertPanel(nil, NSRunAlertPanel(nil,
[NSString stringWithFormat: [NSString stringWithFormat:
@ -295,9 +483,6 @@ static NSString* library_combo =
return NO; return NO;
} }
/* FIXME - need a mechanism for determining default application */
appName = [apps objectAtIndex: 0];
return [self openFile: fullPath withApplication: appName]; return [self openFile: fullPath withApplication: appName];
} }
@ -369,10 +554,10 @@ static NSString* library_combo =
// Manipulating Files // Manipulating Files
// //
- (BOOL) performFileOperation: (NSString *)operation - (BOOL) performFileOperation: (NSString *)operation
source: (NSString *)source source: (NSString *)source
destination: (NSString *)destination destination: (NSString *)destination
files: (NSArray *)files files: (NSArray *)files
tag: (int *)tag tag: (int *)tag
{ {
return NO; return NO;
} }
@ -428,45 +613,64 @@ inFileViewerRootedAtPath: (NSString *)rootFullpath
NSImage *image = nil; NSImage *image = nil;
BOOL isDir = NO; BOOL isDir = NO;
NSString *iconPath = nil; NSString *iconPath = nil;
NSString *pathExtension = nil; NSString *pathExtension = [[aPath pathExtension] lowercaseString];
NSFileManager *mgr = [NSFileManager defaultManager]; NSFileManager *mgr = [NSFileManager defaultManager];
if ([mgr fileExistsAtPath: aPath isDirectory: &isDir] && isDir) if ([mgr fileExistsAtPath: aPath isDirectory: &isDir] && isDir)
{ {
// we have a directory if ([pathExtension isEqualToString: @"app"]
iconPath = [aPath stringByAppendingPathComponent: @".dir.tiff"]; || [pathExtension isEqualToString: @"debug"]
|| [pathExtension isEqualToString: @"profile"])
NSLog(@"iconPath is '%@'", iconPath);
NS_DURING
{ {
image = [[NSImage alloc] initWithContentsOfFile: iconPath]; NSBundle *bundle;
[image autorelease];
}
NS_HANDLER
{
NSLog(@"BAD TIFF FILE '%@'", iconPath);
}
NS_ENDHANDLER
NSLog(@"aPath is '%@'", aPath); bundle = [NSBundle bundleWithPath: aPath];
iconPath = [[bundle infoDictionary] objectForKey: @"NSIcon"];
if (iconPath && [iconPath isAbsolutePath] == NO)
if (((!image)
&& (pathExtension = [aPath pathExtension]))
&& ([pathExtension isEqual: @""] == NO))
{
if ((iconPath = [[_suffixes objectForKey: pathExtension]
objectForKey: @"ICON"]) != nil)
{ {
NSLog(@"using '%@'", iconPath = [aPath stringByAppendingPathComponent: iconPath];
[defaultIconPath stringByAppendingPathComponent: iconPath]); }
/*
* If there is no icon specified in the Info.plist for app
* try 'wrapper/app.tiff' and 'wrapper/.dir.tiff' as
* possible locations for the application icon.
*/
if (iconPath == nil)
{
NSString *str;
image = [[NSImage alloc] initWithContentsOfFile: str = [[aPath lastPathComponent] stringByDeletingPathExtension];
[defaultIconPath stringByAppendingPathComponent: iconPath]]; iconPath = [aPath stringByAppendingPathComponent: str];
[image autorelease]; iconPath = [iconPath stringByAppendingPathExtension: @"tiff"];
if ([mgr isReadableFileAtPath: iconPath] == NO)
{
str = @".dir.tiff";
iconPath = [aPath stringByAppendingPathComponent: str];
if ([mgr isReadableFileAtPath: iconPath] == NO)
iconPath = nil;
}
}
if (iconPath)
{
NS_DURING
{
image = [[NSImage alloc] initWithContentsOfFile: iconPath];
[image autorelease];
}
NS_HANDLER
{
NSLog(@"BAD TIFF FILE '%@'", iconPath);
}
NS_ENDHANDLER
} }
} }
if (image == nil)
{
image = [self _iconForExtension: pathExtension];
}
if (image == nil) if (image == nil)
{ {
if ([aPath isEqual: _rootPath]) if ([aPath isEqual: _rootPath])
@ -475,23 +679,11 @@ inFileViewerRootedAtPath: (NSString *)rootFullpath
image= [self folderImage]; image= [self folderImage];
} }
} }
else // not a directory else
{ {
if (((!image) && (pathExtension = [aPath pathExtension])) NSDebugLog(@"pathExtension is '%@'", pathExtension);
&& ([pathExtension isEqual: @""] == NO))
{
NSLog(@"pathExtension is '%@'",pathExtension);
if ((iconPath = [[_suffixes objectForKey: pathExtension]
objectForKey: @"ICON"]) != nil)
{
NSLog(@"using '%@'",
[defaultIconPath stringByAppendingPathComponent: iconPath]);
image = [[NSImage alloc] initWithContentsOfFile: image = [self _iconForExtension: pathExtension];
[defaultIconPath stringByAppendingPathComponent: iconPath]];
[image autorelease];
}
}
} }
if (image == nil) if (image == nil)
@ -538,7 +730,7 @@ inFileViewerRootedAtPath: (NSString *)rootFullpath
{ {
static NSString *path = nil; static NSString *path = nil;
NSData *data; NSData *data;
NSDictionary *newApps; NSDictionary *dict;
NSTask *task; NSTask *task;
/* /*
@ -552,14 +744,25 @@ inFileViewerRootedAtPath: (NSString *)rootFullpath
if (task != nil) if (task != nil)
[task waitUntilExit]; [task waitUntilExit];
data = [NSData dataWithContentsOfFile: extPrefPath];
if (data)
{
dict = [NSDeserializer deserializePropertyListFromData: data
mutableContainers: NO];
ASSIGN(extPreferences, dict);
}
data = [NSData dataWithContentsOfFile: appListPath]; data = [NSData dataWithContentsOfFile: appListPath];
if (data) if (data)
newApps = [NSDeserializer deserializePropertyListFromData: data {
mutableContainers: NO]; dict = [NSDeserializer deserializePropertyListFromData: data
else mutableContainers: NO];
newApps = [NSDictionary dictionary]; ASSIGN(applications, dict);
}
ASSIGN(applications, newApps); /*
* Invalidate the cache of icons for file extensions.
*/
[iconMap removeAllObjects];
} }
// //
@ -674,6 +877,7 @@ inFileViewerRootedAtPath: (NSString *)rootFullpath
- (void) noteUserDefaultsChanged - (void) noteUserDefaultsChanged
{ {
userDefaultsChanged = YES; userDefaultsChanged = YES;
} }
- (BOOL) userDefaultsChanged - (BOOL) userDefaultsChanged
@ -702,3 +906,141 @@ inFileViewerRootedAtPath: (NSString *)rootFullpath
@end @end
@implementation NSWorkspace (GNUstep)
- (NSString*) getBestAppInRole: (NSString*)role
forExtension: (NSString*)ext
{
NSString *appName = nil;
if (extPreferences != nil)
{
NSDictionary *inf;
inf = [extPreferences objectForKey: [ext lowercaseString]];
if (inf != nil)
{
if (role == nil)
{
appName = [inf objectForKey: @"Editor"];
if (appName == nil)
appName = [inf objectForKey: @"Viewer"];
}
else
{
appName = [inf objectForKey: role];
}
}
}
return appName;
}
- (NSString*) getBestIconForExtension: (NSString*)ext
{
NSString *iconPath = nil;
if (extPreferences != nil)
{
NSDictionary *inf;
inf = [extPreferences objectForKey: [ext lowercaseString]];
if (inf != nil)
iconPath = [inf objectForKey: @"Icon"];
}
return iconPath;
}
- (NSDictionary*) infoForExtension: (NSString*)ext
{
NSDictionary *map;
ext = [ext lowercaseString];
/*
* Get the applications cache (generated by the make_services tool)
* and lookup the special entry that contains a dictionary of all
* file extensions recognised by GNUstep applications. Then find
* the dictionary of applications that can handle our file.
*/
if (applications == nil)
[self findApplications];
map = [applications objectForKey: @"GSExtensionsMap"];
return [map objectForKey: ext];
}
- (void) setBestApp: (NSString*)appName
inRole: (NSString*)role
forExtension: (NSString*)ext
{
NSMutableDictionary *map;
NSMutableDictionary *inf;
NSData *data;
ext = [ext lowercaseString];
if (extPreferences)
map = [extPreferences mutableCopy];
else
map = [NSMutableDictionary new];
inf = [[map objectForKey: ext] mutableCopy];
if (inf == nil)
{
inf = [NSMutableDictionary new];
}
if (appName == nil)
{
if (role == nil)
{
NSString *iconPath = [inf objectForKey: @"Icon"];
[iconPath retain];
[inf removeAllObjects];
if (iconPath)
{
[inf setObject: iconPath forKey: @"Icon"];
}
}
else
{
[inf removeObjectForKey: role];
}
}
else
{
[inf setObject: appName forKey: (role ? role : @"Editor")];
}
[map setObject: inf forKey: ext];
[inf release];
[extPreferences release];
extPreferences = inf;
data = [NSSerializer serializePropertyList: extPreferences];
[data writeToFile: extPrefPath atomically: YES];
}
- (void) setBestIcon: (NSString*)iconPath forExtension: (NSString*)ext
{
NSMutableDictionary *map;
NSMutableDictionary *inf;
NSData *data;
ext = [ext lowercaseString];
if (extPreferences)
map = [extPreferences mutableCopy];
else
map = [NSMutableDictionary new];
inf = [[map objectForKey: ext] mutableCopy];
if (inf == nil)
inf = [NSMutableDictionary new];
if (iconPath)
[inf setObject: iconPath forKey: @"Icon"];
else
[inf removeObjectForKey: @"Icon"];
[map setObject: inf forKey: ext];
[inf release];
[extPreferences release];
extPreferences = inf;
data = [NSSerializer serializePropertyList: extPreferences];
[data writeToFile: extPrefPath atomically: YES];
}
@end