408 lines
12 KiB
Objective-C
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;
|
|
}
|