/*
SRMainWindowControllerAction.m

Author: Makoto Kinoshita

Copyright 2004 The Shiira Project. All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted 
provided that the following conditions are met:

  1. Redistributions of source code must retain the above copyright notice, this list of conditions 
  and the following disclaimer.

  2. Redistributions in binary form must reproduce the above copyright notice, this list of 
  conditions and the following disclaimer in the documentation and/or other materials provided 
  with the distribution.

THIS SOFTWARE IS PROVIDED BY THE SHIIRA PROJECT ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE SHIIRA PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
POSSIBILITY OF SUCH DAMAGE.
*/

#import "SRDefaultsKey.h"

#import "SRAppDelegate.h"
#import "SRDocumentController.h"
#import "SRMainDocument.h"
#import "SRMainWindowController.h"
#import "SRSidebarController.h"
#import "SRSearchFieldController.h"
#import "SRTabExpose.h"
#import "SRIconInstaller.h"
#import "SRBookmark.h"
#import "SRBookmarkStorage.h"
#import "SRAuthenticationController.h"
#import "SRDownloadCenter.h"
#import "SRSearchEnginesController.h"
#import "SRPreferencesController.h"
#import "SRSourceWindowController.h"

#import "SREncodings.h"

#import "SRBookmarksBarView.h"
#import "SRBookmarkButton.h"
#import "SRSearchField.h"
#import "SRTabView.h"
#import "SRURLComboBox.h"
#import "SRWebView.h"
#import "SRRSSRepresentation.h"

#import "SRUtil.h"
#import "FoundationEx.h"
#import "AppKitEx.h"
#import "WebKitEx.h"

#define _OK_BUTTON_TAG   0

@implementation SRMainWindowController (Action)

//--------------------------------------------------------------//
#pragma mark -- Actions --
//--------------------------------------------------------------//

- (void)setTextEncodingAction:(id)sender
{
    // For NSMenuItem
    if ([sender respondsToSelector:@selector(tag)]) {
        // Get web view
        WebView*    webView;
        webView = [self selectedWebView];
        
        // Get encoding value
        int encoding;
        encoding = [sender tag];
        
        // For default
        if (encoding == SRTextEncodingDefaultTag) {
            [webView setCustomTextEncodingName:nil];
            return;
        }
        
        // Get encoding name
        NSString*   encodingName;
        encodingName = [[NSValueTransformer valueTransformerForName:SREncodingToIANATransformerName] 
                transformedValue:[NSNumber numberWithInt:encoding]];
        if (encodingName) {
            [webView setCustomTextEncodingName:encodingName];
        }
    }
}

- (void)goBackAction:(id)sender
{
    // Get selected web view
    WebView*    webView;
    webView = [self selectedWebView];
    
    // Send action to web view
    [webView goBack:sender];
}

- (void)goForwardAction:(id)sender
{
    // Get selected web view
    WebView*    webView;
    webView = [self selectedWebView];
    
    // Send action to web view
    [webView goForward:sender];
}

- (void)goHomeAction:(id)sender
{
    NSUserDefaults* defaults;
    defaults = [NSUserDefaults standardUserDefaults];
    
    // Get home page URL
    NSString*   URLString;
    URLString = [[[NSApp delegate] preferencesController] homeURLString];
    if (!URLString || [URLString length] == 0) {
        return;
    }
    
    [self openURLString:URLString];
}

- (void)showHistoryInSidebarAction:(id)sender
{
    if(([[_sideBarController drawer] state] == NSDrawerOpenState) && 
       ([_sideBarController selectedTab] == SRSidebarHistoryTab))
    {
        [[_sideBarController drawer] close];
    }
    else {
        // Show history
        [_sideBarController showTab:SRSidebarHistoryTab];
        
        // Show sidebar
        [self setSidebarVisible:YES];
    }
}

- (void)openHistoryItemAction:(id)sender
{
    // For NSMenuItem
    if ([sender respondsToSelector:@selector(representedObject)]) {
        id  representedObject;
        representedObject = [sender representedObject];
        
        // For WebHistoryItem
        if ([representedObject isKindOfClass:[WebHistoryItem class]]) {
            // Check in back forward list
            WebView*            webView;
            WebBackForwardList* list;
            webView = [self selectedWebView];
            list = [webView backForwardList];
            if ([list containsItem:representedObject]) {
                // Go to item
                [webView goToBackForwardItem:representedObject];
                
                // Notify it
                [[NSNotificationCenter defaultCenter] 
                        postNotificationName:SRMainWindowGoToHistotyItem object:webView];
            }
            else {
                // Open URL
                [self openURLString:[representedObject URLString]];
            }
        }
    }
}

- (void)showBookmarkInSidebarAction:(id)sender
{
    if(([[_sideBarController drawer] state] == NSDrawerOpenState) && 
       ([_sideBarController selectedTab] == SRSidebarBookmarkTab))
    {
        [[_sideBarController drawer] close];
    }
    else {
        // Show bookmark
        [_sideBarController showTab:SRSidebarBookmarkTab];
        
        // Show sidebar
        [self setSidebarVisible:YES];
    }
}

- (void)takeStringURLFromAction:(id)sender
{
    // Get selected web view
    WebView*    webView;
    webView = [self selectedWebView];
    
    // Send action to web view
    [webView takeStringURLFrom:sender];
}

- (void)toggleToolbarAction:(id)sender
{
    // Toogle toolbar
    [[self window] toggleToolbarShown:sender];
}

- (void)toggleBookmarksBarAction:(id)sender
{
    // Toggle bookmarks bar
    [self setBookmarksBarVisible:![self isBookmarksBarVisible] display:YES];
}

- (void)toggleStatusBarAction:(id)sender
{
    // Toggle status bar
    [self setStatusBarVisible:![self isStatusBarVisible] display:YES];
}

- (void)toggleSidebarAction:(id)sender
{
    // Toogle sidebar
    [self setSidebarVisible:![self isSidebarVisible]];
}

- (void)customizeToolbarAction:(id)sender
{
    // Run toolbar customize panel
    [[[self window] toolbar] runCustomizationPalette:self];
}

- (void)stopLoadingAction:(id)sender
{
    // Stop loading
    [[self selectedWebView] stopLoading:sender];
}

- (void)reloadPageAction:(id)sender
{
    // Get modifier key
    unsigned    modifierFlags;
    unsigned    shiftFlag;
    modifierFlags = [[NSApp currentEvent] modifierFlags];
    shiftFlag = modifierFlags & NSShiftKeyMask;
    
    if (!shiftFlag) {
        // Reload page
        [[self selectedWebView] reload:sender];
    }
    else {
        // Reload without cache
        NSURLRequest*   request;
        NSURLRequest*   requestWithoutCache;
        request = [[[[self selectedWebView] mainFrame] dataSource] request];
        requestWithoutCache = [NSURLRequest requestWithURL:[request URL] 
                cachePolicy:NSURLRequestReloadIgnoringCacheData 
                timeoutInterval:[request timeoutInterval]];
        [self openRequest:requestWithoutCache];
    }
}

- (void)biggerTextAction:(id)sender
{
    // Bigger text
    [[self selectedWebView] makeTextLarger:sender];
}

- (void)smallerTextAction:(id)sender
{
    // Smaller text
    [[self selectedWebView] makeTextSmaller:sender];
}

- (void)findByToolbarAction:(id)sender
{
    NSUserDefaults* defaults;
    defaults = [NSUserDefaults standardUserDefaults];
    
    // Get toolbar
    NSToolbar*  toolbar;
    toolbar = [[self window] toolbar];
    
    // When no search field on toolbar
    if (![toolbar isVisible] || 
        ![self searchField] || 
        [toolbar displayMode] == NSToolbarDisplayModeLabelOnly) 
    {
        if (![self searchFieldOnSheet]) {
            // Create search field
            SRSearchField*  searchFieldOnSheet;
            searchFieldOnSheet = [[SRSearchField alloc] initWithFrame:NSMakeRect(0, 0, 0, 0)];
            [searchFieldOnSheet autorelease];
#if 1
            [[searchFieldOnSheet cell] setControlSize:NSSmallControlSize];
            [searchFieldOnSheet setFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]];
#else
            if ([defaults boolForKey:SRToolbarUseSmallURLAndSearchField]) {
                [[searchFieldOnSheet cell] setControlSize:NSSmallControlSize];
                [searchFieldOnSheet setFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]];
            }
            else {
                [[searchFieldOnSheet cell] setControlSize:NSRegularControlSize];
                [searchFieldOnSheet setFont:[NSFont systemFontOfSize:[NSFont systemFontSize]]];
            }
#endif
            [searchFieldOnSheet sizeToFit];
            [searchFieldOnSheet setTag:0];
            [searchFieldOnSheet setTarget:self];
            [searchFieldOnSheet setAction:@selector(closeSearchPanelAction:)];
            [[searchFieldOnSheet cell] setWraps:NO];
            [[searchFieldOnSheet cell] setScrollable:YES];
            [[searchFieldOnSheet cell] setSendsWholeSearchString:YES];
            
            NSRect  frame;
            frame = [[self searchFieldView] frame];
            frame.origin = NSZeroPoint;
            [searchFieldOnSheet setFrame:frame];
            [searchFieldOnSheet setAutoresizingMask:NSViewWidthSizable | NSViewMinYMargin];
            
            [[self searchFieldView] addSubview:searchFieldOnSheet];
        }
        
        // Set search field to controller
        [_searchFieldController setSearchField:[self searchFieldOnSheet]];
        
        // Show search panel
        [NSApp beginSheet:[self searchPanel] 
                modalForWindow:[self window] 
                modalDelegate:self 
                didEndSelector:@selector(_searchPanelDidEnd:returnCode:contextInfo:) 
                contextInfo:NULL];
        
        return;
    }
    
    // Focus on search field
    [[self window] makeFirstResponder:[self searchField]];
}

- (void)closeSearchPanelAction:(id)sender
{
    // End sheet
    [NSApp endSheet:[self searchPanel] returnCode:[sender tag]];
}

- (void)_searchPanelDidEnd:(NSWindow*)sheet 
        returnCode:(int)returnCode 
        contextInfo:(void*)contextInfo
{
    // Close location panel
    [sheet orderOut:self];
    
    // Search
    if (returnCode == 0) {
        [_searchFieldController searchAction:self];
    }
    
    // Restore search field of controller
    [_searchFieldController setSearchField:[self searchField]];
}

- (void)viewPageSourceAction:(id)sender
{
    // Get page source
    WebDataSource*  dataSource = nil;
    SRXMLDocument*  document = nil;
    
	// Check from context menu
	id  repObj;
    repObj = [sender representedObject];
	
    // For WebFrame
    if ([repObj isKindOfClass:[WebFrame class]]) {
		dataSource = [repObj dataSource];
    }
    // For XML document
    else if ([repObj isKindOfClass:NSClassFromString(@"SRXMLDocument")]) {
        document = repObj;
    }
    else {
        dataSource = [[[self selectedWebView] mainFrame] dataSource];
    }
    
    // View page source
    SRSourceWindowController*   sourceWindowController = nil;
    if (dataSource) {
        sourceWindowController = [SRSourceWindowController sourceWindowWithWebDataSource:dataSource];
    }
    else if (document) {
        sourceWindowController = [SRSourceWindowController sourceWindowWithXMLDocument:document];
    }
    
    if (sourceWindowController) {
        [sourceWindowController showWindow:self];
    }
}

- (void)previousTabAction:(id)sender
{
    // Get selected index
    int selectedIndex;
    int numberOfItems;
    selectedIndex = [_srTabView selectedIndex];
    numberOfItems = [_srTabView numberOfItems];
    if (selectedIndex == -1) {
        return;
    }
    
    // Select previous tab
    if (selectedIndex > 0) {
        [_srTabView selectItemAtIndex:selectedIndex - 1];
    }
    else {
        [_srTabView selectItemAtIndex:numberOfItems - 1];
    }
}

- (void)nextTabAction:(id)sender
{
    // Get item number and selected index
    int numberOfItems;
    int selectedIndex;
    numberOfItems = [_srTabView numberOfItems];
    selectedIndex = [_srTabView selectedIndex];
    if (selectedIndex == -1) {
        return;
    }
    
    // Select next tab
    if (numberOfItems > selectedIndex + 1) {
        [_srTabView selectItemAtIndex:selectedIndex + 1];
    }
    else {
        [_srTabView selectItemAtIndex:0];
    }
}

- (void)newTabAction:(id)sender
{
    // Add new tab
    [self addNewTabWithLabel:NSLocalizedString(@"Untitled", @"Untitled") 
            frameName:nil 
            groupName:nil];
}

- (void)closeWindowAction:(id)sender
{
    // Close window
    [[self window] performClose:sender];
}

- (void)closeTabAction:(id)sender
{
    // Close current tab
    if ([_srTabView numberOfItems] < 2) {
        // Do nothing
        return;
    }
    
    // Get selected index
    int selectedIndex;
    selectedIndex = [_srTabView selectedIndex];
    if (selectedIndex < 0) {
        // Do nothing
        return;
    }
    
    // Remove tab
    [_srTabView removeItemAtIndex:selectedIndex];
}

- (void)closeAllRightTabsAction:(id)sender
{
    // For NSMenuItem
    if ([sender respondsToSelector:@selector(representedObject)]) {
        id  representedObject;
        representedObject = [sender representedObject];
        
        // For tab index
        if ([representedObject isKindOfClass:[NSNumber class]]) {
            // Get number of tab items;
            int numberOfTabs;
            numberOfTabs = [_srTabView numberOfItems];
            
            // Get index
            int index = [representedObject intValue];
            if (index < 0 || index > numberOfTabs - 1) {
                return;
            }
            
            // Close all right tabs
            int i;
            for (i = numberOfTabs - 1; i > index; i--) {
                [_srTabView removeItemAtIndex:i];
            }
        }
    }
}

