mirror of
https://github.com/gnustep/libs-gui.git
synced 2025-05-31 19:00:47 +00:00
Fixups to avoid crashes opening non-document-based apps.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@28844 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
c8916fd438
commit
51e03c6d17
4 changed files with 267 additions and 201 deletions
|
@ -3,7 +3,13 @@
|
|||
* Source/GSThemeTools.m: Fix last changes to compile again (variable
|
||||
declarations not at startof block only work on some compilers).
|
||||
* Source/NSApplication.m: Fixup to show suppressed icon when app is
|
||||
deactivated.
|
||||
deactivated. Fix uninitialisaed variable causing crashes on failing
|
||||
to use document controller to open an untitled document.
|
||||
Drop non-standard method (which didn't work) for determining whether
|
||||
we have a document based app.
|
||||
* Source/NSDocumentController.m: Rewrite code for determining
|
||||
whether the current app is document based. Cache singleton information
|
||||
in static variables rether than ivars.
|
||||
|
||||
2009-10-19 Nicolas Roard <nicolas@roard.com>
|
||||
* Source/GSTheme.m:
|
||||
|
|
|
@ -67,13 +67,18 @@
|
|||
/*" document creation "*/
|
||||
// doesn't create the windowControllers
|
||||
- (id) makeUntitledDocumentOfType: (NSString*)type;
|
||||
- (id)makeDocumentWithContentsOfFile:(NSString *)fileName ofType:(NSString *)type;
|
||||
- (id) makeDocumentWithContentsOfFile: (NSString*)fileName
|
||||
ofType: (NSString*)type;
|
||||
// creates window controllers
|
||||
- (id)openUntitledDocumentOfType:(NSString*)type display:(BOOL)display;
|
||||
- (id)openDocumentWithContentsOfFile:(NSString *)fileName display:(BOOL)display;
|
||||
- (id) openUntitledDocumentOfType: (NSString*)type
|
||||
display: (BOOL)display;
|
||||
- (id) openDocumentWithContentsOfFile: (NSString*)fileName
|
||||
display: (BOOL)display;
|
||||
|
||||
- (id)makeDocumentWithContentsOfURL:(NSURL *)url ofType:(NSString *)type;
|
||||
- (id)openDocumentWithContentsOfURL:(NSURL *)url display:(BOOL)display;
|
||||
- (id) makeDocumentWithContentsOfURL: (NSURL*)url
|
||||
ofType: (NSString*)type;
|
||||
- (id) openDocumentWithContentsOfURL: (NSURL*)url
|
||||
display: (BOOL)display;
|
||||
#if OS_API_VERSION(MAC_OS_X_VERSION_10_4, GS_API_LATEST)
|
||||
- (id) makeDocumentForURL: (NSURL*)url
|
||||
withContentsOfURL: (NSURL*)contents
|
||||
|
@ -122,7 +127,8 @@
|
|||
/*" Open panel "*/
|
||||
- (NSArray*) URLsFromRunningOpenPanel;
|
||||
- (NSArray*) fileNamesFromRunningOpenPanel;
|
||||
- (NSInteger)runModalOpenPanel:(NSOpenPanel *)openPanel forTypes:(NSArray *)openableFileExtensions;
|
||||
- (NSInteger) runModalOpenPanel: (NSOpenPanel*)openPanel
|
||||
forTypes: (NSArray*)openableFileExtensions;
|
||||
|
||||
/*" Document management "*/
|
||||
- (void) addDocument: (NSDocument*)document;
|
||||
|
@ -131,7 +137,8 @@
|
|||
- (void) closeAllDocumentsWithDelegate: (id)delegate
|
||||
didCloseAllSelector: (SEL)didAllCloseSelector
|
||||
contextInfo: (void*)contextInfo;
|
||||
- (BOOL)reviewUnsavedDocumentsWithAlertTitle:(NSString *)title cancellable:(BOOL)cancellable;
|
||||
- (BOOL) reviewUnsavedDocumentsWithAlertTitle: (NSString*)title
|
||||
cancellable: (BOOL)cancellable;
|
||||
- (void) reviewUnsavedDocumentsWithAlertTitle: (NSString*)title
|
||||
cancellable: (BOOL)cancellable
|
||||
delegate: (id)delegate
|
||||
|
@ -157,10 +164,21 @@
|
|||
- (NSString*) typeFromFileExtension: (NSString*)fileExtension;
|
||||
- (NSArray*) fileExtensionsFromType: (NSString*)type;
|
||||
- (Class) documentClassForType: (NSString*)type;
|
||||
|
||||
#if OS_API_VERSION(MAC_OS_X_VERSION_10_4, GS_API_LATEST)
|
||||
/** Returns the first type found for which the application has an editor
|
||||
* role.
|
||||
*/
|
||||
- (NSString*) defaultType;
|
||||
|
||||
/** Returns the names of the NSDocument subclasses handling documents
|
||||
* in this application. This will be nil or empty if this is not a document
|
||||
* based application.
|
||||
*/
|
||||
- (NSArray*) documentClassNames;
|
||||
- (NSString *)typeForContentsOfURL:(NSURL *)url error:(NSError **)err;
|
||||
|
||||
- (NSString*) typeForContentsOfURL: (NSURL*)url
|
||||
error: (NSError**)err;
|
||||
#endif
|
||||
|
||||
#if OS_API_VERSION(MAC_OS_X_VERSION_10_4, GS_API_LATEST)
|
||||
|
|
|
@ -365,10 +365,6 @@ struct _NSModalSession {
|
|||
NSModalSession previous;
|
||||
};
|
||||
|
||||
@interface NSDocumentController (ApplicationPrivate)
|
||||
+ (BOOL) isDocumentBasedApplication;
|
||||
@end
|
||||
|
||||
@interface NSApplication (Private)
|
||||
- _appIconInit;
|
||||
- (NSDictionary*) _notificationUserInfo;
|
||||
|
@ -950,6 +946,7 @@ static NSSize scaledIconSizeForSize(NSSize imageSize)
|
|||
{
|
||||
NSBundle *mainBundle = [NSBundle mainBundle];
|
||||
NSDictionary *infoDict = [mainBundle infoDictionary];
|
||||
NSDocumentController *sdc;
|
||||
NSString *mainModelFile;
|
||||
NSString *appIconFile;
|
||||
NSUserDefaults *defs = [NSUserDefaults standardUserDefaults];
|
||||
|
@ -1104,11 +1101,10 @@ static NSSize scaledIconSizeForSize(NSSize imageSize)
|
|||
* Instantiate the NSDocumentController if we are a doc-based app
|
||||
* and eventually reopen all autosaved documents
|
||||
*/
|
||||
if ([NSDocumentController isDocumentBasedApplication])
|
||||
sdc = [NSDocumentController sharedDocumentController];
|
||||
if ([[sdc documentClassNames] count] > 0)
|
||||
{
|
||||
didAutoreopen =
|
||||
[[NSDocumentController sharedDocumentController]
|
||||
_reopenAutosavedDocuments];
|
||||
didAutoreopen = [sdc _reopenAutosavedDocuments];
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1141,14 +1137,12 @@ static NSSize scaledIconSizeForSize(NSSize imageSize)
|
|||
[_delegate applicationOpenUntitledFile: self];
|
||||
}
|
||||
}
|
||||
else if ([NSDocumentController isDocumentBasedApplication])
|
||||
else if ([[sdc documentClassNames] count] > 0)
|
||||
{
|
||||
NSError *err;
|
||||
NSDocumentController *sdc =
|
||||
[NSDocumentController sharedDocumentController];
|
||||
NSError *err = nil;
|
||||
|
||||
if ([sdc openUntitledDocumentAndDisplay: YES error: &err] == nil &&
|
||||
[sdc presentError: err] == NO)
|
||||
if ([sdc openUntitledDocumentAndDisplay: YES error: &err] == nil
|
||||
&& [sdc presentError: err] == NO)
|
||||
{
|
||||
[self terminate: self];
|
||||
}
|
||||
|
@ -3376,10 +3370,12 @@ struct _DelegateWrapper
|
|||
}
|
||||
else
|
||||
{
|
||||
if ([NSDocumentController isDocumentBasedApplication])
|
||||
NSDocumentController *sdc;
|
||||
|
||||
sdc = [NSDocumentController sharedDocumentController];
|
||||
if ([[sdc documentClassNames] count] > 0)
|
||||
{
|
||||
if ([[NSDocumentController sharedDocumentController]
|
||||
reviewUnsavedDocumentsWithAlertTitle: _(@"Quit")
|
||||
if ([sdc reviewUnsavedDocumentsWithAlertTitle: _(@"Quit")
|
||||
cancellable: YES] == YES)
|
||||
{
|
||||
termination = NSTerminateNow;
|
||||
|
@ -3758,6 +3754,7 @@ struct _DelegateWrapper
|
|||
keyWindow: (NSWindow *)keyWindow
|
||||
mainWindow: (NSWindow *)mainWindow
|
||||
{
|
||||
NSDocumentController *sdc;
|
||||
id resp, delegate;
|
||||
NSWindow *window;
|
||||
|
||||
|
@ -3779,6 +3776,8 @@ struct _DelegateWrapper
|
|||
|
||||
if (window != nil)
|
||||
{
|
||||
NSDocumentController *sdc;
|
||||
|
||||
/* traverse the responder chain including the window's delegate */
|
||||
resp = [window firstResponder];
|
||||
while (resp != nil && resp != self)
|
||||
|
@ -3799,10 +3798,10 @@ struct _DelegateWrapper
|
|||
}
|
||||
|
||||
/* in a document based app try the window's document */
|
||||
if ([NSDocumentController isDocumentBasedApplication])
|
||||
sdc = [NSDocumentController sharedDocumentController];
|
||||
if ([[sdc documentClassNames] count] > 0)
|
||||
{
|
||||
resp = [[NSDocumentController sharedDocumentController]
|
||||
documentForWindow: window];
|
||||
resp = [sdc documentForWindow: window];
|
||||
|
||||
if (resp != nil && [resp respondsToSelector: aSelector])
|
||||
{
|
||||
|
@ -3848,9 +3847,9 @@ struct _DelegateWrapper
|
|||
}
|
||||
|
||||
/* as a last resort in a document based app, try the document controller */
|
||||
if ([NSDocumentController isDocumentBasedApplication]
|
||||
&& [[NSDocumentController sharedDocumentController]
|
||||
respondsToSelector: aSelector])
|
||||
sdc = [NSDocumentController sharedDocumentController];
|
||||
if ([[sdc documentClassNames] count] > 0
|
||||
&& [sdc respondsToSelector: aSelector])
|
||||
{
|
||||
return [NSDocumentController sharedDocumentController];
|
||||
}
|
||||
|
|
|
@ -72,12 +72,16 @@ static NSString *NSViewerRole = @"Viewer";
|
|||
|
||||
static NSDocumentController *sharedController = nil;
|
||||
|
||||
static NSArray *allTypes = nil;
|
||||
static NSArray *classNames = nil;
|
||||
|
||||
#define TYPE_INFO(name) TypeInfoForName(_types, name)
|
||||
#define HR_TYPE_INFO(name) TypeInfoForHumanReadableName(_types, name)
|
||||
|
||||
static NSDictionary *TypeInfoForName (NSArray *types, NSString *typeName)
|
||||
{
|
||||
int i, count = [types count];
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
NSDictionary *dict = [types objectAtIndex: i];
|
||||
|
@ -86,7 +90,8 @@ static NSDictionary *TypeInfoForName (NSArray *types, NSString *typeName)
|
|||
{
|
||||
return dict;
|
||||
}
|
||||
else if ([[dict objectForKey: CFBundleTypeName] isEqualToString: typeName])
|
||||
else if ([[dict objectForKey: CFBundleTypeName]
|
||||
isEqualToString: typeName])
|
||||
{
|
||||
return dict;
|
||||
}
|
||||
|
@ -95,18 +100,22 @@ static NSDictionary *TypeInfoForName (NSArray *types, NSString *typeName)
|
|||
return nil;
|
||||
}
|
||||
|
||||
static NSDictionary *TypeInfoForHumanReadableName (NSArray *types, NSString *typeName)
|
||||
static NSDictionary *
|
||||
TypeInfoForHumanReadableName (NSArray *types, NSString *typeName)
|
||||
{
|
||||
int i, count = [types count];
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
NSDictionary *dict = [types objectAtIndex: i];
|
||||
|
||||
if ([[dict objectForKey: NSHumanReadableNameKey] isEqualToString: typeName])
|
||||
if ([[dict objectForKey: NSHumanReadableNameKey]
|
||||
isEqualToString: typeName])
|
||||
{
|
||||
return dict;
|
||||
}
|
||||
else if ([[dict objectForKey: CFBundleTypeName] isEqualToString: typeName])
|
||||
else if ([[dict objectForKey: CFBundleTypeName]
|
||||
isEqualToString: typeName])
|
||||
{
|
||||
return dict;
|
||||
}
|
||||
|
@ -167,6 +176,76 @@ static NSDictionary *TypeInfoForHumanReadableName (NSArray *types, NSString *typ
|
|||
*/
|
||||
@implementation NSDocumentController
|
||||
|
||||
|
||||
+ (void) initialize
|
||||
{
|
||||
static BOOL beenHere = NO;
|
||||
|
||||
if (beenHere == NO)
|
||||
{
|
||||
NSArray *types;
|
||||
|
||||
beenHere = YES;
|
||||
types = [[[NSBundle mainBundle] infoDictionary]
|
||||
objectForKey: NSTypesKey];
|
||||
if (types == nil)
|
||||
{
|
||||
types = [[[NSBundle mainBundle] infoDictionary]
|
||||
objectForKey: CFBundleDocumentTypes];
|
||||
}
|
||||
if (YES == [types isKindOfClass: [NSArray class]])
|
||||
{
|
||||
unsigned count = [types count];
|
||||
unsigned src;
|
||||
unsigned dst = 0;
|
||||
NSString *names[count];
|
||||
NSDictionary *valid[count];
|
||||
|
||||
for (src = 0; src < count; src++)
|
||||
{
|
||||
NSDictionary *d = [types objectAtIndex: src];
|
||||
|
||||
if (YES == [d isKindOfClass: [NSDictionary class]])
|
||||
{
|
||||
NSString *name = [d objectForKey: NSDocumentClassKey];
|
||||
|
||||
/* Is this type handled by an NSDocument subclass?
|
||||
*/
|
||||
if (YES == [name isKindOfClass: [NSString class]])
|
||||
{
|
||||
Class c = NSClassFromString(name);
|
||||
|
||||
if (YES == [c isSubclassOfClass: [NSDocument class]])
|
||||
{
|
||||
names[dst] = name;
|
||||
valid[dst++] = d;
|
||||
}
|
||||
else if (c == 0)
|
||||
{
|
||||
NSLog(@"NSDocumentClass %@ not found", name);
|
||||
}
|
||||
else
|
||||
{
|
||||
NSLog(@"NSDocumentClass %@ not NSDocument subclass",
|
||||
name);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NSLog(@"Bad item at index %u in %@",
|
||||
src, CFBundleDocumentTypes);
|
||||
}
|
||||
}
|
||||
if (dst > 0)
|
||||
{
|
||||
classNames = [[NSArray alloc] initWithObjects: names count: dst];
|
||||
allTypes = [[NSArray alloc] initWithObjects: valid count: dst];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns the shared instance of the document controller class. You
|
||||
should always use this method to get the NSDocumentController. */
|
||||
+ (id) sharedDocumentController
|
||||
|
@ -180,30 +259,13 @@ static NSDictionary *TypeInfoForHumanReadableName (NSArray *types, NSString *typ
|
|||
return sharedController;
|
||||
}
|
||||
|
||||
/* Private method for use by NSApplication to determine if it should
|
||||
instantiate an NSDocumentController.
|
||||
*/
|
||||
+ (BOOL) isDocumentBasedApplication
|
||||
{
|
||||
return ([[[NSBundle mainBundle] infoDictionary] objectForKey: NSTypesKey] ||
|
||||
[[[NSBundle mainBundle] infoDictionary] objectForKey: CFBundleDocumentTypes])
|
||||
? YES : NO;
|
||||
}
|
||||
|
||||
/** </init>Initializes the document controller class. The first
|
||||
instance of a document controller class that gets initialized
|
||||
becomes the shared instance.
|
||||
*/
|
||||
- init
|
||||
{
|
||||
NSDictionary *customDict = [[NSBundle mainBundle] infoDictionary];
|
||||
|
||||
ASSIGN (_types, [customDict objectForKey: NSTypesKey]);
|
||||
|
||||
if(_types == nil)
|
||||
{
|
||||
ASSIGN(_types, [customDict objectForKey: CFBundleDocumentTypes]);
|
||||
}
|
||||
_types = RETAIN(allTypes);
|
||||
|
||||
_documents = [[NSMutableArray alloc] init];
|
||||
|
||||
|
@ -1151,10 +1213,10 @@ static BOOL _shouldClose = YES;
|
|||
NSDictionary *typeInfo = [_types objectAtIndex: i];
|
||||
|
||||
if ([[typeInfo objectForKey: NSUnixExtensionsKey]
|
||||
containsObject: fileExtension] ||
|
||||
[[typeInfo objectForKey: NSDOSExtensionsKey]
|
||||
containsObject: fileExtension] ||
|
||||
[[typeInfo objectForKey: CFBundleTypeExtensions]
|
||||
containsObject: fileExtension]
|
||||
|| [[typeInfo objectForKey: NSDOSExtensionsKey]
|
||||
containsObject: fileExtension]
|
||||
|| [[typeInfo objectForKey: CFBundleTypeExtensions]
|
||||
containsObject: fileExtension])
|
||||
{
|
||||
NSString *type = [typeInfo objectForKey: NSNameKey];
|
||||
|
@ -1203,28 +1265,7 @@ static BOOL _shouldClose = YES;
|
|||
|
||||
- (NSArray*) documentClassNames
|
||||
{
|
||||
int i, count = [_types count];
|
||||
NSMutableArray *classNames;
|
||||
|
||||
classNames = [[NSMutableArray alloc] initWithCapacity: count];
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
NSDictionary *typeInfo = [_types objectAtIndex: i];
|
||||
NSString *className = [typeInfo objectForKey: NSDocumentClassKey];
|
||||
|
||||
if(className != nil)
|
||||
{
|
||||
[classNames addObject: className];
|
||||
}
|
||||
else
|
||||
{
|
||||
NSLog(@"WARN: The entry does not have an NSDocumentClass name defined: %@",
|
||||
typeInfo);
|
||||
}
|
||||
}
|
||||
|
||||
return AUTORELEASE(classNames);
|
||||
return classNames;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1586,8 +1627,9 @@ static NSString *processName = nil;
|
|||
[recentMenu setMenuChangedMessagesEnabled: NO];
|
||||
|
||||
while ([recentMenu numberOfItems] > 0)
|
||||
{
|
||||
[recentMenu removeItemAtIndex: 0]; // remove them all
|
||||
|
||||
}
|
||||
for (i = [_recent_documents count]; i >= -2; i--)
|
||||
{
|
||||
// add all items incl. a Clear List item if needed
|
||||
|
@ -1614,7 +1656,8 @@ static NSString *processName = nil;
|
|||
// standard item
|
||||
NSURL *u = [_recent_documents objectAtIndex: i]; // get URL
|
||||
if ([u isFileURL])
|
||||
item = [[NSMenuItem alloc] initWithTitle: [[u path] lastPathComponent]
|
||||
item = [[NSMenuItem alloc]
|
||||
initWithTitle: [[u path] lastPathComponent]
|
||||
action: @selector(_openRecentDocument:)
|
||||
keyEquivalent:nil];
|
||||
else
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue