/* * Copyright 2011 Sven Weidauer * * This file is part of NetSurf, http://www.netsurf-browser.org/ * * NetSurf is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License. * * NetSurf is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #import "cocoa/apple_image.h" #import "cocoa/NetsurfApp.h" #import "cocoa/gui.h" #import "cocoa/plotter.h" #import "cocoa/DownloadWindowController.h" #import "cocoa/SearchWindowController.h" #import "cocoa/selection.h" #import "cocoa/fetch.h" #import "utils/filename.h" #import "utils/log.h" #import "utils/messages.h" #import "utils/utils.h" #import "content/urldb.h" #import "utils/nsoption.h" #import "desktop/plotters.h" #import "desktop/save_complete.h" #import "desktop/textinput.h" #import "desktop/tree.h" #import "render/html.h" #import "desktop/mouse.h" #import "desktop/netsurf.h" #ifndef NETSURF_HOMEPAGE #define NETSURF_HOMEPAGE "http://www.netsurf-browser.org/welcome/" #endif @implementation NetSurfApp @synthesize frontTab; static bool cocoa_done = false; /** * Cause an abnormal program termination. * * \note This never returns and is intended to terminate without any cleanup. * * \param error The message to display to the user. */ static void die(const char * const error) { [NSException raise: @"NetsurfDie" format: @"Error: %s", error]; } - (void) loadOptions; { NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; [defaults registerDefaults: [NSDictionary dictionaryWithObjectsAndKeys: cocoa_get_user_path( @"Cookies" ), kCookiesFileOption, cocoa_get_user_path( @"URLs" ), kURLsFileOption, [NSString stringWithUTF8String: NETSURF_HOMEPAGE], kHomepageURLOption, nil]]; nsoption_setnull_charp(cookie_file, strdup( [[defaults objectForKey: kCookiesFileOption] UTF8String] )); nsoption_setnull_charp(cookie_jar, strdup( nsoption_charp(cookie_file) )); nsoption_setnull_charp(homepage_url, strdup( [[defaults objectForKey: kHomepageURLOption] UTF8String] )); urldb_load( [[defaults objectForKey: kURLsFileOption] UTF8String] ); urldb_load_cookies( nsoption_charp(cookie_file) ); cocoa_update_scale_factor(); } - (void) saveOptions; { urldb_save_cookies( nsoption_charp(cookie_file) ); urldb_save( [[[NSUserDefaults standardUserDefaults] objectForKey: kURLsFileOption] UTF8String] ); } - (void) run; { [self finishLaunching]; [self loadOptions]; while (!cocoa_done) { cocoa_autorelease(); NSEvent *event = [NSApp nextEventMatchingMask: NSAnyEventMask untilDate: [NSDate distantFuture] inMode: NSDefaultRunLoopMode dequeue: YES]; if (nil != event) { [NSApp sendEvent: event]; [NSApp updateWindows]; } } [self saveOptions]; } -(void) terminate: (id)sender; { [[NSNotificationCenter defaultCenter] postNotificationName:NSApplicationWillTerminateNotification object:self]; cocoa_done = true; [self postEvent: [NSEvent otherEventWithType: NSApplicationDefined location: NSZeroPoint modifierFlags: 0 timestamp: 0 windowNumber: 0 context: NULL subtype: 0 data1: 0 data2: 0] atStart: YES]; } @end #pragma mark - static NSString *cocoa_get_preferences_path( void ) { NSArray *paths = NSSearchPathForDirectoriesInDomains( NSApplicationSupportDirectory, NSUserDomainMask, YES ); NSCAssert( [paths count] >= 1, @"Where is the application support directory?" ); NSString *netsurfPath = [[paths objectAtIndex: 0] stringByAppendingPathComponent: @"NetSurf"]; NSFileManager *fm = [NSFileManager defaultManager]; BOOL isDirectory = NO; BOOL exists = [fm fileExistsAtPath: netsurfPath isDirectory: &isDirectory]; if (!exists) { exists = [fm createDirectoryAtPath: netsurfPath withIntermediateDirectories: YES attributes: nil error: NULL]; isDirectory = YES; } if (!(exists && isDirectory)) { die( "Cannot create netsurf preferences directory" ); } return netsurfPath; } NSString *cocoa_get_user_path( NSString *fileName ) { return [cocoa_get_preferences_path() stringByAppendingPathComponent: fileName]; } static const char *cocoa_get_options_file( void ) { NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; [defaults registerDefaults: [NSDictionary dictionaryWithObjectsAndKeys: cocoa_get_user_path( @"Options" ), kOptionsFileOption, nil]]; return [[defaults objectForKey: kOptionsFileOption] UTF8String]; } static NSApplication *cocoa_prepare_app( void ) { if (NSApp != nil) return NSApp; NSDictionary *infoDictionary = [[NSBundle mainBundle] infoDictionary]; Class principalClass = NSClassFromString([infoDictionary objectForKey:@"NSPrincipalClass"]); NSCAssert([principalClass respondsToSelector:@selector(sharedApplication)], @"Principal class must implement sharedApplication."); [principalClass sharedApplication]; NSString *mainNibName = [infoDictionary objectForKey:@"NSMainNibFile"]; NSNib *mainNib = [[NSNib alloc] initWithNibNamed:mainNibName bundle:[NSBundle mainBundle]]; [mainNib instantiateNibWithOwner:NSApp topLevelObjects:nil]; [mainNib release]; return NSApp; } void cocoa_autorelease( void ) { static NSAutoreleasePool *pool = nil; [pool release]; pool = [[NSAutoreleasePool alloc] init]; } /** * Set option defaults for cocoa frontend * * @param defaults The option table to update. * @return error status. */ static nserror set_defaults(struct nsoption_s *defaults) { /* Set defaults for absent option strings */ const char * const ca_bundle = [[[NSBundle mainBundle] pathForResource: @"ca-bundle" ofType: @""] UTF8String]; nsoption_setnull_charp(ca_bundle, strdup(ca_bundle)); return NSERROR_OK; } int main( int argc, char **argv ) { nsurl *url; nserror error; struct netsurf_table cocoa_table = { .browser = cocoa_browser_table, .window = cocoa_window_table, .clipboard = cocoa_clipboard_table, .download = cocoa_download_table, .fetch = cocoa_fetch_table, .search = cocoa_search_table, }; cocoa_autorelease(); error = netsurf_register(&cocoa_table); if (error != NSERROR_OK) { die("NetSurf operation table failed registration"); } const char * const messages = [[[NSBundle mainBundle] pathForResource: @"Messages" ofType: @""] UTF8String]; const char * const options = cocoa_get_options_file(); /* initialise logging. Not fatal if it fails but not much we * can do about it either. */ nslog_init(NULL, &argc, argv); /* user options setup */ error = nsoption_init(set_defaults, &nsoptions, &nsoptions_default); if (error != NSERROR_OK) { die("Options failed to initialise"); } nsoption_read(options, NULL); nsoption_commandline(&argc, argv, NULL); /* common initialisation */ error = netsurf_init(messages, NULL); if (error != NSERROR_OK) { die("NetSurf failed to initialise"); } /* Initialise filename allocator */ filename_initialise(); (void)apple_image_init(); NSApplication *app = cocoa_prepare_app(); for (int i = 1; i < argc; i++) { /* skip -psn_* and other possible options */ if (argv[i][0] == '-') continue; error = nsurl_create(argv[i], &url); if (error == NSERROR_OK) { error = browser_window_create(BW_CREATE_HISTORY, url, NULL, NULL, NULL); nsurl_unref(url); } if (error != NSERROR_OK) { warn_user(messages_get_errorcode(error), 0); } } [app run]; netsurf_exit(); return 0; }