- (void)closeAllLeftTabsAction:(id)sender
{
    // For NSMenuItem
    if ([sender respondsToSelector:@selector(representedObject)]) {
        id  representedObject;
        representedObject = [sender representedObject];
        
        // For tab index
        if ([representedObject isKindOfClass:[NSNumber class]]) {
            // Get number of tab items;
            int numberOfTabs;
            numberOfTabs = [_srTabView numberOfItems];
            
            // Get index
            int index = [representedObject intValue];
            if (index < 0 || index > numberOfTabs - 1) {
                return;
            }
            
            // Close all left tabs
            int i;
            for (i = index - 1; i >=0; i--) {
                [_srTabView removeItemAtIndex:i];
            }
        }
    }
}

- (void)closeAllOtherTabsAction:(id)sender
{
    // For NSMenuItem
    if ([sender respondsToSelector:@selector(representedObject)]) {
        id  representedObject;
        representedObject = [sender representedObject];
        
        // For tab index
        if ([representedObject isKindOfClass:[NSNumber class]]) {
            // Get number of tab items;
            int numberOfTabs;
            numberOfTabs = [_srTabView numberOfItems];
            
            // Get index
            int index = [representedObject intValue];
            if (index < 0 || index > numberOfTabs - 1) {
                return;
            }
            
            // Close all right tabs
            int i;
            for (i = numberOfTabs - 1; i > index; i--) {
                [_srTabView removeItemAtIndex:i];
            }
            // Close all left tabs
            for (i = index - 1; i >=0; i--) {
                [_srTabView removeItemAtIndex:i];
            }
        }
    }
}

- (void)reloadTabAction:(id)sender
{
    // For NSMenu
    if ([sender respondsToSelector:@selector(representedObject)]) {
        // Get represented object
        id  representedObject;
        representedObject = [sender representedObject];
        if (!representedObject) {
            return;
        }
        
        // Get web view of selected tab
        int         selectedTabIndex;
        WebView*    webView;
        selectedTabIndex = [representedObject intValue];
        webView = (WebView*)[_srTabView viewAtIndex:selectedTabIndex];
        if (!webView) {
            return;
        }
        
        // Reload page
        [webView reload:self];
    }
}

- (void)reloadAllTabsAction:(id)sender
{
    // Reload all tabs
    int tabNumber;
    int i;
    tabNumber = [_srTabView numberOfItems];
    for (i = 0; i < tabNumber; i++) {
        // Get web view
        WebView*    webView;
        webView = (WebView*)[_srTabView viewAtIndex:i];
        if (!webView) {
            continue;
        }
        
        // Reload page
        [webView reload:self];
    }
}

- (void)bookmarkAllTabsAction:(id)sender
{
    // Set bookmark menu
    NSMenu* bookmarkMenu;
    bookmarkMenu = [[SRBookmarkStorage sharedInstance] bookmarkFolderMenu];
    [[self bookmarkAllPopup] removeAllItems];
    [[self bookmarkAllPopup] setMenu:bookmarkMenu];
    
    // Show add bookmark panel
    [NSApp beginSheet:[self bookmarkAllPanel] 
            modalForWindow:[self window] 
            modalDelegate:self 
            didEndSelector:@selector(_didEndBookmarkAllSheet:returnCode:contextInfo:) 
            contextInfo:NULL];
}

- (void)_didEndBookmarkAllSheet:(NSPanel*)sheet 
        returnCode:(int)returnCode 
        contextInfo:(void*)contextInfo
{
    // Close sheet
    [sheet orderOut:self];
    
    // Check return code
    if (returnCode != _OK_BUTTON_TAG) {
        return;
    }
    
    // Create bookmarks
    NSMutableArray* bookmarks;
    int             tabNum, i;
    bookmarks = [NSMutableArray array];
    tabNum = [_srTabView numberOfItems];
    for (i = 0; i < tabNum; i++) {
        // Get web view
        WebView*    webView;
        webView = (WebView*)[_srTabView viewAtIndex:i];
        if (!webView) {
            continue;
        }
        
        // Get title, URL string, and icon
        WebDataSource*  dataSource;
        NSString*       title;
        NSString*       URLString;
        dataSource = [[webView mainFrame] dataSource];
        if (!dataSource) {
            continue;
        }
        URLString = [[[dataSource request] URL] _web_userVisibleString];
        title = [dataSource pageTitle];
        if (!title) {
            title = URLString;
        }
        if (!title || !URLString) {
            continue;
        }
        
        // Create bookmark
        SRBookmark* bookmark;
        bookmark = [SRBookmark bookmarkWithTitle:title 
                URLString:URLString 
                originalBrowser:SRBrowserShiira];
        
        // Get MIME type
        NSURLResponse*  response;
        NSString*       MIMEType;
        response = [dataSource response];
        MIMEType = [response MIMEType];
        if ([[SRRSSRepresentation RSSMimes] containsObject:MIMEType]) {
            [bookmark setType:SRBookmarkTypeRSS];
        }
        
        [bookmarks addObject:bookmark];
    }
    
    // Get parent
    SRBookmark* parent;
    parent = [[[self bookmarkAllPopup] selectedItem] representedObject];
    
    // Add bookmark
    if ([[SRBookmarkStorage sharedInstance] rootBookmark] != parent) {
        [parent addChildren:bookmarks];
    }
    else {
        NSArray*    children;
        int         i;
        children = [parent children];
        for (i = 0; i < [children count]; i++) {
            if (![[children objectAtIndex:i] isMutable]) {
                break;
            }
        }
        if (i < 0 || i > [children count]) {
            i = [children count];
        }
        
        [parent insertChildren:bookmarks atIndex:i];
    }
}

- (void)closeBookmarkAllSheetAction:(id)sender
{
    // Close sheet
    [NSApp endSheet:[self bookmarkAllPanel] returnCode:[sender tag]];
}

- (void)accordingTabToStringWidthAction:(id)sender
{
    NSUserDefaults* defaults;
    defaults = [NSUserDefaults standardUserDefaults];
    
    // For NSMenuItem
    if ([sender respondsToSelector:@selector(representedObject)]) {
        id  representedObject;
        representedObject = [sender representedObject];
        
        // Get value
        BOOL    isAccordingTo;
        isAccordingTo = [defaults boolForKey:SRTabAccordingToStringWidth];
        
        // Set toggled value
        [defaults setBool:!isAccordingTo forKey:SRTabAccordingToStringWidth];
    }
}

