WebSurf/frontends/gnustep/AppDelegate.m

408 lines
12 KiB
Objective-C

/*
* Copyright 2022 Anthony Cohn-Richardby <anthonyc@gmx.co.uk>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#import <Foundation/Foundation.h>
#import <AppKit/AppKit.h>
#import "netsurf/netsurf.h"
#import "utils/nsoption.h"
#import "utils/nsurl.h"
#import "utils/log.h"
#import "AppDelegate.h"
#import "BrowserWindowController.h"
#import "tables/tables.h"
#import "tables/misc.h"
#import "netsurf/browser_window.h"
#import "DownloadsWindowController.h"
#import "FindPanelController.h"
#import "HistoryWindowController.h"
#import "Website.h"
#import "BookmarkFolder.h"
#import "BookmarksWindowController.h"
#import "PreferencesWindowController.h"
#import "Preferences.h"
#define MAX_RECENT_HISTORY 10
/**
* Set option defaults for (taken from the 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];
if (ca_bundle == NULL) {
return NSERROR_BAD_URL;
}
nsoption_setnull_charp(ca_bundle, strdup(ca_bundle));
return NSERROR_OK;
}
@implementation AppDelegate
-(void)applicationDidFinishLaunching: (NSNotification*)aNotification
{
[NSApp setServicesProvider:self];
[NSBundle loadNibNamed: @"Menu" owner: NSApp];
[self clearBrowsingHistory];
}
-(void)historyUpdated: (NSNotification*)aNotification {
NSLog(@"history updated... %@", aNotification);
id object = [aNotification object];
NSMenu *historyMenu = [[[NSApp menu] itemWithTag: TAG_SUBMENU_HISTORY] submenu];
if ([object isKindOfClass: [Website class]]) {
[recentHistory insertObject: object atIndex: 0];
NSMenuItem *menuItem = [[[NSMenuItem alloc] initWithTitle: [object name]
action: @selector(open) keyEquivalent: nil] autorelease];
[menuItem setTarget: object];
[historyMenu insertItem: menuItem atIndex: 1];
if ([recentHistory count] > MAX_RECENT_HISTORY) {
[recentHistory removeLastObject];
[historyMenu removeItemAtIndex: [historyMenu numberOfItems] - 1];
}
}
}
static NSMenuItem *menuItemForItem(id item) {
if ([item isKindOfClass: [BookmarkFolder class]]) {
NSMenu *menu = [[[NSMenu alloc] initWithTitle: [item name]] autorelease];
NSArray *children = [item children];
for (NSUInteger i = 0; i < [children count]; i++) {
NSMenuItem *menuItem = menuItemForItem([children objectAtIndex: i]);
[menu addItem: menuItem];
}
NSMenuItem *menuItem = [[NSMenuItem alloc] initWithTitle: [item name]
action: nil keyEquivalent: nil];
[menuItem setSubmenu: menu];
return [menuItem autorelease];
} else {
NSMenuItem *menuItem = [[NSMenuItem alloc] initWithTitle: [item name]
action: @selector(open) keyEquivalent: nil];
[menuItem setTarget: item];
return [menuItem autorelease];
}
}
-(void)bookmarksUpdated: (NSNotification*)aNotification {
NSArray *bookmarks = [[BookmarkFolder rootBookmarkFolder] children];
NSMenu *bookmarksMenu = [[[NSApp menu] itemWithTag: TAG_SUBMENU_BOOKMARKS] submenu];
NSInteger nItems = [bookmarksMenu numberOfItems];
for (NSInteger i = 0; i < nItems - 2; i++) {
[bookmarksMenu removeItemAtIndex: 2];
}
id item;
for (NSUInteger i = 0; i < [bookmarks count]; i++) {
item = [bookmarks objectAtIndex: i];
[bookmarksMenu insertItem: menuItemForItem(item) atIndex: 2 + i];
}
}
-(void)awakeFromNib {
NSLog(@"App awake from nib");
recentHistory = [[NSMutableArray alloc] init];
[[NSNotificationCenter defaultCenter] addObserver: self
selector: @selector(historyUpdated:)
name: WebsiteHistoryUpdatedNotificationName
object: nil];
[[NSNotificationCenter defaultCenter] addObserver: self
selector: @selector(bookmarksUpdated:)
name: BookmarksUpdatedNotificationName
object: nil];
[self bookmarksUpdated: nil];
[self historyUpdated: nil];
//[self didTapNewWindow: nil];
}
-(void)didTapNewWindow: (id)sender {
NSLog(@"Will create a new window %@", self);
struct nsurl *url;
nserror error;
NSString *startupUrl = [[Preferences defaultPreferences] startupUrl];
error = nsurl_create([startupUrl cString], &url);
if (error == NSERROR_OK) {
error = browser_window_create(BW_CREATE_HISTORY, url, NULL, NULL, NULL);
nsurl_unref(url);
}
if (error != NSERROR_OK) {
NSLog(@"Failed to create window");
}
}
-(void)showDownloadsWindow: (id)sender {
NSLog(@"Showing downloads ...");
if (!downloadsWindowController) {
downloadsWindowController = [[DownloadsWindowController alloc] init];
[downloadsWindowController loadWindow];
} else {
[downloadsWindowController showWindow: self];
}
}
-(void)showFindPanel: (id)sender {
NSLog(@"Showing find panel ...");
if (!findPanelController) {
findPanelController = [[FindPanelController alloc] init];
[findPanelController loadWindow];
} else {
[findPanelController showWindow: self];
}
}
-(void)showHistoryWindow: (id)sender {
NSLog(@"Showing history ...");
if (!historyWindowController) {
historyWindowController = [[HistoryWindowController alloc] init];
[historyWindowController loadWindow];
} else {
[historyWindowController showWindow: self];
}
}
-(void)showBookmarksWindow: (id)sender {
NSLog(@"Showing bookmarks...");
if (!bookmarksWindowController) {
bookmarksWindowController = [[BookmarksWindowController alloc] init];
[bookmarksWindowController loadWindow];
} else {
[bookmarksWindowController showWindow: self];
}
}
-(void)showPreferencesWindow: (id)sender {
NSLog(@"Show preferences window");
if (!preferencesWindowController) {
preferencesWindowController = [[PreferencesWindowController alloc] init];
[preferencesWindowController loadWindow];
} else {
[preferencesWindowController showWindow: self];
}
}
-(NSURL*)requestDownloadDestination {
NSSavePanel *savePanel = [NSOpenPanel savePanel];
[savePanel setDirectory: NSHomeDirectory()];
if ([savePanel runModal] == NSOKButton) {
return [savePanel URL];
} else {
return nil;
}
}
-(NSURL*)requestFileLocation {
NSSavePanel *openPanel = [NSOpenPanel openPanel];
[openPanel setDirectory: NSHomeDirectory()];
if ([openPanel runModal] == NSOKButton) {
return [openPanel URL];
} else {
return nil;
}
}
-(void)openWebsite: (Website*)aWebsite {
struct nsurl *url;
nserror error;
error = nsurl_create([[aWebsite url] cString], &url);
if (error == NSERROR_OK) {
error = browser_window_create(BW_CREATE_HISTORY, url, NULL, NULL, NULL);
nsurl_unref(url);
}
if (error != NSERROR_OK) {
NSLog(@"Failed to create window");
}
}
-(BrowserWindowController*)activeBrowserWindow {
NSArray *windows = [NSApp windows];
id controller;
for (NSUInteger i = 0; i < [windows count]; i++) {
controller = [[windows objectAtIndex: i] windowController];
if ([controller isKindOfClass: [BrowserWindowController class]]) {
return controller;
}
}
return nil;
}
-(void)clearBrowsingHistory {
NSUInteger days = [[Preferences defaultPreferences] browsingHistoryDays];
if (days > 0) {
NSLog(@"Clearing history older than %u days", days);
[Website deleteHistoryOlderThanDays: days];
} else {
NSLog(@"browsingHistoryDays preference set to 0, won't clear history");
}
}
-(NSString*)currentUrl {
return [[self activeBrowserWindow] visibleUrl];
}
-(void)openDeveloperFileAtPath: (NSString*)path {
NSString *app;
Website *website;
BrowserWindowController *current;
website = [[Website alloc] initWithName: @"" url: [NSString
stringWithFormat: @"file://%@", path]];
[website autorelease];
switch ([[Preferences defaultPreferences] developerViewLocation]) {
case ViewLocationTab:
current = [self activeBrowserWindow];
if (current != nil) {
[current newTab: [website url]];
break;
}
case ViewLocationWindow:
[self openWebsite: website];
break;
case ViewLocationEditor:
if (![[NSWorkspace sharedWorkspace] openFile: path]) {
NSAlert *alert = [[NSAlert alloc] init];
[alert setMessageText: @"No Editor"];
[alert setInformativeText: @"Either no NSWorkspace provider"\
" exists,\nor no app can be found to open this file"\
" type (.txt). \nTry picking a different option for"\
" developer views \nin preferences > appearance."];
[alert addButtonWithTitle: @"Ok"];
[alert runModal];
[alert release];
}
break;
default:
break;
}
}
-(void) openFileWindow: (id)sender
{
Website *website;
NSOpenPanel *openPanel = [NSOpenPanel openPanel];
[openPanel setAllowsMultipleSelection: YES];
if ([openPanel runModal] == NSOKButton) {
for (int i = 0; i < [[openPanel URLs] count]; i++) {
Website *website;
NSURL *url = [[openPanel URLs] objectAtIndex: i];
website = [[Website alloc] initWithName: @"" url: [NSString
stringWithFormat: @"file://%@", [url absoluteString]]];
[website autorelease];
[self openWebsite: website];
}
}
}
- (BOOL) application: (NSApplication *)application
openFile: (NSString *)fileName
{
Website *website;
website = [[Website alloc] initWithName: @"" url: [NSString
stringWithFormat: @"file://%@", fileName]];
[website autorelease];
[self openWebsite: website];
return YES;
}
- (void) openURL: (NSPasteboard*)pb
userData: (NSString*)ud
error: (NSString**)err
{
NSString *webURL;
NSArray *types;
NSArray *args;
NSString *path;
NSTask *task;
NSString *pboardString;
Website *website;
*err = nil;
types = [pb types];
if (![types containsObject:NSStringPboardType] ||
!(pboardString = [pb stringForType:NSStringPboardType]))
{
*err = NSLocalizedString(@"Error: Pasteboard doesn't contain a string.",
@"Pasteboard couldn't give string.");
return;
}
webURL = [pb stringForType: NSStringPboardType];
if (webURL == nil)
{
*err = @"No string value supplied on pasteboard";
return;
}
website = [[Website alloc] initWithName: @"" url: webURL];
[website autorelease];
[self openWebsite: website];
return;
}
@end
int main(int argc, char **argv) {
NSAutoreleasePool *pool = [NSAutoreleasePool new];
nslog_init(NULL, &argc, argv);
nserror error;
struct netsurf_table gnustep_table = {
.misc = &gnustep_misc_table,
.window = &gnustep_window_table,
.clipboard = &gnustep_clipboard_table,
.download = &gnustep_download_table,
.fetch = &gnustep_fetch_table,
.search = &gnustep_search_table,
.bitmap = &gnustep_bitmap_table,
.layout = &gnustep_layout_table,
};
error = netsurf_register(&gnustep_table);
NSCAssert(error == NSERROR_OK, @"NetSurf operation table failed registration");
/* common initialisation */
error = nsoption_init(set_defaults, &nsoptions, &nsoptions_default);
NSCAssert(error == NSERROR_OK, @"Options failed to initialise");
error = netsurf_init(NULL);
NSCAssert(error == NSERROR_OK, @"NetSurf failed to initialise");
/* Load user options */
error = nsoption_read([NS_PREFS_FILE cString], nsoptions);
if (error != NSERROR_OK) {
NSLog(@"Failed to load user preferences");
}
NSApplication *app = [NSApplication sharedApplication];
AppDelegate *delegate = [AppDelegate new];
[app setDelegate: delegate];
[app run];
[pool release];
return 0;
}