/* * Grouch.app Copyright (C) 2006 Andy Sveikauskas * ------------------------------------------------------------------------ * This program is free software under the GNU General Public License * -- * Application delegate. */ #import #import #import #import #import #import #import #import #import #import #import #import #import #import #import #import #import #import #import static void url_backup_function( NSString *url ); @protocol ActiveUser - getActiveUser; @end @protocol ActiveClient - getActiveClient; @end @protocol ActiveListItem - getActiveListItem; @end @interface GrouchAppDelegate : NSObject - (NSObject*)activeWindowDelegate; - (User*)activeUser; - (ClientInstance*)activeClient; - activeListItem; - (void)newClient:sender; - (void)imWindow:sender; - (void)getUserInfo:sender; - (void)setAway:sender; - (void)joinChannel:sender; - (void)signOff:sender; - (void)removeBuddy:sender; - (void)windowForUser:(User*)u; - (void)infoForUser:(User*)u; - applicationDidFinishLaunching:(NSNotification*)n; @end @implementation GrouchAppDelegate - (NSObject*)activeWindowDelegate { NSWindow *wnd = [NSApp keyWindow]; if( wnd ) return [wnd delegate]; else return nil; } - (User*)activeUser { NSObject *del = [self activeWindowDelegate]; if( del && [del respondsToSelector:@selector(getActiveUser)] ) return [(id)del getActiveUser]; else return nil; } - (ClientInstance*)activeClient { NSObject *del = [self activeWindowDelegate]; if( del && [del respondsToSelector:@selector(getActiveClient)] ) return [(id)del getActiveClient]; else if( del && [del respondsToSelector:@selector(getActiveUser)] ) { User *u = [(id)del getActiveUser]; if( u ) return [u instance]; else return nil; } else return nil; } - activeListItem { NSObject *del = [self activeWindowDelegate]; if( del && [del respondsToSelector:@selector(getActiveListItem)] ) return [(id)del getActiveListItem]; else return nil; } - (void)imWindow:sender { ClientInstance *cli = [self activeClient]; User *u = [self activeUser]; if( u ) [self windowForUser:u]; else { UserChooser *chooser = [UserChooser chooseWithSelector:@selector(windowForUser:) target:self]; NSString *clientName = nil; if( cli ) clientName = [cli nick]; if( clientName ) [chooser setLogin:clientName]; } } - (void)signOff:sender { ClientInstance *cli = [self activeClient]; if( cli ) [cli logOff]; } - (void)windowForUser:(User*)u { [u createWindow]; } - (void)getUserInfo:sender { User *u = [self activeUser]; ClientInstance *cli = [self activeClient]; if( u ) [self infoForUser:u]; else { UserChooser *choose = [UserChooser chooseWithSelector:@selector(infoForUser:) target:self]; NSString *clientName = nil; if( cli ) clientName = [cli nick]; if( clientName ) [choose setLogin:clientName]; } } - (void)infoForUser:(User*)u { [[[u instance] session] getInfo:[InfoWindow infoWithNick:[u name]] forUser:[u name]]; } - (void)setAway:sender { ClientInstance *cli = [self activeClient]; NSString *nick; if( cli ) { if( [cli isAway] ) { [cli returnFromAway]; return; } else if( (nick = [cli nick]) ) { [[SetAwayMessage new] setLogin:nick]; return; } } [SetAwayMessage new]; } - (void)setProfile:sender { SetProfile *obj = [SetProfile new]; ClientInstance *cli = [self activeClient]; NSString *nick; if( cli && (nick = [cli nick]) ) [obj setLogin:nick]; } - (void)joinChannel:sender { JoinChannel *obj = [JoinChannel new]; ClientInstance *cli = [self activeClient]; NSString *nick; if( cli && (nick = [cli nick]) ) [obj setLogin:nick]; } - (void)newClient:sender { [LoginWindow new]; } - (void)addBuddy:sender { ClientInstance *cli = [self activeClient]; User *u = [self activeUser]; AddWindow *w; if( !cli ) return; w = [AddWindow windowWithInstance:cli]; if( u ) [w setUser:u]; } - (void)removeBuddy:sender { ClientInstance *cli = [self activeClient]; id item = [self activeListItem]; if( !item ) item = [self activeUser]; if( !cli || !item ) [ErrorWindow errorWithString: [GrouchString getString:@"select-list-item"]]; else { NSInvocation *call; NonModalAlertPanel *panel; NSString *descr, *message; id session = [cli session]; SEL sel = @selector(removeFromList:); call = [[NSInvocation invocationWithMethodSignature: [(NSObject*)session methodSignatureForSelector:sel]] retain]; [call setTarget:session]; [call setSelector:sel]; [call setArgument:&item atIndex:2]; [call retainArguments]; if( [item isKindOfClass:[NSArray class]] ) descr = [item objectAtIndex:0]; else descr = [item alias]; message = [NSString stringWithFormat: [GrouchString getString:@"remove-confirm"], descr]; panel = [NonModalAlertPanel new]; [panel setTarget:call]; [panel setAction:@selector(invokeForGrouch:)]; [panel setTitle:[GrouchString getString:@"remove"] message:message def:[GrouchString getString:@"yes"] alt:[GrouchString getString:@"no"] other:nil]; } } - applicationDidFinishLaunching:(NSNotification*)n { NSString *menuName = [NSString stringWithFormat:@"Menu.%@", [Defaults get:@"Menu Type"]]; [NSBundle loadGSMarkupNamed:menuName owner:self]; #if defined(__APPLE__) && !defined(GNUSTEP) /* Keyboard shortcut hack. Renaissance can't do this. */ NSMenu *menu; NSMenuItem *hideOthers; menu = [NSApp mainMenu]; hideOthers = [[[menu itemAtIndex:0] submenu] itemWithTitle: [GrouchString getString:@"Hide Others"]]; if( hideOthers && ![[hideOthers keyEquivalent] length] ) { int mask = NSAlternateKeyMask | NSCommandKeyMask; [hideOthers setKeyEquivalent:@"h"]; [hideOthers setKeyEquivalentModifierMask:mask]; } #endif [self newClient:self]; return self; } - (BOOL)textView:text clickedOnLink:(NSURL*)link atIndex:(unsigned)index { if( ![[NSWorkspace sharedWorkspace] openURL:link] ) url_backup_function([link absoluteString]); return YES; } - (void)renameUser:sender { id obj = [self activeListItem]; if( !obj ) obj = [self activeUser]; if( obj ) [AliasWindow windowForClient:[self activeClient] forObject:obj]; } - (void)inferLinks:sender { NSWindow *k = [NSApp keyWindow]; if(k) { NSTextView *txt = [k firstResponder]; if(txt && [txt isKindOfClass:[NSTextView class]]) if([txt isEditable]) [[txt textStorage] inferLinks]; } } @end @implementation NSInvocation (Grouch) - (void)invokeForGrouch:(int)value { if( value == NSAlertDefaultReturn ) [self invoke]; [self release]; } @end int main( int argc, const char **argv ) { NSAutoreleasePool *pool = [NSAutoreleasePool new]; int r; [NSApplication sharedApplication]; [NSApp setDelegate:[GrouchAppDelegate new]]; [Defaults registerDefaults]; [pool release]; pool = [NSAutoreleasePool new]; r = NSApplicationMain( argc, argv ); [pool release]; return r; } #ifdef _WIN32 #include static void url_backup_function( NSString *url ) { ShellExecute( NULL, NULL, [url cString], NULL, NULL, SW_SHOW ); } #else #include static int try_exec( const char *progname, NSString *str ) { return execlp ( progname, "mozilla", "-remote", [str cString], (void*)NULL // cast avoids warning on OpenBSD. ); } static void url_backup_function( NSString *url ) { if( (!fork()) ) { NSString *cmd; NSLog(@"trying to invoke mozilla ..."); cmd = [NSString stringWithFormat:@"OpenURL(%@, new-window)", url]; try_exec( "mozilla", cmd ); exit(try_exec( "mozilla-firefox", cmd )); } } #endif