- (void)openLocationAction:(id)sender
{
    NSUserDefaults* defaults;
    defaults = [NSUserDefaults standardUserDefaults];
    
    // Get toolbar
    NSToolbar*  toolbar;
    toolbar = [[self window] toolbar];
    
    // When no URL combo box on toolbar
    if (![toolbar isVisible] || 
        ![self URLComboBox] || 
        [toolbar displayMode] == NSToolbarDisplayModeLabelOnly) 
    {
        if (![self URLComboBoxOnSheet]) {
            // Create URL combo box
            SRURLComboBox*  locationURLComboBox;
            locationURLComboBox = [[SRURLComboBox alloc] initWithFrame:NSMakeRect(0, 0, 0, 0)];
            [locationURLComboBox autorelease];
#if 1
            [[locationURLComboBox cell] setControlSize:NSSmallControlSize];
            [locationURLComboBox setFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]];
#else
            if ([defaults boolForKey:SRToolbarUseSmallURLAndSearchField]) {
                [[locationURLComboBox cell] setControlSize:NSSmallControlSize];
                [locationURLComboBox setFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]];
            }
            else {
                [[locationURLComboBox cell] setControlSize:NSRegularControlSize];
                [locationURLComboBox setFont:[NSFont systemFontOfSize:[NSFont systemFontSize]]];
            }
#endif
            [locationURLComboBox setImage:[[WebIconDatabase sharedIconDatabase] defaultIconWithSize:NSMakeSize(16, 16)]];
            [[locationURLComboBox cell] setSendsActionOnEndEditing:NO];
            [locationURLComboBox setCompletes:YES];
            [locationURLComboBox setDelegate:self];
            [locationURLComboBox setTarget:self];
            [locationURLComboBox setAction:@selector(closeLocationPanelAction:)];
            [locationURLComboBox sizeToFit];
            
            NSRect  frame;
            frame = [[self locationURLView] frame];
            frame.origin = NSZeroPoint;
            [locationURLComboBox setFrame:frame];
            [locationURLComboBox setAutoresizingMask:NSViewWidthSizable | NSViewMinYMargin];
            
            [[self locationURLView] addSubview:locationURLComboBox];
        }
        
        // Show location panel
        [NSApp beginSheet:[self locationPanel] 
                modalForWindow:[self window] 
                modalDelegate:self 
                didEndSelector:@selector(_locationPanelDidEnd:returnCode:contextInfo:) 
                contextInfo:NULL];
        return;
    }
    
    // Make combo box first responder
    [[self window] makeFirstResponder:[self URLComboBox]];
}

- (void)closeLocationPanelAction:(id)sender
{
    // End sheet
    [NSApp endSheet:[self locationPanel] returnCode:[sender tag]];
}

- (void)_locationPanelDidEnd:(NSWindow*)sheet 
        returnCode:(int)returnCode 
        contextInfo:(void*)contextInfo
{
    // Close location panel
    [sheet orderOut:self];
    
    // For not go button
    if (returnCode != 0) {
        return;
    }
    
    // Treat as URL combo action
    [self URLComboBoxAction:[self URLComboBoxOnSheet]];
}

- (void)processComboBoxURLString:(NSString*)URLString
{
    NSUserDefaults* defaults;
    defaults = [NSUserDefaults standardUserDefaults];
    
    // Check argument
    if (!URLString || [URLString length] == 0 || [URLString isEqualToString:@"http://"]) {
        // Do not open page
        [[self window] makeFirstResponder:[self URLComboBox]];
        return;
    }
    
    // Get selected web view
    WebView*    webView;
    webView = [self selectedWebView];
    
    // Create request
    NSURLRequest*   request;
    request = [self createRequestWithURLString:URLString];
    
    // Open request with action
    SROpenActionType    openAction;
    openAction = SROpenActionTypeFromModifierFlags([[NSApp currentEvent] modifierFlags]);
    [self openRequest:request frameName:nil groupName:nil withOpenAction:openAction];
}

- (void)URLComboBoxAction:(id)sender
{
    // Get string
    NSString*   string;
    string = [sender stringValue];
    
    // handle search keyword if one was entered
    NSDictionary* searchEngine = nil;
    NSRange whitespaceRange;
    whitespaceRange = [string rangeOfCharacterFromSet:[NSCharacterSet whitespaceCharacterSet]];
    
    if(whitespaceRange.length) {
        NSString* keyword;
        keyword = [string substringWithRange:NSMakeRange(0,whitespaceRange.location)];
        
        NSEnumerator* enumerator;
        enumerator = [[[SRSearchEnginesManager sharedInstance] searchEngines] objectEnumerator];
        
        NSDictionary* eachEngine;
        
        while((searchEngine == nil) && (eachEngine = [enumerator nextObject])) {
            if([[eachEngine objectForKey:@"keyword"] isEqualToString:keyword]) {
                searchEngine = eachEngine;
            }
        }
    }
    
    NSString*   URLString = nil;
    
    // Create URL string from search engine template
    if(searchEngine) {
        NSRange searchTermRange;
        searchTermRange = NSMakeRange(NSMaxRange(whitespaceRange),[string length] - NSMaxRange(whitespaceRange));
                                      
        NSString* searchTerm;
        searchTerm = [string substringWithRange:searchTermRange];
        
        URLString = SRCreateSearchURLStringFromSearchEngine(searchTerm, searchEngine);
    }
    else {
        // Get URL string from combo box
        URLString = [sender absoluteURLStringOfCompletedString:string];
    }
    
    // Open URL string
    [self processComboBoxURLString:URLString];
}

- (void)createNewBookmarkFolderAction:(id)sender
{
    // Pass to side bar controller
    [_sideBarController createNewBookmarkFolderAction:sender];
}

- (void)openBookmarkAction:(id)sender
{
    SRBookmark* bookmark = nil;
    
    // For NSMenuItem
    if ([sender respondsToSelector:@selector(representedObject)]) {
        id  representedObject;
        representedObject = [sender representedObject];
        
        // For SRBookmark
        if ([representedObject isKindOfClass:[SRBookmark class]]) {
            bookmark = representedObject;
        }
        // For SRBookmarkButton
        else if ([representedObject respondsToSelector:@selector(bookmark)]) {
            bookmark = [representedObject bookmark];
        }
    }
    // For SRBookmarkButton
    else if ([sender respondsToSelector:@selector(bookmark)]) {
        bookmark = [sender bookmark];
    }
    
    if (!bookmark) {
        return;
    }
    
    // Open bookmark
    if ([bookmark isFolderType]) {
        if ([bookmark isAutoTab]) {
            // Open in tabs
            [self openInTabsBookmark:bookmark];
        }
    }
    else {
        // Get open action
        SROpenActionType    openAction;
        openAction = SROpenActionTypeFromModifierFlags([[NSApp currentEvent] modifierFlags]);
        
        // Open bookmark wiht open action
        [self openBookmark:bookmark withOpenAction:openAction];
    }
}

- (void)openBookmarkInNewWindowAction:(id)sender
{
    // For NSMenuItem
    if ([sender respondsToSelector:@selector(representedObject)]) {
        id  representedObject;
        representedObject = [sender representedObject];
        
        // For SRBookmarkButton
        if ([representedObject respondsToSelector:@selector(bookmark)]) {
            // Open bookmark
            [self openInNewWindowBookmark:[representedObject bookmark]];
        }
        // For SRBookmark
        if ([representedObject isKindOfClass:[SRBookmark class]]) {
            // Open bookmark
            [self openInNewWindowBookmark:representedObject];
        }
    }
}

- (void)openBookmarkInNewBackgroundWindowAction:(id)sender
{
    // For NSMenuItem
    if ([sender respondsToSelector:@selector(representedObject)]) {
        id  representedObject;
        representedObject = [sender representedObject];
        
        // For SRBookmarkButton
        if ([representedObject respondsToSelector:@selector(bookmark)]) {
            // Open bookmark
            [self openInNewBackgroundWindowBookmark:[representedObject bookmark]];
        }
        // For SRBookmark
        if ([representedObject isKindOfClass:[SRBookmark class]]) {
            // Open bookmark
            [self openInNewBackgroundWindowBookmark:representedObject];
        }
    }
}

