diff --git a/Headers/gnustep/gui/NSApplication.h b/Headers/gnustep/gui/NSApplication.h index d51fb6597..6a154be83 100644 --- a/Headers/gnustep/gui/NSApplication.h +++ b/Headers/gnustep/gui/NSApplication.h @@ -70,6 +70,7 @@ extern NSString *NSEventTrackingRunLoopMode; id key_window; id main_window; id delegate; + id listener; int window_count; NSMenu *main_menu; NSMenuItem *windows_menu; @@ -210,7 +211,9 @@ extern NSString *NSEventTrackingRunLoopMode; - (void)registerServicesMenuSendTypes:(NSArray *)sendTypes returnTypes:(NSArray *)returnTypes; - (NSMenu *)servicesMenu; +- (id)servicesProvider; - (void)setServicesMenu:(NSMenu *)aMenu; +- (void)setServicesProvider:(id)anObject; - validRequestorForSendType:(NSString *)sendType returnType:(NSString *)returnType; @@ -331,6 +334,11 @@ BOOL NSPerformService(NSString *item, NSPasteboard *pboard); // void NSUpdateDynamicServices(void); +// +// Register object to handle services requests. +// +void +NSRegisterServicesProvider(id provider, NSString *name); int NSApplicationMain(int argc, const char **argv); diff --git a/Source/NSApplication.m b/Source/NSApplication.m index 076cf77d8..0c5e77ce0 100644 --- a/Source/NSApplication.m +++ b/Source/NSApplication.m @@ -32,6 +32,7 @@ #include #include +#include #include #include #include @@ -39,14 +40,13 @@ #include #include #include - -#ifndef LIB_FOUNDATION_LIBRARY -# include -#endif +#include +#include #include #include #include +#include #include #include #include @@ -56,14 +56,589 @@ #include -#define CONVEY(a, b) [b retain]; \ - [a release]; \ - a = b; +extern NSDictionary *GSAllServicesDictionary(); + +/* + * Local class for handling incoming service requests etc. + */ +@interface ApplicationListener : NSObject +{ + id servicesProvider; + NSApplication *application; + NSMenu *servicesMenu; + NSMutableArray *languages; + NSMutableSet *returnInfo; + NSMutableDictionary *combinations; + NSMutableDictionary *title2info; + NSArray *menuTitles; + BOOL isRegistered; +} ++ (ApplicationListener*) newWithApplication: (NSApplication*)app; +- (void) doService: (NSCell*)item; +- (BOOL) hasRegisteredTypes: (NSDictionary*)service; +- (NSString*) item2title: (NSCell*)item; +- (void) rebuildServices; +- (void) rebuildServicesMenu; +- (void) registerAsServiceProvider; +- (void) registerSendTypes: (NSArray *)sendTypes + returnTypes: (NSArray *)returnTypes; +- (NSMenu *) servicesMenu; +- (id) servicesProvider; +- (void) setServicesMenu: (NSMenu *)anObject; +- (void) setServicesProvider: (id)anObject; +- (BOOL) validateMenuItem: (NSCell*)item; +- (void) updateServicesMenu; +@end + +@implementation ApplicationListener +/* + * Create a new listener for this application. + * Uses NSRegisterServicesProvider() to register itsself as a service + * provider with the applications name so we can handle incoming + * service requests. + */ ++ (ApplicationListener*) newWithApplication: (NSApplication*)app +{ + ApplicationListener *listener = [ApplicationListener alloc]; + + /* + * Don't retain application object - that would reate a cycle. + */ + listener->application = app; + listener->returnInfo = [[NSMutableSet alloc] initWithCapacity: 16]; + listener->combinations = [[NSMutableDictionary alloc] initWithCapacity: 16]; + return listener; +} + +- (void) doService: (NSCell*)item +{ + NSString *title = [self item2title: item]; + NSDictionary *info = [title2info objectForKey: title]; + NSArray *sendTypes = [info objectForKey: @"NSSendTypes"]; + NSArray *returnTypes = [info objectForKey: @"NSReturnTypes"]; + unsigned i, j; + unsigned es = [sendTypes count]; + unsigned er = [returnTypes count]; + NSWindow *resp = [[application keyWindow] firstResponder]; + id obj = nil; + + for (i = 0; i <= es; i++) + { + NSString *sendType; + + sendType = (i < es) ? [sendTypes objectAtIndex: i] : nil; + + for (j = 0; j <= er; j++) + { + NSString *returnType; + + returnType = (j < er) ? [returnTypes objectAtIndex: j] : nil; + + obj = [resp validRequestorForSendType: sendType + returnType: returnType]; + if (obj != nil) + { + NSPasteboard *pb; + + pb = [NSPasteboard pasteboardWithUniqueName]; + if ([obj writeSelectionToPasteboard: pb + types: sendTypes] == NO) + { + NSLog(@"object failed to write to pasteboard\n"); + } + else if (NSPerformService(title, pb) == NO) + { + NSLog(@"Failed to perform %@\n", title); + } + else if ([obj readSelectionFromPasteboard: pb] == NO) + { + NSLog(@"object failed to read from pasteboard\n"); + } + return; + } + } + } +} + +- (BOOL) hasRegisteredTypes: (NSDictionary*)service +{ + NSArray *sendTypes = [service objectForKey: @"NSSendTypes"]; + NSArray *returnTypes = [service objectForKey: @"NSReturnTypes"]; + NSString *type; + unsigned i; + + /* + * We know that both sendTypes and returnTypes can't be nil since + * make_services has validated the service entry for us. + */ + if (sendTypes == nil || [sendTypes count] == 0) + { + for (i = 0; i < [returnTypes count]; i++) + { + type = [returnTypes objectAtIndex: i]; + if ([returnInfo member: type] != nil) + { + return YES; + } + } + } + else if (returnTypes == nil || [returnTypes count] == 0) + { + for (i = 0; i < [sendTypes count]; i++) + { + type = [sendTypes objectAtIndex: i]; + if ([combinations objectForKey: type] != nil) + { + return YES; + } + } + } + else + { + for (i = 0; i < [sendTypes count]; i++) + { + NSSet *rset; + + type = [sendTypes objectAtIndex: i]; + rset = [combinations objectForKey: type]; + if (rset != nil) + { + unsigned j; + + for (j = 0; j < [returnTypes count]; j++) + { + type = [returnTypes objectAtIndex: j]; + if ([rset member: type] != nil) + { + return YES; + } + } + } + } + } + return NO; +} + +/* + * Use tag in menu cell to identify slot in menu titles array that + * contains the full title of the service. + * Return nil if this is not one of our service menu cells. + */ +- (NSString*) item2title: (NSCell*)item +{ + unsigned pos; + + if ([item target] != self) + return nil; + pos = [item tag]; + if (pos > [menuTitles count]) + return nil; + return [menuTitles objectAtIndex: pos]; +} + + +- (void) dealloc +{ + NSRegisterServicesProvider(nil, nil); + [languages release]; + [servicesProvider release]; + [returnInfo release]; + [combinations release]; + [title2info release]; + [menuTitles release]; + [servicesMenu release]; + [super dealloc]; +} + +- forward: (SEL)aSel :(arglist_t)frame +{ + NSString *selName = NSStringFromSelector(aSel); + + /* + * If the selector matches the correct form for a services request, + * send the message to the services provider - otherwise raise an + * exception to say the method is not implemented. + */ + if ([selName hasSuffix: @":userData:error:"]) + return [servicesProvider performv: aSel :frame]; + else + return [self notImplemented: aSel]; +} + +- (void) rebuildServices +{ + NSDictionary *services; + NSUserDefaults *defs; + NSMutableArray *newLang; + NSSet *disabled; + NSMutableSet *alreadyFound; + NSMutableDictionary *newServices; + unsigned pos; + + /* + * If the application has not yet started up fully and registered us, + * we defer the rebuild intil we are registered. This avoids loads + * of successive rebuilds as responder classes register the types they + * can handle on startup. + */ + if (isRegistered == NO) + return; + + defs = [NSUserDefaults standardUserDefaults]; + newLang = [[[defs arrayForKey: @"Languages"] mutableCopy] autorelease]; + if (newLang == nil) + { + newLang = [NSMutableArray arrayWithCapacity: 1]; + } + if ([newLang containsObject: @"default"] == NO) + { + [newLang addObject: @"default"]; + } + ASSIGN(languages, newLang); + + disabled = [NSSet setWithArray: [defs arrayForKey: @"DisabledServices"]]; + services = [GSAllServicesDictionary() objectForKey: @"ByService"]; + + newServices = [NSMutableDictionary dictionaryWithCapacity: 16]; + alreadyFound = [NSMutableSet setWithCapacity: 16]; + + /* + * Build dictionary of services we can use. + * 1. make sure we make dictionary keyed on preferred menu item language + * 2. don't include entries for services already examined. + * 3. don't include entries for menu items specifically disabled. + * 4. don't include entries for which we have no registered types. + */ + for (pos = 0; pos < [languages count]; pos++) + { + NSDictionary *byLanguage; + + byLanguage = [services objectForKey: [languages objectAtIndex: pos]]; + if (byLanguage != nil) + { + NSEnumerator *enumerator = [byLanguage keyEnumerator]; + NSString *menuItem; + + while ((menuItem = [enumerator nextObject]) != nil) + { + NSDictionary *service = [byLanguage objectForKey: menuItem]; + + if ([alreadyFound member: service] != nil) + continue; + + [alreadyFound addObject: service]; + + if ([disabled member: menuItem] != nil) + continue; + + if ([self hasRegisteredTypes: service]) + [newServices setObject: service forKey: menuItem]; + } + } + } + if ([newServices isEqual: title2info] == NO) + { + NSArray *titles; + + ASSIGN(title2info, newServices); + titles = [title2info allKeys]; + titles = [titles sortedArrayUsingSelector: @selector(compare:)]; + ASSIGN(menuTitles, titles); + [self rebuildServicesMenu]; + } +} + +- (void) rebuildServicesMenu +{ + if (isRegistered && servicesMenu) + { + NSArray *itemArray; + NSMutableSet *keyEquivalents; + unsigned pos; + unsigned loc0; + unsigned loc1; + SEL sel = @selector(doService:); + NSMenu *submenu = nil; + + itemArray = [[servicesMenu itemArray] retain]; + pos = [itemArray count]; + while (pos > 0) + { + [servicesMenu removeItem: [itemArray objectAtIndex: --pos]]; + } + [itemArray release]; + + keyEquivalents = [NSMutableSet setWithCapacity: 4]; + for (loc0 = pos = 0; pos < [menuTitles count]; pos++) + { + NSString *title = [menuTitles objectAtIndex: pos]; + NSString *equiv = @""; + NSDictionary *info = [title2info objectForKey: title]; + NSDictionary *titles; + NSDictionary *equivs; + NSRange r; + unsigned lang; + id item; + + /* + * Find the key equivalent corresponding to this menu title + * in the service definition. + */ + titles = [info objectForKey: @"NSMenuItem"]; + equivs = [info objectForKey: @"NSKeyEquivalent"]; + for (lang = 0; lang < [languages count]; lang++) + { + NSString *language = [languages objectAtIndex: lang]; + NSString *t = [titles objectForKey: language]; + + if ([t isEqual: title]) + { + equiv = [equivs objectForKey: language]; + } + } + + /* + * Make a note that we are using the key equivalent, or + * set to nil if we have already used it in this menu. + */ + if (equiv) + { + if ([keyEquivalents member: equiv] == nil) + { + [keyEquivalents addObject: equiv]; + } + else + { + equiv = @""; + } + } + + r = [title rangeOfString: @"/"]; + if (r.length > 0) + { + NSString *subtitle = [title substringFromIndex: r.location+1]; + NSString *parentTitle = [title substringToIndex: r.location]; + NSMenu *menu; + + item = [servicesMenu itemWithTitle: parentTitle]; + if (item == nil) + { + loc1 = 0; + item = [servicesMenu insertItemWithTitle: parentTitle + action: 0 + keyEquivalent: @"" + atIndex: loc0++]; + menu = [[NSMenu alloc] initWithTitle: parentTitle]; + [servicesMenu setSubmenu: submenu + forItem: item]; + } + else + { + menu = (NSMenu*)[item target]; + } + if (menu != submenu) + { + [submenu sizeToFit]; + submenu = menu; + } + item = [submenu insertItemWithTitle: subtitle + action: sel + keyEquivalent: equiv + atIndex: loc1++]; + [item setTarget: self]; + [item setTag: pos]; + } + else + { + item = [servicesMenu insertItemWithTitle: title + action: sel + keyEquivalent: equiv + atIndex: loc0++]; + [item setTarget: self]; + [item setTag: pos]; + } + } + [submenu sizeToFit]; + [servicesMenu sizeToFit]; + [servicesMenu update]; + } +} + +/* + * Set up connection to listen for incoming service requests. + */ +- (void) registerAsServiceProvider +{ + if (isRegistered == NO) + { + NSString *appName; + + isRegistered = YES; + [self rebuildServices]; + appName = [[[NSProcessInfo processInfo] processName] lastPathComponent]; + NSRegisterServicesProvider(self, appName); + } +} + +/* + * Register send and return types that an object can handle - we keep + * a note of all the possible combinations - + * 'returnInfo' is a set of all the return types that can be handled + * without a send. + * 'combinations' is a dictionary of all send types, with the assciated + * values being sets of possible return types. + */ +- (void) registerSendTypes: (NSArray *)sendTypes + returnTypes: (NSArray *)returnTypes +{ + BOOL didChange = NO; + unsigned i; + + for (i = 0; i < [sendTypes count]; i++) + { + NSString *sendType = [sendTypes objectAtIndex: i]; + NSMutableSet *returnSet = [combinations objectForKey: sendType]; + + if (returnSet == nil) + { + returnSet = [NSMutableSet setWithCapacity: [returnTypes count]]; + [combinations setObject: returnSet forKey: sendType]; + [returnSet addObjectsFromArray: returnTypes]; + didChange = YES; + } + else + { + unsigned count = [returnSet count]; + + [returnSet addObjectsFromArray: returnTypes]; + if ([returnSet count] != count) + { + didChange = YES; + } + } + } + + i = [returnInfo count]; + [returnInfo addObjectsFromArray: returnTypes]; + if ([returnInfo count] != i) + { + didChange = YES; + } + + if (didChange) + { + [self rebuildServices]; + } +} + +- (NSMenu*) servicesMenu +{ + return servicesMenu; +} + +- (id) servicesProvider +{ + return servicesProvider; +} + +- (void) setServicesMenu: (NSMenu*)aMenu +{ + ASSIGN(servicesMenu, aMenu); + [self rebuildServicesMenu]; +} + +- (void) setServicesProvider: (id)anObject +{ + ASSIGN(servicesProvider, anObject); +} + +- (BOOL) validateMenuItem: (NSCell*)item +{ + NSString *title = [self item2title: item]; + NSDictionary *info = [title2info objectForKey: title]; + NSArray *sendTypes = [info objectForKey: @"NSSendTypes"]; + NSArray *returnTypes = [info objectForKey: @"NSReturnTypes"]; + unsigned i, j; + unsigned es = [sendTypes count]; + unsigned er = [returnTypes count]; + NSWindow *resp = [[application keyWindow] firstResponder]; + + /* + * If the menu item is not in our map, it must be the cell containing + * a sub-menu - so we see if any cell in the submenu is valid. + */ + if (title == nil) + { + NSMenu *sub = [item target]; + + if (sub && [sub isKindOfClass: [NSMenu class]]) + { + NSArray *a = [sub itemArray]; + + for (i = 0; i < [a count]; i++) + { + if ([self validateMenuItem: [a objectAtIndex: i]] == YES) + { + return YES; + } + } + } + return NO; + } + + /* + * The cell corresponds to one of our services - so we check to see if + * there is anything that can deal with it. + */ + for (i = 0; i <= es; i++) + { + NSString *sendType; + + sendType = (i < es) ? [sendTypes objectAtIndex: i] : nil; + + for (j = 0; j <= er; j++) + { + NSString *returnType; + + returnType = (j < er) ? [returnTypes objectAtIndex: j] : nil; + + if ([resp validRequestorForSendType: sendType + returnType: returnType] != nil) + { + return YES; + } + } + } + return NO; +} + +- (void) updateServicesMenu +{ + if (servicesMenu) + { + NSArray *a = [servicesMenu itemArray]; + unsigned i; + + for (i = 0; i < [a count]; i++) + { + NSCell *cell = [a objectAtIndex: i]; + + if ([self validateMenuItem: cell] == YES) + { + [cell setEnabled: YES]; + } + } + } +} +@end + + + // // Class variables // static BOOL gnustep_gui_app_is_in_dealloc; -static NSEvent *null_event; +static NSEvent *null_event; static id NSApp; @implementation NSApplication @@ -73,25 +648,25 @@ static id NSApp; // + (void)initialize { - if (self == [NSApplication class]) - { - NSDebugLog(@"Initialize NSApplication class\n"); - // Initial version - [self setVersion:1]; - // So the application knows - gnustep_gui_app_is_in_dealloc = NO; // its within dealloc and - } // can prevent -release -} // loops. + if (self == [NSApplication class]) + { + NSDebugLog(@"Initialize NSApplication class\n"); + // Initial version + [self setVersion:1]; + // So the application knows + gnustep_gui_app_is_in_dealloc = NO; // its within dealloc and + } // can prevent -release +} // loops. + (NSApplication *)sharedApplication -{ // If the global application does - if (!NSApp) // not exist yet then create it - { - NSApp = [self alloc]; // Don't combine the following two - [NSApp init]; // statements into one to avoid - } // problems with some classes' - // initialization code that tries - return NSApp; // to get the shared application. +{ // If the global application does + if (!NSApp) // not exist yet then create it + { + NSApp = [self alloc]; // Don't combine the following two + [NSApp init]; // statements into one to avoid + } // problems with some classes' + // initialization code that tries + return NSApp; // to get the shared application. } // @@ -103,74 +678,79 @@ static id NSApp; // - init { - [super init]; + [super init]; - NSDebugLog(@"Begin of NSApplication -init\n"); + NSDebugLog(@"Begin of NSApplication -init\n"); - window_list = [NSMutableArray new]; // allocate window list - window_count = 1; + listener = [ApplicationListener newWithApplication: self]; + window_list = [NSMutableArray new]; // allocate window list + window_count = 1; - main_menu = nil; - windows_need_update = YES; + main_menu = nil; + windows_need_update = YES; - event_queue = [NSMutableArray new]; // allocate event queue - current_event = [NSEvent new]; // no current event - null_event = [NSEvent new]; // create dummy event + event_queue = [NSMutableArray new]; // allocate event queue + current_event = [NSEvent new]; // no current event + null_event = [NSEvent new]; // create dummy event - [self setNextResponder:NULL]; // We are the end of - // the responder chain + [self setNextResponder:NULL]; // We are the end of + // the responder chain - // Set up the run loop - // object for the - // current thread - [self setupRunLoopInputSourcesForMode:NSDefaultRunLoopMode]; - [self setupRunLoopInputSourcesForMode:NSConnectionReplyMode]; - [self setupRunLoopInputSourcesForMode:NSModalPanelRunLoopMode]; - [self setupRunLoopInputSourcesForMode:NSEventTrackingRunLoopMode]; + // Set up the run loop + // object for the + // current thread + [self setupRunLoopInputSourcesForMode:NSDefaultRunLoopMode]; + [self setupRunLoopInputSourcesForMode:NSConnectionReplyMode]; + [self setupRunLoopInputSourcesForMode:NSModalPanelRunLoopMode]; + [self setupRunLoopInputSourcesForMode:NSEventTrackingRunLoopMode]; - return self; + return self; } - (void)finishLaunching { -NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; -NSBundle* mainBundle = [NSBundle mainBundle]; -NSString* resourcePath = [mainBundle resourcePath]; -NSString* infoFilePath = [resourcePath - stringByAppendingPathComponent:@"Info-gnustep.plist"]; -NSDictionary* infoDict; -NSString* mainModelFile; + NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; + NSBundle* mainBundle = [NSBundle mainBundle]; + NSDictionary* infoDict; + NSString* mainModelFile; - infoDict = [[NSString stringWithContentsOfFile:infoFilePath] propertyList]; - mainModelFile = [infoDict objectForKey:@"NSMainNibFile"]; + infoDict = [mainBundle infoDictionary]; + mainModelFile = [infoDict objectForKey:@"NSMainNibFile"]; - if (mainModelFile && ![mainModelFile isEqual:@""]) - { - if (![GMModel loadIMFile:mainModelFile - owner:[NSApplication sharedApplication]]) - NSLog (@"Cannot load the main model file '%@", mainModelFile); - } - // post notification that - // launch will finish - [nc postNotificationName: NSApplicationWillFinishLaunchingNotification - object: self]; - // finish the launching - // post notification that - // launching has finished - [nc postNotificationName: NSApplicationDidFinishLaunchingNotification - object: self]; + if (mainModelFile && ![mainModelFile isEqual:@""]) + { + if (![GMModel loadIMFile:mainModelFile + owner:[NSApplication sharedApplication]]) + NSLog(@"Cannot load the main model file '%@'", mainModelFile); + } + // post notification that + // launch will finish + [nc postNotificationName: NSApplicationWillFinishLaunchingNotification + object: self]; + + /* + * Register our listener to handle incoming services requests etc. + */ + [listener registerAsServiceProvider]; + + // finish the launching + // post notification that + // launching has finished + [nc postNotificationName: NSApplicationDidFinishLaunchingNotification + object: self]; } - (void)dealloc { - NSDebugLog(@"Freeing NSApplication\n"); - // Let ourselves know we - gnustep_gui_app_is_in_dealloc = YES; // are within dealloc - - [window_list release]; - [event_queue release]; - [current_event release]; - [super dealloc]; + NSDebugLog(@"Freeing NSApplication\n"); + // Let ourselves know we + gnustep_gui_app_is_in_dealloc = YES; // are within dealloc + + [listener release]; + [window_list release]; + [event_queue release]; + [current_event release]; + [super dealloc]; } // @@ -178,17 +758,17 @@ NSString* mainModelFile; // - (void)activateIgnoringOtherApps:(BOOL)flag { - app_is_active = YES; + app_is_active = YES; } - (void)deactivate { - app_is_active = NO; + app_is_active = NO; } - (BOOL)isActive { - return app_is_active; + return app_is_active; } // @@ -200,125 +780,132 @@ NSString* mainModelFile; - (NSModalSession)beginModalSessionForWindow:(NSWindow *)theWindow { - return NULL; + return NULL; } - (void)endModalSession:(NSModalSession)theSession { } -- (BOOL)isRunning +- (BOOL) isRunning { - return app_is_running; + return app_is_running; } -- (void)run +- (void) run { -NSEvent *e; -NSAutoreleasePool* pool; + NSEvent *e; + NSAutoreleasePool* pool; - NSDebugLog(@"NSApplication -run\n"); + NSDebugLog(@"NSApplication -run\n"); - [self finishLaunching]; + [self finishLaunching]; - app_should_quit = NO; - app_is_running = YES; + app_should_quit = NO; + app_is_running = YES; - do { - pool = [NSAutoreleasePool new]; + do + { + pool = [NSAutoreleasePool new]; - e = [self nextEventMatchingMask:NSAnyEventMask - untilDate:[NSDate distantFuture] - inMode:NSDefaultRunLoopMode - dequeue:YES]; - if (e) - [self sendEvent: e]; + e = [self nextEventMatchingMask: NSAnyEventMask + untilDate: [NSDate distantFuture] + inMode: NSDefaultRunLoopMode + dequeue: YES]; + if (e) + [self sendEvent: e]; - if(windows_need_update) // send an update message - [self updateWindows]; // to all visible windows - - [pool release]; - } - while (!app_should_quit); + // send an update message + // to all visible windows + if (windows_need_update) + [self updateWindows]; + + [pool release]; + } + while (!app_should_quit); - NSDebugLog(@"NSApplication end of run loop\n"); + NSDebugLog(@"NSApplication end of run loop\n"); } - (int)runModalForWindow:(NSWindow *)theWindow { - [theWindow display]; - [theWindow makeKeyAndOrderFront: self]; + [theWindow display]; + [theWindow makeKeyAndOrderFront: self]; - return 0; + return 0; } - (int)runModalSession:(NSModalSession)theSession { - return 0; + return 0; } - (void)sendEvent:(NSEvent *)theEvent { - if (theEvent == null_event) // Don't send null event - { - NSDebugLog(@"Not sending the Null Event\n"); - return; - } + if (theEvent == null_event) // Don't send null event + { + NSDebugLog(@"Not sending the Null Event\n"); + return; + } - switch ([theEvent type]) // determine the event type - { - case NSPeriodic: // NSApplication traps the - break; // periodic events + switch ([theEvent type]) // determine the event type + { + case NSPeriodic: + // NSApplication traps the + // periodic events + break; - case NSKeyDown: - { - NSDebugLog(@"send key down event\n"); - [[theEvent window] sendEvent:theEvent]; - break; - } + case NSKeyDown: + { + NSDebugLog(@"send key down event\n"); + [[theEvent window] sendEvent:theEvent]; + break; + } - case NSKeyUp: - { - NSDebugLog(@"send key up event\n"); - [[theEvent window] sendEvent:theEvent]; - break; - } + case NSKeyUp: + { + NSDebugLog(@"send key up event\n"); + [[theEvent window] sendEvent:theEvent]; + break; + } - case NSRightMouseDown: // Right mouse down - if(main_menu) - { - static NSMenu *copyOfMainMenu = nil; - NSWindow *copyMenuWindow; - - if(!copyOfMainMenu) // display the menu - copyOfMainMenu = [main_menu copy]; // under the mouse - copyMenuWindow = [copyOfMainMenu menuWindow]; - [copyOfMainMenu _rightMouseDisplay]; - [copyMenuWindow captureMouse:self]; - [[copyOfMainMenu menuCells] mouseDown:theEvent]; - [copyMenuWindow releaseMouse:self]; - } - break; + case NSRightMouseDown: // Right mouse down + if (main_menu) + { + static NSMenu *copyOfMainMenu = nil; + NSWindow *copyMenuWindow; + + if (!copyOfMainMenu) // display the menu + copyOfMainMenu = [main_menu copy]; // under the mouse + copyMenuWindow = [copyOfMainMenu menuWindow]; + [copyOfMainMenu _rightMouseDisplay]; + [copyMenuWindow captureMouse:self]; + [[copyOfMainMenu menuCells] mouseDown:theEvent]; + [copyMenuWindow releaseMouse:self]; + } + break; - default: // pass all other events to - { // the event's window - NSWindow* window = [theEvent window]; + default: + // pass all other events to + // the event's window + { + NSWindow* window = [theEvent window]; - if (!theEvent) - NSDebugLog(@"NSEvent is nil!\n"); - NSDebugLog(@"NSEvent type: %d", [theEvent type]); - NSDebugLog(@"send event to window"); - NSDebugLog([window description]); - if (!window) - NSDebugLog(@"no window"); - [window sendEvent:theEvent]; - } - } + if (!theEvent) + NSDebugLog(@"NSEvent is nil!\n"); + NSDebugLog(@"NSEvent type: %d", [theEvent type]); + NSDebugLog(@"send event to window"); + NSDebugLog([window description]); + if (!window) + NSDebugLog(@"no window"); + [window sendEvent:theEvent]; + } + } } - (void)stop:sender { - app_is_running = NO; + app_is_running = NO; } - (void)stopModal @@ -335,342 +922,372 @@ NSAutoreleasePool* pool; - (NSEvent *)currentEvent; { - return current_event; + return current_event; } - (void)discardEventsMatchingMask:(unsigned int)mask - beforeEvent:(NSEvent *)lastEvent + beforeEvent:(NSEvent *)lastEvent { int i = 0, count; NSEvent* event = nil; -BOOL match = NO; +BOOL match = NO; - count = [event_queue count]; - event = [event_queue objectAtIndex:i]; - while((event != lastEvent) && (i < count)) - { - if (mask == NSAnyEventMask) // any event is a match - match = YES; - else - { - if (event == null_event) - match = YES; // dump all null events - else - { - switch([event type]) - { - case NSLeftMouseDown: - if (mask & NSLeftMouseDownMask) - match = YES; - break; - - case NSLeftMouseUp: - if (mask & NSLeftMouseUpMask) - match = YES; - break; - - case NSRightMouseDown: - if (mask & NSRightMouseDownMask) - match = YES; - break; - - case NSRightMouseUp: - if (mask & NSRightMouseUpMask) - match = YES; - break; - - case NSMouseMoved: - if (mask & NSMouseMovedMask) - match = YES; - break; - - case NSMouseEntered: - if (mask & NSMouseEnteredMask) - match = YES; - break; - - case NSMouseExited: - if (mask & NSMouseExitedMask) - match = YES; - break; - - case NSLeftMouseDragged: - if (mask & NSLeftMouseDraggedMask) - match = YES; - break; - - case NSRightMouseDragged: - if (mask & NSRightMouseDraggedMask) - match = YES; - break; - - case NSKeyDown: - if (mask & NSKeyDownMask) - match = YES; - break; - - case NSKeyUp: - if (mask & NSKeyUpMask) - match = YES; - break; - - case NSFlagsChanged: - if (mask & NSFlagsChangedMask) - match = YES; - break; - - case NSPeriodic: - if (mask & NSPeriodicMask) - match = YES; - break; - - case NSCursorUpdate: - if (mask & NSCursorUpdateMask) - match = YES; - break; - - default: - match = NO; - break; - } } } // remove event from - // the queue if it - if (match) // matched the mask - [event_queue removeObjectAtIndex:i]; - event = [event_queue objectAtIndex:++i]; // get the next event - }; // in the queue + count = [event_queue count]; + event = [event_queue objectAtIndex:i]; + while((event != lastEvent) && (i < count)) + { + if (mask == NSAnyEventMask) // any event is a match + match = YES; + else + { + if (event == null_event) + match = YES; // dump all null events + else + { + switch([event type]) + { + case NSLeftMouseDown: + if (mask & NSLeftMouseDownMask) + match = YES; + break; + + case NSLeftMouseUp: + if (mask & NSLeftMouseUpMask) + match = YES; + break; + + case NSRightMouseDown: + if (mask & NSRightMouseDownMask) + match = YES; + break; + + case NSRightMouseUp: + if (mask & NSRightMouseUpMask) + match = YES; + break; + + case NSMouseMoved: + if (mask & NSMouseMovedMask) + match = YES; + break; + + case NSMouseEntered: + if (mask & NSMouseEnteredMask) + match = YES; + break; + + case NSMouseExited: + if (mask & NSMouseExitedMask) + match = YES; + break; + + case NSLeftMouseDragged: + if (mask & NSLeftMouseDraggedMask) + match = YES; + break; + + case NSRightMouseDragged: + if (mask & NSRightMouseDraggedMask) + match = YES; + break; + + case NSKeyDown: + if (mask & NSKeyDownMask) + match = YES; + break; + + case NSKeyUp: + if (mask & NSKeyUpMask) + match = YES; + break; + + case NSFlagsChanged: + if (mask & NSFlagsChangedMask) + match = YES; + break; + + case NSPeriodic: + if (mask & NSPeriodicMask) + match = YES; + break; + + case NSCursorUpdate: + if (mask & NSCursorUpdateMask) + match = YES; + break; + + default: + match = NO; + break; + } } } // remove event from + // the queue if it + if (match) // matched the mask + [event_queue removeObjectAtIndex:i]; + event = [event_queue objectAtIndex:++i]; // get the next event + }; // in the queue } -- (NSEvent*)_eventMatchingMask:(unsigned int)mask dequeue:(BOOL)flag -{ -NSEvent* event; // return the next -int i, count; // event in the queue -BOOL match = NO; // which matches mask +- (NSEvent*) _eventMatchingMask: (unsigned int)mask + dequeue: (BOOL)flag +{ + NSEvent* event; + int i, count; + BOOL match = NO; + // return the next + // event in the queue + // which matches mask - [self _nextEvent]; + [self _nextEvent]; + [listener updateServicesMenu]; - if ((count = [event_queue count])) // if queue contains - { // events check them - for (i = 0; i < count; i++) - { // Get next event from - event = [event_queue objectAtIndex:i]; // the events queue + // if queue contains + // events check them + if ((count = [event_queue count])) + { + for (i = 0; i < count; i++) + { + // Get next event from + // the events queue + event = [event_queue objectAtIndex:i]; - if (mask == NSAnyEventMask) // the any event mask - match = YES; // matches all events - else - { - if (event == null_event) // do not send the null - { // event - match = NO; - if(flag) // dequeue null event - { // if flag is set - [event retain]; - [event_queue removeObjectAtIndex:i]; - } - } - else - { - switch([event type]) - { - case NSLeftMouseDown: - if (mask & NSLeftMouseDownMask) - match = YES; - break; - - case NSLeftMouseUp: - if (mask & NSLeftMouseUpMask) - match = YES; - break; - - case NSRightMouseDown: - if (mask & NSRightMouseDownMask) - match = YES; - break; - - case NSRightMouseUp: - if (mask & NSRightMouseUpMask) - match = YES; - break; - - case NSMouseMoved: - if (mask & NSMouseMovedMask) - match = YES; - break; - - case NSMouseEntered: - if (mask & NSMouseEnteredMask) - match = YES; - break; - - case NSMouseExited: - if (mask & NSMouseExitedMask) - match = YES; - break; - - case NSLeftMouseDragged: - if (mask & NSLeftMouseDraggedMask) - match = YES; - break; - - case NSRightMouseDragged: - if (mask & NSRightMouseDraggedMask) - match = YES; - break; - - case NSKeyDown: - if (mask & NSKeyDownMask) - match = YES; - break; - - case NSKeyUp: - if (mask & NSKeyUpMask) - match = YES; - break; - - case NSFlagsChanged: - if (mask & NSFlagsChangedMask) - match = YES; - break; - - case NSPeriodic: - if (mask & NSPeriodicMask) - match = YES; - break; - - case NSCursorUpdate: - if (mask & NSCursorUpdateMask) - match = YES; - break; - - default: - match = NO; - break; - } } } - - if (match) - { - if(flag) // dequeue the event if - { // flag is set - [event retain]; - [event_queue removeObjectAtIndex:i]; - } - CONVEY(current_event, event); - - return event; // return an event from - } // the queue which - } // matches the mask - } - // no event in the - return nil; // queue matches mask -} + // the any event mask + // matches all events + if (mask == NSAnyEventMask) + match = YES; + else + { + // do not send the null + // event + if (event == null_event) + { + match = NO; + // dequeue null event + // if flag is set + if (flag) + { + [event retain]; + [event_queue removeObjectAtIndex:i]; + } + } + else + { + switch ([event type]) + { + case NSLeftMouseDown: + if (mask & NSLeftMouseDownMask) + match = YES; + break; + + case NSLeftMouseUp: + if (mask & NSLeftMouseUpMask) + match = YES; + break; + + case NSRightMouseDown: + if (mask & NSRightMouseDownMask) + match = YES; + break; + + case NSRightMouseUp: + if (mask & NSRightMouseUpMask) + match = YES; + break; + + case NSMouseMoved: + if (mask & NSMouseMovedMask) + match = YES; + break; + + case NSMouseEntered: + if (mask & NSMouseEnteredMask) + match = YES; + break; + + case NSMouseExited: + if (mask & NSMouseExitedMask) + match = YES; + break; + + case NSLeftMouseDragged: + if (mask & NSLeftMouseDraggedMask) + match = YES; + break; + + case NSRightMouseDragged: + if (mask & NSRightMouseDraggedMask) + match = YES; + break; + + case NSKeyDown: + if (mask & NSKeyDownMask) + match = YES; + break; + + case NSKeyUp: + if (mask & NSKeyUpMask) + match = YES; + break; + + case NSFlagsChanged: + if (mask & NSFlagsChangedMask) + match = YES; + break; + + case NSPeriodic: + if (mask & NSPeriodicMask) + match = YES; + break; + + case NSCursorUpdate: + if (mask & NSCursorUpdateMask) + match = YES; + break; + + default: + match = NO; + break; + } + } + } -- (NSEvent *)nextEventMatchingMask:(unsigned int)mask - untilDate:(NSDate *)expiration - inMode:(NSString *)mode - dequeue:(BOOL)flag + if (match) + { + // dequeue the event if + // flag is set + if (flag) + { + [event retain]; + [event_queue removeObjectAtIndex:i]; + } + ASSIGN(current_event, event); + + // return an event from + // the queue which + // matches the mask + return event; + } + } + } + // no event in the + // queue matches mask + return nil; +} + +- (NSEvent*) nextEventMatchingMask: (unsigned int)mask + untilDate: (NSDate *)expiration + inMode: (NSString *)mode + dequeue: (BOOL)flag { -NSEvent *event; -BOOL done = NO; + NSEvent *event; + BOOL done = NO; - if(mode == NSEventTrackingRunLoopMode) // temporary hack to - inTrackingLoop = YES; // regulate translation - else // of X motion events - inTrackingLoop = NO; // while not in a - // tracking loop - if ((event = [self _eventMatchingMask:mask dequeue:flag])) - done = YES; - else - if (!expiration) - expiration = [NSDate distantFuture]; + if(mode == NSEventTrackingRunLoopMode) // temporary hack to + inTrackingLoop = YES; // regulate translation + else // of X motion events + inTrackingLoop = NO; // while not in a + // tracking loop + if ((event = [self _eventMatchingMask:mask dequeue:flag])) + done = YES; + else + if (!expiration) + expiration = [NSDate distantFuture]; - while (!done) // Not in queue so wait - { // for next event - NSDate *limitDate, *originalLimitDate; - NSRunLoop* currentLoop = [NSRunLoop currentRunLoop]; - // Retain the limitDate so that it doesn't get released - // accidentally by runMode:beforeDate: if a timer which - // has this date as fire date gets released. - limitDate = [[currentLoop limitDateForMode:mode] retain]; - originalLimitDate = limitDate; + // Not in queue so wait + // for next event + while (!done) + { + NSDate *limitDate, *originalLimitDate; + NSRunLoop* currentLoop = [NSRunLoop currentRunLoop]; + // Retain the limitDate so that it doesn't get released + // accidentally by runMode:beforeDate: if a timer which + // has this date as fire date gets released. + limitDate = [[currentLoop limitDateForMode:mode] retain]; + originalLimitDate = limitDate; - if ((event = [self _eventMatchingMask:mask dequeue:flag])) - { - [limitDate release]; - break; - } + if ((event = [self _eventMatchingMask:mask dequeue:flag])) + { + [limitDate release]; + break; + } - if (limitDate) - limitDate = [expiration earlierDate:limitDate]; - else - limitDate = expiration; + if (limitDate) + limitDate = [expiration earlierDate:limitDate]; + else + limitDate = expiration; - [currentLoop runMode:mode beforeDate:limitDate]; - [originalLimitDate release]; + [currentLoop runMode:mode beforeDate:limitDate]; + [originalLimitDate release]; - if ((event = [self _eventMatchingMask:mask dequeue:flag])) - break; - } - // no need to unhide cursor - if (!inTrackingLoop) // while in a tracking loop - { - if ([NSCursor isHiddenUntilMouseMoves]) // do so only if we should - { // unhide when mouse moves - NSEventType type = [event type]; // and event is mouse event - if ((type == NSLeftMouseDown) || (type == NSLeftMouseUp) - || (type == NSRightMouseDown) || (type == NSRightMouseUp) - || (type == NSMouseMoved)) - { - [NSCursor unhide]; - } - } - } + if ((event = [self _eventMatchingMask:mask dequeue:flag])) + break; + } + // no need to unhide cursor + // while in a tracking loop + if (!inTrackingLoop) + { + // do so only if we should + // unhide when mouse moves + // and event is mouse event + if ([NSCursor isHiddenUntilMouseMoves]) + { + NSEventType type = [event type]; - return event; + if ((type == NSLeftMouseDown) || (type == NSLeftMouseUp) + || (type == NSRightMouseDown) || (type == NSRightMouseUp) + || (type == NSMouseMoved)) + { + [NSCursor unhide]; + } + } + } + + return event; } - (void)postEvent:(NSEvent *)event atStart:(BOOL)flag { - if (!flag) - [event_queue addObject: event]; - else - [event_queue insertObject: event atIndex: 0]; + if (!flag) + [event_queue addObject: event]; + else + [event_queue insertObject: event atIndex: 0]; } // // Sending action messages // - (BOOL)sendAction:(SEL)aSelector to:aTarget from:sender -{ // If target responds - if ([aTarget respondsToSelector:aSelector]) // to the selector then - { // have it perform it - [aTarget performSelector:aSelector withObject:sender]; +{ // If target responds + if ([aTarget respondsToSelector:aSelector]) // to the selector then + { // have it perform it + [aTarget performSelector:aSelector withObject:sender]; - return YES; - } + return YES; + } - return NO; // Otherwise traverse -} // the responder chain + return NO; // Otherwise traverse +} // the responder chain - targetForAction:(SEL)aSelector { - return self; + return self; } - (BOOL)tryToPerform:(SEL)aSelector with:anObject { - return NO; + return NO; } - (void)setApplicationIconImage:(NSImage *)anImage -{ // Set the app's icon - if (app_icon != nil) - [app_icon release]; +{ // Set the app's icon + if (app_icon != nil) + [app_icon release]; - app_icon = [anImage retain]; + app_icon = [anImage retain]; } - (NSImage *)applicationIconImage { - return app_icon; + return app_icon; } // @@ -678,54 +1295,55 @@ BOOL done = NO; // - (void)hide:sender { -int i, count; -NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; + int i, count; + NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; - // notify that we will hide - [nc postNotificationName: NSApplicationWillHideNotification - object: self]; - // TODO: hide the menu + // notify that we will hide + [nc postNotificationName: NSApplicationWillHideNotification + object: self]; + // TODO: hide the menu - // Tell the windows to hide - for (i = 0, count = [window_list count]; i < count; i++) - [[window_list objectAtIndex:i] performHide:sender]; + // Tell the windows to hide + for (i = 0, count = [window_list count]; i < count; i++) + [[window_list objectAtIndex:i] performHide:sender]; - app_is_hidden = YES; - // notify that we did hide - [nc postNotificationName: NSApplicationDidHideNotification - object: self]; + app_is_hidden = YES; + // notify that we did hide + [nc postNotificationName: NSApplicationDidHideNotification + object: self]; } - (BOOL)isHidden { - return app_is_hidden; + return app_is_hidden; } - (void)unhide:sender { -int i, count; - // Tell windows to unhide - for (i = 0, count = [window_list count]; i < count; i++) - [[window_list objectAtIndex:i] performUnhide:sender]; + int i, count; + // Tell windows to unhide + for (i = 0, count = [window_list count]; i < count; i++) + [[window_list objectAtIndex:i] performUnhide:sender]; - // TODO: unhide the menu + // TODO: unhide the menu - app_is_hidden = NO; - // Bring the key window to - [[self keyWindow] makeKeyAndOrderFront:self]; // the front + app_is_hidden = NO; + // Bring the key window to + // the front + [[self keyWindow] makeKeyAndOrderFront:self]; } - (void)unhideWithoutActivation { -NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; - // notify we will unhide + NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; + // notify we will unhide [nc postNotificationName: NSApplicationWillUnhideNotification - object: self]; + object: self]; [self unhide: self]; - // notify we did unhide + // notify we did unhide [nc postNotificationName: NSApplicationDidUnhideNotification - object: self]; + object: self]; } // @@ -733,47 +1351,47 @@ NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; // - (NSWindow *)keyWindow { -int i, j; -id w; + int i, j; + id w; - j = [window_list count]; - for (i = 0;i < j; ++i) - { - w = [window_list objectAtIndex:i]; - if ([w isKeyWindow]) - return w; - } + j = [window_list count]; + for (i = 0;i < j; ++i) + { + w = [window_list objectAtIndex:i]; + if ([w isKeyWindow]) + return w; + } - return nil; + return nil; } - (NSWindow *)mainWindow { -int i, j; -id w; + int i, j; + id w; - j = [window_list count]; - for (i = 0;i < j; ++i) - { - w = [window_list objectAtIndex:i]; - if ([w isMainWindow]) - return w; - } + j = [window_list count]; + for (i = 0;i < j; ++i) + { + w = [window_list objectAtIndex:i]; + if ([w isMainWindow]) + return w; + } - return nil; + return nil; } - (NSWindow *)makeWindowsPerform:(SEL)aSelector inOrder:(BOOL)flag { - return nil; + return nil; } - (void)miniaturizeAll:sender { -int i, count; + int i, count; - for (i = 0, count = [window_list count]; i < count; i++) - [[window_list objectAtIndex:i] miniaturize:sender]; + for (i = 0, count = [window_list count]; i < count; i++) + [[window_list objectAtIndex:i] miniaturize:sender]; } - (void)preventWindowOrdering @@ -782,46 +1400,46 @@ int i, count; - (void)setWindowsNeedUpdate:(BOOL)flag { - windows_need_update = flag; + windows_need_update = flag; } -- (void)updateWindows // send an update message -{ // to all visible windows -int i, count; +- (void)updateWindows // send an update message +{ // to all visible windows +int i, count; NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; - // notify that an update is - // imminent - [nc postNotificationName:NSApplicationWillUpdateNotification object:self]; + // notify that an update is + // imminent + [nc postNotificationName:NSApplicationWillUpdateNotification object:self]; - for (i = 0, count = [window_list count]; i < count; i++) - { - NSWindow *win = [window_list objectAtIndex:i]; - if([win isVisible]) // send update only if the - [win update]; // window is visible - } - // notify update did occur - [nc postNotificationName:NSApplicationDidUpdateNotification object:self]; + for (i = 0, count = [window_list count]; i < count; i++) + { + NSWindow *win = [window_list objectAtIndex:i]; + if([win isVisible]) // send update only if the + [win update]; // window is visible + } + // notify update did occur + [nc postNotificationName:NSApplicationDidUpdateNotification object:self]; } - (NSArray *)windows { - return window_list; + return window_list; } - (NSWindow *)windowWithWindowNumber:(int)windowNum { -int i, j; -NSWindow *w; + int i, j; + NSWindow *w; - j = [window_list count]; - for (i = 0;i < j; ++i) - { - w = [window_list objectAtIndex:i]; - if ([w windowNumber] == windowNum) - return w; - } + j = [window_list count]; + for (i = 0;i < j; ++i) + { + w = [window_list objectAtIndex:i]; + if ([w windowNumber] == windowNum) + return w; + } - return nil; + return nil; } // @@ -848,57 +1466,61 @@ NSWindow *w; // - (NSMenu *)mainMenu { - return main_menu; + return main_menu; } - (void)setMainMenu:(NSMenu *)aMenu { -int i, j; -NSMenuItem *mc; -NSArray *mi; + int i, j; + NSMenuItem *mc; + NSArray *mi; - [aMenu retain]; // Release old menu and - if(main_menu) // retain new - [main_menu release]; - main_menu = aMenu; + [aMenu retain]; // Release old menu and + if (main_menu) // retain new + [main_menu release]; + main_menu = aMenu; - mi = [main_menu itemArray]; // find a menucell with - j = [mi count]; // the title Windows - windows_menu = nil; // this is the default - for (i = 0;i < j; ++i) // windows menu - { - mc = [mi objectAtIndex:i]; - if ([[mc stringValue] compare:@"Windows"] == NSOrderedSame) - { - windows_menu = mc; // Found it! - break; - } - } + // find a menucell with + // the title Windows + // this is the default + // windows menu + mi = [main_menu itemArray]; + j = [mi count]; + windows_menu = nil; + for (i = 0;i < j; ++i) + { + mc = [mi objectAtIndex:i]; + if ([[mc stringValue] compare:@"Windows"] == NSOrderedSame) + { + windows_menu = mc; // Found it! + break; + } + } } // // Managing the Windows menu // - (void)addWindowsItem:aWindow - title:(NSString *)aString - filename:(BOOL)isFilename + title:(NSString *)aString + filename:(BOOL)isFilename { int i; - if (![aWindow isKindOfClass:[NSWindow class]]) // proceed only if subclass - return; // of window + if (![aWindow isKindOfClass:[NSWindow class]]) // proceed only if subclass + return; // of window - i = [window_list count]; // Add to our window list, - [window_list addObject:aWindow]; // the array retains it + i = [window_list count]; // Add to our window list, + [window_list addObject:aWindow]; // the array retains it - [aWindow setWindowNumber:window_count]; // set its window number - ++window_count; - - if (i == 0) // If this was the first - { // window then make it the - [aWindow becomeMainWindow]; // main and key window - [aWindow becomeKeyWindow]; - } + [aWindow setWindowNumber:window_count]; // set its window number + ++window_count; + + if (i == 0) // If this was the first + { // window then make it the + [aWindow becomeMainWindow]; // main and key window + [aWindow becomeKeyWindow]; + } } - (void)arrangeInFront:sender @@ -906,33 +1528,33 @@ int i; } - (void)changeWindowsItem:aWindow - title:(NSString *)aString - filename:(BOOL)isFilename + title:(NSString *)aString + filename:(BOOL)isFilename { } - (void)removeWindowsItem:aWindow { - if (aWindow == key_window) // This should be different - key_window = nil; - if (aWindow == main_window) - main_window = nil; + if (aWindow == key_window) // This should be different + key_window = nil; + if (aWindow == main_window) + main_window = nil; - // If we are within our dealloc then don't remove the window - // Most likely dealloc is removing windows from our window list - // and subsequently NSWindow is caling us to remove itself. - if (gnustep_gui_app_is_in_dealloc) - return; - // Remove window from the - [window_list removeObject: aWindow]; // window list + // If we are within our dealloc then don't remove the window + // Most likely dealloc is removing windows from our window list + // and subsequently NSWindow is caling us to remove itself. + if (gnustep_gui_app_is_in_dealloc) + return; + // Remove window from the + [window_list removeObject: aWindow]; // window list - return; + return; } - (void)setWindowsMenu:aMenu { - if (windows_menu) - [windows_menu setSubmenu:aMenu]; + if (windows_menu) + [windows_menu setTarget:aMenu]; } - (void)updateWindowsItem:aWindow @@ -941,42 +1563,59 @@ int i; - (NSMenu *)windowsMenu { - if(windows_menu) - return [windows_menu submenu]; - else - return nil; + if (windows_menu) + return [windows_menu target]; + else + return nil; } // // Managing the Service menu // -- (void)registerServicesMenuSendTypes:(NSArray *)sendTypes - returnTypes:(NSArray *)returnTypes +- (void) registerServicesMenuSendTypes: (NSArray *)sendTypes + returnTypes: (NSArray *)returnTypes { + [listener registerSendTypes: sendTypes + returnTypes: returnTypes]; } -- (NSMenu *)servicesMenu +- (NSMenu *) servicesMenu { - return nil; + return [listener servicesMenu]; } -- (void)setServicesMenu:(NSMenu *)aMenu +- (id) servicesProvider { + return [listener servicesProvider]; } -- validRequestorForSendType:(NSString *)sendType - returnType:(NSString *)returnType +- (void) setServicesMenu: (NSMenu *)aMenu { - return nil; + [listener setServicesMenu: aMenu]; } -- (GPSDrawContext *)context // return the DPS context +- (void) setServicesProvider: (id)anObject { - return [GPSDrawContext currentContext]; + [listener setServicesProvider: anObject]; } - // Reporting an exception -- (void)reportException:(NSException *)anException + +- (id) validRequestorForSendType: (NSString *)sendType + returnType: (NSString *)returnType { + return nil; +} + +- (GPSDrawContext *)context // return the DPS context +{ + return [GPSDrawContext currentContext]; +} + // Reporting an exception +- (void) reportException: (NSException *)anException +{ + if (anException) + { + NSLog(@"reported exception - %@", anException); + } } // @@ -984,29 +1623,29 @@ int i; // - (void)terminate:sender { - if ([self applicationShouldTerminate:self]) - { // app should end run loop - app_should_quit = YES; - [event_queue addObject: null_event]; // add dummy event to queue - } // to assure loop cycles -} // at least one more time + if ([self applicationShouldTerminate:self]) + { // app should end run loop + app_should_quit = YES; + [event_queue addObject: null_event]; // add dummy event to queue + } // to assure loop cycles +} // at least one more time -- delegate // Assigning a delegate +- delegate // Assigning a delegate { - return delegate; + return delegate; } - (void)setDelegate:anObject { -NSNotificationCenter* nc = [NSNotificationCenter defaultCenter]; + NSNotificationCenter* nc = [NSNotificationCenter defaultCenter]; delegate = anObject; #define SET_DELEGATE_NOTIFICATION(notif_name) \ if ([delegate respondsToSelector:@selector(application##notif_name:)]) \ [nc addObserver:delegate \ - selector:@selector(application##notif_name:) \ - name:NSApplication##notif_name##Notification object:self] + selector:@selector(application##notif_name:) \ + name:NSApplication##notif_name##Notification object:self] SET_DELEGATE_NOTIFICATION(DidBecomeActive); SET_DELEGATE_NOTIFICATION(DidFinishLaunching); @@ -1034,7 +1673,7 @@ BOOL result = NO; return result; } - + - (BOOL)application:(NSApplication *)app openFile:(NSString *)filename { BOOL result = NO; @@ -1060,7 +1699,7 @@ BOOL result = NO; if ([delegate respondsToSelector:@selector(applicationDidBecomeActive:)]) [delegate applicationDidBecomeActive:aNotification]; } - + - (void)applicationDidFinishLaunching:(NSNotification *)aNotification { if ([delegate respondsToSelector:@selector(applicationDidFinishLaunching:)]) @@ -1177,21 +1816,21 @@ BOOL result = YES; + (void)setNullEvent:(NSEvent *)e { - CONVEY(null_event, e); + ASSIGN(null_event, e); } + (NSEvent *)getNullEvent; -{ // return the class - return null_event; // dummy event +{ // return the class + return null_event; // dummy event } -- (void)_nextEvent // get next event -{ // implemented in -} // backend +- (void)_nextEvent // get next event +{ // implemented in +} // backend - (void)setupRunLoopInputSourcesForMode:(NSString*)mode -{ // implemented in -} // backend +{ // implemented in +} // backend @end @@ -1200,10 +1839,10 @@ BOOL result = YES; NSString *NSOpenStepRootDirectory(void) { NSString* root = [[[NSProcessInfo processInfo] environment] - objectForKey:@"GNUSTEP_SYSTEM_ROOT"]; + objectForKey:@"GNUSTEP_SYSTEM_ROOT"]; - if (!root) - root = @"/"; + if (!root) + root = @"/"; - return root; + return root; } diff --git a/Source/NSText.m b/Source/NSText.m index 7a4fb6dec..29ae77eef 100644 --- a/Source/NSText.m +++ b/Source/NSText.m @@ -59,8 +59,15 @@ #include static NSRange MakeRangeFromAbs(int a1,int a2) // not the same as NSMakeRange! -{ if(a1< a2) return NSMakeRange(a1,a2-a1); - else return NSMakeRange(a2,a1-a2); +{ + if (a1 < 0) + a1 = 0; + if (a2 < 0) + a2 = 0; + if (a1 < a2) + return NSMakeRange(a1,a2-a1); + else + return NSMakeRange(a2,a1-a2); } extern BOOL NSEqualRanges(NSRange range1, NSRange range2); // should define in base FIX ME FAR @@ -334,9 +341,19 @@ typedef enum // + (void)initialize { - if (self == [NSText class]) - { [self setVersion:1]; // Initial version - } + if (self == [NSText class]) + { + NSArray *r; + NSArray *s; + + [self setVersion:1]; // Initial version + + r = [NSArray arrayWithObjects: NSStringPboardType, nil]; + s = [NSArray arrayWithObjects: NSStringPboardType, nil]; + + [[NSApplication sharedApplication] registerServicesMenuSendTypes: s + returnTypes: r]; + } } // @@ -407,6 +424,65 @@ typedef enum nil]; } +/* + * Handle enabling/disabling of services menu items. + */ +- (id) validRequestorForSendType: (NSString*)sendType + returnType: (NSString*)returnType +{ + if ((!sendType || [sendType isEqual: NSStringPboardType]) && + (!returnType || [returnType isEqual: NSStringPboardType])) + { + if (([self selectedRange].length || !sendType) && + ([self isEditable] || !returnType)) + { + return self; + } + } + return [super validRequestorForSendType: sendType + returnType: returnType]; + +} + +- (BOOL) readSelectionFromPasteboard: (NSPasteboard*)pb +{ + NSArray *types; + NSString *string; + NSRange range; + + types = [pb types]; + if ([types containsObject: NSStringPboardType] == NO) + { + return NO; + } + string = [pb stringForType: NSStringPboardType]; + range = [self selectedRange]; + [self deleteRange: range backspace: NO]; + [self insertText: string]; + range.length = [string length]; + [self setSelectedRange: range]; + + return YES; +} + +- (BOOL) writeSelectionToPasteboard: (NSPasteboard*)pb + types: (NSArray*)sendTypes +{ + NSArray *types; + NSRange range; + NSString *string; + + if ([sendTypes containsObject: NSStringPboardType] == NO) + { + return NO; + } + types = [NSArray arrayWithObjects: NSStringPboardType, nil]; + [pb declareTypes: types owner: nil]; + range = [self selectedRange]; + string = [self string]; + string = [string substringWithRange: range]; + return [pb setString: string forType: NSStringPboardType]; +} // // handle font pasteboard as well! diff --git a/Source/NSWindow.m b/Source/NSWindow.m index 4dff23ceb..e277cb323 100644 --- a/Source/NSWindow.m +++ b/Source/NSWindow.m @@ -1022,7 +1022,17 @@ NSView *v; - validRequestorForSendType:(NSString *)sendType returnType:(NSString *)returnType { - return nil; + id result = nil; + + if (delegate && [delegate respondsToSelector: _cmd]) + result = [delegate validRequestorForSendType: sendType + returnType: returnType]; + + if (result == nil) + result = [[NSApplication sharedApplication] + validRequestorForSendType: sendType + returnType: returnType]; + return result; } //