/*
SRMainWindowController.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 "SRRSSManager.h"

#import "SREncodings.h"

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

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

// Toolbar items
static NSArray* _toolbarItemIdentifiers = nil;
static NSArray* _toolbarDefaultItemIdentifiers = nil;

// Toolbar identifier
NSString*   SRMainWindowToolbarIdentifier = @"SRMainWindowToolbarIdentifier";

// Toolbar item identifier
NSString*   SRGoBackIdentifier = @"SRGoBack";
NSString*   SRGoForwardIdentifier = @"SRGoForward";
NSString*   SRReloadPageIdentifier = @"SRReloadPage";
NSString*   SRStopLoadingIdentifier = @"SRStopLoading";
NSString*   SRGoHomeIdentifier = @"SRGoHome";
NSString*   SRURLIdentifier = @"SRURL";
NSString*   SRSidebarIdentifier = @"SRSidebar";
NSString*   SRHideSidebarIdentifier = @"SRHideSidebar";
NSString*   SRBookmarkPageIdentifier = @"SRBookmarkPage";
NSString*   SRNewTabIdentifier = @"SRNewTab";
NSString*   SRCloseTabIdentifier = @"SRCloseTab";
NSString*   SRBiggerTextIdentifier = @"SRBiggerText";
NSString*   SRSmallerTextIdentifier = @"SRSmallerText";
NSString*   SRCustomizeIdentifier = @"SRCustomize";
NSString*   SRSearchIdentifier = @"SRSearch";
NSString*   SRBrowseIdentifier = @"SRBrowse";
NSString*   SRBrowseDefaultIdentifier = @"SRBrowseDefault";
NSString*   SRBrowseTabIdentifier = @"SRBrowseTab";
NSString*   SRBrowseNewTabIdentifier = @"SRBrowseNewTab";
NSString*   SRBrowseBackTabIdentifier = @"SRBrowseBackTab";

NSString*   SRMainToolbarLabelTable = @"MainToolbar";

// Key path
NSString*   SRMainWebViewTitle = @"webViewTitle";
NSString*   SRMainWebViewURLString = @"webViewURLString";
NSString*   SRMainWebViewIsLoading = @"webViewIsLoading";
NSString*   SRMainWebViewIsIndeterminate = @"webViewIsIndeterminate";
NSString*   SRMainWebViewEstimatedProgress = @"webViewEstimatedProgress";
NSString*   SRMainWebViewStatus = @"webViewStatus";
NSString*   SRMainWebViewIsSecured = @"webViewIsSecured";

NSString*   SRMainWindowGoToHistotyItem = @"SRMainWindowGoToHistotyItem";
NSString*   SRMainWindowSelectedWebViewChanged = @"SRMainWindowSelectedWebViewChanged";
NSString*   SRMainWindowDidChangeLocationWithinPage = @"SRMainWindowDidChangeLocationWithinPage";
NSString*   SRMainWindowDidBecomeMain = @"SRMainWindowDidBecomeMain";
NSString*   SRMainWindowDidResignMain = @"SRMainWindowDidResignMain";
NSString*   SRMainWindowWillClose = @"SRMainWindowWillClose";

// Toolbar icons
static NSDictionary*    _iconImageDict = nil;

// URL location
int         SRURLMinWidth = 48;
int         SRURLMaxWidth = 1024;

// Search field
int         SRSearchMinWidth = 48;
int         SRSearchMaxWidth = 128;

// Browse mode
int         SRBrowseSmallWidth = 56;
int         SRBrowseSmallHeight = 24;
int         SRBrowseLargeWidth = 56;
int         SRBrowseLargeHeight = 32;

// URL button tags
enum {
    SRURLButtonIDN = 0, 
};

@interface SRMainWindowController (private)
- (void)_setUserAgentOfWebView:(WebView*)webView;
@end

#pragma mark -

@implementation SRMainWindowController

//--------------------------------------------------------------//
#pragma mark -- Initialize --
//--------------------------------------------------------------//

- (id)initWithWindowNibName:(NSString*)nibName 
        initialFrameName:(NSString*)frameName 
        initialGroupName:(NSString*)groupName
{
    NSUserDefaults* defaults;
    defaults = [NSUserDefaults standardUserDefaults];
    
    self = [super initWithWindowNibName:nibName];
    if (!self) {
        return nil;
    }
    
    static  BOOL    _isInitialized = NO;
    if (!_isInitialized) {
        // Create toolbar item identifiers
        _toolbarItemIdentifiers = [[NSArray arrayWithObjects:
            SRGoBackIdentifier, SRGoForwardIdentifier, SRReloadPageIdentifier, SRStopLoadingIdentifier, 
            SRGoHomeIdentifier, SRURLIdentifier, SRSidebarIdentifier, SRBookmarkPageIdentifier, 
            SRNewTabIdentifier, SRCloseTabIdentifier, SRBiggerTextIdentifier, SRSmallerTextIdentifier, 
            SRCustomizeIdentifier, SRSearchIdentifier, SRBrowseIdentifier, 
            NSToolbarSeparatorItemIdentifier, NSToolbarSpaceItemIdentifier, 
            NSToolbarFlexibleSpaceItemIdentifier, NSToolbarPrintItemIdentifier, nil] retain];
        _toolbarDefaultItemIdentifiers = [[NSArray arrayWithObjects:
            SRGoBackIdentifier, SRGoForwardIdentifier, SRReloadPageIdentifier, SRStopLoadingIdentifier, 
            SRURLIdentifier, SRSearchIdentifier, SRSidebarIdentifier, 
            nil] retain];
    }
    
    // Load nib file    
    _sideBarController = [[SRSideBarController alloc] initWithMainWindowController:self];
    if (![NSBundle loadNibNamed:@"SideBar" owner:_sideBarController]) {
        // Fatal error
        SR_FATAL(@"Could not load SideBar.nib");
    }
    
    // Configure tab view
    [self addNewTabWithLabel:NSLocalizedString(@"Untitled", @"Untitled") 
            frameName:frameName 
            groupName:groupName];
    [_srTabView selectItemAtIndex:0];
    [_srTabView setDelegate:self];
    [_srTabView setTabShown:[defaults boolForKey:SRTabEnableTabbedBrowsing]];
    [_srTabView setTabShownAlways:[defaults boolForKey:SRTabAlwaysShowTabBar]];
    [_srTabView setAccordingToStringWidth:[defaults boolForKey:SRTabAccordingToStringWidth]];
    [[_srTabView tabBarView] setCellClassWithName:[defaults stringForKey:SRTabStyleClassName]];
    [[_srTabView tabBarView] setFont:[NSFont boldSystemFontOfSize:11.0]];
    
    // Initialize instance variables
    _isResizedByJavaScript = NO;
    _isInitializedSidebarVisibility = NO;
    _isFullScreenMode = NO;
    
    SRSearchField*  searchField;
    searchField = [self searchField];
    _searchFieldController = [[SRSearchFieldController alloc] initWithMainWindowController:self];
    [_searchFieldController setSearchField:searchField];
    [searchField setTarget:_searchFieldController];
    
    _tabExposeController = [[SRTabExposeController alloc] init];
    _searchingURLDict = [[NSMutableDictionary alloc] init];
    
    // Initialize properties
    [self setValue:NSLocalizedString(@"Untitled", @"Untitled") forKey:SRMainWebViewTitle];
    [self setValue:@"" forKey:SRMainWebViewURLString];
    [self setValue:[NSNumber numberWithBool:NO] forKey:SRMainWebViewIsLoading];
    [self setValue:[NSNumber numberWithBool:NO] forKey:SRMainWebViewIsIndeterminate];
    [self setValue:[NSNumber numberWithDouble:0.0] forKey:SRMainWebViewEstimatedProgress];
    [self setValue:@"" forKey:SRMainWebViewStatus];
    [self setValue:[NSNumber numberWithBool:NO] forKey:SRMainWebViewIsSecured];
    
    // Open default page
    int defaultPage;
    defaultPage = [defaults integerForKey:SRGeneralNewWindowsOpenWith];
    switch (defaultPage) {
    case SRGeneralNewWindowsOpenWithHomePage: {
        // Go Home
        [self goHomeAction:self];
        break;
    }
    case SRGeneralNewWindowsOpenWithSamePage: {
        // Get front window
        NSWindow*   frontWindow;
        frontWindow = SRGetFrontMainWindow();
        if (frontWindow) {
            // Get request
            NSURLRequest*   request;
            request = [[[[[frontWindow windowController] selectedWebView] 
                    mainFrame] dataSource] request];
            
            // Open request
            [self openRequest:request];
            break;
        }
        break;
    }
    }
    
    // Register notifications
    NSNotificationCenter*   center;
    center = [NSNotificationCenter defaultCenter];
    [center addObserver:self 
            selector:@selector(webViewProgressStarted:) name:WebViewProgressStartedNotification object:nil];
    [center addObserver:self 
            selector:@selector(webViewProgressEstimateChanged:) name:WebViewProgressEstimateChangedNotification object:nil];
    [center addObserver:self 
            selector:@selector(webViewProgressFinished:) name:WebViewProgressFinishedNotification object:nil];
    
    [center addObserver:self 
            selector:@selector(webImageSizeChanged:) name:SRWebImageSizeChangeNotification object:nil];
    
    [center addObserver:self 
            selector:@selector(bookmarkUpdated:) name:SRBookmarkAddedNotificationName object:nil];
    [center addObserver:self 
            selector:@selector(bookmarkUpdated:) name:SRBookmarkRemovedNotificationName object:nil];
    [center addObserver:self 
            selector:@selector(bookmarkUpdated:) name:SRBookmarkChangedNotificationName object:nil];
    
    [center addObserver:self 
            selector:@selector(faviconAdded:) name:WebIconDatabaseDidAddIconNotification object:nil];
    
    // Register key value observation
    [defaults addObserver:self 
            forKeyPath:SRBookmarkBookmarksBar options:NSKeyValueObservingOptionNew context:NULL];
    [defaults addObserver:self 
            forKeyPath:SRTabEnableTabbedBrowsing options:NSKeyValueObservingOptionNew context:NULL];
    [defaults addObserver:self 
            forKeyPath:SRTabSelectNewTabs options:NSKeyValueObservingOptionNew context:NULL];
    [defaults addObserver:self 
            forKeyPath:SRTabAlwaysShowTabBar options:NSKeyValueObservingOptionNew context:NULL];
    [defaults addObserver:self 
            forKeyPath:SRTabAccordingToStringWidth options:NSKeyValueObservingOptionNew context:NULL];
    [defaults addObserver:self 
            forKeyPath:SRUserAgent options:NSKeyValueObservingOptionNew context:NULL];
    [defaults addObserver:self 
            forKeyPath:SRUserAgentOtherName options:NSKeyValueObservingOptionNew context:NULL];
    [defaults addObserver:self 
            forKeyPath:SRIconName options:NSKeyValueObservingOptionNew context:NULL];
    [defaults addObserver:self 
            forKeyPath:SRIconMetalName options:NSKeyValueObservingOptionNew context:NULL];
    [defaults addObserver:self 
            forKeyPath:SRIconUseFavicon options:NSKeyValueObservingOptionNew context:NULL];
    [defaults addObserver:self 
            forKeyPath:SRIconUseFaviconBookmarkBar options:NSKeyValueObservingOptionNew context:NULL];
    [defaults addObserver:self 
            forKeyPath:SREnableJavaScirptStatusMessage options:NSKeyValueObservingOptionNew context:NULL];
    [defaults addObserver:self 
            forKeyPath:SRBrowseMode options:NSKeyValueObservingOptionNew context:NULL];
    
    [self addObserver:self 
            forKeyPath:SRMainWebViewURLString options:NSKeyValueObservingOptionNew context:NULL];
    
    return self;
}

- (void)windowDidLoad
{
    NSUserDefaults* defaults;
    defaults = [NSUserDefaults standardUserDefaults];
    
    // Get default window size
    NSString*   sizeString;
    sizeString = [defaults objectForKey:SRMainWindowContentSize];
    
    // Bookmarks bar and status bar visiblity
    [self setBookmarksBarVisible:[defaults boolForKey:SRMainWindowBookmarksBarVisible] display:NO];
    [self setStatusBarVisible:[defaults boolForKey:SRMainWindowStatusBarVisible] display:NO];
    
    // Get window
    NSWindow*   window;
    window = [self window];
    
    // Set default window size
    if (sizeString) {
        // Restore size
        NSSize  size;
        size = NSSizeFromString(sizeString);
        
        if (size.width > 200 && size.height > 200) { // Minimum size
            // Make window default size
            [window setContentSize:size];
        }
    }
    
    // For first window
    if ([[[NSDocumentController sharedDocumentController] documents] count] == 1) {
        // Get default window origin
        NSString*   originString;
        originString = [defaults objectForKey:SRMainWindowFrameOrigin];
        if (originString) {
            // Restore origin
            NSPoint origin;
            origin = NSPointFromString(originString);
            
            if (!NSEqualPoints(origin, NSZeroPoint)) {
                // Make window default origin
                [window setFrameTopLeftPoint:origin];
            }
        }
    }
    // For other windows
    else {
        // Get front window
        NSWindow*   frontWindow;
        frontWindow = SRGetFrontMainWindow();
        if (frontWindow) {
            // Calculate cascaded point
            NSRect  frontWindowFrame;
            NSPoint frontWindowPoint;
            frontWindowFrame = [frontWindow frame];
            frontWindowPoint = frontWindowFrame.origin;
            frontWindowPoint.y += frontWindowFrame.size.height;
            [window setFrameTopLeftPoint:[window cascadeTopLeftFromPoint:frontWindowPoint]];
        }
    }
    
    // Get toolbar icons
    NSString*   iconName;
    if (!([[self window] styleMask] & NSTexturedBackgroundWindowMask)) {
        iconName = [defaults stringForKey:SRIconName];
    }
    else {
        iconName = [defaults stringForKey:SRIconMetalName];
    }
    _iconImageDict = [[[[NSApp delegate] iconInstaller] iconsOfName:iconName] retain];
    
    // Create toolbar
    NSToolbar*  toolbar;
    toolbar = [[NSToolbar alloc] 
            initWithIdentifier:SRMainWindowToolbarIdentifier];
    [toolbar autorelease];
    [toolbar setDelegate:self];
    [toolbar setAllowsUserCustomization:YES];
    [toolbar setAutosavesConfiguration:YES];
    [window setToolbar:toolbar];
    
    // Check window position
    NSRect  visibleFrame;
    NSRect  windowFrame, originalFrame;
    visibleFrame = [[window screen] visibleFrame];
    windowFrame = [window frame];
    originalFrame = windowFrame;
    
    if (windowFrame.origin.x < visibleFrame.origin.x ||
        windowFrame.origin.x + windowFrame.size.width > visibleFrame.origin.x + visibleFrame.size.width)
    {
        windowFrame.origin.x = visibleFrame.origin.x;
    }
    if (windowFrame.origin.y < visibleFrame.origin.y)
    {
        windowFrame.origin.y = visibleFrame.origin.y + visibleFrame.size.height - windowFrame.size.height;
    }
    
    if (!NSEqualRects(windowFrame, originalFrame)) {
        [window setFrame:windowFrame display:YES];
    }
    
    // Create lock image view
    _lockIconView = [[NSImageView alloc] initWithFrame:
            NSMakeRect(windowFrame.size.width - 44, windowFrame.size.height - 19, 14, 16)];
    [_lockIconView setImage:[NSImage imageNamed:@"Lock"]];
    [_lockIconView setAutoresizingMask:NSViewMinXMargin | NSViewMinYMargin];
    [[[window contentView] superview] addSubview:_lockIconView];
    [_lockIconView setHidden:YES];
    
#ifdef SR_SUPPORT_RSS
    // Create RSS button
    _RSSButton = [[NSButton alloc] initWithFrame:
            NSMakeRect(windowFrame.size.width - 75, windowFrame.size.height - 18, 29, 13)];
    [_RSSButton setImage:[NSImage imageNamed:@"rss"]];
    [_RSSButton setAutoresizingMask:NSViewMinXMargin | NSViewMinYMargin];
    [_RSSButton setBordered:NO];
    [_RSSButton setAction:@selector(showRSSAction:)];
    [[[window contentView] superview] addSubview:_RSSButton];
    [_RSSButton setHidden:YES];
#endif // SR_SUPPORT_RSS
    
    // Dose not use automatic cascading
    [self setShouldCascadeWindows:NO];
    
    // Update browser of bookmarks bar
    _bookmarksBarBrowser = -1; // Dummy
    [self setBookmarksBarBrowser:
            [defaults integerForKey:SRBookmarkBookmarksBar]];
    
    // Update file menu
    [[[[NSApp mainMenu] itemWithTag:SRFileTag] submenu] update];
}

- (void)dealloc
{
    // Release controllers
    [_sideBarController release];
    [_authController release];
    [_searchFieldController release];
    [_lockIconView release];
#ifdef SR_SUPPORT_RSS
    [_RSSButton release];
#endif // RS_SUPPORT_RSS
    [_tabExposeController release];
    [_searchingURLDict release];
    [_openingBookmark release];
    
    // Remove observers
    NSUserDefaults* defaults;
    defaults = [NSUserDefaults standardUserDefaults];
    [defaults removeObserver:self forKeyPath:SRBookmarkBookmarksBar];
    [defaults removeObserver:self forKeyPath:SRTabEnableTabbedBrowsing];
    [defaults removeObserver:self forKeyPath:SRTabSelectNewTabs];
    [defaults removeObserver:self forKeyPath:SRTabAlwaysShowTabBar];
    [defaults removeObserver:self forKeyPath:SRTabAccordingToStringWidth];
    [defaults removeObserver:self forKeyPath:SRUserAgent];
    [defaults removeObserver:self forKeyPath:SRUserAgentOtherName];
    [defaults removeObserver:self forKeyPath:SRIconName];
    [defaults removeObserver:self forKeyPath:SRIconMetalName];
    [defaults removeObserver:self forKeyPath:SRIconUseFavicon];
    [defaults removeObserver:self forKeyPath:SRIconUseFaviconBookmarkBar];
    [defaults removeObserver:self forKeyPath:SRBrowseMode];
    
	[[NSNotificationCenter defaultCenter] removeObserver:self];
    
    [_srTabView setDelegate:nil];
    [[[self window] toolbar] setDelegate:nil];
    [[self searchField] setTarget:nil];
    [[self searchFieldOnSheet] setTarget:nil];
    [[self URLComboBox] setDelegate:nil];
    [[self URLComboBox] setTarget:nil];
    [[self URLComboBoxOnSheet] setDelegate:nil];
    [[self URLComboBoxOnSheet] setTarget:nil];
    
    int count, i;
    count = [_srTabView numberOfItems];
    for (i = 0; i < count; i++) {
        WebView*    webView;
        webView = (WebView*)[_srTabView viewAtIndex:i];
        [webView setFrameLoadDelegate:nil];
        [webView setResourceLoadDelegate:nil];
        [webView setPolicyDelegate:nil];
        [webView setUIDelegate:nil];
    }
    
    [super dealloc];
}

//--------------------------------------------------------------//
#pragma mark -- Controller --
//--------------------------------------------------------------//

- (SRSideBarController*)sideBarController
{
    return _sideBarController;
}

//--------------------------------------------------------------//
#pragma mark -- Outlets --
//--------------------------------------------------------------//

- (void)_loadDialogs
{
    // Load MainWindowDialogs.nib
    if (![NSBundle loadNibNamed:@"MainWindowDialogs" owner:self]) {
        // Fatal error
        SR_FATAL(@"Could not load MainWindowDialogs.nib");
    }
}

- (id)addBookmarkPanel
{
    if (!_addBookmarkPanel) {
        [self _loadDialogs];
    }
    return _addBookmarkPanel;
}

- (id)addBookmarkTextField
{
    if (!_addBookmarkTextField) {
        [self _loadDialogs];
    }
    return _addBookmarkTextField;
}

- (id)addBookmarkPopup
{
    if (!_addBookmarkPopup) {
        [self _loadDialogs];
    }
    return _addBookmarkPopup;
}

- (id)bookmarkAllPanel
{
    if (!_bookmarkAllPanel) {
        [self _loadDialogs];
    }
    return _bookmarkAllPanel;
}

- (id)bookmarkAllPopup
{
    if (!_bookmarkAllPopup) {
        [self _loadDialogs];
    }
    return _bookmarkAllPopup;
}

- (id)newFolderPanel
{
    if (!_newFolderPanel) {
        [self _loadDialogs];
    }
    return _newFolderPanel;
}

- (id)newFolderTextField
{
    if (!_newFolderTextField) {
        [self _loadDialogs];
    }
    return _newFolderTextField;
}

- (id)addToBarPanel
{
    if (!_addToBarPanel) {
        [self _loadDialogs];
    }
    return _addToBarPanel;
}

- (id)addToBarTextField
{
    if (!_addToBarTextField) {
        [self _loadDialogs];
    }
    return _addToBarTextField;
}

- (id)locationPanel
{
    if (!_locationPanel) {
        [self _loadDialogs];
    }
    return _locationPanel;
}

- (id)locationURLView
{
    if (!_locationURLView) {
        [self _loadDialogs];
    }
    return _locationURLView;
}

- (id)searchPanel
{
    if (!_searchPanel) {
        [self _loadDialogs];
    }
    return _searchPanel;
}

- (id)searchFieldView
{
    if (!_searchFieldView) {
        [self _loadDialogs];
    }
    return _searchFieldView;
}

//--------------------------------------------------------------//
#pragma mark -- Web view and toolbar items --
//--------------------------------------------------------------//

- (WebView*)selectedWebView
{
    id  view;
    view = [_srTabView viewOfSelectedTabViewItem];
    if (!view) {
        return nil;
    }
    SR_VERIFY([view isKindOfClass:[WebView class]]);
    
    return view;
}

- (SRURLComboBox*)URLComboBox
{
    // Get URL combo box from toolbar items
    NSEnumerator*   enumerator;
    NSToolbarItem*  toolbarItem;
    enumerator = [[[[self window] toolbar] visibleItems] objectEnumerator];
    while (toolbarItem = [enumerator nextObject]) {
        if ([[toolbarItem itemIdentifier] isEqualToString:SRURLIdentifier]) {
            id  view;
            view = [toolbarItem view];
            SR_VERIFY([view isKindOfClass:[SRURLComboBox class]]);
            
            return view;
        }
    }
    
    return nil;
}

- (SRURLComboBox*)URLComboBoxOnSheet
{
    // Return first children of location URL view
    NSArray*    subviews;
    subviews = [[self locationURLView] subviews];
    
    if ([subviews count] < 1) {
        return nil;
    }
    
    id  view;
    view = [subviews objectAtIndex:0];
    SR_VERIFY([view isKindOfClass:[SRURLComboBox class]]);
    
    return view;
}

- (SRSearchField*)searchField
{
    // Get search field from toolbar items
    NSEnumerator*   enumerator;
    NSToolbarItem*  toolbarItem;
    enumerator = [[[[self window] toolbar] visibleItems] objectEnumerator];
    while (toolbarItem = [enumerator nextObject]) {
        if ([[toolbarItem itemIdentifier] isEqualToString:SRSearchIdentifier]) {
            id  view;
            view = [toolbarItem view];
            SR_VERIFY([view isKindOfClass:[SRSearchField class]]);
            
            return view;
        }
    }
    
    return nil;
}

- (SRSearchField*)searchFieldOnSheet
{
    // Return first children of search field view
    NSArray*    subviews;
    subviews = [[self searchFieldView] subviews];
    
    if ([subviews count] < 1) {
        return nil;
    }
    id  view;
    view = [subviews objectAtIndex:0];
    SR_VERIFY([view isKindOfClass:[SRSearchField class]]);
    
    return view;
}

//--------------------------------------------------------------//
#pragma mark -- Tab management --
//--------------------------------------------------------------//

- (SRTabView*)srTabView
{
    return _srTabView;
}

- (WebView*)addNewTabWithLabel:(NSString*)label
        frameName:(NSString*)frameName 
        groupName:(NSString*)groupName
{
    return [self addNewTabWithLabel:label 
            frameName:frameName 
            groupName:groupName 
            select:[[NSUserDefaults standardUserDefaults] boolForKey:SRTabEnableTabbedBrowsing]];
}

- (WebView*)addNewTabWithLabel:(NSString*)label 
        frameName:(NSString*)frameName 
        groupName:(NSString*)groupName 
        select:(BOOL)select
{
    NSUserDefaults* defaults;
    defaults = [NSUserDefaults standardUserDefaults];
    
    // Create WebView
    WebView*    webView;
    webView = [[SRWebView alloc] initWithFrame:[[_srTabView tabView] frame] 
            frameName:frameName groupName:groupName];
    [webView autorelease];
    [webView setHostWindow:[self window]];  // For Plug-in, JavaScript
    [webView setFrameLoadDelegate:self];
    [webView setResourceLoadDelegate:self];
    [webView setPolicyDelegate:self];
    [webView setUIDelegate:self];
    [webView setDownloadDelegate:[SRDownloadCenter sharedInstance]];
//    [webView setPreferencesIdentifier:SRWebPreferencesIdentifier];
    [webView setPreferences:[SRPreferencesController defaultWebPreferences]];
    
    // Set user agent
    [self _setUserAgentOfWebView:webView];
    
// For force custom encoding for Japanese character code
#if 0
    // Get default encoding
    NSStringEncoding    encoding;
    encoding = [[defaults objectForKey:SRDefaultTextEncoding] unsignedIntValue];
    
    // For Jpanese encoding
    if (encoding == SRConvertedShiftJISStringEncoding || 
        encoding == SRConvertedJapaneseEUCStringEncoding || 
        encoding == SRConvertedISO2022JPStringEncoding)
    {
        // Set it as custom web view encoding
        NSValueTransformer* transformer;
        NSString*           encodingName;
        transformer = [NSValueTransformer valueTransformerForName:SRIANAToEncodingTransformerName];
        encodingName = [transformer reverseTransformedValue:
                [NSNumber numberWithUnsignedInt:encoding]];
        [webView setCustomTextEncodingName:encodingName];
    }
#endif
    
    // Dummy
    WebPreferences* pref;
    int             defaultFontSize;
    pref = [webView preferences];
    defaultFontSize = [pref defaultFontSize];
    [pref setDefaultFontSize:defaultFontSize + 1];
    [pref setDefaultFontSize:defaultFontSize];
    
    // Set icon
    if (select) {
        [[self URLComboBox] setImage:[[WebIconDatabase sharedIconDatabase] 
                defaultIconWithSize:NSMakeSize(16, 16)]];
    }
    
    // Add new tab and select
    [_srTabView addItemWithLabel:label view:webView select:select];
    
    return webView;
}

- (void)selectLeftTab
{
    // Get selected index
    int index;
    index = [_srTabView selectedIndex];
    
    // Select left tab
    if (index == 0) {
        [_srTabView selectItemAtIndex:[_srTabView numberOfItems] - 1];
    }
    else {
        [_srTabView selectItemAtIndex:index - 1];
    }
}

- (void)selectRightTab
{
    // Get selected index
    int index;
    index = [_srTabView selectedIndex];
    
    // Select right tab
    if (index == [_srTabView numberOfItems] - 1) {
        [_srTabView selectItemAtIndex:0];
    }
    else {
        [_srTabView selectItemAtIndex:index + 1];
    }
}

//--------------------------------------------------------------//
#pragma mark -- Opening page with request --
//--------------------------------------------------------------//

- (void)_openRequest:(NSURLRequest*)request atWebView:(WebView*)webView
{
    // Check scheme
    NSString*	scheme;
    NSString*   lowercase;
    scheme = [[request URL] scheme];
    lowercase = [scheme lowercaseString];
    if (scheme && ![scheme isEqualToString:lowercase]) {
        // Change scheme
        NSMutableString*    URLString;
        NSRange             range;
        URLString = [NSMutableString stringWithString:[[request URL] absoluteString]];
        range = [URLString rangeOfString:scheme];
        if (range.location != NSNotFound) {
            [URLString replaceCharactersInRange:range withString:lowercase];
        }
        
        request = [self createRequestWithURLString:URLString];
    }
    
#ifdef SR_SUPPORT_RSS
    // For feed scheme
    scheme = [[request URL] scheme];
    if ([scheme isEqualToString:@"feed"]) {
        // Change scheme
        NSMutableString*    URLString;
        NSRange             range;
        URLString = [NSMutableString stringWithString:[[request URL] absoluteString]];
        range = [URLString rangeOfString:scheme];
        if (range.location != NSNotFound) {
            [URLString replaceCharactersInRange:range withString:@"http"];
        }
        
        request = [self createRequestWithURLString:URLString];
    }
#endif // SR_SUPPORT_RSS
    
    // Do JavaScript
    NSString*   URLString;
    URLString = [[request URL] absoluteString];
    if ([URLString hasPrefix:@"javascript:"]) {
        NSString*   script;
        NSString*   result;
        script = [URLString substringWithRange:NSMakeRange(11, [URLString length] - 11)]; // Remove 'javascript:'
        script = [script stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
        result = [webView stringByEvaluatingJavaScriptFromString:script];
        
        return;
    }
    
    // Open request
    [[webView mainFrame] loadRequest:request];
    
    // Set icon
    if ([self selectedWebView] == webView) {
        [[self URLComboBox] setImage:[[WebIconDatabase sharedIconDatabase] 
                defaultIconWithSize:NSMakeSize(16, 16)]];
    }
}

- (WebView*)openRequest:(NSURLRequest*)request
{
    // Get selected web view
    WebView*    webView;
    webView = [self selectedWebView];
    
    // Open request
    [self _openRequest:request atWebView:webView];
    
    return webView;
}

- (WebView*)openRequest:(NSURLRequest*)request atIndex:(int)index
{
    // Get selected web view
    WebView*    webView;
    webView = (WebView*)[_srTabView viewAtIndex:index];
    
    // Open request
    [self _openRequest:request atWebView:webView];
    
    return webView;
}

- (id)openRequest:(NSURLRequest*)request 
        frameName:(NSString*)frameName 
        groupName:(NSString*)groupName 
        withOpenAction:(SROpenActionType)openAction
{
    switch (openAction) {
    case SROpenAction: {
        return [self openRequest:request];
    }
    case SROpenInNewTabAction: {
        return [self openInNewTabRequest:request frameName:frameName groupName:groupName select:YES];
    }
    case SROpenInNewBackgroundTabAction: {
        return [self openInNewTabRequest:request frameName:frameName groupName:groupName select:NO];
    }
    case SROpenInNewWindowAction: {
        return [self openInNewWindowRequest:request frameName:frameName groupName:groupName];
    }
    case SROpenInNewBackgroundWindowAction: {
        return [self openInNewBackgroundWindowRequest:request frameName:frameName groupName:groupName];
    }
    case SROpenOptionAction: {
        // Download it
        SRDownloadCenter*   downloadCenter;
        NSURLDownload*      download;
        downloadCenter = [SRDownloadCenter sharedInstance];
        download = [[NSURLDownload alloc] initWithRequest:request delegate:downloadCenter];
        [download autorelease];
        
        return download;
    }
    }
    
    // Never reach here
    return nil;
}

- (WebView*)openInNewTabRequest:(NSURLRequest*)request 
        frameName:(NSString*)frameName 
        groupName:(NSString*)groupName
{
    return [self openInNewTabRequest:request 
            frameName:frameName 
            groupName:groupName 
            select:[[NSUserDefaults standardUserDefaults] boolForKey:SRTabSelectNewTabs]];
}

- (WebView*)openInNewTabRequest:(NSURLRequest*)request 
        frameName:(NSString*)frameName 
        groupName:(NSString*)groupName 
        select:(BOOL)select
{
    // Add new tab
    WebView*    webView;
    webView = [self addNewTabWithLabel:NSLocalizedString(@"Untitled", @"Untitled") 
            frameName:frameName 
            groupName:groupName 
            select:select];
    
    // Open request
    [self _openRequest:request atWebView:webView];
    
    return webView;
}

- (SRMainDocument*)openInNewWindowRequest:(NSURLRequest*)request 
        frameName:(NSString*)frameName 
        groupName:(NSString*)groupName
{
    // Create new document
    SRDocumentController*   documentController;
    SRMainDocument*         document;
    documentController = [NSDocumentController sharedDocumentController];
    document = [documentController makeUntitledDocumentOfType:SRHTMLDocumentType];
    [documentController addDocument:document];
    
    // Make window controllers
    [document makeWindowControllersWithInitialFrameName:frameName groupName:groupName];
    
    // Get main window controller
    SRMainWindowController* mainWindowController;
    mainWindowController = [document mainWindowController];
    
    // Get window and make it front
    [[mainWindowController window] makeKeyAndOrderFront:self];
    
    // Open request in new window
    [mainWindowController openRequest:request];
//    [document showWindows];
    
    return document;
}

- (SRMainDocument*)openInNewBackgroundWindowRequest:(NSURLRequest*)request 
        frameName:(NSString*)frameName 
        groupName:(NSString*)groupName
{
    // Create new document
    SRDocumentController*   documentController;
    SRMainDocument*         document;
    documentController = [NSDocumentController sharedDocumentController];
    document = [documentController makeUntitledDocumentOfType:SRHTMLDocumentType];
    [documentController addDocument:document];
    
    // Make window controllers
    [document makeWindowControllersWithInitialFrameName:frameName groupName:groupName];
    
    // Get main window controller
    SRMainWindowController* mainWindowController;
    mainWindowController = [document mainWindowController];
    
    // Get window and make it back
    [[mainWindowController window] orderWindow:NSWindowBelow relativeTo:[[self window] windowNumber]];
    
    // Open bookmark in new window
    [mainWindowController openRequest:request];
//    [document showWindows];
    
    return document;
}

//--------------------------------------------------------------//
#pragma mark -- Opening page with URL string --
//--------------------------------------------------------------//

- (NSURLRequest*)createRequestWithURL:(NSURL*)url
{
    NSUserDefaults* defaults;
    defaults = [NSUserDefaults standardUserDefaults];
    
    // Get timeout
    int timeout;
    timeout = [defaults integerForKey:SRGeneralTimeout];
    if (timeout == -1) {
        // Never timeout
        timeout = 99999;
    }
    
    // Create request
    return [NSURLRequest requestWithURL:url 
            cachePolicy:NSURLRequestUseProtocolCachePolicy 
            timeoutInterval:timeout];
}

- (NSURLRequest*)createRequestWithURLString:(NSString*)URLString
{
    return [self createRequestWithURL:[NSURL _web_URLWithUserTypedString:URLString]];
}

- (WebView*)openURLString:(NSString*)URLString
{
    // Create and open request
    return [self openRequest:[self createRequestWithURLString:URLString]];
}

- (WebView*)openURLString:(NSString*)URLString atIndex:(int)index
{
    // Create and open request
    return [self openRequest:[self createRequestWithURLString:URLString] atIndex:index];
}

- (id)openURLString:(NSString*)URLString withOpenAction:(SROpenActionType)openAction
{
    // Create and open request
    return [self openRequest:[self createRequestWithURLString:URLString] 
            frameName:nil 
            groupName:nil 
            withOpenAction:openAction];
}

- (WebView*)openInNewTabURLString:(NSString*)URLString
{
    // Create and open request
    return [self openInNewTabRequest:[self createRequestWithURLString:URLString] 
            frameName:nil 
            groupName:nil];
}

- (WebView*)openInNewTabURLString:(NSString*)URLString select:(BOOL)select
{
    // Create and open request
    return [self openInNewTabRequest:[self createRequestWithURLString:URLString] 
            frameName:nil 
            groupName:nil 
            select:select];
}

- (SRMainDocument*)openInNewWindowURLString:(NSString*)URLString
{
    // Create and open request
    return [self openInNewWindowRequest:[self createRequestWithURLString:URLString] 
            frameName:nil 
            groupName:nil];
}

- (SRMainDocument*)openInNewBackgroundWindowURLString:(NSString*)URLString
{
    // Create and open request
    return [self openInNewBackgroundWindowRequest:[self createRequestWithURLString:URLString] 
            frameName:nil 
            groupName:nil];
}

- (NSArray*)openInNewTabsURLStrings:(NSArray*)URLStrings select:(BOOL)select
{
    // Check strings
    if (!URLStrings || [URLStrings count] == 0) {
        return nil;
    }
    
    // Enumerate URL strings
    NSMutableArray* webViews;
    NSEnumerator*   enumerator;
    NSString*       URLString;
    WebView*        webView;
    webViews = [NSMutableArray arrayWithCapacity:[URLStrings count]];
    enumerator = [URLStrings objectEnumerator];
    while (URLString = [enumerator nextObject]) {
        // Open URL string in new tab
        webView = [self openInNewTabURLString:URLString select:select];
        if (webView) {
            [webViews addObject:webView];
        }
    }
    
    return webViews;
}

//--------------------------------------------------------------//
#pragma mark -- Opening page with URL --
//--------------------------------------------------------------//

- (WebView*)openURL:(NSURL*)url
{
    // Create and open request
    return [self openRequest:[self createRequestWithURL:url]];
}

- (WebView*)openURL:(NSURL*)url atIndex:(int)index
{
    // Create and open request
    return [self openRequest:[self createRequestWithURL:url] atIndex:index];
}

- (id)openURL:(NSURL*)url withOpenAction:(SROpenActionType)openAction
{
    // Create and open request
    return [self openRequest:[self createRequestWithURL:url] 
            frameName:nil 
            groupName:nil 
            withOpenAction:openAction];
}

- (WebView*)openInNewTabURL:(NSURL*)url
{
    // Create and open request
    return [self openInNewTabRequest:[self createRequestWithURL:url] 
            frameName:nil 
            groupName:nil];
}

- (WebView*)openInNewTabURL:(NSURL*)url select:(BOOL)select
{
    // Create and open request
    return [self openInNewTabRequest:[self createRequestWithURL:url] 
            frameName:nil 
            groupName:nil 
            select:select];
}

- (SRMainDocument*)openInNewWindowURL:(NSURL*)url
{
    // Create and open request
    return [self openInNewWindowRequest:[self createRequestWithURL:url] 
            frameName:nil 
            groupName:nil];
}

- (SRMainDocument*)openInNewBackgroundWindowURL:(NSURL*)url
{
    // Create and open request
    return [self openInNewBackgroundWindowRequest:[self createRequestWithURL:url] 
            frameName:nil 
            groupName:nil];
}

//--------------------------------------------------------------//
#pragma mark -- Opening page with bookmark --
//--------------------------------------------------------------//

- (WebView*)openBookmark:(SRBookmark*)bookmark
{
    // For RSS
    if ([bookmark type] == SRBookmarkTypeRSS) {
        SRRSSManager*   RSSMgr;
        RSSMgr = [SRRSSManager sharedInstance];
        [RSSMgr makeItemsPreviewed:
                [[RSSMgr channelWithDocumentIdentifier:[bookmark URLString]] objectForKey:@"items"]];
    }
    
    // Retain bookmark
    [_openingBookmark release];
    _openingBookmark = [bookmark retain];
    
    // For HTML or RSS bookmark
    if ([bookmark type] == SRBookmarkTypeHTML || 
        [bookmark type] == SRBookmarkTypeRSS)
    {
        // Open URL string
        return [self openURLString:[bookmark URLString]];
    }
    
    return nil;
}

- (WebView*)openBookmark:(SRBookmark*)bookmark atIndex:(int)index
{
    // For RSS
    if ([bookmark type] == SRBookmarkTypeRSS) {
        SRRSSManager*   RSSMgr;
        RSSMgr = [SRRSSManager sharedInstance];
        [RSSMgr makeItemsPreviewed:
                [[RSSMgr channelWithDocumentIdentifier:[bookmark URLString]] objectForKey:@"items"]];
    }
    
    // Retain bookmark
    [_openingBookmark release];
    _openingBookmark = [bookmark retain];
    
    // For HTML or RSS bookmark
    if ([bookmark type] == SRBookmarkTypeHTML || 
        [bookmark type] == SRBookmarkTypeRSS)
    {
        // Open URL string
        return [self openURLString:[bookmark URLString] atIndex:(int)index];
    }
    
    return nil;
}

- (id)openBookmark:(SRBookmark*)bookmark withOpenAction:(SROpenActionType)openAction
{
    // For RSS
    if ([bookmark type] == SRBookmarkTypeRSS) {
        SRRSSManager*   RSSMgr;
        RSSMgr = [SRRSSManager sharedInstance];
        [RSSMgr makeItemsPreviewed:
                [[RSSMgr channelWithDocumentIdentifier:[bookmark URLString]] objectForKey:@"items"]];
    }
    
    // Retain bookmark
    [_openingBookmark release];
    _openingBookmark = [bookmark retain];
    
    // For HTML or RSS bookmark
    if ([bookmark type] == SRBookmarkTypeHTML || 
        [bookmark type] == SRBookmarkTypeRSS)
    {
        // Open URL string
        return [self openURLString:[bookmark URLString] withOpenAction:openAction];
    }
    
    return nil;
}

- (WebView*)openInNewTabBookmark:(SRBookmark*)bookmark
{
    // For RSS
    if ([bookmark type] == SRBookmarkTypeRSS) {
        SRRSSManager*   RSSMgr;
        RSSMgr = [SRRSSManager sharedInstance];
        [RSSMgr makeItemsPreviewed:
                [[RSSMgr channelWithDocumentIdentifier:[bookmark URLString]] objectForKey:@"items"]];
    }
    
    // Retain bookmark
    [_openingBookmark release];
    _openingBookmark = [bookmark retain];
    
    // For HTML or RSS bookmark
    if ([bookmark type] == SRBookmarkTypeHTML || 
        [bookmark type] == SRBookmarkTypeRSS)
    {
        // Open URL string
        return [self openInNewTabURLString:[bookmark URLString]];
    }
    
    return nil;
}

- (WebView*)openInNewTabBookmark:(SRBookmark*)bookmark select:(BOOL)select
{
    // For RSS
    if ([bookmark type] == SRBookmarkTypeRSS) {
        SRRSSManager*   RSSMgr;
        RSSMgr = [SRRSSManager sharedInstance];
        [RSSMgr makeItemsPreviewed:
                [[RSSMgr channelWithDocumentIdentifier:[bookmark URLString]] objectForKey:@"items"]];
    }
    
    // Retain bookmark
    [_openingBookmark release];
    _openingBookmark = [bookmark retain];
    
    // For HTML or RSS bookmark
    if ([bookmark type] == SRBookmarkTypeHTML || 
        [bookmark type] == SRBookmarkTypeRSS)
    {
        // Open URL string
        return [self openInNewTabURLString:[bookmark URLString] select:select];
    }
    
    return nil;
}

- (SRMainDocument*)openInNewWindowBookmark:(SRBookmark*)bookmark
{
    // For RSS
    if ([bookmark type] == SRBookmarkTypeRSS) {
        SRRSSManager*   RSSMgr;
        RSSMgr = [SRRSSManager sharedInstance];
        [RSSMgr makeItemsPreviewed:
                [[RSSMgr channelWithDocumentIdentifier:[bookmark URLString]] objectForKey:@"items"]];
    }
    
    // For HTML or RSS bookmark
    if ([bookmark type] == SRBookmarkTypeHTML || 
        [bookmark type] == SRBookmarkTypeRSS)
    {
        // Open URL string
        return [self openInNewWindowURLString:[bookmark URLString]];
    }
    
    return nil;
}

- (SRMainDocument*)openInNewBackgroundWindowBookmark:(SRBookmark*)bookmark
{
    // For RSS
    if ([bookmark type] == SRBookmarkTypeRSS) {
        SRRSSManager*   RSSMgr;
        RSSMgr = [SRRSSManager sharedInstance];
        [RSSMgr makeItemsPreviewed:
                [[RSSMgr channelWithDocumentIdentifier:[bookmark URLString]] objectForKey:@"items"]];
    }
    
    // For HTML or RSS bookmark
    if ([bookmark type] == SRBookmarkTypeHTML || 
        [bookmark type] == SRBookmarkTypeRSS)
    {
        // Open URL string
        return [self openInNewBackgroundWindowURLString:[bookmark URLString]];
    }
    
    return nil;
}

- (NSArray*)openInTabsBookmark:(SRBookmark*)bookmark
{
    // For bookmark folder
    if ([bookmark isFolderType]) {
        // Open children
        return [self openInTabsBookmarks:[bookmark children]];
    }
    
    return nil;
}

- (NSArray*)openInTabsBookmarks:(NSArray*)bookmarks
{
    // Check bookmarks
    if (!bookmarks || [bookmarks count] == 0) {
        return nil;
    }
    
    // Get current tab number
    int numberOfTab;
    numberOfTab = [_srTabView numberOfItems];
    
    // Enumerate bookmark
    NSMutableArray* webViews;
    NSEnumerator*   enumerator;
    SRBookmark*     bookmark;
    WebView*        webView;
    int             index = 0;
    webViews = [NSMutableArray arrayWithCapacity:numberOfTab];
    enumerator = [bookmarks objectEnumerator];
    while (bookmark = [enumerator nextObject]) {
        if (index < numberOfTab) {
            // Open bookmark in tab
            webView = [self openBookmark:bookmark atIndex:index];
        }
        else {
            // Open bookmark in new tab
            webView = [self openInNewTabBookmark:bookmark select:NO];
        }
        if (webView) {
            [webViews addObject:webView];
            index++;
        }
    }
    
    // Select first tab
    [_srTabView selectItemAtIndex:0];
    
    return webViews;
}

//--------------------------------------------------------------//
#pragma mark -- Opening page with history --
//--------------------------------------------------------------//

- (WebView*)openHistory:(WebHistoryItem*)historyItem
{
    // Open URL string
    return [self openURLString:[historyItem URLString]];
}

- (WebView*)openHistory:(WebHistoryItem*)historyItem atIndex:(int)index
{
    // Open URL string
    return [self openURLString:[historyItem URLString] atIndex:index];
}

- (WebView*)openHistory:(WebHistoryItem*)historyItem withOpenAction:(SROpenActionType)openAction
{
    // Open URL string
    return [self openURLString:[historyItem URLString] withOpenAction:openAction];
}

- (WebView*)openInNewTabHistory:(WebHistoryItem*)historyItem
{
    // Open URL string
    return [self openInNewTabURLString:[historyItem URLString]];
}

- (WebView*)openInNewTabHistory:(WebHistoryItem*)historyItem select:(BOOL)select
{
    // Open URL string
    return [self openInNewTabURLString:[historyItem URLString] select:select];
}

- (SRMainDocument*)openInNewWindowHistory:(WebHistoryItem*)historyItem
{
    // Open URL string
    return [self openInNewWindowURLString:[historyItem URLString]];
}

- (SRMainDocument*)openInNewBackgroundWindowHistory:(WebHistoryItem*)historyItem
{
    // Open URL string
    return [self openInNewBackgroundWindowURLString:[historyItem URLString]];
}

- (NSArray*)openInTabsHistory:(NSArray*)historyItems
{
    // Check history items
    if (!historyItems || [historyItems count] == 0) {
        return nil;
    }
    
    // Get current tab number
    int numberOfTab;
    numberOfTab = [_srTabView numberOfItems];
    
    // Enumerate bookmark
    NSMutableArray* webViews;
    NSEnumerator*   enumerator;
    WebHistoryItem* historyItem;
    WebView*        webView;
    int             index = 0;
    webViews = [NSMutableArray arrayWithCapacity:numberOfTab];
    enumerator = [historyItems objectEnumerator];
    while (historyItem = [enumerator nextObject]) {
        if (![historyItem isKindOfClass:[WebHistoryItem class]]) {
            continue;
        }
        
        if (index < numberOfTab) {
            // Open history item in tab
            webView = [self openHistory:historyItem atIndex:index];
        }
        else {
            // Open history item in new tab
            webView = [self openInNewTabHistory:historyItem select:NO];
        }
        [webViews addObject:webView];
        
        index++;
    }
    
    // Select first tab
    [_srTabView selectItemAtIndex:0];
    
    return webViews;
}

//--------------------------------------------------------------//
#pragma mark -- Realod URL --
//--------------------------------------------------------------//

// from openURL
- (BOOL)reloadURLIfExists:(NSURL*)URL
{
    int i,cnt;
    NSArray*    tabViewItems=[[_srTabView tabView]tabViewItems];
    cnt=[tabViewItems count];
    for(i=0;i<cnt;i++){
        WebDataSource*  dataSource;
        NSURLRequest*   request;
        WebView*    webView;
        NSURL*      aURL;
        
        webView = (WebView*)[[tabViewItems objectAtIndex:i]view];
        if([webView isMemberOfClass:[WebView class]]){
            dataSource = [[webView mainFrame] dataSource];
            request = [dataSource request];
            aURL=[request URL];
            if([URL isEqual:aURL]){
                //use existed WebView
                [_srTabView selectItemAtIndex:i];
                [webView reload:self];
                [self showWindow:self];
                return YES;
            }
        }
    }
    return NO;
}

//--------------------------------------------------------------//
#pragma mark -- Appearnace --
//--------------------------------------------------------------//

- (BOOL)isBookmarksBarVisible
{
    return ![_bookmarksBarView isHidden];
}

- (void)setBookmarksBarVisible:(BOOL)isVisible 
        display:(BOOL)display
{
    NSUserDefaults* defaults;
    defaults = [NSUserDefaults standardUserDefaults];
    
    // Show bookmarks bar
    if (isVisible && [_bookmarksBarView isHidden]) {
        // Show bookmarks box
        [_bookmarksBarView setHidden:NO];
        
        // Get frames
        NSRect  barFrame;
        NSRect  windowFrame;
        NSRect  parentFrame;
        barFrame = [_bookmarksBarView frame];
        windowFrame = [[self window] frame];
        parentFrame = [_parentView frame];
        
        // Expand window
        int mask;
        mask = [_parentView autoresizingMask];
        [_parentView setAutoresizingMask:NSViewMaxYMargin];
        [[self window] setFrame:NSMakeRect(
                windowFrame.origin.x, 
                windowFrame.origin.y - barFrame.size.height, 
                windowFrame.size.width, 
                windowFrame.size.height + barFrame.size.height) display:display animate:YES]; 
        [_parentView setAutoresizingMask:mask];
    }
    
    // Hide bookmarks bar
    else if (!isVisible && ![_bookmarksBarView isHidden]) {
        // Get frames
        NSRect  barFrame;
        NSRect  windowFrame;
        NSRect  parentFrame;
        barFrame = [_bookmarksBarView frame];
        windowFrame = [[self window] frame];
        parentFrame = [_parentView frame];
        
        // Shrink window
        int mask;
        mask = [_parentView autoresizingMask];
        [_parentView setAutoresizingMask:NSViewMaxYMargin];
        [[self window] setFrame:NSMakeRect(
                windowFrame.origin.x, 
                windowFrame.origin.y + barFrame.size.height, 
                windowFrame.size.width, 
                windowFrame.size.height - barFrame.size.height) display:display animate:YES]; 
        [_parentView setAutoresizingMask:mask];
        
        // Hide bookmarks box
        [_bookmarksBarView setHidden:YES];
    }
    
    // Show or hide separator of tab view
    [_srTabView setSeparatorShow:isVisible];
    
    // Set it default database
    if (!_isResizedByJavaScript) {
        [defaults setBool:isVisible forKey:SRMainWindowBookmarksBarVisible];
    }
}

- (BOOL)isStatusBarVisible
{
    return ![_statusBox isHidden];
}

- (void)setStatusBarVisible:(BOOL)isVisible 
        display:(BOOL)display
{
    NSUserDefaults* defaults;
    defaults = [NSUserDefaults standardUserDefaults];
    
    // Show status bar
    if (isVisible && [_statusBox isHidden]) {
        // Show status box
        [_statusBox setHidden:NO];
        
        // Get frames
        NSRect  boxFrame;
        NSRect  windowFrame;
        NSRect  parentFrame;
        boxFrame = [_statusBox frame];
        windowFrame = [[self window] frame];
        parentFrame = [_parentView frame];
        
        // Expand window
        int mask;
        mask = [_parentView autoresizingMask];
        [_parentView setAutoresizingMask:NSViewMinYMargin];
        [[self window] setFrame:NSMakeRect(
                windowFrame.origin.x, 
                windowFrame.origin.y - boxFrame.size.height, 
                windowFrame.size.width, 
                windowFrame.size.height + boxFrame.size.height) display:display animate:YES]; 
        [_parentView setAutoresizingMask:mask];
    }
    
    // Hide status bar
    else if (!isVisible && ![_statusBox isHidden]) {
        // Get frames
        NSRect  boxFrame;
        NSRect  windowFrame;
        NSRect  parentFrame;
        boxFrame = [_statusBox frame];
        windowFrame = [[self window] frame];
        parentFrame = [_parentView frame];
        
        // Shrink window
        int mask;
        mask = [_parentView autoresizingMask];
        [_parentView setAutoresizingMask:NSViewMinYMargin];
        [[self window] setFrame:NSMakeRect(
                windowFrame.origin.x, 
                windowFrame.origin.y + boxFrame.size.height, 
                windowFrame.size.width, 
                windowFrame.size.height - boxFrame.size.height) display:display animate:YES]; 
        [_parentView setAutoresizingMask:mask];
        
        // Hide status box
        [_statusBox setHidden:YES];
    }
    
    // Set it default database
    if (!_isResizedByJavaScript) {
        [defaults setBool:isVisible forKey:SRMainWindowStatusBarVisible];
    }
}

- (BOOL)isTabVisible
{
    return [_srTabView isTabShown];
}

- (void)setTabVisible:(BOOL)isVisible 
        display:(BOOL)display
{
    [_srTabView setTabShown:isVisible];
}

- (BOOL)isSidebarVisible
{
    int state;
    state = [[_sideBarController drawer] state];
    return state == NSDrawerOpenState || state == NSDrawerOpeningState;
}

- (void)setSidebarVisible:(BOOL)isVisible
{
    NSUserDefaults* defaults;
    defaults = [NSUserDefaults standardUserDefaults];
    
    NSDrawer*   drawer;
    drawer = [_sideBarController drawer];
    
    // Set visible status
    if (isVisible) {
        BOOL    usePreferredEdge;
        int     edge;
        usePreferredEdge = [defaults boolForKey:SRSidebarPreferredEdge];
        edge = [defaults integerForKey:SRSidebarEdge];
        if (edge == SRSidebarEdgeLeft) {
            if (usePreferredEdge) {
                [drawer setPreferredEdge:NSMaxXEdge];
                [drawer open];
            }
            else {
                [drawer openOnEdge:NSMinXEdge];
            }
        }
        else if (edge == SRSidebarEdgeRight) {
            if (usePreferredEdge) {
                [drawer setPreferredEdge:NSMinXEdge];
                [drawer open];
            }
            else {
                [drawer openOnEdge:NSMaxXEdge];
            }
        }
        else {
            [drawer open];
        }
    }
    else {
        [drawer close];
    }
    
#if 0
    // Set it default database
    if (!_isResizedByJavaScript) {
        [defaults setBool:isVisible forKey:SRMainWindowSidebarVisible];
    }
#endif
}

- (BOOL)isResizedByJavaScript
{
    return _isResizedByJavaScript;
}

//--------------------------------------------------------------//
#pragma mark -- Supported schemes --
//--------------------------------------------------------------//

- (BOOL)isSchemeSupported:(NSString *)scheme
{
    // For javascript window.open
    if (!scheme || [scheme length] <= 0) {
        return YES;
    }
    
    return [scheme isEqualToString:@"http"] || 
           [scheme isEqualToString:@"https"] || 
           [scheme isEqualToString:@"file"];
}

//--------------------------------------------------------------//
#pragma mark -- Bookmarks bar --
//--------------------------------------------------------------//

- (void)setBookmarksBarBrowser:(int)browser
{
    _bookmarksBarBrowser = browser;
    
    // Find bookmarks bar
    SRBookmark* bookmarksBar = nil;
    
    switch(_bookmarksBarBrowser) {
    case SRBrowserShiira: {
        bookmarksBar = [[SRBookmarkStorage sharedInstance] shiiraBookmarksBar];
        break;
    }
    case SRBrowserSafari: {
        bookmarksBar = [[SRBookmarkStorage sharedInstance] safariBookmarksBar];
        break;
    }
    case SRBrowserFirefox: {
        bookmarksBar = [[SRBookmarkStorage sharedInstance] firefoxBookmarksBar];
        break;
    }
    }
    
    if (bookmarksBar) {
        // Set accept drag
        [_bookmarksBarView setAcceptDrag:[bookmarksBar isMutable]];
        
        // Set bookmarks bar
        [_bookmarksBarView setBookmarksBar:bookmarksBar];
    }
}

//--------------------------------------------------------------//
#pragma mark -- User agent --
//--------------------------------------------------------------//

- (void)_setUserAgentOfWebView:(WebView*)webView
{
    NSUserDefaults* defaults;
    defaults = [NSUserDefaults standardUserDefaults];
    
    // Set user agent
    int         userAgent;
    NSString*   customUserAgentName;
    userAgent = [defaults integerForKey:SRUserAgent];
    customUserAgentName = [defaults stringForKey:SRUserAgentOtherName];
    
    // For Shiira user agent
    if (userAgent == SRUserAgentShiira) {
        [webView setCustomUserAgent:nil];
        
        // Get version
        NSBundle*   bundle;
        NSString*   version;
        NSString*   userAgentName = @"Shiira";
        bundle = [NSBundle mainBundle];
        version = [[bundle infoDictionary] objectForKey:@"CFBundleShortVersionString"];
        if (version) {
            userAgentName = [NSString stringWithFormat:@"%@/%@", userAgentName, version];
        }
        [webView setApplicationNameForUserAgent:userAgentName];
        
        // Get composited user agent name
        NSString*   compUserAgentName;
        compUserAgentName = [webView userAgentForURL:[NSURL URLWithString:@"http://local"]];
        
        // If user agent name dose not contain 'Safari', add it
        if ([compUserAgentName rangeOfString:@"Safari"].location == NSNotFound) {
            compUserAgentName = [NSString stringWithFormat:@"%@ Safari/125", compUserAgentName];
        }
        [webView setCustomUserAgent:compUserAgentName];
        
        // Show user agent name on preferences panel
        [defaults setValue:compUserAgentName forKey:SRUserAgentShiiraName];
    }
    // For default user agents
    if (userAgent > SRUserAgentShiira && userAgent < SRUserAgentOther) {
        // Get user agents plist
        NSArray*    userAgents;
        userAgents = [SRPreferencesController userAgents];
        if (userAgents && [userAgents count] > userAgent - 1) {
            NSDictionary*   userAgentInfo;
            NSString*       userAgentName;
            userAgentInfo = [userAgents objectAtIndex:userAgent - 1];
            userAgentName = [userAgentInfo objectForKey:@"userAgent"];
            if (userAgentName) {
                [webView setCustomUserAgent:userAgentName];
                
                // Show user agent name on preferences panel
                [defaults setValue:userAgentName forKey:SRUserAgentShiiraName];
            }
        }
    }
    // For other
    if (userAgent == SRUserAgentOther) {
        [webView setCustomUserAgent:customUserAgentName];
        
        // Set other user agent name on preferences panel
        [defaults setValue:customUserAgentName forKey:SRUserAgentShiiraName];
    }
}

- (void)setUserAgent:(int)userAgent
{
    NSUserDefaults* defaults;
    defaults = [NSUserDefaults standardUserDefaults];
    
    // Get custom user agent name
    NSString*   customUserAgentName;
    customUserAgentName = [defaults stringForKey:SRUserAgentOtherName];
    
    // Set it web view
    NSEnumerator*   enumerator;
    NSTabViewItem*  tabViewItem;
    enumerator = [[[_srTabView tabView] tabViewItems] objectEnumerator];
    while (tabViewItem = [enumerator nextObject]) {
        // Get web view
        WebView*    webView;
        webView = (WebView*)[tabViewItem view];
        
        // Set user agent
        [self _setUserAgentOfWebView:webView];
    }
}

//--------------------------------------------------------------//
#pragma mark -- Icon and texture --
//--------------------------------------------------------------//

- (void)setTexture:(int)texture
{
}

//--------------------------------------------------------------//
#pragma mark -- Authentication --
//--------------------------------------------------------------//

- (SRAuthenticationController*)authenticationController
{
    if (!_authController) {
        // Load AuthenticationPanel.nib
        _authController = [[SRAuthenticationController alloc] initWithWindowNibName:@"AuthenticationPanel"];
        if (!_authController) {
            // Fatal
            SR_FATAL(@"Could not load AuthenticationPanel.nib");
        }
    }
    
    return _authController;
}

//--------------------------------------------------------------//
#pragma mark -- Full screen mode --
//--------------------------------------------------------------//

- (void)switchToFullScreenModeWithMenu:(BOOL)flag
{
    // Make it full screen mode
    _isFullScreenMode = YES;
    
    // Show or hide menu bar
    if ((flag && ![NSMenu menuBarVisible]) || 
        (!flag && [NSMenu menuBarVisible]))
    {
        [NSMenu setMenuBarVisible:flag];
    }
    
    // Get window
    NSWindow*   window;
    window = [self window];
    
    // Get visible frame
    NSScreen*   screen;
    NSRect     visibleFrame;
    screen = [window screen];
    visibleFrame = [screen visibleFrame];
    
    // Set frame
    //[window setContentSize:visibleFrame.size];
    //[window setFrameOrigin:NSZeroPoint];
//    [window setFrame:visibleFrame display:YES animate:NO];
}

- (void)escapeFromFullScreenMode
{
    // Disable full screen mode
    _isFullScreenMode = NO;
    
    // Show menu bar
    if (![NSMenu menuBarVisible]) {
        [NSMenu setMenuBarVisible:YES];
    }
}

- (BOOL)isFullScreenMode
{
    return _isFullScreenMode;
}

//--------------------------------------------------------------//
#pragma mark -- Search --
//--------------------------------------------------------------//

- (void)setSearchTemplateURL:(NSString*)templateURL requestURLString:(NSString*)URLString
{
    [_searchingURLDict setObject:templateURL forKey:URLString];
}

#ifdef SR_SUPPORT_RSS
//--------------------------------------------------------------//
#pragma mark -- RSS --
//--------------------------------------------------------------//

- (BOOL)hasRSSLinkAtWebView:(WebView*)webView
{
    // Decide link elements has RSS alternate
    BOOL    hasRSSLink = NO;
    
    // Get link elements
    DOMDocument*    document;
    DOMNodeList*    linkElements = nil;
    document = [[webView mainFrame] DOMDocument];
    if (document) {
        linkElements = [document getElementsByTagName:@"link"];
    }
    if (linkElements && [linkElements length] > 0) {
        // Find RSS types
        int i;
        for (i = 0; i < [linkElements length]; i++) {
            DOMElement* linkElement;
            linkElement = (DOMElement*)[linkElements item:i];
            
            // Get type
            NSString*   type;
            type = [linkElement getAttribute:@"type"];
            if ([[SRRSSRepresentation RSSMimes] containsObject:type]) {
                hasRSSLink = YES;
                break;
            }
        }
    }
    
    return hasRSSLink;
}

- (NSArray*)RSSLinksAtWebView:(WebView*)webView
{
    NSMutableArray* links;
    links = [NSMutableArray array];
    
    // Get link elements
    DOMDocument*    document;
    DOMNodeList*    linkElements = nil;
    document = [[webView mainFrame] DOMDocument];
    if (document) {
        linkElements = [document getElementsByTagName:@"link"];
    }
    if (linkElements && [linkElements length] > 0) {
        // Find RSS types
        int i;
        for (i = 0; i < [linkElements length]; i++) {
            DOMElement* linkElement;
            linkElement = (DOMElement*)[linkElements item:i];
            
            // Get type
            NSString*   type;
            type = [linkElement getAttribute:@"type"];
            if ([[SRRSSRepresentation RSSMimes] containsObject:type]) {
                // Get href
                NSString*   href;
                href = [linkElement getAttribute:@"href"];
                if (href) {
                    [links addObject:href];
                }
            }
        }
    }
    
    return links;
}

#endif // SR_SUPPORT_RSS

//--------------------------------------------------------------//
#pragma mark -- Menu item validation --
//--------------------------------------------------------------//

- (BOOL)validateMenuItem:(id<NSMenuItem>)menuItem
{
    NSUserDefaults* defaults;
    defaults = [NSUserDefaults standardUserDefaults];
    
    // Get tag
    int tag;
    tag = [menuItem tag];
    
    // For browse mode text menu
    if ([menuItem menu] == _menuFormSubmenu) {
        // Get browse mode
        int browseMode;
        browseMode = [defaults integerForKey:SRBrowseMode];
        if (browseMode > SRNumberOfBrowseMode) {
            browseMode = SRDefaultBrowseMode;
        }
        
        // Set state
        [menuItem setState:tag == browseMode ? NSOnState : NSOffState];
    }
    
    // Get web view
    WebView*    webView;
    webView = [self selectedWebView];
    
    switch (tag) {
    // File menu
    case SRNewTabTag: {
        // Check tab browsing
        return [defaults boolForKey:SRTabEnableTabbedBrowsing];
    }
    case SRCloseWindowTag: {
        // Check number of tab
        if (![defaults boolForKey:SRTabEnableTabbedBrowsing] || 
            [_srTabView numberOfItems] < 2)
        {
            [menuItem setKeyEquivalent:@"w"];
            [menuItem setKeyEquivalentModifierMask:NSCommandKeyMask];
        }
        else {
            [menuItem setKeyEquivalent:@"W"];
            [menuItem setKeyEquivalentModifierMask:NSCommandKeyMask];
        }
        
        // Always YES
        return YES;
    }
    case SRCloseTabTag: {
        // Check number of tab
        if (![defaults boolForKey:SRTabEnableTabbedBrowsing] || 
            [_srTabView numberOfItems] < 2)
        {
            [menuItem setKeyEquivalent:@""];
            return NO;
        }
        else {
            [menuItem setKeyEquivalent:@"w"];
            [menuItem setKeyEquivalentModifierMask:NSCommandKeyMask];
            return YES;
        }
    }
    
    // View menu
    case SRToolbarTag: {
        // Set menu status
        BOOL    isToolbarVisible;
        isToolbarVisible = [[[self window] toolbar] isVisible];
        [menuItem setState:isToolbarVisible ? NSOnState : NSOffState];
        
        // Always YES
        return YES;
    }
    case SRBookmarksBarTag: {
        // Set menu status
        BOOL    isBookmarksBarVisible;
        isBookmarksBarVisible = [self isBookmarksBarVisible];
        [menuItem setState:isBookmarksBarVisible ? NSOnState : NSOffState];
        
        // Always YES
        return YES;
    }
    case SRStatusBarTag: {
        // Set menu status
        BOOL    isStatusBarVisible;
        isStatusBarVisible = [self isStatusBarVisible];
        [menuItem setState:isStatusBarVisible ? NSOnState : NSOffState];
        
        // Always YES
        return YES;
    }
    case SRSidebarTag: {
        // Set menu status
        BOOL    isSidebarVisible;
        isSidebarVisible = [[_sideBarController drawer] state] == NSDrawerOpenState;
        [menuItem setState:isSidebarVisible ? NSOnState : NSOffState];
        
        // Always YES
        return YES;
    }
    case SRCustomizeToolbarTag: {
        // Always YES
        return YES;
    }
    case SRStopLoadingTag: {
        if (!webView) {
            return NO;
        }
        
        // Get data source
        WebDataSource*  provisionalDataSource;
        WebDataSource*  dataSource;
        provisionalDataSource = [[webView mainFrame] provisionalDataSource];
        dataSource = [[webView mainFrame] dataSource];
        
        if (provisionalDataSource) {
            return [provisionalDataSource isLoading];
        }
        if (dataSource) {
            if ([dataSource request]) {
                return NO;
            }
            return [dataSource isLoading];
        }
        return NO;
    }
    case SRReloadPageTag: {
        if (!webView) {
            return NO;
        }
        
        // Get data source
        WebDataSource*  provisionalDataSource;
        WebDataSource*  dataSource;
        provisionalDataSource = [[webView mainFrame] provisionalDataSource];
        dataSource = [[webView mainFrame] dataSource];
        
        if (provisionalDataSource) {
            return ![provisionalDataSource isLoading];
        }
        if (dataSource) {
            if (![dataSource request]) {
                return NO;
            }
            return ![dataSource isLoading];
        }
        return NO;
    }
    case SRBiggerTextTag: {
        if (!webView) {
            return NO;
        }
        
        return [webView canMakeTextLarger];
    }
    case SRSmallerTextTag: {
        if (!webView) {
            return NO;
        }
        
        return [webView canMakeTextSmaller];
    }
    case SRViewPageSourceTag: {
        // Get data source
        WebDataSource*  dataSource;
        dataSource = [[webView mainFrame] dataSource];
        if (!dataSource) {
            return NO;
        }
        
        return [[dataSource representation] canProvideDocumentSource];
    }
    case SROpenURLWithBrowserItemTag: {
        NSURL*  url;
        url = [[[[webView mainFrame] dataSource] request] URL];
        return url != nil;
    }
    case SRTextEncodingDefaultTag: {
        // Update submenu
        NSMenu*             textEncodingMenu;
        NSString*           encodingName;
        NSStringEncoding    encoding;
        textEncodingMenu = [menuItem menu];
        encodingName = [webView customTextEncodingName];
        if (!encodingName) {
            encoding = SRTextEncodingDefaultTag;
        }
        else {
            // Get text encoding
            encoding = [[[NSValueTransformer valueTransformerForName:SREncodingToIANATransformerName] 
                    reverseTransformedValue:encodingName] intValue];
        }
        
        // Get correspond menu item
        id<NSMenuItem>  encodingMenuItem;
        encodingMenuItem = [textEncodingMenu itemWithTag:encoding];
        
        // Set state
        NSEnumerator*   enumerator;
        id<NSMenuItem>  item;
        enumerator = [[textEncodingMenu itemArray] objectEnumerator];
        while (item = [enumerator nextObject]) {
            [item setState:item == encodingMenuItem ? NSOnState : NSOffState];
        }
        
        return YES;
    }
    
    // History menu
    case SRBackTag: {
        if (!webView) {
            return NO;
        }
        
        return [webView canGoBack];
    }
    case SRForwardTag: {
        if (!webView) {
            return NO;
        }
        
        return [webView canGoForward];
    }
    case SRHomeTag: {
        // Get home page URL
        NSString*   URLString;
        URLString = [[[NSApp delegate] preferencesController] homeURLString];
        return URLString && [URLString length] > 0;
    }
    case SRClearHistoryTag: {
        return YES;
    }
    
    // Bookmark menu
    case SRAddToBookmarkTag: {
        // Get selected web view
        WebView*    webView;
        webView = [self selectedWebView];
        if (![[[webView mainFrame] dataSource] request]) {
            return NO;
        }
        return YES;
    }
    case SRAddBookmarkFolderTag: {
        // Always YES
        return YES;
    }
    case SRShowBookmarkInSidebarTag: {
        // Always YES
        return YES;
    }
    
    // Window menu
    case SRPreviousTabTag: {
        // Get selected index
        int numberOfItems;
        int selectedIndex;
        numberOfItems = [_srTabView numberOfItems];
        selectedIndex = [_srTabView selectedIndex];
        if (selectedIndex == -1) {
            return NO;
        }
        
        return numberOfItems > 1;
    }
    case SRNextTabTag: {
        // Get item number and selected index
        int numberOfItems;
        int selectedIndex;
        numberOfItems = [_srTabView numberOfItems];
        selectedIndex = [_srTabView selectedIndex];
        if (selectedIndex == -1) {
            return NO;
        }
        
        return numberOfItems > 1;
    }
    case SRShowAllTabsTag: {
        return [_srTabView numberOfItems] > 1;
    }
    }
    
    return YES;
}

//--------------------------------------------------------------//
#pragma mark -- NSMenu delegate --
//--------------------------------------------------------------//

- (BOOL)menuHasKeyEquivalent:(NSMenu*)menu 
        forEvent:(NSEvent*)event 
        target:(id*)target 
        action:(SEL*)action
{
    NSUserDefaults* defaults;
    defaults = [NSUserDefaults standardUserDefaults];
    
    // Get attributes
    unsigned int    modifierFlags;
    BOOL            cmdFlag, optFlag, shiftFlag;
    NSString*       characters;
    modifierFlags = [event modifierFlags];
    cmdFlag = modifierFlags & NSCommandKeyMask;
    optFlag = modifierFlags & NSAlternateKeyMask;
    shiftFlag = modifierFlags & NSShiftKeyMask;
    characters = [event charactersIgnoringModifiers];
    
    // For file menu
    if (menu == [SRAppDelegate fileMenu]) {
        // For cmd + 'w'
        if (cmdFlag && !optFlag && !shiftFlag && [characters isEqualToString:@"w"]) {
            // Check number of tab
            if (![defaults boolForKey:SRTabEnableTabbedBrowsing] || 
                [_srTabView numberOfItems] < 2)
            {
                // Use close window action
                *target = nil;
                *action = @selector(closeWindowAction:);
            }
            else {
                // Use close tab action
                *target = nil;
                *action = @selector(closeTabAction:);
            }
            
            return YES;
        }
    }
    
    return NO;
}

//--------------------------------------------------------------//
#pragma mark -- NSToolbar delegate --
//--------------------------------------------------------------//

- (NSArray*)toolbarAllowedItemIdentifiers:(NSToolbar*)toolbar
{
    return _toolbarItemIdentifiers;
}

- (NSArray*)toolbarDefaultItemIdentifiers:(NSToolbar*)toolbar
{
    return _toolbarDefaultItemIdentifiers;
}

- (NSToolbarItem*)toolbar:(NSToolbar*)toolbar 
        itemForItemIdentifier:(NSString*)itemIdentifier 
        willBeInsertedIntoToolbar:(BOOL)flag
{
    NSUserDefaults* defaults;
    defaults = [NSUserDefaults standardUserDefaults];
    
    // Create toolbar item
    id  item;
    if ([itemIdentifier isEqualToString:SRBrowseIdentifier]) {
        item = [[SRBrowseToolbarItem alloc] initWithItemIdentifier:itemIdentifier];
    }
    else {
        item = [[NSToolbarItem alloc] initWithItemIdentifier:itemIdentifier];
    }
    [item autorelease];
    [item setTarget:self];
    
    // Get label, image, and action
    NSString*   label = nil;
    NSImage*    image = nil;
    SEL         action = NULL;
    NSString*   paletteLabel = nil;
    
    // Go back
    if ([itemIdentifier isEqualToString:SRGoBackIdentifier]) {
        static NSString*    goBackLabel = nil;
        if (!goBackLabel) {
            goBackLabel = [NSLocalizedStringFromTable(itemIdentifier, SRMainToolbarLabelTable, nil) retain];
        }
        label = goBackLabel;
        image = [_iconImageDict objectForKey:itemIdentifier];
        action = @selector(goBackAction:);
    }
    // Go forward
    else if ([itemIdentifier isEqualToString:SRGoForwardIdentifier]) {
        static NSString*    goForwardLabel = nil;
        if (!goForwardLabel) {
            goForwardLabel = [NSLocalizedStringFromTable(itemIdentifier, SRMainToolbarLabelTable, nil) retain];
        }
        label = goForwardLabel;
        image = [_iconImageDict objectForKey:itemIdentifier];
        action = @selector(goForwardAction:);
    }
    // Reload page
    else if ([itemIdentifier isEqualToString:SRReloadPageIdentifier]) {
        static NSString*    reloadPageLabel = nil;
        if (!reloadPageLabel) {
            reloadPageLabel = [NSLocalizedStringFromTable(itemIdentifier, SRMainToolbarLabelTable, nil) retain];
        }
        label = reloadPageLabel;
        image = [_iconImageDict objectForKey:itemIdentifier];
        action = @selector(reloadPageAction:);
    }
    // Stop loading
    else if ([itemIdentifier isEqualToString:SRStopLoadingIdentifier]) {
        static NSString*    stopLoadingLabel = nil;
        if (!stopLoadingLabel) {
            stopLoadingLabel = [NSLocalizedStringFromTable(itemIdentifier, SRMainToolbarLabelTable, nil) retain];
        }
        label = stopLoadingLabel;
        image = [_iconImageDict objectForKey:itemIdentifier];
        action = @selector(stopLoadingAction:);
    }
    // Go home
    else if ([itemIdentifier isEqualToString:SRGoHomeIdentifier]) {
        static NSString*    goHomeLabel = nil;
        if (!goHomeLabel) {
            goHomeLabel = [NSLocalizedStringFromTable(itemIdentifier, SRMainToolbarLabelTable, nil) retain];
        }
        label = goHomeLabel;
        image = [_iconImageDict objectForKey:itemIdentifier];
        action = @selector(goHomeAction:);
    }
    // URL
    else if ([itemIdentifier isEqualToString:SRURLIdentifier]) {
        static NSString*    urlLabel = nil;
        if (!urlLabel) {
            urlLabel = [NSLocalizedStringFromTable(itemIdentifier, SRMainToolbarLabelTable, nil) retain];
        }
        
        // Create URL combo box
        SRURLComboBox*  URLComboBox;
        URLComboBox = [[SRURLComboBox alloc] initWithFrame:NSMakeRect(0, 0, 0, 0)];
        [URLComboBox autorelease];
#if 1
        [[URLComboBox cell] setControlSize:NSSmallControlSize];
        [URLComboBox setFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]];
#else
        if ([defaults boolForKey:SRToolbarUseSmallURLAndSearchField]) {
            [[URLComboBox cell] setControlSize:NSSmallControlSize];
            [URLComboBox setFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]];
        }
        else {
            [[URLComboBox cell] setControlSize:NSRegularControlSize];
            [URLComboBox setFont:[NSFont systemFontOfSize:[NSFont systemFontSize]]];
        }
#endif
        [URLComboBox setImage:[[WebIconDatabase sharedIconDatabase] 
                defaultIconWithSize:NSMakeSize(16, 16)]];
        [URLComboBox sizeToFit];
        
        [item setView:URLComboBox];
        [item setMinSize:NSMakeSize(SRURLMinWidth, [URLComboBox frame].size.height)];
        [item setMaxSize:NSMakeSize(SRURLMaxWidth, [URLComboBox frame].size.height)];
        
        NSMenuItem* menuItem;
        menuItem = [[NSMenuItem alloc] initWithTitle:urlLabel 
                action:@selector(openLocationAction:) 
                keyEquivalent:@""];
        [menuItem autorelease];
        [item setMenuFormRepresentation:menuItem];
        
        label = urlLabel;
    }
    // Show sidebar
    else if ([itemIdentifier isEqualToString:SRSidebarIdentifier]) {
        static NSString*    showSidebarLabel = nil;
        if (!showSidebarLabel) {
            showSidebarLabel = [NSLocalizedStringFromTable(itemIdentifier, SRMainToolbarLabelTable, nil) retain];
        }
        label = showSidebarLabel;
        image = [_iconImageDict objectForKey:itemIdentifier];
        action = @selector(toggleSidebarAction:);
    }
    // Bookmark page
    else if ([itemIdentifier isEqualToString:SRBookmarkPageIdentifier]) {
        static NSString*    bookmarkPageLabel = nil;
        if (!bookmarkPageLabel) {
            bookmarkPageLabel = [NSLocalizedStringFromTable(itemIdentifier, SRMainToolbarLabelTable, nil) retain];
        }
        label = bookmarkPageLabel;
        image = [_iconImageDict objectForKey:itemIdentifier];
        action = @selector(addToBookmarkAction:);
    }
    // New tab
    else if ([itemIdentifier isEqualToString:SRNewTabIdentifier]) {
        static NSString*    newTabLabel = nil;
        if (!newTabLabel) {
            newTabLabel = [NSLocalizedStringFromTable(itemIdentifier, SRMainToolbarLabelTable, nil) retain];
        }
        label = newTabLabel;
        image = [_iconImageDict objectForKey:itemIdentifier];
        action = @selector(newTabAction:);
    }
    // Close tab
    else if ([itemIdentifier isEqualToString:SRCloseTabIdentifier]) {
        static NSString*    closeTabLabel = nil;
        if (!closeTabLabel) {
            closeTabLabel = [NSLocalizedStringFromTable(itemIdentifier, SRMainToolbarLabelTable, nil) retain];
        }
        label = closeTabLabel;
        image = [_iconImageDict objectForKey:itemIdentifier];
        action = @selector(closeTabAction:);
    }
    // Bigger Text
    else if ([itemIdentifier isEqualToString:SRBiggerTextIdentifier]) {
        static NSString*    biggerTextLabel = nil;
        if (!biggerTextLabel) {
            biggerTextLabel = [NSLocalizedStringFromTable(itemIdentifier, SRMainToolbarLabelTable, nil) retain];
        }
        label = biggerTextLabel;
        image = [_iconImageDict objectForKey:itemIdentifier];
        action = @selector(biggerTextAction:);
    }
    // Smaller Text
    else if ([itemIdentifier isEqualToString:SRSmallerTextIdentifier]) {
        static NSString*    smallerTextLabel = nil;
        if (!smallerTextLabel) {
            smallerTextLabel = [NSLocalizedStringFromTable(itemIdentifier, SRMainToolbarLabelTable, nil) retain];
        }
        label = smallerTextLabel;
        image = [_iconImageDict objectForKey:itemIdentifier];
        action = @selector(smallerTextAction:);
    }
    // Customize
    else if ([itemIdentifier isEqualToString:SRCustomizeIdentifier]) {
        static NSString*    customizeLabel = nil;
        if (!customizeLabel) {
            customizeLabel = [NSLocalizedStringFromTable(itemIdentifier, SRMainToolbarLabelTable, nil) retain];
        }
        label = customizeLabel;
        image = [_iconImageDict objectForKey:itemIdentifier];
        action = @selector(customizeToolbarAction:);
    }
    // Search
    else if ([itemIdentifier isEqualToString:SRSearchIdentifier]) {
        static NSString*    searchLabel = nil;
        if (!searchLabel) {
            searchLabel = [NSLocalizedStringFromTable(itemIdentifier, SRMainToolbarLabelTable, nil) retain];
        }
        
        SRSearchField*  searchField;
        searchField = [[SRSearchField alloc] initWithFrame:NSZeroRect];
        [searchField autorelease];
        [searchField setAction:@selector(searchAction:)];
#if 1
        [[searchField cell] setControlSize:NSSmallControlSize];
        [searchField setFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]];
#else
        if ([defaults boolForKey:SRToolbarUseSmallURLAndSearchField]) {
            [[searchField cell] setControlSize:NSSmallControlSize];
            [searchField setFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]];
        }
        else {
            [[searchField cell] setControlSize:NSRegularControlSize];
            [searchField setFont:[NSFont systemFontOfSize:[NSFont systemFontSize]]];
        }
#endif
        [searchField sizeToFit];
        [[searchField cell] setWraps:NO];
        [[searchField cell] setScrollable:YES];
        [[searchField cell] setSendsWholeSearchString:YES];
        [searchField setFlexible:YES];
        
        [item setView:searchField];
        int width;
        width = [[NSUserDefaults standardUserDefaults] integerForKey:SRSearchFieldWidth];
        if (width < SRSearchFieldMinWidth) {
            width = SRSearchFieldMinWidth;
        }
        if (width > SRSearchFieldMaxWidth) {
            width = SRSearchFieldMaxWidth;
        }
        [item setMinSize:NSMakeSize(width, [searchField frame].size.height)];
        [item setMaxSize:NSMakeSize(width, [searchField frame].size.height)];
        
        NSMenuItem* menuItem;
        menuItem = [[NSMenuItem alloc] initWithTitle:searchLabel 
                action:@selector(findByToolbarAction:) 
                keyEquivalent:@""];
        [menuItem autorelease];
        [item setMenuFormRepresentation:menuItem];
        
        label = searchLabel;
    }
    // Browse
    else if ([itemIdentifier isEqualToString:SRBrowseIdentifier]) {
        static NSString*    browseLabel = nil;
        if (!browseLabel) {
            browseLabel = [NSLocalizedStringFromTable(itemIdentifier, SRMainToolbarLabelTable, @"Browse") retain];
        }
        label = browseLabel;
        
        // For toolbar
        if (flag) {
            NSPopUpButton*  browsePullsDown;
            browsePullsDown = [[NSPopUpButton alloc] initWithFrame:NSMakeRect(0, 0, SRBrowseLargeWidth, SRBrowseLargeHeight) pullsDown:YES];
            [browsePullsDown autorelease];
            [browsePullsDown setBordered:NO];
            //[[browsePullsDown cell] setBezelStyle:NSRegularSquareBezelStyle];
            [browsePullsDown setTarget:self];
            [browsePullsDown setAction:@selector(selectBrowseModeAction:)];
            
            [browsePullsDown addItemWithTitle:@""];
            [[browsePullsDown lastItem] setTag:-1];
            
            // Get menu strings
            NSMenu*     viewMenu;
            NSString*   localized;
            NSMenuItem* menuItem;
            viewMenu = [SRAppDelegate viewMenu];
            _menuFormSubmenu = [[NSMenu alloc] initWithTitle:@""];
            [_menuFormSubmenu autorelease];
            
            // Default
            localized = [[viewMenu itemWithTag:SRDefaultBrowsingTag] title];
            [browsePullsDown addItemWithTitle:localized];
            [[browsePullsDown lastItem] setTag:SRDefaultBrowseMode];
            menuItem = [[NSMenuItem alloc] initWithTitle:localized 
                    action:NULL 
                    keyEquivalent:@""];
            [menuItem setTarget:self];
            [menuItem setAction:@selector(selectBrowseModeAction:)];
            [menuItem setTag:SRDefaultBrowseMode];
            [_menuFormSubmenu addItem:menuItem];
            
            // Same tab
            localized = [[viewMenu itemWithTag:SRAlwaysInSameTabTag] title];
            [browsePullsDown addItemWithTitle:localized];
            [[browsePullsDown lastItem] setTag:SRAlwaysInSameTabBrowseMode];
            menuItem = [[NSMenuItem alloc] initWithTitle:localized 
                    action:NULL 
                    keyEquivalent:@""];
            [menuItem setTarget:self];
            [menuItem setAction:@selector(selectBrowseModeAction:)];
            [menuItem setTag:SRAlwaysInSameTabBrowseMode];
            [_menuFormSubmenu addItem:menuItem];
            
            // New tab
            localized = [[viewMenu itemWithTag:SRAlwaysInNewTabTag] title];
            [browsePullsDown addItemWithTitle:localized];
            [[browsePullsDown lastItem] setTag:SRAlwaysInNewTabBrowseMode];
            menuItem = [[NSMenuItem alloc] initWithTitle:localized 
                    action:NULL 
                    keyEquivalent:@""];
            [menuItem setTarget:self];
            [menuItem setAction:@selector(selectBrowseModeAction:)];
            [menuItem setTag:SRAlwaysInNewTabBrowseMode];
            [_menuFormSubmenu addItem:menuItem];
            
            // Back tab
            localized = [[viewMenu itemWithTag:SRAlwaysInNewBackgroundTabTag] title];
            [browsePullsDown addItemWithTitle:localized];
            [[browsePullsDown lastItem] setTag:SRAlwaysInNewBackgroundTabBrowseMode];
            menuItem = [[NSMenuItem alloc] initWithTitle:localized 
                    action:NULL 
                    keyEquivalent:@""];
            [menuItem setTarget:self];
            [menuItem setAction:@selector(selectBrowseModeAction:)];
            [menuItem setTag:SRAlwaysInNewBackgroundTabBrowseMode];
            [_menuFormSubmenu addItem:menuItem];
            
            [item setView:browsePullsDown];
            
            // Update size
            [item setMinSize:NSMakeSize(SRBrowseSmallWidth, SRBrowseSmallHeight)];
            [item setMaxSize:NSMakeSize(SRBrowseLargeWidth, SRBrowseLargeHeight)];
            [item validate];
            
            // Set menu form
            menuItem = [[NSMenuItem alloc] initWithTitle:browseLabel 
                    action:NULL 
                    keyEquivalent:@""];
            [menuItem autorelease];
            [menuItem setSubmenu:_menuFormSubmenu];
            [item setMenuFormRepresentation:menuItem];
        }
        // For customize palette
        else {
            // Use browse default icon as default
            image = [_iconImageDict objectForKey:SRBrowseDefaultIdentifier];
        }
    }
    
    // Set item attributes
    if (label) {
        [item setLabel:label];
    }
    if (image) {
        [item setImage:image];
    }
    if (action) {
        [item setAction:action];
    }
    if (paletteLabel) {
        [item setPaletteLabel:paletteLabel];
    }
    else {
        if (label) {
            [item setPaletteLabel:label];
        }
    }
    return item;
}

- (void)toolbarWillAddItem:(NSNotification*)notification
{
    // Get item
    NSToolbarItem*  item;
    item = [[notification userInfo] objectForKey:@"item"];
    if (!item) {
        return;
    }
    
    // URL combo box
    if ([[item itemIdentifier] isEqualToString:SRURLIdentifier]) {
        SRURLComboBox*  URLComboBox;
        URLComboBox = (SRURLComboBox*)[item view];
        
        [URLComboBox setTarget:self];
        [URLComboBox setAction:@selector(URLComboBoxAction:)];
        [[URLComboBox cell] setSendsActionOnEndEditing:NO];
        [URLComboBox setCompletes:YES];
        [URLComboBox setDelegate:self];
        [URLComboBox bind:@"value" 
                toObject:_webViewController 
                withKeyPath:@"selection.webViewURLString" 
                options:nil];
        
        return;
    }
}

//--------------------------------------------------------------//
#pragma mark -- NSToolbarItemValidation informal protocol --
//--------------------------------------------------------------//

- (BOOL)validateToolbarItem:(NSToolbarItem*)item
{
    // Get item identifier
    id  identifier;
    identifier = [item itemIdentifier];
    
    // User defaults
    NSUserDefaults* defaults;
    defaults = [NSUserDefaults standardUserDefaults];
    
    // Get selected web view
    WebView*    webView;
    webView = [self selectedWebView];
    
    // Go Back
    if ([identifier isEqualToString:SRGoBackIdentifier]) {
        if (!webView) {
            return NO;
        }
        
        return [webView canGoBack];
    }
    // Go Forward
    if ([identifier isEqualToString:SRGoForwardIdentifier]) {
        if (!webView) {
            return NO;
        }
        return [webView canGoForward];
    }
    // Reload Page
    if ([identifier isEqualToString:SRReloadPageIdentifier]) {
        if (!webView) {
            return NO;
        }
        
        // Get data source
        WebDataSource*  provisionalDataSource;
        WebDataSource*  dataSource;
        provisionalDataSource = [[webView mainFrame] provisionalDataSource];
        dataSource = [[webView mainFrame] dataSource];
        
        if (provisionalDataSource) {
            return ![provisionalDataSource isLoading];
        }
        if (dataSource) {
            if (![dataSource request]) {
                return NO;
            }
            return ![dataSource isLoading];
        }
        return NO;
    }
    // Stop Loading
    if ([identifier isEqualToString:SRStopLoadingIdentifier]) {
        if (!webView) {
            return NO;
        }
        
        // Get data source
        WebDataSource*  provisionalDataSource;
        WebDataSource*  dataSource;
        provisionalDataSource = [[webView mainFrame] provisionalDataSource];
        dataSource = [[webView mainFrame] dataSource];
        
        if (provisionalDataSource) {
            return [provisionalDataSource isLoading];
        }
        if (dataSource) {
            if (![dataSource request]) {
                return NO;
            }
            return [dataSource isLoading];
        }
        return NO;
    }
    // Go Home
    if ([identifier isEqualToString:SRGoHomeIdentifier]) {
        // Get home page URL
        NSString*   URLString;
        URLString = [[[NSApp delegate] preferencesController] homeURLString];
        return URLString && [URLString length] > 0;
    }
    // Show Sidebar
    if ([identifier isEqualToString:SRSidebarIdentifier]) {
        // Check draewr state
        int state;
        state = [[_sideBarController drawer] state];
        if (state == NSDrawerClosedState || 
            state == NSDrawerClosingState)
        {
            //[item setImage:];
        }
        else {
            //[item setImage:];
        }
        
        // Always YES
        return YES;
    }
    // Bookmark Page
    if ([identifier isEqualToString:SRBookmarkPageIdentifier]) {
        if (!webView) {
            return NO;
        }
        return [[[webView mainFrame] dataSource] request] != nil;
    }
    // New Tab
    if ([identifier isEqualToString:SRNewTabIdentifier]) {
        // Check tab browsing
        return [defaults boolForKey:SRTabEnableTabbedBrowsing];
    }
    // Close Tab
    if ([identifier isEqualToString:SRCloseTabIdentifier]) {
        // Check tab browsing
        if (![defaults boolForKey:SRTabEnableTabbedBrowsing]) {
            return NO;
        }
        
        // Check number of tab
        if ([_srTabView numberOfItems] < 2) {
            return NO;
        }
        
        return YES;
    }
    // Bigger Text
    if ([identifier isEqualToString:SRBiggerTextIdentifier]) {
        if (!webView) {
            return NO;
        }
        return [webView canMakeTextLarger];
    }
    // Smaller Text
    if ([identifier isEqualToString:SRSmallerTextIdentifier]) {
        if (!webView) {
            return NO;
        }
        return [webView canMakeTextSmaller];
    }
    // Customize
    if ([identifier isEqualToString:SRCustomizeIdentifier]) {
        // Always YES
        return YES;
    }
    
    return NO;
}

//--------------------------------------------------------------//
#pragma mark -- WebViewImageEx notification --
//--------------------------------------------------------------//

- (void)webImageSizeChanged:(NSNotification*)notification
{
    // Get web view, data source and request
    WebView*        webView;
    WebDataSource*  dataSource;
    webView = [self selectedWebView];
    dataSource = [[webView mainFrame] dataSource];
    if (!dataSource) {
        dataSource = [[webView mainFrame] provisionalDataSource];
    }
    
    // Reset window title
    [self setValue:[dataSource pageTitle] forKey:SRMainWebViewTitle];
}

//--------------------------------------------------------------//
#pragma mark -- WebIconDatabase notification --
//--------------------------------------------------------------//

- (void)faviconAdded:(NSNotification*)notification
{
    NSUserDefaults* defaults;
    defaults = [NSUserDefaults standardUserDefaults];
    
    // Check favicon availability
    BOOL    isFaviconUsed;
    isFaviconUsed = [defaults boolForKey:SRIconUseFavicon];
    if (isFaviconUsed) {
        // Get web view, data source and request
        WebView*        webView;
        WebDataSource*  dataSource;
        NSURLRequest*   request;
        webView = [self selectedWebView];
        dataSource = [[webView mainFrame] dataSource];
        if (!dataSource) {
            dataSource = [[webView mainFrame] provisionalDataSource];
        }
        request = [dataSource request];
        
        if (request) {
            // Get URL string
            NSString*   URLString;
            NSImage*    icon;
            URLString = [[request URL] absoluteString];
            icon = [[WebIconDatabase sharedIconDatabase] iconForURL:URLString withSize:NSMakeSize(16, 16)];
            
            // Set icon
            if (icon) {
                [[self URLComboBox] setImage:icon];
            }
        }
    }
    
    // Update bookmark bar
    [_bookmarksBarView updateButtons];
}

//--------------------------------------------------------------//
#pragma mark -- NSWindow delegate --
//--------------------------------------------------------------//

- (void)windowDidBecomeKey:(NSNotification*)notification
{
    // Update file menu
    [[[[NSApp mainMenu] itemWithTag:SRFileTag] submenu] update];
}

- (void)windowDidBecomeMain:(NSNotification*)notification
{
    // Change first responder
    NSWindow*       window;
    WebView*        webView;
    WebDataSource*  dataSource;
    window = [self window];
    webView = [self selectedWebView];
    dataSource = [[webView mainFrame] dataSource];
    if (!dataSource) {
        [window makeFirstResponder:[self URLComboBox]];
    }

    // Invoke _showSideBar after a moment
    if (!_isResizedByJavaScript && !_isInitializedSidebarVisibility) {
        [self performSelector:@selector(_showSideBar:) withObject:self afterDelay:0.1];
        _isInitializedSidebarVisibility = YES;
    }
    
    // Notify change
    [[NSNotificationCenter defaultCenter] 
            postNotificationName:SRMainWindowDidBecomeMain object:webView];
}

- (void)_showSideBar:(id)sender
{
    // This method will be called only once in intialize phase
    
    NSUserDefaults* defaults;
    defaults = [NSUserDefaults standardUserDefaults];
    
    // Check sidebar visiblity
    BOOL    isSidebarVisible;
    isSidebarVisible = [defaults boolForKey:SRMainWindowSidebarVisible];
    if (isSidebarVisible) {
        // Set sidebar visibility only for first window
        [self setSidebarVisible:YES];
    }
}

- (void)windowDidResignMain:(NSNotification*)notification
{
    // Notify change
    [[NSNotificationCenter defaultCenter] 
            postNotificationName:SRMainWindowDidResignMain object:[self selectedWebView]];
}

- (void)windowDidMove:(NSNotification*)notification
{
    // Check flag
    if (_isResizedByJavaScript) {
        return;
    }
    
    // Get origin
    NSWindow*   window;
    NSPoint     origin;
    window = [notification object];
    origin = [window frame].origin;
    origin.y += [window frame].size.height;
    
    // Save to defaults database
    NSUserDefaults* defaults;
    defaults = [NSUserDefaults standardUserDefaults];
    [defaults setObject:NSStringFromPoint(origin) 
            forKey:SRMainWindowFrameOrigin];
}

- (void)windowDidResize:(NSNotification*)notification
{
    // Check flag
    if (_isResizedByJavaScript) {
        return;
    }
    if ([[self sideBarController] isResizedByDrawer]) {
        return;
    }
    
    // Get size
    NSWindow*   window;
    NSSize      size;
    window = [notification object];
    size = [[window contentView] frame].size;
    
    // Save to defaults database
    NSUserDefaults* defaults;
    defaults = [NSUserDefaults standardUserDefaults];
    [defaults setObject:NSStringFromSize(size) 
            forKey:SRMainWindowContentSize];
}

- (NSRect)windowWillUseStandardFrame:(NSWindow*)window defaultFrame:(NSRect)defaultFrame
{
    // Get selected web view
    WebView*    webView;
    webView = [self selectedWebView];
    if (!webView) {
        return defaultFrame;
    }
    
    // Get document view
    id  documentView;
    documentView = [[[webView mainFrame] frameView] documentView];
    if (!documentView) {
        return defaultFrame;
    }
    
    // Get current window frame
    NSRect  windowFrame;
    windowFrame = [[self window] frame];
    
    // Decide new frame
    NSSize  size;
    NSRect  frame = defaultFrame;
    size = [documentView frame].size;
    frame.origin.x = windowFrame.origin.x;
    frame.size.width = size.width;
    
    // When frame view has scroll bars
    NSArray*    subviews;
    subviews = [[[webView mainFrame] frameView] subviews];
    if ([subviews count] > 0) {
        id  subview;
        subview = [subviews objectAtIndex:0];
        if ([subview isKindOfClass:[NSScrollView class]]) {
            if ([subview hasVerticalScroller]) {
                frame.size.width += [NSScroller scrollerWidth];
            }
        }
    }
    
    return frame;
}

- (BOOL)shouldCloseDocument
{
    return YES;
}

- (void)windowWillClose:(NSNotification*)notification
{
	// Clean up tab view
	[_srTabView removeAllItems];
	
    // Unbind from URL combo box
	[[self URLComboBox] unbind:@"value"];
    
    // Close side bar
    [[_sideBarController drawer] close];
    
    // Clear web view controller content
    [_webViewController setContent:nil];
    
    // Remove parent window of drawer
    [[_sideBarController drawer] setParentWindow:nil];
    
    // Notify change
    [[NSNotificationCenter defaultCenter] 
            postNotificationName:SRMainWindowWillClose object:[self selectedWebView]];
}

//--------------------------------------------------------------//
#pragma mark -- SRTabView delegate --
//--------------------------------------------------------------//

- (void)srTabView:(SRTabView*)tabView 
        didSelectTabViewItem:(SRTabViewItem*)tabViewItem
{
    NSUserDefaults* defaults;
    defaults = [NSUserDefaults standardUserDefaults];
    
    // Check favicon availability
    BOOL    isFaviconUsed;
    isFaviconUsed = [defaults boolForKey:SRIconUseFavicon];
    
    // Get web view, data source and request
    WebView*        webView;
    WebDataSource*  dataSource;
    BOOL            isIndeterminate = NO;
    NSURLRequest*   request;
    webView = (WebView*)[tabViewItem view];
    dataSource = [[webView mainFrame] dataSource];
    if (!dataSource) {
        dataSource = [[webView mainFrame] provisionalDataSource];
        
        // If there is provisional data source, isIndeterminate is true
        isIndeterminate = dataSource != nil;
    }
    request = [dataSource request];
    
    if (!request) {
        // Set window title
        [self setValue:NSLocalizedString(@"Untitled", @"Untitled") forKey:SRMainWebViewTitle];
        // Set URL String
        [self setValue:@"" forKey:SRMainWebViewURLString];
        // Set status message
        [self setValue:@"" forKey:SRMainWebViewStatus];
        // Set loading
        [self setValue:[NSNumber numberWithBool:NO] forKey:SRMainWebViewIsLoading];
        [self setValue:[NSNumber numberWithBool:NO] forKey:SRMainWebViewIsIndeterminate];
        // Set icon
        [[self URLComboBox] setImage:[[WebIconDatabase sharedIconDatabase] defaultIconWithSize:NSMakeSize(16, 16)]];
        // Set secure
        [self setValue:[NSNumber numberWithBool:NO] forKey:SRMainWebViewIsSecured];
        [_lockIconView setHidden:YES];
        [_RSSButton setHidden:YES];
    }
    else {
        // Get URL string
        NSURL*      url;
        NSString*   URLString;
        url = [request URL];
        URLString = [url _web_userVisibleString];
        
        // Set window title
        [self setValue:[dataSource pageTitle] forKey:SRMainWebViewTitle];
        // Set URL String
        [self setValue:URLString forKey:SRMainWebViewURLString];
        // Set status message
        [self setValue:@"" forKey:SRMainWebViewStatus];
        // Set loading
        [self setValue:[NSNumber numberWithBool:[dataSource isLoading]] 
                forKey:SRMainWebViewIsLoading];
        [self setValue:[NSNumber numberWithBool:isIndeterminate] 
                forKey:SRMainWebViewIsIndeterminate];
        // Set icon
        if (isFaviconUsed) {
            [[self URLComboBox] setImage:
                    [[WebIconDatabase sharedIconDatabase] iconForURL:URLString 
                            withSize:NSMakeSize(16, 16) 
                            cache:YES]];
        }
        // Set secure
        [self setValue:[NSNumber numberWithBool:[[url scheme] isEqualToString:@"https"]] 
                forKey:SRMainWebViewIsSecured];
        [_lockIconView setHidden:![[url scheme] isEqualToString:@"https"]];
        
#ifdef SR_SUPPORT_RSS
        // RSS button
        [_RSSButton setHidden:![self hasRSSLinkAtWebView:webView]];
#endif // SR_SUPPORT_RSS
    }
    
    // Change first responder
    NSWindow*   window;
    window = [self window];
    if (!dataSource) {
        [window makeFirstResponder:[self URLComboBox]];
    }
    
    // Check error
    NSDictionary*   errorInfo;
    errorInfo = [tabViewItem userInfo];
    if (errorInfo) {
        // Show error dialog
        NSError*    error;
        WebFrame*   frame;
        error = [errorInfo objectForKey:@"error"];
        frame = [errorInfo objectForKey:@"frame"];
        if (error && frame) {
            [self showAlertWithError:error forFrame:frame];
        }
        
        // Clear user info
        [tabViewItem setUserInfo:nil];
    }
    
    // Notify change
    [[NSNotificationCenter defaultCenter] 
            postNotificationName:SRMainWindowSelectedWebViewChanged object:webView];
}

- (void)srTabViewDidChangeNumberOfTabViewItems:(SRTabView*)tabView
{
    // Update menu
    [[[[NSApp mainMenu] itemWithTag:SRFileTag] submenu] update];
}

//--------------------------------------------------------------//
#pragma mark -- NSComboBox delegate --
//--------------------------------------------------------------//

- (void)comboBoxWillDismiss:(NSNotification*)notification
{
    // Get combo box
    NSComboBox* combo;
    combo = [notification object];
    
    // Select text
    [combo selectText:self];
    
    // For enter key pressing event
    NSEvent*    event;
    event = [NSApp currentEvent];
    if ([event type] == NSKeyDown) {
        // Send action only enter key is pressed
        [[combo target] performSelector:[combo action] withObject:combo];
    }
}

- (void)comboBoxWillPopUp:(NSNotification*)notification
{
    // Get combo box
    NSComboBox* combo;
    combo = [notification object];
    
    // Select first one
    if ([combo numberOfItems] > 0) {
        [combo selectItemAtIndex:0];
    }
}

//- (void)comboBoxSelectionIsChanging:(NSNotification*)notification

- (void)comboBoxSelectionDidChange:(NSNotification*)notification
{
    // Get combo box
    NSComboBox* combo;
    combo = [notification object];
    
    // Get selected index
    int selectedIndex;
    selectedIndex = [combo indexOfSelectedItem];
    
    // Select item again. It changes string value of combo box
    [combo selectItemAtIndex:selectedIndex];
}

//--------------------------------------------------------------//
#pragma mark -- NSControl delegate --
//--------------------------------------------------------------//

- (void)controlTextDidChange:(NSNotification*)notification
{
    id  control;
    control = [notification object];
    
    // For SRURLComboBox
    if ([control isKindOfClass:[SRURLComboBox class]]) {
        // Get string
        NSString*   string;
        string = [control stringValue];
        
        // Remove new line characters
        NSCharacterSet* newLineCharacterSet;
        newLineCharacterSet = [NSCharacterSet newLineCharacterSet];
        if ([string rangeOfCharacterFromSet:newLineCharacterSet 
                options:NSLiteralSearch].location != NSNotFound)
        {
            string = [string stringByTrimmingCharactersInSet:newLineCharacterSet];
            
            [control setStringValue:string];
        }
        
        // Clear image
        [control setImage:[[WebIconDatabase sharedIconDatabase] defaultIconWithSize:NSMakeSize(16, 16)]];
    }
}

//--------------------------------------------------------------//
#pragma mark -- SRBookmarkStorage notification --
//--------------------------------------------------------------//

- (void)bookmarkUpdated:(NSNotification*)notification
{
    NSUserDefaults* defaults;
    defaults = [NSUserDefaults standardUserDefaults];
    
    // Get browser
    int browser;
    browser = [defaults integerForKey:SRBookmarkBookmarksBar];
    
    // Set bookmarks browser
    [self setBookmarksBarBrowser:browser];
}

//--------------------------------------------------------------//
#pragma mark -- Key value observation --
//--------------------------------------------------------------//

- (void)observeValueForKeyPath:(NSString*)keyPath 
        ofObject:(id)object 
        change:(NSDictionary*)change 
        context:(void *)context
{
    // Browse mode
    if ([keyPath isEqualToString:SRBrowseMode]) {
        // Validate browse toolbar
        id  toolbarItem;
        toolbarItem = [[[self window] toolbar] toolbarItemWithIdentifier:SRBrowseIdentifier];
        if (toolbarItem) {
            [toolbarItem validate];
        }
    }
    
    // Bookmark preferences
    if ([keyPath isEqualToString:SRBookmarkBookmarksBar]) {
        // Get value
        int browser;
        browser = [object integerForKey:SRBookmarkBookmarksBar];
        
        // Set bookmarks browser
        [self setBookmarksBarBrowser:browser];
        return;
    }
    
    // Tab preferences
    if ([keyPath isEqualToString:SRTabEnableTabbedBrowsing]) {
        // Get value
        BOOL    isEnabled;
        isEnabled = [object boolForKey:SRTabEnableTabbedBrowsing];
        
        // Set visible
        [self setTabVisible:isEnabled display:YES];
        
        // Update file menu
        [[[[NSApp mainMenu] itemWithTag:SRFileTag] submenu] update];
        return;
    }
    if ([keyPath isEqualToString:SRTabSelectNewTabs]) {
        // Do nothing
        return;
    }
    if ([keyPath isEqualToString:SRTabAlwaysShowTabBar]) {
        // Get value
        BOOL    isEnabled;
        isEnabled = [object boolForKey:SRTabAlwaysShowTabBar];
        
        // Set value
        [_srTabView setTabShownAlways:isEnabled];
        return;
    }
    if ([keyPath isEqualToString:SRTabAccordingToStringWidth]) {
        // Get value
        BOOL    isAccordingTo;
        isAccordingTo = [object boolForKey:SRTabAccordingToStringWidth];
        
        // Set value
        [_srTabView setAccordingToStringWidth:isAccordingTo];
        return;
    }
    
    // Securrity preference
    if ([keyPath isEqualToString:SREnableJavaScirptStatusMessage]) {
        // Get value
        BOOL    isEnabled;
        isEnabled = [object boolForKey:SREnableJavaScirptStatusMessage];
        
        // Clear status message
        if (!isEnabled) {
            [self setValue:@"" forKey:SRMainWebViewStatus];
        }
    }
    
    // Advanced preference
    if ([keyPath isEqualToString:SRUserAgent]) {
        // Get value
        int userAgent;
        userAgent = [object integerForKey:SRUserAgent];
        [self setUserAgent:userAgent];
        
        // Check SRUserAgentOtherIsUging
        BOOL    isUsing;
        isUsing = [object boolForKey:SRUserAgentOtherIsUging];
        
        if ((userAgent == SRUserAgentOther && !isUsing) || 
            (userAgent != SRUserAgentOther && isUsing))
        {
            [object setBool:!isUsing forKey:SRUserAgentOtherIsUging];
        }
        
        return;
    }
    if ([keyPath isEqualToString:SRUserAgentOtherName]) {
        // Update user agent
        [self setUserAgent:SRUserAgentOther];
        return;
    }
    
    // Icon preference
    if ([keyPath isEqualToString:SRIconName] || 
        [keyPath isEqualToString:SRIconMetalName])
    {
        // Get toolbar icons
        NSString*   iconName = nil;
        if ([keyPath isEqualToString:SRIconName] && 
            !([[self window] styleMask] & NSTexturedBackgroundWindowMask))
        {
            iconName = [object stringForKey:SRIconName];
        }
        else if ([keyPath isEqualToString:SRIconMetalName] && 
                 [[self window] styleMask] & NSTexturedBackgroundWindowMask)
        {
            iconName = [object stringForKey:SRIconMetalName];
        }
        
        if (!iconName) {
            return;
        }
        
        [_iconImageDict release];
        _iconImageDict = [[[[NSApp delegate] iconInstaller] iconsOfName:iconName] retain];
        
        // Update toolbar icon
        NSArray*        items;
        NSEnumerator*   enumerator;
        NSToolbarItem*  item;
        items = [[[self window] toolbar] items];
        enumerator = [items objectEnumerator];
        while (item = [enumerator nextObject]) {
            NSImage*    image;
            image = [_iconImageDict objectForKey:[item itemIdentifier]];
            if (image) {
                [item setImage:image];
            }
        }
    }
    if ([keyPath isEqualToString:SRIconUseFavicon] || 
        [keyPath isEqualToString:SRIconUseFaviconBookmarkBar])
    {
        // Update bookmark bar
        [_bookmarksBarView updateButtons];
        [_bookmarksBarView setNeedsDisplay:YES];
    }
    
    // URL string
    if ([keyPath isEqualToString:SRMainWebViewURLString]) {
        // Get URL combo box
        SRURLComboBox*  comboBox;
        comboBox = [self URLComboBox];
        if (!comboBox) {
            return;
        }
        
        BOOL    showIDNButton = NO;
        
        // Check URL string
        if ([_webViewURLString length] > 0) {
            // Create NSURL and get host
            NSURL*      url;
            NSString*   host;
            url = [NSURL _web_URLWithUserTypedString:_webViewURLString];
            host = [url host];
            // For Punycode host
            if (host && [host rangeOfString:@"xn--"].location != NSNotFound) {
                showIDNButton = YES;
            }
        }
        
        // Get URL IDN button
        NSButton*   button;
        button = [comboBox buttonWithTag:SRURLButtonIDN];
        
        // Hide button
        if (!showIDNButton) {
            if (button) {
                [comboBox removeButton:button];
            }
        }
        // Show button
        else {
            if (!button) {
                button = [comboBox addButtonWithSize:NSMakeSize(16, 16)];
                [button setTag:SRURLButtonIDN];
                [button setBordered:NO];
                [button setButtonType:NSMomentaryLight];
                [button setImage:[NSImage imageNamed:@"idn"]];
                [button setTarget:self];
                [button setAction:@selector(toggleURLIDNAction:)];
            }
        }
    }
}

@end

#pragma mark -

@implementation SRBrowseToolbarItem

- (void)validate
{
    static NSArray* _browseIdentifiers = nil;
    if (!_browseIdentifiers) {
        _browseIdentifiers = [[NSArray arrayWithObjects:
                SRBrowseDefaultIdentifier, SRBrowseTabIdentifier, 
                SRBrowseNewTabIdentifier, SRBrowseBackTabIdentifier, 
                nil] retain];
    }
    
    NSUserDefaults* defaults;
    defaults = [NSUserDefaults standardUserDefaults];
    
    // Get pulls down
    NSPopUpButton*  pullsDown;
    pullsDown = (NSPopUpButton*)[self view];
    
    // Get browse mode
    int browseMode;
    browseMode = [defaults integerForKey:SRBrowseMode];
    if (browseMode > SRNumberOfBrowseMode) {
        browseMode = SRDefaultBrowseMode;
    }
    
    // Select poup menu
    id<NSMenuItem>  menuItem;
    int i;
    for (i = 1; i < [pullsDown numberOfItems]; i++) {
        menuItem = [pullsDown itemAtIndex:i];
        [menuItem setState:i - 1 == browseMode ? NSOnState : NSOffState];
    }
    
    // Get toolbar
    NSToolbar*  toolbar;
    toolbar = [self toolbar];
    
    // Get size mode
    NSToolbarSizeMode   sizeMode;
    NSSize              iconSize = { 32, 32 };
    sizeMode = [toolbar sizeMode];
    if (sizeMode == NSToolbarSizeModeSmall) {
        iconSize.width = 24;
        iconSize.height = 24;
    }
    
    // Set size
    NSRect  frame;
    frame = [pullsDown frame];
    if (sizeMode == NSToolbarSizeModeSmall && frame.size.height != SRBrowseSmallHeight) {
        frame.origin.y += (frame.size.height - SRBrowseSmallHeight) / 2;
        frame.size.height = SRBrowseSmallHeight;
        [pullsDown setFrame:frame];
    }
    else if (sizeMode != NSToolbarSizeModeSmall && frame.size.height != SRBrowseLargeHeight) {
        frame.origin.y += (frame.size.height - SRBrowseLargeHeight) / 2;
        frame.size.height = SRBrowseLargeHeight;
        [pullsDown setFrame:frame];
    }
    
    // Swap top icon
    NSImage*    icon;
    menuItem = [pullsDown itemAtIndex:0];
    if ([menuItem tag] != browseMode) {
        icon = [[_iconImageDict objectForKey:[_browseIdentifiers objectAtIndex:browseMode]] copy];
        [icon setScalesWhenResized:YES];
        [icon setSize:iconSize];
        menuItem = [pullsDown itemAtIndex:0];
        [menuItem setImage:icon];
        [menuItem setTag:browseMode];
    }
    
    // Check icon size of first menu item
    icon = [[pullsDown itemAtIndex:1] image];
    if (!NSEqualSizes(iconSize, [icon size])) {
        // Reset icon size
        for (i = 0; i < [pullsDown numberOfItems]; i++) {
            if (i == 0) {
                icon = [[_iconImageDict objectForKey:[_browseIdentifiers objectAtIndex:browseMode]] copy];
            }
            else {
                icon = [[_iconImageDict objectForKey:[_browseIdentifiers objectAtIndex:i - 1]] copy];
            }
            [icon setScalesWhenResized:YES];
            [icon setSize:iconSize];
            menuItem = [pullsDown itemAtIndex:i];
            [menuItem setImage:icon];
        }
    }
}

@end

#pragma mark -

SROpenActionType SROpenActionTypeFromModifierFlags(
        unsigned modifierFlags)
{
    NSUserDefaults* defaults;
    defaults = [NSUserDefaults standardUserDefaults];
    
    // Get modifier key flag
    unsigned int    cmdFlag, optionFlag, shiftFlag;
    cmdFlag = modifierFlags & NSCommandKeyMask;
    optionFlag = modifierFlags & NSAlternateKeyMask;
    shiftFlag = modifierFlags & NSShiftKeyMask;
    
    // For option key
    if (!cmdFlag && optionFlag && !shiftFlag) {
        return SROpenOptionAction;
    }
    
    // Check tab browsing
    BOOL    enableTabbedBrowsing, selectNewTabs;
    enableTabbedBrowsing = [defaults boolForKey:SRTabEnableTabbedBrowsing];
    selectNewTabs = [defaults boolForKey:SRTabSelectNewTabs];
    
    // If tabbed browsing is enable
    if (enableTabbedBrowsing) {
        // If select new tabs
        if (selectNewTabs) {
            // Open in new tabs and select it
            if (cmdFlag && !optionFlag && !shiftFlag) {
                return SROpenInNewTabAction;
            }
            // Open in new tabs
            else if (cmdFlag && !optionFlag && shiftFlag) {
                return SROpenInNewBackgroundTabAction;
            }
            // Open in new window
            else if (cmdFlag && optionFlag && !shiftFlag) {
                return SROpenInNewWindowAction;
            }
            // Open in new window in background
            else if (cmdFlag && optionFlag && shiftFlag) {
                return SROpenInNewBackgroundWindowAction;
            }
        }
        // If not select new tabs
        else {
            // Open in new tabs
            if (cmdFlag && !optionFlag && !shiftFlag) {
                return SROpenInNewBackgroundTabAction;
            }
            // Open in new tabs and select it
            else if (cmdFlag && !optionFlag && shiftFlag) {
                return SROpenInNewTabAction;
            }
            // Open in new window in background
            else if (cmdFlag && optionFlag && !shiftFlag) {
                return SROpenInNewBackgroundWindowAction;
            }
            // Open in new window
            else if (cmdFlag && optionFlag && shiftFlag) {
                return SROpenInNewWindowAction;
            }
        }
    }
    // If tabbed browsing is disable
    else {
        // Open in new window
        if (cmdFlag && !shiftFlag) {
            return SROpenInNewWindowAction;
        }
        // Open in new window in background
        else if (cmdFlag && shiftFlag) {
            return SROpenInNewBackgroundWindowAction;
        }
    }
    
    return SROpenAction;
}