- (void)openBookmarkInNewTabAction:(id)sender
{
    // For NSMenuItem
    if ([sender respondsToSelector:@selector(representedObject)]) {
        id  representedObject;
        representedObject = [sender representedObject];
        
        // For SRBookmarkButton
        if ([representedObject respondsToSelector:@selector(bookmark)]) {
            // Open bookmark
            [self openInNewTabBookmark:[representedObject bookmark] select:YES];
        }
        
        // For SRBookmark
        if ([representedObject isKindOfClass:[SRBookmark class]]) {
            // Open bookmark
            [self openInNewTabBookmark:representedObject select:YES];
        }
    }
}

- (void)openBookmarkInNewBackgroundTabAction:(id)sender
{
    // For NSMenuItem
    if ([sender respondsToSelector:@selector(representedObject)]) {
        id  representedObject;
        representedObject = [sender representedObject];
        
        // For SRBookmarkButton
        if ([representedObject respondsToSelector:@selector(bookmark)]) {
            // Open bookmark
            [self openInNewTabBookmark:[representedObject bookmark] select:NO];
        }
        
        // For SRBookmark
        if ([representedObject isKindOfClass:[SRBookmark class]]) {
            // Open bookmark
            [self openInNewTabBookmark:representedObject select:NO];
        }
    }
}

- (void)openBookmarkInTabsAction:(id)sender
{
    // For NSMenuItem
    if ([sender respondsToSelector:@selector(representedObject)]) {
        id  representedObject;
        representedObject = [sender representedObject];
        
        // For SRBookmarkButton
        if ([representedObject respondsToSelector:@selector(bookmark)]) {
            // Open bookmark folder
            [self openInTabsBookmark:[representedObject bookmark]];
        }
        // For SRBookmark
        if ([representedObject isKindOfClass:[SRBookmark class]]) {
            // Open bookmark folder
            [self openInTabsBookmark:representedObject];
        }
        // For NSArray
        if ([representedObject isKindOfClass:[NSArray class]]) {
            // Open bookmarks
            [self openInTabsBookmarks:representedObject];
        }
    }
}

- (void)deleteBookmarkAction:(id)sender
{
    // For NSMenuItem
    if ([sender respondsToSelector:@selector(representedObject)]) {
        id  representedObject;
        representedObject = [sender representedObject];
        
        // For SRBookmark
        if ([representedObject isKindOfClass:[SRBookmark class]]) {
            // Get parent
            SRBookmark* parent;
            parent = [[SRBookmarkStorage sharedInstance] parentOfBookmark:representedObject];
            
            if (parent) {
                // Remove bookmark
                [parent removeChild:representedObject];
            }
        }
        // For NSArray
        if ([representedObject isKindOfClass:[NSArray class]]) {
            [[[SRBookmarkStorage sharedInstance] rootBookmark] removeChildren:representedObject];
        }
    }
}

- (void)openBookmarkBarAtAction:(id)sender
{
    // For NSEvent
    if ([sender isKindOfClass:[NSEvent class]]) {
        // Get unicode character
        NSString*   characters;
        unichar     unicodeChar = 0;
        characters = [(NSEvent*)sender characters];
        if (characters && [characters length] > 0) {
            unicodeChar = [characters characterAtIndex:0];
        }
        
        // Get index for bookmark bar
        int index = -1;
        if (unicodeChar >= '1' && unicodeChar <= '9') {
            index = unicodeChar - '1';
        }
        else if (unicodeChar == '0') {
            index = 10;
        }
        if (index < 0) {
            return;
        }
        
        // Get bookmarks bar
        SRBookmark* bookmarksBar;
        bookmarksBar = [_bookmarksBarView bookmarksBar];
        if (!bookmarksBar) {
            return;
        }
        
        // Get bookmark
        NSArray*    children;
        SRBookmark* bookmark;
        children = [bookmarksBar children];
        if (!children || [children count] < index) {
            return;
        }
        bookmark = [children objectAtIndex:index];
        
        // Open bookmark
        if ([bookmark type] == SRBookmarkTypeHTML || 
            [bookmark type] == SRBookmarkTypeRSS)
        {
            [self openBookmark:bookmark];
            return;
        }
        if ([bookmark isFolderType] && [bookmark isAutoTab]) {
            [self openInTabsBookmark:bookmark];
            return;
        }
    }
}

- (void)openLinkInNewTabAction:(id)sender
{
    // For NSMenuItem
    if ([sender respondsToSelector:@selector(representedObject)]) {
        id  representedObject;
        representedObject = [sender representedObject];
        
        // For NSURL
        if ([representedObject isKindOfClass:[NSURL class]]) {
            // Open request in new tab
            [self openInNewTabURL:representedObject select:YES];
        }
    }
}

- (void)openLinkInNewBackgroundTabAction:(id)sender
{
    // For NSMenuItem
    if ([sender respondsToSelector:@selector(representedObject)]) {
        id  representedObject;
        representedObject = [sender representedObject];
        
        // For NSURL
        if ([representedObject isKindOfClass:[NSURL class]]) {
            // Open request in new tab
            [self openInNewTabURL:representedObject select:NO];
        }
    }
}

- (void)openLinkInNewWindowAction:(id)sender
{
    // For NSMenuItem
    if ([sender respondsToSelector:@selector(representedObject)]) {
        id  representedObject;
        representedObject = [sender representedObject];
        
        // For NSURL
        if ([representedObject isKindOfClass:[NSURL class]]) {
            // Open request in new window
            [self openInNewWindowURL:representedObject];
        }
    }
}

- (void)openLinkInNewBackgroundWindowAction:(id)sender
{
    // For NSMenuItem
    if ([sender respondsToSelector:@selector(representedObject)]) {
        id  representedObject;
        representedObject = [sender representedObject];
        
        // For NSURL
        if ([representedObject isKindOfClass:[NSURL class]]) {
            // Open request in new backround window
            [self openInNewBackgroundWindowURL:representedObject];
        }
    }
}

- (void)openAllLinksInNewTabsAction:(id)sender
{
    // For NSMenuItem
    if ([sender respondsToSelector:@selector(representedObject)]) {
        id  representedObject;
        representedObject = [sender representedObject];
        
        // For NSArray
        if ([representedObject isKindOfClass:[NSArray class]]) {
            // Open request in new tabs
            [self openInNewTabsURLStrings:representedObject select:YES];
        }
    }
}

- (void)openAllLinksInNewBackgroundTabsAction:(id)sender
{
    // For NSMenuItem
    if ([sender respondsToSelector:@selector(representedObject)]) {
        id  representedObject;
        representedObject = [sender representedObject];
        
        // For NSArray
        if ([representedObject isKindOfClass:[NSArray class]]) {
            // Open request in background tabs
            [self openInNewTabsURLStrings:representedObject select:NO];
        }
    }
}

- (void)openHistoryAction:(id)sender
{
    WebHistoryItem* historyItem = nil;
    
    // For NSMenuItem
    if ([sender respondsToSelector:@selector(representedObject)]) {
        id  representedObject;
        representedObject = [sender representedObject];
        
        // For WebHistoryItem
        if ([representedObject isKindOfClass:[WebHistoryItem class]]) {
            historyItem = representedObject;
        }
    }
    
    if (!historyItem) {
        return;
    }
    
    // Open hisory item
    [self openHistory:historyItem];
}

