/* copyright 2002 Alexander Malmberg */ #include #include #include #include #include #include #include #include #include #include "MsgDB.h" #include "LogWindowController.h" #include "FolderWindowController.h" #include "FolderListController.h" #include "ComposeWindowController.h" #include "main.h" #include "VERSION" AppDelegate *app_delegate; #define LOG_MESSAGES_ONLY #define LogWindowVisibleKey @"LogWindowVisible" #define FolderListVisibleKey @"FolderListVisible" #define FoldersVisibleKey @"FoldersVisible" #define LocationKey @"MessageDatabaseLocation" NSString *DefaultEncodingChangedNotification = @"DefaultEncodingChangedNotification"; @interface NSMenu (im_lazy) -(id ) addItemWithTitle: (NSString *)s; -(id ) addItemWithTitle: (NSString *)s action: (SEL)sel; @end @implementation NSMenu (im_lazy) -(id ) addItemWithTitle: (NSString *)s { return [self addItemWithTitle: s action: NULL keyEquivalent: nil]; } -(id ) addItemWithTitle: (NSString *)s action: (SEL)sel { return [self addItemWithTitle: s action: sel keyEquivalent: nil]; } @end #include @implementation AppDelegate -(void) composeArticle: (NSDictionary *)headers; { [[[ComposeWindowController alloc] initWithHeaders: headers] showWindow: self]; } -(void) composeFollowupToMessage: (Message *)msg { [[[ComposeWindowController alloc] initWithFollowupToMessage: msg] showWindow: self]; } -(void) composeNewArticle: (id)sender { [self composeArticle: nil]; } -(void) postArticleFrom: (id)sender : (const unsigned char *)data : (int)length { /* TODO */ NSObject *src; // fprintf(stderr,"post article %@\n",sender); src=[[mdb sources] objectAtIndex: 0]; if (!src || ![src respondsToSelector: @selector(postArticle:length:sender:)]) { fprintf(stderr,"no source!\n"); NSBeep(); return; } [src postArticle: data length: length sender: sender]; } - initWithApp: (NSApplication *)a { CREATE_AUTORELEASE_POOL(arp); NSString *dir; if (!(self=[super init])) return nil; app=a; folder_windows=[[NSMutableDictionary alloc] init]; dir=[[NSUserDefaults standardUserDefaults] objectForKey: LocationKey]; if (!dir) { dir=[NSSearchPathForDirectoriesInDomains(NSLibraryDirectory,NSUserDomainMask,YES) objectAtIndex: 0]; dir=[[dir stringByAppendingPathComponent: @"LuserNET"] stringByStandardizingPath]; [[NSUserDefaults standardUserDefaults] setObject: dir forKey: LocationKey]; } mdb=[[MsgDB alloc] initWithDirectory: dir]; DESTROY(arp); return self; } -(void) applicationWillTerminate: (NSNotification *)n { [mdb syncToDisk]; [[NSNotificationCenter defaultCenter] removeObserver: self]; { NSUserDefaults *ud=[NSUserDefaults standardUserDefaults]; NSMutableArray *a; NSEnumerator *e; NSString *fn; [ud setBool: [[log_window window] isVisible] forKey: LogWindowVisibleKey]; if (folder_list) [ud setBool: [[folder_list window] isVisible] forKey: FolderListVisibleKey]; else [ud setBool: NO forKey: FolderListVisibleKey]; a=[[NSMutableArray alloc] init]; for (e=[folder_windows keyEnumerator];(fn=[e nextObject]);) { if ([[[folder_windows objectForKey: fn] window] isVisible]) [a addObject: fn]; } [ud setObject: a forKey: FoldersVisibleKey]; [a release]; } DESTROY(preferences_window); DESTROY(log_window); DESTROY(folder_list); DESTROY(folder_windows); DESTROY(mdb); } -(void) openFolderWindow: (NSString *)folder_name { FolderWindowController *fw; fw=[folder_windows objectForKey: folder_name]; if (!fw) { fw=[[FolderWindowController alloc] initWithMsgDB: mdb folder: folder_name]; if (!fw) return; /* TODO: bring up error panel? */ [folder_windows setObject: fw forKey: folder_name]; [fw release]; } [fw showWindow: self]; } -(void) openMessageWindow: (msg_id_t)mid { NSLog(@"TODO: openMessageWindow: %i\n",mid); } -(void) quit: (id)sender { [app terminate: sender]; } -(void) update: (id)sender { [mdb updateAll]; } -(void) listFolders: (id)sender { if (!folder_list) folder_list=[[FolderListController alloc] initWithMsgDB: mdb]; [folder_list showWindow: self]; } -(void) logWindow: (id)sender { [log_window showWindow: self]; } -(void) logMessage: (NSNotification *)n { #ifdef LOG_MESSAGES_ONLY [log_window addLogString: [[n userInfo] objectForKey: @"Message"]]; #else [log_window addLogString: [NSString stringWithFormat: @"%@: %@ %@ %@",n,[n name],[n object],[n userInfo]]]; #endif } -(void) changeEncoding:(id)sender { NSDictionary *charsets = [CWCharset allCharsets]; // [sender selectItemWithTitle:[sender title]]; // [sender synchronizeTitleAndSelectedItem]; [[NSUserDefaults standardUserDefaults] setObject: [[charsets allKeysForObject:[sender title]] objectAtIndex:0] forKey:@"DefaultEncoding"]; [[NSNotificationCenter defaultCenter] postNotificationName: DefaultEncodingChangedNotification object: nil]; } -(void) applicationWillFinishLaunching: (NSNotification *)n { NSMenu *menu,*m,*m2; menu=[[NSMenu alloc] init]; /* 'Info' menu */ m=[[NSMenu alloc] init]; [m addItemWithTitle: _(@"Preferences...") action: @selector(openPreferences:)]; [m addItemWithTitle: _(@"Info...") action: @selector(orderFrontStandardInfoPanel:)]; [menu setSubmenu: m forItem: [menu addItemWithTitle: _(@"Info")]]; [m release]; /* 'Folder list' menu */ m=[[NSMenu alloc] init]; [m addItemWithTitle: _(@"Open list") action: @selector(listFolders:) keyEquivalent: @"f"]; [m addItemWithTitle: _(@"Open folder") action: @selector(openFolder:)]; [menu setSubmenu: m forItem: [menu addItemWithTitle: _(@"Folder list")]]; [m release]; /* 'Folder' menu */ m=[[NSMenu alloc] init]; /* Folder->Move to */ m2=[[NSMenu alloc] init]; [m2 addItemWithTitle: _(@"Parent") action: @selector(moveToParent:) keyEquivalent: @"P"]; [m2 addItemWithTitle: _(@"Next unread") action: @selector(moveToNextUnread:) keyEquivalent: @"n"]; [m2 addItemWithTitle: _(@"Scroll/next") action: @selector(scrollNextUnread:) keyEquivalent: @" "]; [m2 addItemWithTitle: _(@"Next branch") action: @selector(skipBranch:) keyEquivalent: @"b"]; [m2 addItemWithTitle: _(@"Next thread") action: @selector(skipBranch:) keyEquivalent: @"t"]; [m setSubmenu: m2 forItem: [m addItemWithTitle: _(@"Move to")]]; [m2 release]; /* Folder->Mark read */ m2=[[NSMenu alloc] init]; [m2 addItemWithTitle: _(@"Branch") action: @selector(skipBranchMark:) keyEquivalent: @"B"]; [m2 addItemWithTitle: _(@"Thread") action: @selector(skipBranchMark:) keyEquivalent: @"T"]; [m2 addItemWithTitle: _(@"All") action: @selector(markAll:) keyEquivalent: @"A"]; [m setSubmenu: m2 forItem: [m addItemWithTitle: _(@"Mark read")]]; [m2 release]; /* Folder->Sort by */ m2=[[NSMenu alloc] init]; [m2 addItemWithTitle: _(@"Thread") action: @selector(folderSortThread)]; [m2 addItemWithTitle: _(@"Reverse thread") action: @selector(folderSortReverseThread)]; /* TODO: these are currently unusably slow [m2 addItemWithTitle: _(@"Subject") action: @selector(folderSortSubject)]; [m2 addItemWithTitle: _(@"Reverse subject") action: @selector(folderSortReverseSubject)]; [m2 addItemWithTitle: _(@"From") action: @selector(folderSortFrom)]; [m2 addItemWithTitle: _(@"Reverse from") action: @selector(folderSortReverseFrom)]; [m2 addItemWithTitle: _(@"Date") action: @selector(folderSortDate)]; [m2 addItemWithTitle: _(@"Reverse date") action: @selector(folderSortReverseDate)];*/ [m2 addItemWithTitle: _(@"Arrival") action: @selector(folderSortOrder)]; [m2 addItemWithTitle: _(@"Reverse arrival") action: @selector(folderSortReverseOrder)]; [m setSubmenu: m2 forItem: [m addItemWithTitle: _(@"Sort by")]]; [m2 release]; [menu setSubmenu: m forItem: [menu addItemWithTitle: _(@"Folder")]]; [m release]; /* 'Message' menu */ m=[[NSMenu alloc] init]; /* [m addItemWithTitle: _(@"Open") action: @selector(openMessage:)];*/ m2=[[NSMenu alloc] init]; NSDictionary *charsets = [CWCharset allCharsets]; NSEnumerator *en = [[charsets allValues] objectEnumerator]; NSString *encoding; while((encoding = [en nextObject])) { [m2 addItemWithTitle: encoding action: @selector(changeEncoding:)]; } [m setSubmenu: m2 forItem: [m addItemWithTitle: _(@"Change encoding...")]]; [m addItemWithTitle: _(@"Toggle read/unread") action: @selector(messageToggleRead:) keyEquivalent: @"m"]; [m addItemWithTitle: _(@"Switch font") action: @selector(switchFont) keyEquivalent: @"F"]; [m addItemWithTitle: _(@"Show source") action: @selector(showSource)]; [m addItemWithTitle: _(@"Download") action: @selector(messageDownload)]; [m addItemWithTitle: _(@"Save...") action: @selector(messageSave) keyEquivalent: @"s"]; [menu setSubmenu: m forItem: [menu addItemWithTitle: _(@"Message")]]; [m release]; /* 'Compose' menu */ m=[[NSMenu alloc] init]; [m addItemWithTitle: _(@"New article") action: @selector(composeNewArticle:)]; [m addItemWithTitle: _(@"Followup to group") action: @selector(composeFollowup:) keyEquivalent: @"r"]; [menu setSubmenu: m forItem: [menu addItemWithTitle: _(@"Compose")]]; [m release]; /* 'Edit' menu */ m=[[NSMenu alloc] init]; [m addItemWithTitle: _(@"Copy") action: @selector(copy:) keyEquivalent: @"c"]; [m addItemWithTitle: _(@"Cut") action: @selector(cut:) keyEquivalent: @"x"]; [m addItemWithTitle: _(@"Paste") action: @selector(paste:) keyEquivalent: @"v"]; [menu setSubmenu: m forItem: [menu addItemWithTitle: _(@"Edit")]]; [m release]; /* Main menu entries */ [menu addItemWithTitle: _(@"Update") action: @selector(update:) keyEquivalent: @"u"]; [menu addItemWithTitle: _(@"Log window") action: @selector(logWindow:) keyEquivalent: @"l"]; m=[[NSMenu alloc] init]; [m addItemWithTitle: _(@"Close") action: @selector(performClose:) keyEquivalent: @"w"]; [menu setSubmenu: m forItem: [menu addItemWithTitle: _(@"Windows")]]; [app setWindowsMenu: m]; [m release]; m=[[NSMenu alloc] init]; [menu setSubmenu: m forItem: [menu addItemWithTitle: _(@"Services")]]; [app setServicesMenu: m]; [m release]; [menu addItemWithTitle: _(@"Hide") action: @selector(hide:) keyEquivalent: @"h"]; [menu addItemWithTitle: _(@"Quit") action: @selector(quit:) keyEquivalent: @"q"]; [app setMainMenu: menu]; [menu setTitle: @"LuserNET.app"]; [menu release]; log_window=[[LogWindowController alloc] init]; [log_window addLogString: [NSString stringWithFormat: _(@"Welcome to LuserNET.app v%s"),VERSION]]; [log_window addLogString: _(@"alt-f brings up the folder lists; alt-u checks for new messages")]; [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(logMessage:) #ifdef LOG_MESSAGES_ONLY name: MsgDB_LogMessageNotification #else name: nil #endif object: mdb]; } -(void) applicationDidFinishLaunching: (NSNotification *)n { NSUserDefaults *ud=[NSUserDefaults standardUserDefaults]; NSArray *a; if ([ud boolForKey: LogWindowVisibleKey]) [log_window showWindow: self]; if ([ud boolForKey: FolderListVisibleKey]) [self listFolders: self]; a=[ud arrayForKey: FoldersVisibleKey]; if (a) { int i,c=[a count]; for (i=0;i