- (void)openHistoryInNewWindowAction:(id)sender
{
    WebHistoryItem* historyItem = nil;
    
    // For NSMenuItem
    if ([sender respondsToSelector:@selector(representedObject)]) {
        id  representedObject;
        representedObject = [sender representedObject];
        
        // For WebHistoryItem
        if ([representedObject isKindOfClass:[WebHistoryItem class]]) {
            historyItem = representedObject;
        }
    }
    
    if (!historyItem) {
        return;
    }
    
    // Open hisory item in new window
    [self openInNewWindowHistory:historyItem];
}

- (void)openHistoryInNewTabAction:(id)sender
{
    WebHistoryItem* historyItem = nil;
    
    // For NSMenuItem
    if ([sender respondsToSelector:@selector(representedObject)]) {
        id  representedObject;
        representedObject = [sender representedObject];
        
        // For WebHistoryItem
        if ([representedObject isKindOfClass:[WebHistoryItem class]]) {
            historyItem = representedObject;
        }
    }
    
    if (!historyItem) {
        return;
    }
    
    // Open hisory item in new tab
    [self openInNewTabHistory:historyItem];
}

- (void)openHistoryInTabsAction:(id)sender
{
    NSArray*    historyItems = nil;
    
    // For NSMenuItem
    if ([sender respondsToSelector:@selector(representedObject)]) {
        id  representedObject;
        representedObject = [sender representedObject];
        
        // For NSArray
        if ([representedObject isKindOfClass:[NSArray class]]) {
            historyItems = representedObject;
        }
    }
    
    if (!historyItems) {
        return;
    }
    
    // Open hisory items in tabs
    [self openInTabsHistory:historyItems];
}

- (void)openHistoryInNewBackgroundWindowAction:(id)sender
{
    WebHistoryItem* historyItem = nil;
    
    // For NSMenuItem
    if ([sender respondsToSelector:@selector(representedObject)]) {
        id  representedObject;
        representedObject = [sender representedObject];
        
        // For WebHistoryItem
        if ([representedObject isKindOfClass:[WebHistoryItem class]]) {
            historyItem = representedObject;
        }
    }
    
    if (!historyItem) {
        return;
    }
    
    // Open hisory item in new background window
    [self openInNewBackgroundWindowHistory:historyItem];
}

- (void)openHistoryInNewBackgroundTabAction:(id)sender
{
    WebHistoryItem* historyItem = nil;
    
    // For NSMenuItem
    if ([sender respondsToSelector:@selector(representedObject)]) {
        id  representedObject;
        representedObject = [sender representedObject];
        
        // For WebHistoryItem
        if ([representedObject isKindOfClass:[WebHistoryItem class]]) {
            historyItem = representedObject;
        }
    }
    
    if (!historyItem) {
        return;
    }
    
    // Open hisory item in new background tab
    [self openInNewTabHistory:historyItem select:NO];
}

- (void)deleteHistoryAction:(id)sender
{
    // For NSMenuItem
    if ([sender respondsToSelector:@selector(representedObject)]) {
        id  representedObject;
        representedObject = [sender representedObject];
        
        // For WebHistoryItem
        if ([representedObject isKindOfClass:[WebHistoryItem class]]) {
            // Remove history item
            [[WebHistory optionalSharedHistory] removeItems:[NSArray arrayWithObject:representedObject]];
        }
        // For NSArray
        if ([representedObject isKindOfClass:[NSArray class]]) {
            // Remove history items
            [[WebHistory optionalSharedHistory] removeItems:representedObject];
        }
    }
}

- (void)addToBookmarkAction:(id)sender
{
    // Get current page URL, title
    NSString*   URLString = nil;
    NSString*   title;
    
    // For RSS
    BOOL    isRSS = NO;
    
    // For NSMenuItem
    if ([sender respondsToSelector:@selector(representedObject)]) {
        id  representedObject;
        representedObject = [sender representedObject];
        
        // For NSDictionary
        if ([representedObject isKindOfClass:[NSDictionary class]]) {
            // Get URL and title
            NSURL*      linkURL;
            linkURL = [representedObject objectForKey:WebElementLinkURLKey];
            URLString = [linkURL _web_userVisibleString];
            if (!URLString) {
                return;
            }
            title = [representedObject objectForKey:WebElementLinkLabelKey];
            if (!title) {
                title = URLString;
            }
        }
    }
    // Get address from selected web view
    if (!URLString) {
        // Get request and page info
        WebDataSource*  dataSource;
        NSURLRequest*   request;
        dataSource = [[[self selectedWebView] mainFrame] dataSource];
        request = [dataSource request];
        if (!request) {
            return;
        }
        URLString = [[request URL] _web_userVisibleString];
        title = [dataSource pageTitle];
        if (!title) {
            title = URLString;
        }
        
        // Get MIME type
        NSURLResponse*  response;
        NSString*       MIMEType;
        response = [dataSource response];
        MIMEType = [response MIMEType];
        if ([[SRRSSRepresentation RSSMimes] containsObject:MIMEType]) {
            isRSS = YES;
        }
    }
    
    // Set title to add bookmark text field
    NSText* text;
    text = [[self addBookmarkTextField] currentEditor];
    [[self addBookmarkTextField] setStringValue:title];
    [text moveToBeginningOfDocument:self];
    [text selectAll:self];
    
    // Create bookmark for adding
    // Note that this bookmark is retained
    // It will be released in _didEndAddBookmarkSheet:returnCode:contextInfo
    SRBookmark* bookmark;
    bookmark = [SRBookmark bookmarkWithTitle:title 
            URLString:URLString 
            originalBrowser:SRBrowserShiira];
    [bookmark retain];
    
    // For RSS
    if (isRSS) {
        [bookmark setType:SRBookmarkTypeRSS];
    }
    
    // Set bookmark menu
    NSMenu* bookmarkMenu;
    bookmarkMenu = [[SRBookmarkStorage sharedInstance] bookmarkFolderMenu];
    [[self addBookmarkPopup] removeAllItems];
    [[self addBookmarkPopup] setMenu:bookmarkMenu];
    
    // Show add bookmark panel
    [NSApp beginSheet:[self addBookmarkPanel] 
            modalForWindow:[self window] 
            modalDelegate:self 
            didEndSelector:@selector(_didEndAddBookmarkSheet:returnCode:contextInfo:) 
            contextInfo:(void*)bookmark];
}

- (void)_didEndAddBookmarkSheet:(NSPanel*)sheet 
        returnCode:(int)returnCode 
        contextInfo:(void*)contextInfo
{
    // Close sheet
    [sheet orderOut:self];
    
    if (returnCode == _OK_BUTTON_TAG) {
        // Get bookmark and parent
        SRBookmark* bookmark;
        SRBookmark* parent;
        bookmark = (SRBookmark*)contextInfo;
        parent = [[[self addBookmarkPopup] selectedItem] representedObject];
        
        // Get bookmark title
        NSString*   title;
        title = [[self addBookmarkTextField] stringValue];
        if (title && [title length] > 0) {
            [bookmark setTitle:title];
        }
        
        // Add bookmark
        SRBookmark* rootBookmark;
        rootBookmark = [[SRBookmarkStorage sharedInstance] rootBookmark];
        if (rootBookmark != parent) {
            [parent addChild:bookmark];
        }
        else {
            NSArray*    children;
            int         i;
            children = [parent children];
            for (i = 0; i < [children count]; i++) {
                if (![[children objectAtIndex:i] isMutable]) {
                    break;
                }
            }
            if (i < 0 || i > [children count]) {
                i = [children count];
            }
            
            [parent insertChild:bookmark atIndex:i];
        }
    }
    
    // Release bookmark
    [(id)contextInfo release];
}

- (void)closeAddBookmarkSheetAction:(id)sender
{
    // Close sheet
    [NSApp endSheet:[self addBookmarkPanel] returnCode:[sender tag]];
}

- (void)addToBookmarksBarAction:(id)sender
{
}

- (void)closeAddToBarSheetAction:(id)sender
{
}

- (void)showNewFolderAction:(id)sender
{
    // Show new folder dialog as modal
    int result;
    result = [NSApp runModalForWindow:[self newFolderPanel]];
    [[self newFolderPanel] orderOut:self];
    if (result != _OK_BUTTON_TAG) {
        return;
    }
    
    // Get folder name
    NSString*   folderName;
    folderName = [[self newFolderTextField] stringValue];
    if (!folderName || [folderName length] == 0) {
        return;
    }
    
    //
    // Create new bookmark folder
    //
    
    // Get bookmark popup
    NSPopUpButton*  popup = nil;
    if ([[self addBookmarkPanel] isVisible]) {
        popup = [self addBookmarkPopup];
    }
    if ([[self bookmarkAllPanel] isVisible]) {
        popup = [self bookmarkAllPopup];
    }
    if (!popup) {
        return;
    }
    
    // Get parent bookmark folder
    SRBookmark* parent = nil;
    parent = [[popup selectedItem] representedObject];
    if (!parent) {
        return;
    }
    
    // For immutable bookmark folder
    if (![parent isMutable]) {
        // Get root folder
        parent = [[SRBookmarkStorage sharedInstance] rootBookmark];
    }
    
    // Add bookmark folder
    SRBookmark* folder;
    folder = [SRBookmark folderWithTitle:folderName 
            originalBrowser:SRBrowserShiira];
    if (parent == [[SRBookmarkStorage sharedInstance] rootBookmark]) {
        // Insert it before immutable folders
        NSArray*    children;
        int         index;
        children = [parent children];
        for (index = 0; index < [children count]; index++) {
            SRBookmark* child;
            child = [children objectAtIndex:index];
            if (![child isMutable]) {
                break;
            }
        }
        
        [parent insertChild:folder atIndex:index];
    }
    else {
        [parent addChild:folder];
    }
    
    // Update bookmark popup
    NSMenu* bookmarkMenu;
    bookmarkMenu = [[SRBookmarkStorage sharedInstance] bookmarkFolderMenu];
    [popup removeAllItems];
    [popup setMenu:bookmarkMenu];
    
    // Select new one
    int index;
    index = [popup indexOfItemWithRepresentedObject:folder];
    if (index != -1) {
        [popup selectItemAtIndex:index];
    }
}

- (void)closeNewFolderPanelAction:(id)sender
{
    // Cloase new folder panel
    [NSApp stopModalWithCode:[sender tag]];
}

- (void)findBySearchEngineAction:(id)sender
{
    if (![self searchField]) {
        return;
    }
    
    // Get web view
    WebView*    webView;
    webView = [self selectedWebView];
    if (!webView) {
        return;
    }
    
    // Get information for search
    NSDictionary*   searchItem;
    NSString*       searchString;
    NSString*       engineName;
    NSString*       URLString;
    searchItem = [sender representedObject];
    searchString = [searchItem objectForKey:@"string"];
    engineName = [searchItem objectForKey:@"title"];
    URLString = [searchItem objectForKey:@"URLString"];
    
    // Add to recent item
    [[SRSearchEnginesManager sharedInstance] addRecentWord:searchString 
            engineName:engineName 
            URLString:URLString];
    
    // Search string with current modifierFlags
    SROpenActionType    openAction;
    openAction = SROpenActionTypeFromModifierFlags([[NSApp currentEvent] modifierFlags]);
    if(openAction == SROpenOptionAction){
        openAction = SROpenAction;
    }
    [self openURLString:URLString withOpenAction:openAction];
}

- (IBAction)showDownloadsAction:(id)sender
{
    // Open sidebar
    if([[_sideBarController drawer] state] != NSDrawerOpenState) {
        [self setSidebarVisible:YES];
    }
    
    // Show download tab
    if ([_sideBarController selectedTab] != SRSidebarDownloadTab) {
        [_sideBarController showTab:SRSidebarDownloadTab];
    }
}

- (IBAction)toggleDownloadsAction:(id)sender
{
    if(([[_sideBarController drawer] state] == NSDrawerOpenState) && 
       ([_sideBarController selectedTab] == SRSidebarDownloadTab))
    {
        [[_sideBarController drawer] close];
    }
    else {
        // Open sidebar
        [self setSidebarVisible:YES];
        
        // Show download tab
        [_sideBarController showTab:SRSidebarDownloadTab];
    }
}

- (void)copyImageURLToClipboardAction:(id)sender
{
    if ([sender respondsToSelector:@selector(representedObject)]) {
        id  representedObject;
        representedObject = [sender representedObject];
        
        // For NSURL
        if ([representedObject isKindOfClass:[NSURL class]]) {
            NSPasteboard*   pb;
            pb = [NSPasteboard generalPasteboard];
            
            [pb declareTypes:[NSArray arrayWithObjects:NSStringPboardType,NSURLPboardType,nil] owner:nil];
            [representedObject writeToPasteboard:pb];
            [pb setString:[representedObject _web_userVisibleString] forType:NSStringPboardType];
        }
    }
}

- (void)openURLWithAction:(id)sender
{
    if ([sender respondsToSelector:@selector(representedObject)]) {
        id  representedObject;
        representedObject = [sender representedObject];
        
        // For NSURL
        if ([representedObject isKindOfClass:[NSURL class]]) {
            // Get bundle identifier
            NSString*   bundleId;
            bundleId = [[NSBundle bundleWithPath:[representedObject path]] bundleIdentifier];
            if (!bundleId) {
                return;
            }
            
            // Get current URL
            NSURL*  url;
            url = [[[[[self selectedWebView] mainFrame] dataSource] request] URL];
            if (!url) {
                return;
            }
            
            // Open URL
            [[NSWorkspace sharedWorkspace] 
                    openURLs:[NSArray arrayWithObject:url] 
                    withAppBundleIdentifier:bundleId 
                    options:0 
                    additionalEventParamDescriptor:nil 
                    launchIdentifiers:nil];
        }
    }
}

- (void)printPageAsPDFAction:(id)sender
{
    // Get selected web view and document view
    WebView*    webView;
    NSView*     documentView;
    webView = [self selectedWebView];
    documentView = [[[webView mainFrame] frameView] documentView];
    if (!documentView) {
        return;
    }
    
    // Get title
    NSString*   title;
    title = [[[webView mainFrame] dataSource] pageTitle];
    if (!title || [title length] == 0) {
        title = NSLocalizedString(@"Untitled", @"Untitled");
    }
    
    // Get accessory view
    SRMainDocument* document;
    NSView*         accessoryView;
    document = [self document];
    accessoryView = [document printAccessoryView];
    
    // Set properties of print panel
    WebPreferences* preferences;
    preferences = [SRPreferencesController defaultWebPreferences];
    [document setValue:[NSNumber numberWithBool:[preferences shouldPrintBackgrounds]] 
            forKey:@"printBackground"];
    
    // Show save dialog
    NSSavePanel*    savePanel;
    savePanel = [NSSavePanel savePanel];
    [savePanel setAccessoryView:accessoryView];
    [savePanel beginSheetForDirectory:nil 
            file:[title stringByAppendingPathExtension:@"pdf"] 
            modalForWindow:[self window] 
            modalDelegate:self 
            didEndSelector:@selector(didEndPrintPageAsPDFPanel:returnCode:contextInfo:) 
            contextInfo:NULL];
}

- (void)didEndPrintPageAsPDFPanel:(NSSavePanel*)sheet 
        returnCode:(int)returnCode 
        contextInfo:(void*)contextInfo
{
    if (returnCode != NSOKButton) {
        return;
    }
    
    // Get selected web view and document view
    WebView*    webView;
    NSView*     documentView;
    webView = [self selectedWebView];
    documentView = [[[webView mainFrame] frameView] documentView];
    if (!documentView) {
        return;
    }
    
    // Get file name
    NSString*   fileName;
    fileName = [sheet filename];
    if (!fileName) {
        return;
    }
    
    // Print page as a PDF
    [[documentView dataWithPDFInsideRect:[documentView frame]] 
            writeToFile:fileName atomically:YES];
}

- (void)showAllTabsAction:(id)sender
{
    // Deexpose
    if ([SRTabExposeController isExposing]) {
        [_tabExposeController deexpose];
        return;
    }
    
    // Check number of tab
    if ([_srTabView numberOfItems] < 2) {
        return;
    }
    
    // Expose
    [_tabExposeController exposeWithTabView:_srTabView];
}

- (void)toggleURLIDNAction:(id)sender
{
    // Get URL combo box
    SRURLComboBox*  comboBox;
    comboBox = [self URLComboBox];
    if (!comboBox) {
        return;
    }
    
    // Check URL string
    if ([_webViewURLString length] > 0) {
        // Create NSURL
        NSURL*  url;
        url = [NSURL _web_URLWithUserTypedString:_webViewURLString];
        
        // Use Punycode
        NSString*   URLString;
        URLString = [url _web_userVisibleString];
        if (![_webViewURLString isEqualToString:URLString]) {
            [self setValue:URLString forKey:SRMainWebViewURLString];
            return;
        }
        
        // Use ASCII
        URLString = [url absoluteString];
        if (![_webViewURLString isEqualToString:URLString]) {
            [self setValue:URLString forKey:SRMainWebViewURLString];
            return;
        }
    }
}

- (void)toggleSmallURLAndSearchFieldAction:(id)sender
{
    NSUserDefaults* defaults;
    defaults = [NSUserDefaults standardUserDefaults];
    
    // Check default
    BOOL    useSmall;
    useSmall = [defaults boolForKey:SRToolbarUseSmallURLAndSearchField];
    
    // Toggle it
    useSmall = !useSmall;
    
    NSControlSize   controlSize;
    NSFont*         font;
    if (useSmall) {
        controlSize = NSSmallControlSize;
        font = [NSFont systemFontOfSize:[NSFont smallSystemFontSize]];
    }
    else {
        controlSize = NSRegularControlSize;
        font = [NSFont systemFontOfSize:[NSFont systemFontSize]];
    }
    
    // Toggle URL combo box size
    SRURLComboBox*  URLComboBox;
    URLComboBox = [self URLComboBox];
    if (URLComboBox) {
        NSRect  frame;
        frame = [URLComboBox frame];
        
        [[URLComboBox cell] setControlSize:controlSize];
        [URLComboBox setFont:font];
        [URLComboBox sizeToFit];
        frame.size.height = [URLComboBox frame].size.height;
        [URLComboBox setFrame:frame];
        
        NSToolbarItem*  item;
        item = [[[self window] toolbar] toolbarItemWithIdentifier:SRURLIdentifier];
        [item setMinSize:NSMakeSize(SRURLMinWidth, [URLComboBox frame].size.height)];
        [item setMaxSize:NSMakeSize(SRURLMaxWidth, [URLComboBox frame].size.height)];
    }
    
    // Toggle search field size
    SRSearchField*  searchField;
    searchField = [self searchField];
    if (searchField) {
        NSRect  frame;
        frame = [searchField frame];
        
        [[searchField cell] setControlSize:controlSize];
        [searchField setFont:font];
        [searchField sizeToFit];
        frame.size.height = [searchField frame].size.height;
        [searchField setFrame:frame];
        
        NSToolbarItem*  item;
        item = [[[self window] toolbar] toolbarItemWithIdentifier:SRSearchIdentifier];
        [item setMinSize:NSMakeSize(SRSearchMinWidth, [searchField frame].size.height)];
        [item setMaxSize:NSMakeSize(SRSearchMaxWidth, [searchField frame].size.height)];
    }
    
    // Set it default
    [defaults setBool:useSmall forKey:SRToolbarUseSmallURLAndSearchField];
}

- (void)selectBrowseModeAction:(id)sender
{
    int tag = 0;
    
    // For NSPopUpButton
    if ([sender respondsToSelector:@selector(selectedItem)]) {
        // Get tag
        id<NSMenuItem>  item;
        item = [sender selectedItem];
        tag = [item tag];
    }
    // For NSMenuItem
    else if ([sender respondsToSelector:@selector(tag)]) {
        tag = [sender tag];
    }
    
    // Select browse mode
    if (tag >= SRDefaultBrowseMode && tag <= SRAlwaysInNewBackgroundTabBrowseMode) {
        [[NSUserDefaults standardUserDefaults] setInteger:tag forKey:SRBrowseMode];
    }
}

- (void)switchToFullScreenModeAction:(id)sender
{
    [self switchToFullScreenModeWithMenu:NO];
}

- (void)switchToFullScreenModeWithMenuAction:(id)sender
{
    [self switchToFullScreenModeWithMenu:YES];
}

- (void)showRSSAction:(id)sender
{
    // Get RSS links
    NSArray*    links;
    links = [self RSSLinksAtWebView:[self selectedWebView]];
    if (!links || [links count] < 1) {
        return;
    }
    
    // Get RSS link
    NSString*   link;
    link = [links objectAtIndex:0];
    if (![link hasPrefix:@"http://"]) {
        // It might be relative link
        WebDataSource*  dataSource;
        dataSource = [[[self selectedWebView] mainFrame] dataSource];
        if (!dataSource) {
            dataSource = [[[self selectedWebView] mainFrame] provisionalDataSource];
        }
        
        NSURL*  absoluteURL;
        absoluteURL = [NSURL URLWithString:link relativeToURL:[[dataSource request] URL]];
        link = [absoluteURL absoluteString];
    }
    
    // Open RSS in HTML
    [self openURLString:link];
}

@end
