2705 lines
80 KiB
C++
2705 lines
80 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
|
*
|
|
* The contents of this file are subject to the Netscape Public License
|
|
* Version 1.0 (the "NPL"); you may not use this file except in
|
|
* compliance with the NPL. You may obtain a copy of the NPL at
|
|
* http://www.mozilla.org/NPL/
|
|
*
|
|
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
|
* for the specific language governing rights and limitations under the
|
|
* NPL.
|
|
*
|
|
* The Initial Developer of this code under the NPL is Netscape
|
|
* Communications Corporation. Portions created by Netscape are
|
|
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
|
* Reserved.
|
|
*/
|
|
|
|
#include "Netscape_Constants.h"
|
|
#include "CBrowserWindow.h"
|
|
#ifdef MOZ_OFFLINE
|
|
#include "MailNewsgroupWindow_Defines.h" // for the offline button id
|
|
#endif //MOZ_OFFLINE
|
|
|
|
#include "CAutoPtrXP.h"
|
|
|
|
#include "CBevelView.h"
|
|
#include "CApplicationEventAttachment.h"
|
|
#include "CHTMLView.h"
|
|
#include "CBrowserContext.h"
|
|
#include "CHistoryMenu.h"
|
|
#include "mimages.h"
|
|
#include "mversion.h"
|
|
#include "CURLEditField.h"
|
|
#include "CURLCaption.h"
|
|
#include "CProxyPane.h"
|
|
#include "URDFUtilities.h" // for LaunchURL
|
|
|
|
//#include "CEditView.h" // need for SetWindowContext, using CEditView::class_ID
|
|
#include "CEditorWindow.h"
|
|
// need these for dynamic window modification - mjc
|
|
#include "CDragBar.h" // need for GetChromeInfo
|
|
#include "CDragBarContainer.h" // need for SetChromeInfo, using CDragBarContainer::class_ID
|
|
#include "CHyperScroller.h" // need for SetChromeInfo
|
|
#include "CPaneEnabler.h"
|
|
#include "UDeferredTask.h"
|
|
|
|
#include "CSpinningN.h"
|
|
#include "CBrowserSecurityButton.h"
|
|
#include "CMiniSecurityButton.h"
|
|
|
|
#include "CRDFCoordinator.h"
|
|
#include "CRDFToolbarContainer.h" // to handle HT commands, we need to tell the container
|
|
|
|
// stuff added by deeje
|
|
#include "macutil.h"
|
|
#include "xp.h"
|
|
#include "uerrmgr.h" // GetPString prototype
|
|
#include "shist.h"
|
|
#include "resgui.h"
|
|
#include "CURLDispatcher.h"
|
|
#include "prefapi.h"
|
|
#include "CPrefsDialog.h"
|
|
#include "xp_ncent.h" // for XP_SetLastActiveContext
|
|
|
|
|
|
#include "libi18n.h"
|
|
#include "ufilemgr.h"
|
|
|
|
// stuff for AppleEvent support
|
|
#include "CAppleEventHandler.h"
|
|
#include "resae.h"
|
|
#include "uapp.h"
|
|
|
|
#include "CMochaHacks.h" // for SendMoveEvent, SendResizeEvent, and RemoveDependents 1997-02-26 mjc
|
|
|
|
#include "RandomFrontEndCrap.h" // for IsSpecialBrowserWindow
|
|
|
|
#include <UReanimator.h>
|
|
#include <UMemoryMgr.h>
|
|
#include <Sound.h>
|
|
|
|
// pane id constants - for SetChromeInfo and GetChromeInfo - mjc
|
|
const PaneIDT HTML_Container_PaneID = 'HtCt';
|
|
const PaneIDT Button_Bar_PaneID = 'NBar';
|
|
const PaneIDT Location_Bar_PaneID = 'LBar';
|
|
const PaneIDT Directory_Bar_PaneID = 'DBar';
|
|
const PaneIDT PersonalToolbar_PaneID = 'PBar';
|
|
const PaneIDT SWatch_View_PaneID = 'SwBv';
|
|
const PaneIDT Hyper_Scroller_PaneID = 1005;
|
|
const PaneIDT Status_Bar_PaneID = 'StBv';
|
|
const PaneIDT CoBrandLogo_PaneID = 'Bnet';
|
|
|
|
// These are obsolete once scc puts in the configurable toolbars. They should go away for 5.0
|
|
const char* Pref_ShowToolbar = "browser.chrome.show_toolbar";
|
|
const char* Pref_ShowLocationBar = "browser.chrome.show_url_bar";
|
|
const char* Pref_ShowPersonalToolbar = "browser.chrome.show_personal_toolbar";
|
|
|
|
enum { eNavigationBar,
|
|
eLocationBar,
|
|
eStatusBar,
|
|
ePersonalToolbar };
|
|
|
|
|
|
CPopdownRDFCoordinator* CBrowserWindow::sPopdownParent = NULL;
|
|
|
|
|
|
// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
// ¥
|
|
// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
|
|
CBrowserWindow::CBrowserWindow(LStream* inStream)
|
|
: CNetscapeWindow(inStream, WindowType_Browser),
|
|
CSaveWindowStatus(this)
|
|
{
|
|
mProgressListener = NULL;
|
|
mContext = NULL;
|
|
mAlwaysOnBottom = false; // javascript alwaysLowered window property - mjc
|
|
mZLocked = false;
|
|
mMenubarMode = BrWn_Menubar_Default;
|
|
mCommandsDisabled = false;
|
|
fCloseNotifier = MakeNoProcessPSN();
|
|
mSupportsPageServices = false;
|
|
mAllowSubviewPopups = true;
|
|
mIsRootDocInfo = false;
|
|
mIsViewSource = false;
|
|
mIsHTMLHelp = false;
|
|
mHTMLView = nil;
|
|
mNavCenterParent = nil;
|
|
mToolbarContainer = nil;
|
|
|
|
mPopdownParent = nil; // popdown tree view stuff
|
|
mSavedPopdownTarget = nil;
|
|
}
|
|
|
|
// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
// ¥
|
|
// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
|
|
CBrowserWindow::~CBrowserWindow()
|
|
{
|
|
delete mProgressListener;
|
|
if (mContext != NULL) CMochaHacks::RemoveDependents(*mContext); // close windows declared as dependents in Javascript - 1997-02-26 mjc
|
|
SetWindowContext(NULL);
|
|
|
|
RemoveAllAttachments();
|
|
// Kludgy, but prevents crash in LUndoer caused by view being destroyed before
|
|
// attachments. This happens if a form element which is a text field exists.
|
|
|
|
// if there is a popdown window it will be destroyed when the view hierarchy is
|
|
// destroyed so we don't need to delete it ourselves.
|
|
ClosePopdownTreeView();
|
|
|
|
}
|
|
|
|
// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
// ¥
|
|
// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
|
|
void CBrowserWindow::FinishCreateSelf(void)
|
|
{
|
|
CNetscapeWindow::FinishCreateSelf();
|
|
|
|
mHTMLView = dynamic_cast<CHTMLView*>(FindPaneByID(CHTMLView::pane_ID));
|
|
ThrowIfNil_(mHTMLView);
|
|
|
|
mNavCenterParent = dynamic_cast<CDockedRDFCoordinator*>(FindPaneByID(CDockedRDFCoordinator::pane_ID));
|
|
|
|
if (HasAttribute(windAttr_Regular) && HasAttribute(windAttr_Resizable))
|
|
FinishCreateWindow();
|
|
AdjustStagger(WindowType_Browser); // <--- I moved this down to CNetscapeWindow - jrm 98/04/14
|
|
UReanimator::LinkListenerToControls(this, this, mPaneID);
|
|
|
|
// Get the toolbar container. If it is an RDF container, store it so that we can send HT
|
|
// commands to it later. Recall that editor has a 'DbCt' as well
|
|
mToolbarContainer = dynamic_cast<CRDFToolbarContainer*>(FindPaneByID('DbCt'));
|
|
|
|
// Show/hide toolbars based on preference settings
|
|
XP_Bool value;
|
|
PREF_GetBoolPref(Pref_ShowToolbar, &value);
|
|
mToolbarShown[eNavigationBar] = value;
|
|
ShowOneDragBar(Button_Bar_PaneID, value);
|
|
PREF_GetBoolPref(Pref_ShowLocationBar, &value);
|
|
mToolbarShown[eLocationBar] = value;
|
|
ShowOneDragBar(Location_Bar_PaneID, value);
|
|
PREF_GetBoolPref(Pref_ShowPersonalToolbar, &value);
|
|
mToolbarShown[ePersonalToolbar] = value;
|
|
ShowOneDragBar(PersonalToolbar_PaneID, value);
|
|
mToolbarShown[eStatusBar] = TRUE; // no pref for status bar
|
|
|
|
// Handle NavCenter pane.
|
|
//
|
|
//¥¥¥For now, always hide it at startup, but this will proabably change, hopefully
|
|
//¥¥¥with an XP callback so this code can stay the same...
|
|
if ( mNavCenterParent ) {
|
|
mNavCenterParent->NavCenterShelf().SetShelfState ( false );
|
|
} // if there is a navcenter
|
|
|
|
// Delete the Admin Kit co-brand button if a
|
|
// custom animation has not been installed
|
|
if ( !CPrefs::HasCoBrand() ) {
|
|
LPane* button = FindPaneByID(CoBrandLogo_PaneID);
|
|
if (button) {
|
|
RemoveSubPane(button);
|
|
delete button;
|
|
}
|
|
}
|
|
|
|
/*
|
|
// the HTML view handles many of the buttons in the tool bar
|
|
LListener* theHTMLView = (LListener*) FindPaneByID(CHTMLView::pane_ID);
|
|
if (theHTMLView != nil)
|
|
{
|
|
UReanimator::LinkListenerToControls(theHTMLView, this, mPaneID);
|
|
}
|
|
*/
|
|
|
|
// Make the tab group the latent sub commander
|
|
|
|
CURLEditField* theURLEditField = dynamic_cast<CURLEditField*>(FindPaneByID(CURLEditField::class_ID));
|
|
if (theURLEditField)
|
|
{
|
|
// Find the tab group which is a super commander of the edit field and make it
|
|
// the latent sub commander which should rotate the target to the first target.
|
|
|
|
LCommander* theCommander = theURLEditField->GetSuperCommander();
|
|
LTabGroup* theTabGroup = nil;
|
|
while (theCommander && !(theTabGroup = dynamic_cast<LTabGroup*>(theCommander)))
|
|
{
|
|
theCommander = theCommander->GetSuperCommander();
|
|
}
|
|
|
|
if (theTabGroup)
|
|
{
|
|
SetLatentSub(theTabGroup);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// HookupContextToToolbars
|
|
//
|
|
// Handle connecting the current context to the various bits and pieces in the toolbars. This
|
|
// routine may be called multiple times w/out problems because PP is smart enough not to
|
|
// add listeners for things already registered.
|
|
//
|
|
void
|
|
CBrowserWindow :: HookupContextToToolbars ( )
|
|
{
|
|
if ( mContext ) {
|
|
// now hook up CProxyPane to listen to context
|
|
CProxyPane* browserPageProxy = dynamic_cast<CProxyPane*>(FindPaneByID(CProxyPane::class_ID));
|
|
if (browserPageProxy)
|
|
mContext->AddListener(browserPageProxy);
|
|
// now hook up CURLCaption to listen to context
|
|
CURLCaption* urlCaption = dynamic_cast<CURLCaption*>(FindPaneByID(CURLCaption::class_ID));
|
|
if (urlCaption)
|
|
mContext->AddListener(urlCaption);
|
|
// now hook up CURLEditField to listen to context
|
|
CURLEditField* urlField = dynamic_cast<CURLEditField*>(FindPaneByID(CURLEditField::class_ID));
|
|
if (urlField)
|
|
{
|
|
mContext->AddListener(urlField);
|
|
urlField->AddListener(this);
|
|
if (urlCaption)
|
|
urlField->AddListener(urlCaption);
|
|
}
|
|
CSpinningN* theN = dynamic_cast<CSpinningN*>(FindPaneByID(CSpinningN::class_ID));
|
|
if (theN)
|
|
mContext->AddListener(theN);
|
|
}
|
|
|
|
} // HookupContextToToolbars
|
|
|
|
|
|
// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
// ¥
|
|
// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
// NOTE: This will handle registering/unregistering the embedded navCenter
|
|
// for sitemap info. When the context is cleared (by passing NULL),
|
|
// it will unregister so we don't need to do it elsewhere.
|
|
void CBrowserWindow::SetWindowContext(CBrowserContext* inContext)
|
|
{
|
|
if (mContext != NULL) {
|
|
if ( mNavCenterParent )
|
|
mNavCenterParent->UnregisterNavCenter();
|
|
mContext->RemoveUser(this);
|
|
}
|
|
|
|
mContext = inContext;
|
|
|
|
if (mContext != NULL)
|
|
{
|
|
mContext->SetRequiresClone(true);
|
|
mContext->AddListener(this);
|
|
try {
|
|
// Let there be a progress listener, placed in my firmament,
|
|
// which shall listen to the context
|
|
mProgressListener = new CProgressListener(this, inContext);
|
|
} catch (...) {
|
|
mProgressListener = NULL;
|
|
}
|
|
mContext->AddUser(this);
|
|
|
|
HookupContextToToolbars();
|
|
|
|
CBrowserSecurityButton* securityButton =
|
|
dynamic_cast<CBrowserSecurityButton*>(FindPaneByID(CBrowserSecurityButton::class_ID));
|
|
if (securityButton)
|
|
mContext->AddListener(securityButton);
|
|
|
|
CMiniSecurityButton* miniSecurityButton =
|
|
dynamic_cast<CMiniSecurityButton*>(FindPaneByID(CMiniSecurityButton::class_ID));
|
|
if (miniSecurityButton)
|
|
mContext->AddListener(miniSecurityButton);
|
|
|
|
#ifdef MOZ_OFFLINE
|
|
// hook up the offline icon
|
|
LBroadcaster* offlineButton
|
|
= dynamic_cast<LBroadcaster*>(FindPaneByID(kOfflineButtonPaneID));
|
|
if (offlineButton)
|
|
offlineButton->AddListener(CFrontApp::GetApplication());
|
|
#endif //MOZ_OFFLINE
|
|
|
|
// setup navCenter for sitemaps
|
|
if ( mNavCenterParent && !HasAttribute(windAttr_Floating))
|
|
mNavCenterParent->RegisterNavCenter ( *inContext );
|
|
|
|
}
|
|
|
|
GetHTMLView()->SetContext(mContext);
|
|
|
|
// This call links up the model object hierarchy for any potential
|
|
// sub model that gets created within the scope of the html view.
|
|
GetHTMLView()->SetFormElemBaseModel(this);
|
|
|
|
}
|
|
|
|
// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
// ¥
|
|
// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
|
|
CNSContext* CBrowserWindow::GetWindowContext() const
|
|
{
|
|
return mContext;
|
|
}
|
|
|
|
// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
// ¥
|
|
// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
|
|
void CBrowserWindow::FindCommandStatus(
|
|
CommandT inCommand,
|
|
Boolean &outEnabled,
|
|
Boolean &outUsesMark,
|
|
Char16 &outMark,
|
|
Str255 outName)
|
|
{
|
|
outUsesMark = false;
|
|
|
|
if (mIsHTMLHelp && UDesktop::FrontWindowIsModal() && inCommand != cmd_About)
|
|
{
|
|
outEnabled = false;
|
|
return;
|
|
}
|
|
// Floating browser windows whose commands have been disabled should only disable the
|
|
// commands that apply to the floating window.
|
|
if (mCommandsDisabled)
|
|
if (HasAttribute(windAttr_Floating))
|
|
{
|
|
if (
|
|
inCommand == cmd_GoBack ||
|
|
inCommand == cmd_GoForward ||
|
|
inCommand == cmd_Home ||
|
|
inCommand == cmd_Close ||
|
|
inCommand == cmd_ToggleToolbar ||
|
|
inCommand == cmd_ToggleLocationBar ||
|
|
inCommand == cmd_Reload ||
|
|
inCommand == cmd_LoadImages ||
|
|
inCommand == cmd_Stop ||
|
|
inCommand == cmd_FontLarger ||
|
|
inCommand == cmd_FontSmaller
|
|
#ifdef EDITOR
|
|
||
|
|
inCommand == cmd_EditFrameSet ||
|
|
inCommand == cmd_EditDocument
|
|
#endif // EDITOR
|
|
)
|
|
{
|
|
outEnabled = false;
|
|
return;
|
|
}
|
|
}
|
|
// Commands may be disabled from javascript. The motivation for this is to prevent
|
|
// users from loading new content into windows that have a special purpose (i.e. Constellation).
|
|
// Don't disable Apple Menu Items or Quit menu item.
|
|
// NOTE: it appears that the Apple Menu Items will be disabled unless I enable
|
|
// the About command. Assume for now that menubar hiding will be implemented, so the
|
|
// user won't be able to access the About menu item.
|
|
else if (
|
|
inCommand != cmd_Quit &&
|
|
inCommand != cmd_SecurityInfo &&
|
|
inCommand != cmd_About)
|
|
{
|
|
outEnabled = false;
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Handle the remainder of commands
|
|
//
|
|
switch (inCommand)
|
|
{
|
|
case cmd_DocumentInfo:
|
|
case cmd_ViewSource:
|
|
if (mContext && (mIsRootDocInfo || mIsViewSource || mIsHTMLHelp))
|
|
{
|
|
outEnabled = false;
|
|
break;
|
|
}
|
|
case cmd_PageSetup:
|
|
case cmd_Print:
|
|
case cmd_PrintOne:
|
|
case cmd_AddToBookmarks:
|
|
case cmd_SaveAs:
|
|
case cmd_SecurityInfo:
|
|
case cmd_FTPUpload:
|
|
case cmd_Find:
|
|
case cmd_MailDocument:
|
|
case cmd_LoadImages:
|
|
case cmd_Reload:
|
|
case cmd_FontLarger:
|
|
case cmd_FontSmaller:
|
|
case cmd_PrivDisplayPolicy:
|
|
case cmd_PrivDisplaySiteInfo:
|
|
{
|
|
// Need to be very careful what gets delegated here, in order to aviod infinite
|
|
// recursion a la bug #313498. Handling the command status in CBrowserView is not
|
|
// sufficient - it also needs to be handled in CHTMLView, which is the class that
|
|
// will receive this if it's a Composer window instead of a Browser window.
|
|
|
|
// Delegate this to the view.
|
|
GetHTMLView()->FindCommandStatus(inCommand, outEnabled, outUsesMark, outMark, outName);
|
|
break;
|
|
}
|
|
case cmd_GoForward:
|
|
if (CApplicationEventAttachment::CurrentEventHasModifiers(optionKey))
|
|
{
|
|
LString::CopyPStr(::GetPString(MENU_FORWARD_ONE_HOST), outName);
|
|
}
|
|
else
|
|
{
|
|
LString::CopyPStr(::GetPString(MENU_FORWARD), outName);
|
|
}
|
|
|
|
if (mContext != NULL)
|
|
{
|
|
outEnabled = mContext->CanGoForward() && !(mIsRootDocInfo || mIsViewSource || mIsHTMLHelp);
|
|
|
|
}
|
|
break;
|
|
case cmd_GoBack:
|
|
if (CApplicationEventAttachment::CurrentEventHasModifiers(optionKey))
|
|
{
|
|
LString::CopyPStr(::GetPString(MENU_BACK_ONE_HOST), outName);
|
|
}
|
|
else
|
|
{
|
|
LString::CopyPStr(::GetPString(MENU_BACK), outName);
|
|
}
|
|
|
|
if (mContext != NULL)
|
|
{
|
|
outEnabled = mContext->CanGoBack() && !(mIsRootDocInfo || mIsViewSource || mIsHTMLHelp);
|
|
|
|
}
|
|
break;
|
|
case cmd_Home:
|
|
outEnabled = (mContext) ? !(mIsRootDocInfo || mIsViewSource || mIsHTMLHelp) : true;
|
|
break;
|
|
|
|
case cmd_ToggleToolbar:
|
|
outEnabled = (mContext) ? !(mIsRootDocInfo || mIsViewSource || mIsHTMLHelp || PREF_PrefIsLocked(Pref_ShowToolbar)) : true;
|
|
::GetIndString(outName, BROWSER_MENU_TOGGLE_STRINGS_ID, (mToolbarShown[eNavigationBar] ? HIDE_NAVIGATION_TOOLBAR_STRING : SHOW_NAVIGATION_TOOLBAR_STRING));
|
|
break;
|
|
|
|
case cmd_ToggleLocationBar:
|
|
outEnabled = (mContext) ? !(mIsRootDocInfo || mIsViewSource || mIsHTMLHelp || PREF_PrefIsLocked(Pref_ShowLocationBar)) : true;
|
|
::GetIndString(outName, BROWSER_MENU_TOGGLE_STRINGS_ID, (mToolbarShown[eLocationBar] ? HIDE_LOCATION_TOOLBAR_STRING : SHOW_LOCATION_TOOLBAR_STRING));
|
|
break;
|
|
|
|
case cmd_TogglePersonalToolbar:
|
|
outEnabled = (mContext) ? !(mIsRootDocInfo || mIsViewSource || mIsHTMLHelp || PREF_PrefIsLocked(Pref_ShowPersonalToolbar)) : true;
|
|
::GetIndString(outName, BROWSER_MENU_TOGGLE_STRINGS_ID, (mToolbarShown[ePersonalToolbar] ? HIDE_PERSONAL_TOOLBAR_STRING : SHOW_PERSONAL_TOOLBAR_STRING));
|
|
break;
|
|
|
|
case cmd_NetSearch:
|
|
outEnabled = (mContext) ? !(mIsRootDocInfo || mIsViewSource || mIsHTMLHelp) : true;
|
|
break;
|
|
|
|
case cmd_ToolbarButton:
|
|
// we always want the toolbar buttons that don't correspond to any real command (that are
|
|
// either HT containers or just simple url's) to be enabled and clickable.
|
|
outEnabled = true;
|
|
break;
|
|
|
|
case cmd_Stop:
|
|
{
|
|
// Default name is STOP_LOADING_INDEX
|
|
|
|
::GetIndString(outName, STOP_STRING_LIST, STOP_LOADING_INDEX );
|
|
|
|
if (mContext)
|
|
{
|
|
if (XP_IsContextStoppable((MWContext*) (*mContext)))
|
|
{
|
|
outEnabled = true;
|
|
}
|
|
else if (mContext->IsContextLooping())
|
|
{
|
|
outEnabled = true;
|
|
|
|
::GetIndString(outName, STOP_STRING_LIST, STOP_ANIMATIONS_INDEX );
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
#ifdef EDITOR
|
|
case cmd_EditFrameSet:
|
|
case cmd_EditDocument:
|
|
{
|
|
if ((mContext != nil) && !(XP_IsContextBusy(*mContext)) && !Memory_MemoryIsLow())
|
|
outEnabled = !(mIsRootDocInfo || mIsViewSource || mIsHTMLHelp);
|
|
break;
|
|
}
|
|
#endif // EDITOR
|
|
|
|
case cmd_PageServices:
|
|
outEnabled = mSupportsPageServices;
|
|
break;
|
|
|
|
default:
|
|
{
|
|
if(inCommand >= ENCODING_BASE && inCommand < ENCODING_CEILING)
|
|
{
|
|
// Delegate this to the view.
|
|
GetHTMLView()->FindCommandStatus(inCommand, outEnabled, outUsesMark, outMark, outName);
|
|
}
|
|
else
|
|
CNetscapeWindow::FindCommandStatus(inCommand, outEnabled, outUsesMark, outMark, outName);
|
|
}
|
|
}
|
|
}
|
|
|
|
// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
// ¥
|
|
// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
|
|
// Revised to handle back, forward, home, reload through AppleEvents - 1997-02-26 mjc
|
|
Boolean CBrowserWindow::ObeyCommand(
|
|
CommandT inCommand,
|
|
void *ioParam)
|
|
{
|
|
if ( inCommand >= cmd_NavCenterBase && inCommand <= cmd_NavCenterCap ) {
|
|
if ( mToolbarContainer)
|
|
mToolbarContainer->HandleHTCommand(inCommand);
|
|
return true;
|
|
}
|
|
|
|
LCommander *target;
|
|
Boolean cmdHandled = false;
|
|
// check for synthetic commands from history items
|
|
if (CHistoryMenu::IsHistoryMenuSyntheticCommandID(inCommand) && mContext != NULL)
|
|
{
|
|
// Compute correct history list index.
|
|
// Menu item number - last non-dynamic menu item number is
|
|
// index to history entry starting from the *END* of history list --
|
|
// because we list history entries in menu bar starting with the most
|
|
// recent history entry at the top which is at the end of the history list in the
|
|
// MWContext. Therefore, compute correct history list index before calling
|
|
// CNSContext::LoadHistoryEntry
|
|
Int32 histIndex = mContext->GetHistoryListCount() -
|
|
(CHistoryMenu::GetFirstSyntheticCommandID() - inCommand);
|
|
// histIndex should now be the one-based index to the history entry we want
|
|
// starting from the beginning of the list.
|
|
mContext->LoadHistoryEntry(histIndex);
|
|
cmdHandled = true;
|
|
}
|
|
else
|
|
{
|
|
switch (inCommand)
|
|
{
|
|
case cmd_Print:
|
|
case cmd_PrintOne:
|
|
// if the current target happens to be a subview of our main HTMLView, let it
|
|
// handle the command. else, hand it to our main HTML view.
|
|
target = LCommander::GetTarget();
|
|
while (target && target != GetHTMLView())
|
|
target = target->GetSuperCommander();
|
|
if (target == GetHTMLView())
|
|
LCommander::GetTarget()->ObeyCommand (inCommand, ioParam);
|
|
else
|
|
GetHTMLView()->ObeyCommand (inCommand, ioParam);
|
|
break;
|
|
case cmd_ViewSource:
|
|
case cmd_Find:
|
|
case cmd_AddToBookmarks:
|
|
case cmd_SaveAs:
|
|
case cmd_SecurityInfo:
|
|
case cmd_DocumentInfo:
|
|
case cmd_MailDocument:
|
|
case cmd_LoadImages:
|
|
case cmd_FTPUpload:
|
|
case cmd_FontLarger:
|
|
case cmd_FontSmaller:
|
|
case cmd_PrivDisplayPolicy:
|
|
case cmd_PrivDisplaySiteInfo:
|
|
{
|
|
// Delegate this to the view.
|
|
GetHTMLView()->ObeyCommand(inCommand, ioParam);
|
|
}
|
|
break;
|
|
|
|
case cmd_GoForward:
|
|
if (CApplicationEventAttachment::CurrentEventHasModifiers(optionKey))
|
|
{
|
|
if (mContext)
|
|
{
|
|
mContext->GoForwardOneHost();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
SendAEGo(kAENext);
|
|
}
|
|
cmdHandled = true;
|
|
break;
|
|
|
|
case cmd_GoBack:
|
|
if (CApplicationEventAttachment::CurrentEventHasModifiers(optionKey))
|
|
{
|
|
if (mContext)
|
|
{
|
|
mContext->GoBackOneHost();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
SendAEGo(kAEPrevious);
|
|
}
|
|
cmdHandled = true;
|
|
break;
|
|
|
|
case cmd_Home:
|
|
SendAEGo(AE_www_go_home);
|
|
|
|
// ¥¥¥ what the hell is this? deeje 97-03-06
|
|
// cmdHandled = CNetscapeWindow::ObeyCommand(inCommand, ioParam);
|
|
break;
|
|
|
|
case cmd_NetSearch:
|
|
HandleNetSearchCommand();
|
|
break;
|
|
|
|
case cmd_ToggleToolbar:
|
|
ToggleDragBar(Button_Bar_PaneID, eNavigationBar, Pref_ShowToolbar);
|
|
cmdHandled = true;
|
|
break;
|
|
|
|
case cmd_ToggleLocationBar:
|
|
ToggleDragBar(Location_Bar_PaneID, eLocationBar, Pref_ShowLocationBar);
|
|
cmdHandled = true;
|
|
break;
|
|
|
|
case cmd_TogglePersonalToolbar:
|
|
ToggleDragBar(PersonalToolbar_PaneID, ePersonalToolbar, Pref_ShowPersonalToolbar);
|
|
cmdHandled = true;
|
|
break;
|
|
|
|
case cmd_Reload:
|
|
{
|
|
if (CApplicationEventAttachment::CurrentEventHasModifiers(optionKey) ||
|
|
CApplicationEventAttachment::CurrentEventHasModifiers(shiftKey))
|
|
{
|
|
SendAEGo(AE_www_super_reload);
|
|
}
|
|
else
|
|
{
|
|
SendAEGo(AE_www_go_again);
|
|
}
|
|
cmdHandled = true;
|
|
break;
|
|
}
|
|
|
|
case cmd_Stop:
|
|
{
|
|
TrySetCursor(watchCursor);
|
|
XP_InterruptContext(*mContext);
|
|
SetCursor( &qd.arrow );
|
|
cmdHandled = true;
|
|
break;
|
|
}
|
|
|
|
#ifdef EDITOR
|
|
case cmd_EditFrameSet:
|
|
case cmd_EditDocument:
|
|
MWContext *frontWindowMWContext;
|
|
frontWindowMWContext = XP_GetNonGridContext( GetWindowContext()->operator MWContext*() );
|
|
CEditorWindow::MakeEditWindowFromBrowser( frontWindowMWContext );
|
|
cmdHandled = true;
|
|
break;
|
|
#endif // EDITOR
|
|
|
|
case cmd_SaveDefaultCharset:
|
|
{
|
|
Int32 default_csid = GetDefaultCSID();
|
|
CPrefs::SetLong(default_csid, CPrefs::DefaultCharSetID);
|
|
}
|
|
break;
|
|
|
|
case cmd_PageServices:
|
|
{
|
|
char* url = SHIST_GetCurrentPageServicesURL(*mContext);
|
|
if (url)
|
|
{
|
|
URL_Struct* newURL = NET_CreateURLStruct(url, NET_DONT_RELOAD);
|
|
if (newURL)
|
|
mContext->SwitchLoadURL(newURL, FO_CACHE_AND_PRESENT);
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
{
|
|
if ( inCommand > ENCODING_BASE && inCommand < ENCODING_CEILING )
|
|
{
|
|
// Delegate this to the view.
|
|
GetHTMLView()->SetDefaultCSID(CPrefs::CmdNumToDocCsid(inCommand));
|
|
cmdHandled = true;
|
|
}
|
|
else
|
|
cmdHandled = CNetscapeWindow::ObeyCommand(inCommand, ioParam);
|
|
break;
|
|
}
|
|
|
|
} // case of which command
|
|
} // else not a history command
|
|
|
|
return cmdHandled;
|
|
}
|
|
|
|
// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
// ¥
|
|
// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
|
|
void CBrowserWindow::ListenToMessage(MessageT inMessage, void* ioParam)
|
|
{
|
|
switch (inMessage)
|
|
{
|
|
case msg_NSCConfirmLoadNewURL:
|
|
long response = 0;
|
|
// kludge alert:
|
|
// expand windowshaded floating windows to work around bug reported with system 7.6.1 (and probably earlier)
|
|
// which breaks the window when a new url is loaded.
|
|
if (IsVisible() &&
|
|
HasAttribute(windAttr_TitleBar) &&
|
|
HasAttribute(windAttr_Floating) &&
|
|
::EmptyRgn(((WindowPeek)GetMacPort())->contRgn) &&
|
|
(noErr == ::Gestalt (gestaltSystemVersion, &response)) &&
|
|
(response < 0x800))
|
|
{
|
|
GrafPtr savePort; // get the port rectangle and convert
|
|
::GetPort(&savePort); // to global coordinates
|
|
::SetPort(GetMacPort());
|
|
Rect expandedRect = GetMacPort()->portRect;
|
|
::LocalToGlobal(&topLeft(expandedRect));
|
|
::LocalToGlobal(&botRight(expandedRect));
|
|
::SetPort(savePort);
|
|
DoSetBounds(expandedRect);
|
|
}
|
|
break;
|
|
|
|
case msg_NSCDocTitleChanged:
|
|
NoteDocTitleChanged((const char*)ioParam);
|
|
break;
|
|
|
|
case msg_NSCInternetKeywordChanged:
|
|
NoteInternetKeywordChanged((const char*)ioParam);
|
|
break;
|
|
|
|
case msg_NSCLayoutNewDocument:
|
|
NoteBeginLayout();
|
|
break;
|
|
|
|
case msg_NSCFinishedLayout:
|
|
NoteFinishedLayout();
|
|
break;
|
|
|
|
case msg_NSCAllConnectionsComplete:
|
|
NoteAllConnectionsComplete();
|
|
break;
|
|
|
|
case msg_UserSubmittedURL:
|
|
// user hit enter or return in URL edit field
|
|
const char* urlString = (const char*)ioParam;
|
|
|
|
if (urlString && *urlString && mContext)
|
|
SendAEGetURL(urlString);
|
|
break;
|
|
|
|
case CPopdownRDFCoordinator::msg_ClosePopdownTree:
|
|
ClosePopdownTreeView();
|
|
break;
|
|
|
|
case cmd_GoForward:
|
|
case cmd_GoBack:
|
|
case cmd_Home:
|
|
case cmd_Reload:
|
|
case cmd_Stop:
|
|
case cmd_LoadImages:
|
|
case cmd_Print:
|
|
case cmd_CoBrandLogo:
|
|
case cmd_NetSearch:
|
|
case cmd_SecurityInfo:
|
|
case LOGO_BUTTON:
|
|
ObeyCommand(inMessage, ioParam);
|
|
break;
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------------------
|
|
void CBrowserWindow::DoClose()
|
|
//----------------------------------------------------------------------------------------
|
|
{
|
|
AttemptCloseWindow();
|
|
super::DoClose();
|
|
}
|
|
|
|
//----------------------------------------------------------------------------------------
|
|
Boolean CBrowserWindow::AttemptQuitSelf(Int32 /* inSaveOption */)
|
|
// Derived classes should be careful to call DeferredClose if they override this fn.
|
|
//----------------------------------------------------------------------------------------
|
|
{
|
|
CDeferredCloseTask::DeferredClose(this);
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------------------
|
|
void CBrowserWindow::AttemptClose()
|
|
{
|
|
if (HasProcess(fCloseNotifier)) // If someone has registered for window closing, notify them
|
|
Try_
|
|
{
|
|
AEAddressDesc closeApp;
|
|
AppleEvent closeEvent;
|
|
Int32 aWindowID = mContext->GetContextUniqueID();
|
|
|
|
OSErr err = ::AECreateDesc(typeProcessSerialNumber, &fCloseNotifier,
|
|
sizeof(fCloseNotifier), &closeApp);
|
|
ThrowIfOSErr_(err);
|
|
err = ::AECreateAppleEvent(AE_spy_send_suite, AE_spy_winClosed,
|
|
&closeApp,
|
|
kAutoGenerateReturnID,
|
|
kAnyTransactionID,
|
|
&closeEvent);
|
|
ThrowIfOSErr_(err);
|
|
|
|
// windowID is the direct object
|
|
err = ::AEPutParamPtr(&closeEvent, keyDirectObject,
|
|
typeLongInteger, &aWindowID, sizeof(aWindowID));
|
|
ThrowIfOSErr_(err);
|
|
|
|
// Are we quitting is another parameter
|
|
Boolean quitting = (CFrontApp::GetApplication()->GetState() == programState_Quitting);
|
|
err =::AEPutParamPtr(&closeEvent, AE_spy_winClosedExiting, typeBoolean,
|
|
&quitting, sizeof(quitting));
|
|
ThrowIfOSErr_(err);
|
|
|
|
// send the event
|
|
AppleEvent reply;
|
|
::AESend(&closeEvent,&reply,kAENoReply,kAENormalPriority,0,nil, nil);
|
|
}
|
|
Catch_(inErr){}
|
|
EndCatch_
|
|
|
|
CDeferredCloseTask::DeferredClose(this);
|
|
}
|
|
|
|
|
|
// modified so z-locked window will not automatically be selected - mjc
|
|
void
|
|
CBrowserWindow::Select()
|
|
{
|
|
if (!mZLocked)
|
|
{
|
|
SendSelfAE(kAEMiscStandards, kAESelect, false);
|
|
UDesktop::SelectDeskWindow(this);
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// ActivateSelf
|
|
//
|
|
// When this window comes to the front, we want to make sure that RDF knows about this window's
|
|
// context so that navCenter windows can display the site map info correctly for this window.
|
|
//
|
|
// Make sure not to do this for floating windows or for editor windows.
|
|
//
|
|
void
|
|
CBrowserWindow::ActivateSelf ( )
|
|
{
|
|
super::ActivateSelf();
|
|
if ( mNavCenterParent && !HasAttribute(windAttr_Floating) )
|
|
XP_SetLastActiveContext ( *GetWindowContext() );
|
|
}
|
|
|
|
|
|
//
|
|
// DeactivateSelf
|
|
//
|
|
// When this window loses focus, hide the popdown tree view if it exists
|
|
//
|
|
void
|
|
CBrowserWindow :: DeactivateSelf ( )
|
|
{
|
|
// don't need to check if one is already open, CPTV() does that for us.
|
|
ClosePopdownTreeView();
|
|
|
|
CNetscapeWindow::DeactivateSelf();
|
|
|
|
} // DeactivateSelf
|
|
|
|
|
|
// ClickInDrag modified so z-locked window will not automatically be selected - mjc
|
|
void
|
|
CBrowserWindow::ClickInDrag(const EventRecord &inMacEvent)
|
|
{
|
|
if (mZLocked)
|
|
{
|
|
EventRecord filterMacEvent = inMacEvent;
|
|
filterMacEvent.modifiers = filterMacEvent.modifiers | cmdKey; // command-key modifier disables select
|
|
super::ClickInDrag(filterMacEvent);
|
|
}
|
|
else super::ClickInDrag(inMacEvent);
|
|
}
|
|
|
|
// Allow us to restrict user from growing the window by setting the Resizable attribute,
|
|
// even if there is a grow box.
|
|
void
|
|
CBrowserWindow::ClickInGrow(const EventRecord &inMacEvent)
|
|
{
|
|
if (HasAttribute(windAttr_Resizable))
|
|
super::ClickInGrow(inMacEvent);
|
|
}
|
|
|
|
// Return the window for the top-level context of the one passed in.
|
|
CBrowserWindow*
|
|
CBrowserWindow::WindowForContext(CBrowserContext* inContext)
|
|
{
|
|
if (inContext == NULL) return NULL;
|
|
|
|
CMediatedWindow* theIterWindow = NULL;
|
|
DataIDT windowType = WindowType_Browser;
|
|
CWindowIterator theWindowIterator(windowType);
|
|
|
|
CBrowserContext* theTopContext = inContext->GetTopContext();
|
|
|
|
while (theWindowIterator.Next(theIterWindow))
|
|
{
|
|
CBrowserWindow* theBrowserWindow = dynamic_cast<CBrowserWindow*>(theIterWindow);
|
|
CNSContext* theCurrentContext = theBrowserWindow->GetWindowContext();
|
|
if (theBrowserWindow->GetWindowContext() == theTopContext)
|
|
{
|
|
return theBrowserWindow;
|
|
break;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
// Retrieve a window with the given Window ID
|
|
// In : ID of window
|
|
// Out: Pointer returned. (ct hull)
|
|
// GetWindowByID
|
|
// return the window for the context.
|
|
CBrowserWindow*
|
|
CBrowserWindow::GetWindowByID(const Int32 windowID)
|
|
{
|
|
CMediatedWindow* theIterWindow = NULL;
|
|
DataIDT windowType = WindowType_Browser;
|
|
CWindowIterator theWindowIterator(windowType);
|
|
while (theWindowIterator.Next(theIterWindow))
|
|
{
|
|
CBrowserWindow* theBrowserWindow = dynamic_cast<CBrowserWindow*>(theIterWindow);
|
|
CNSContext* theCurrentContext = theBrowserWindow->GetWindowContext();
|
|
if (theCurrentContext->GetContextUniqueID() == windowID)
|
|
{
|
|
return theBrowserWindow;
|
|
break;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
Boolean
|
|
CBrowserWindow::IsRestrictedTarget(void)
|
|
{
|
|
return mContext->IsRestrictedTarget();
|
|
}
|
|
|
|
// override to send javascript move, resize, and zoom events
|
|
void
|
|
CBrowserWindow::DoSetPosition(Point inPosition)
|
|
{
|
|
super::DoSetPosition(inPosition);
|
|
|
|
if (mContext != NULL)
|
|
{
|
|
Rect bounds;
|
|
bounds = UWindows::GetWindowStructureRect(GetMacPort());
|
|
CMochaHacks::SendMoveEvent(*mContext, bounds.left, bounds.top - ::GetMBarHeight());
|
|
}
|
|
}
|
|
|
|
void
|
|
CBrowserWindow::DoSetBounds(const Rect &inBounds)
|
|
{
|
|
// inBounds is in global coordinates
|
|
|
|
// Early exit if the bounds have not
|
|
// really changed.
|
|
Rect bounds = UWindows::GetWindowContentRect(GetMacPort());
|
|
|
|
if (::EqualRect(&bounds, &inBounds))
|
|
return;
|
|
|
|
Boolean didMove = (bounds.top != inBounds.top) || (bounds.left != inBounds.left);
|
|
|
|
// Set size and location of Toolbox
|
|
// WindowRecord
|
|
::SizeWindow(mMacWindowP, inBounds.right - inBounds.left,
|
|
inBounds.bottom - inBounds.top, false);
|
|
::MoveWindow(mMacWindowP, inBounds.left, inBounds.top, false);
|
|
|
|
// Set our Frame
|
|
ResizeFrameTo(inBounds.right - inBounds.left,
|
|
inBounds.bottom - inBounds.top, true);
|
|
|
|
SDimension16 frameSize; // For Windows, Image is always the
|
|
GetFrameSize(frameSize); // same size as its Frame
|
|
ResizeImageTo(frameSize.width, frameSize.height, false);
|
|
|
|
// Changing Bounds establishes a
|
|
// new User state for zooming
|
|
CalcPortFrameRect(mUserBounds);
|
|
PortToGlobalPoint(topLeft(mUserBounds));
|
|
PortToGlobalPoint(botRight(mUserBounds));
|
|
mMoveOnlyUserZoom = false;
|
|
|
|
|
|
if (mContext != NULL)
|
|
{
|
|
Rect structureBounds = UWindows::GetWindowStructureRect(GetMacPort());
|
|
if (didMove)
|
|
CMochaHacks::SendMoveEvent(*mContext, structureBounds.left, structureBounds.top - ::GetMBarHeight());
|
|
//CMochaHacks::SendResizeEvent(*mContext, structureBounds.right - structureBounds.left, structureBounds.bottom - structureBounds.top);
|
|
}
|
|
}
|
|
|
|
void
|
|
CBrowserWindow::DoSetZoom(Boolean inZoomToStdState)
|
|
{
|
|
if (!HasAttribute(windAttr_Zoomable)) {
|
|
ThrowOSErr_(errAENotModifiable);
|
|
}
|
|
|
|
Rect currBounds = UWindows::GetWindowContentRect(mMacWindowP);
|
|
Rect zoomBounds;
|
|
|
|
if (CApplicationEventAttachment::CurrentEventHasModifiers(optionKey))
|
|
{
|
|
|
|
StValueChanger<Int16> changeStandardWidth(mStandardSize.width, max_Int16);
|
|
StValueChanger<Int16> changeStandardHeight(mStandardSize.height, max_Int16);
|
|
|
|
CalcStandardBounds(zoomBounds);
|
|
|
|
|
|
// Changing bounds via option-zoom
|
|
// establishes a new User state
|
|
// for zooming
|
|
mUserBounds = zoomBounds;
|
|
}
|
|
else
|
|
{
|
|
if (inZoomToStdState) { // Zoom to Standard state
|
|
if (CalcStandardBounds(zoomBounds)) {
|
|
return; // Already at Standard state
|
|
}
|
|
|
|
} else { // Zoom to User state
|
|
zoomBounds = mUserBounds;
|
|
|
|
if (mMoveOnlyUserZoom) { // Special case for zooming a Window
|
|
// that is at standard size, but
|
|
// is partially offscreen
|
|
zoomBounds.right = zoomBounds.left +
|
|
(currBounds.right - currBounds.left);
|
|
zoomBounds.bottom = zoomBounds.top +
|
|
(currBounds.bottom - currBounds.top);
|
|
}
|
|
}
|
|
}
|
|
|
|
Int16 zoomWidth = zoomBounds.right - zoomBounds.left;
|
|
Int16 zoomHeight = zoomBounds.bottom - zoomBounds.top;
|
|
mMoveOnlyUserZoom = false;
|
|
|
|
// To avoid unnecessary redraws, we check to see if the
|
|
// current and zoom states are either the same size
|
|
// or at the same location
|
|
|
|
if ( ((currBounds.right - currBounds.left) == zoomWidth) &&
|
|
((currBounds.bottom - currBounds.top) == zoomHeight) ) {
|
|
// Same size, just move
|
|
::MoveWindow(mMacWindowP, zoomBounds.left, zoomBounds.top, false);
|
|
mMoveOnlyUserZoom = true;
|
|
|
|
} else if (::EqualPt(topLeft(currBounds), topLeft(zoomBounds))) {
|
|
// Same location, just resize
|
|
::SizeWindow(mMacWindowP, zoomWidth, zoomHeight, false);
|
|
ResizeFrameTo(zoomWidth, zoomHeight, true);
|
|
|
|
} else { // Different size and location
|
|
// Zoom appropriately
|
|
FocusDraw();
|
|
ApplyForeAndBackColors();
|
|
::EraseRect(&mMacWindowP->portRect);
|
|
if (inZoomToStdState) {
|
|
SetWindowStandardState(mMacWindowP, &zoomBounds);
|
|
::ZoomWindow(mMacWindowP, inZoomOut, false);
|
|
} else {
|
|
SetWindowUserState(mMacWindowP, &zoomBounds);
|
|
::ZoomWindow(mMacWindowP, inZoomIn, false);
|
|
}
|
|
ResizeFrameTo(zoomWidth, zoomHeight, false);
|
|
}
|
|
|
|
if (mContext != NULL)
|
|
{
|
|
Rect bounds;
|
|
bounds = UWindows::GetWindowStructureRect(GetMacPort());
|
|
CMochaHacks::SendMoveEvent(*mContext, bounds.left, bounds.top - ::GetMBarHeight());
|
|
//CMochaHacks::SendResizeEvent(*mContext, bounds.right - bounds.left, bounds.bottom - bounds.top);
|
|
}
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// ¥ CalcStandardBoundsForScreen
|
|
// ---------------------------------------------------------------------------
|
|
|
|
void
|
|
CBrowserWindow::CalcStandardBoundsForScreen(
|
|
const Rect& inScreenBounds,
|
|
Rect& outStdBounds) const
|
|
{
|
|
CHTMLView* theHTMLView = nil;
|
|
CBrowserContext* theTopContext = nil;
|
|
|
|
theTopContext = dynamic_cast<CBrowserContext*>(mContext->GetTopContext());
|
|
if (theTopContext)
|
|
{
|
|
theHTMLView = ::ExtractHyperView((MWContext*)(*theTopContext));
|
|
}
|
|
|
|
StValueChanger<Int16> saveStandardWidth(const_cast<CBrowserWindow*>(this)->mStandardSize.width, max_Int16);
|
|
StValueChanger<Int16> saveStandardHeight(const_cast<CBrowserWindow*>(this)->mStandardSize.height, max_Int16);
|
|
|
|
CHTMLView::CalcStandardSizeForWindowForScreen(
|
|
theHTMLView,
|
|
*this,
|
|
inScreenBounds,
|
|
const_cast<CBrowserWindow*>(this)->mStandardSize);
|
|
|
|
// Calculate standard bounds given standard size
|
|
|
|
super::CalcStandardBoundsForScreen(inScreenBounds, outStdBounds);
|
|
}
|
|
|
|
// dynamically show/hide the status bar - mjc
|
|
void
|
|
CBrowserWindow::ShowStatus(Chrome* inChromeInfo)
|
|
{
|
|
LPane* theSWatchStuff = FindPaneByID(SWatch_View_PaneID);
|
|
LPane* theStatusBar = FindPaneByID(Status_Bar_PaneID);
|
|
|
|
// ¥ show or hide status bar
|
|
if (theStatusBar != nil && theSWatchStuff != nil)
|
|
{
|
|
if (!inChromeInfo->show_bottom_status_bar) // status=no
|
|
{
|
|
// FIXME grow box draws correctly?
|
|
if (mToolbarShown[eStatusBar])
|
|
{
|
|
SDimension16 theStatusSize = {0, 0};
|
|
theStatusBar->GetFrameSize(theStatusSize);
|
|
theStatusBar->Hide();
|
|
theSWatchStuff->ResizeFrameBy(0, theStatusSize.height, false);
|
|
mToolbarShown[eStatusBar] = false;
|
|
// 97-05-12 pkc -- have CHyperScroller handle grow icon if we're
|
|
// resizeable
|
|
// 97-06-05 pkc -- hide size box because it looks bad
|
|
ClearAttribute(windAttr_SizeBox);
|
|
if (inChromeInfo->allow_resize)
|
|
{
|
|
CHyperScroller* scroller = dynamic_cast<CHyperScroller*>(FindPaneByID(Hyper_Scroller_PaneID));
|
|
if (scroller)
|
|
scroller->SetHandleGrowIconManually(true);
|
|
}
|
|
}
|
|
}
|
|
else if (!mToolbarShown[eStatusBar]) // status=yes
|
|
{
|
|
// we want to show status bar, but it's currently hidden
|
|
SDimension16 theStatusSize = {0, 0};
|
|
theStatusBar->Show();
|
|
theStatusBar->GetFrameSize(theStatusSize);
|
|
theSWatchStuff->ResizeFrameBy(0, -theStatusSize.height, false);
|
|
mToolbarShown[eStatusBar] = true;
|
|
// 97-05-12 pkc -- tell CHyperScroller not to handle grow icon if we're
|
|
// resizeable
|
|
if (inChromeInfo->allow_resize)
|
|
{
|
|
CHyperScroller* scroller = dynamic_cast<CHyperScroller*>(FindPaneByID(Hyper_Scroller_PaneID));
|
|
if (scroller)
|
|
{
|
|
SetAttribute(windAttr_SizeBox);
|
|
scroller->SetHandleGrowIconManually(false);
|
|
}
|
|
// make sure we turn on bevelling of grow icon area
|
|
SetSystemGrowIconBevel();
|
|
}
|
|
else
|
|
ClearAttribute(windAttr_SizeBox);
|
|
}
|
|
else if (!inChromeInfo->allow_resize)
|
|
{
|
|
// we want to show status bar, it's already showing, and we don't
|
|
// want it resizeable
|
|
ClearAttribute(windAttr_SizeBox);
|
|
// also clear bevelling of grow icon area
|
|
ClearSystemGrowIconBevel();
|
|
}
|
|
}
|
|
}
|
|
|
|
// dynamically show/hide the drag bars - mjc (without changing pref value)
|
|
// modified to synchronize with menu items by using ShowOneDragBar and mToolbarShown - 1997-02-27 mjc
|
|
void
|
|
CBrowserWindow::ShowDragBars(Boolean inShowNavBar, Boolean inShowLocBar, Boolean inShowPersToolbar)
|
|
{
|
|
ShowOneDragBar(Button_Bar_PaneID, inShowNavBar);
|
|
mToolbarShown[eNavigationBar] = inShowNavBar;
|
|
|
|
ShowOneDragBar(Location_Bar_PaneID, inShowLocBar);
|
|
mToolbarShown[eLocationBar] = inShowLocBar;
|
|
|
|
ShowOneDragBar(PersonalToolbar_PaneID, inShowPersToolbar);
|
|
mToolbarShown[ePersonalToolbar] = inShowPersToolbar;
|
|
}
|
|
|
|
void
|
|
CBrowserWindow::ClearSystemGrowIconBevel()
|
|
{
|
|
CBevelView* statusArea = dynamic_cast<CBevelView*>(FindPaneByID('StBv'));
|
|
if (statusArea)
|
|
statusArea->DontBevelGrowIcon();
|
|
}
|
|
|
|
void
|
|
CBrowserWindow::SetSystemGrowIconBevel()
|
|
{
|
|
CBevelView* statusArea = dynamic_cast<CBevelView*>(FindPaneByID('StBv'));
|
|
if (statusArea)
|
|
statusArea->BevelGrowIcon();
|
|
}
|
|
|
|
// set up the window based on the chrome structure
|
|
// this may be called more than once.
|
|
void CBrowserWindow::SetChromeInfo(Chrome* inChrome, Boolean inNotifyMenuBarModeChanged, Boolean inFirstTime)
|
|
{
|
|
LPane* theHTMLContainer = FindPaneByID(HTML_Container_PaneID);
|
|
LPane* theSWatchStuff = FindPaneByID(SWatch_View_PaneID);
|
|
CHyperScroller* theScroller = (CHyperScroller*)FindPaneByID(Hyper_Scroller_PaneID);
|
|
|
|
if (inChrome != nil)
|
|
{
|
|
Assert_(mMacWindowP != NULL);
|
|
Rect windowBounds = {0, 0, 0, 0};
|
|
Rect contentBounds = {0, 0, 0, 0};
|
|
Rect newWindowBounds = {0, 0, 0, 0};
|
|
Rect portRect = mMacWindowP->portRect;
|
|
short titlebarHeight, deltaWidth, deltaHeight;
|
|
|
|
FocusDraw();
|
|
|
|
// ¥ reposition bars based on chrome attributes. The "directory button" is really
|
|
// the personal toolbar, though no one has thought to update the chrome structure yet.
|
|
ShowDragBars(inChrome->show_button_bar, inChrome->show_url_bar, inChrome->show_directory_buttons);
|
|
|
|
// ¥ show or hide scrollbars
|
|
if (theScroller != nil)
|
|
{
|
|
if (inChrome->show_scrollbar)
|
|
GetHTMLView()->ResetScrollMode();
|
|
else GetHTMLView()->SetScrollMode(LO_SCROLL_NEVER);
|
|
}
|
|
|
|
//¥¥¥ This should be reflected in the Chrome data structure, but since I'm too scared to
|
|
// touch it, we can hack it so that if the chrome says not to have a personal toolbar, then
|
|
// we probably don't want the NavCenter showing up. Don't let this temporary setting of
|
|
// the shelf states affect the global preference, however.
|
|
if ( mNavCenterParent ) {
|
|
if ( !inChrome->show_directory_buttons )
|
|
mNavCenterParent->NavCenterShelf().SetShelfState(CShelf::kClosed, false);
|
|
}
|
|
ShowStatus(inChrome);
|
|
|
|
// w_hint and h_hint are inner dimensions (html view).
|
|
// outw_hint and outh_hint are outer dimensions (window structure).
|
|
// l_hint and t_hint are position of window structure.
|
|
// location_is_chrome will always be set for positioning so that {0,0}
|
|
// positioning is possible (i.e. we know the chrome record is not just zeroed out).
|
|
// ALERT: positioning applies menubar height regardless of multiple monitor situation.
|
|
|
|
windowBounds = UWindows::GetWindowStructureRect(GetMacPort());
|
|
contentBounds = UWindows::GetWindowContentRect(GetMacPort());
|
|
// if the window is windowshaded then correct the windowBounds because height of content is zero.
|
|
if (IsVisible() && HasAttribute(windAttr_TitleBar) && ::EmptyRgn(((WindowPeek)GetMacPort())->contRgn))
|
|
{
|
|
short lostHeight = portRect.bottom - portRect.top; // portRect is immune to windowshading
|
|
windowBounds.bottom = windowBounds.bottom + lostHeight;
|
|
contentBounds.bottom = contentBounds.bottom + lostHeight;
|
|
}
|
|
deltaWidth = (windowBounds.right - windowBounds.left) - (contentBounds.right - contentBounds.left); // difference of width of structure and content
|
|
deltaHeight = (windowBounds.bottom - windowBounds.top) - (contentBounds.bottom - contentBounds.top); // difference of height of structure and content
|
|
titlebarHeight = contentBounds.top - windowBounds.top;
|
|
|
|
// convert newWindowBounds to the content rect suitable for passing to DoSetBounds().
|
|
if ((inChrome->outw_hint && inChrome->outh_hint) ||
|
|
(inChrome->w_hint && inChrome->h_hint) ||
|
|
(inChrome->location_is_chrome)) // reposition is intended
|
|
{
|
|
RgnHandle desktopRgnH = ::GetGrayRgn(); // max size of window is size of desktop region
|
|
short maxWidth = MAX((**desktopRgnH).rgnBBox.right - (**desktopRgnH).rgnBBox.left, 100);
|
|
short maxHeight = MAX((**desktopRgnH).rgnBBox.bottom - (**desktopRgnH).rgnBBox.top, 100);
|
|
|
|
if (inChrome->location_is_chrome) { // position if specified
|
|
newWindowBounds.left = inChrome->l_hint + contentBounds.left - windowBounds.left;
|
|
newWindowBounds.top = inChrome->t_hint + titlebarHeight + ::GetMBarHeight();
|
|
}
|
|
else {
|
|
newWindowBounds.left = contentBounds.left;
|
|
newWindowBounds.top = contentBounds.top;
|
|
}
|
|
|
|
// set outer dimensions if specified or inner dimensions. Prevent a non-resizable
|
|
// window from being resized unless it's the first time we're setting chrome info.
|
|
if ((inChrome->outw_hint > 0) &&
|
|
(inChrome->outh_hint > 0) &&
|
|
(inChrome->allow_resize || inFirstTime)) // outer dimensions both > 0
|
|
{
|
|
// pin the window dimensions specified in the chrome to the maximum dimensions
|
|
inChrome->outw_hint = MIN(maxWidth, inChrome->outw_hint);
|
|
inChrome->outh_hint = MIN(maxHeight, inChrome->outh_hint);
|
|
newWindowBounds.right = MIN(SHRT_MAX, newWindowBounds.left + inChrome->outw_hint - deltaWidth);
|
|
newWindowBounds.bottom = MIN(SHRT_MAX, newWindowBounds.top + inChrome->outh_hint - deltaHeight);
|
|
}
|
|
else if ((inChrome->w_hint > 0) &&
|
|
(inChrome->h_hint > 0) &&
|
|
(inChrome->allow_resize || inFirstTime)) // inner dimensions both > 0
|
|
{
|
|
SDimension16 theInnerSize;
|
|
/* if (theScroller != nil) theScroller->GetFrameSize(theInnerSize);
|
|
else */ GetHTMLView()->GetFrameSize(theInnerSize);
|
|
// pin the window dimensions specified in the chrome to the maximum dimensions
|
|
inChrome->w_hint = MIN(maxWidth, inChrome->w_hint);
|
|
inChrome->h_hint = MIN(maxHeight, inChrome->h_hint);
|
|
newWindowBounds.right = MIN(SHRT_MAX, newWindowBounds.left + portRect.right - portRect.left + (inChrome->w_hint - theInnerSize.width));
|
|
newWindowBounds.bottom = MIN(SHRT_MAX, newWindowBounds.top + portRect.bottom - portRect.top + (inChrome->h_hint - theInnerSize.height));
|
|
}
|
|
else // no dimensions specified, so get default dimensions from port rect.
|
|
{
|
|
newWindowBounds.right = newWindowBounds.left + portRect.right - portRect.left;
|
|
newWindowBounds.bottom = newWindowBounds.top + portRect.bottom - portRect.top;
|
|
}
|
|
if (!::EqualRect(&newWindowBounds, &contentBounds))
|
|
DoSetBounds(newWindowBounds);
|
|
}
|
|
|
|
// ¥ set window attributes
|
|
// the layout's window attributes don't necessarily specify floating so set it here.
|
|
// z-lock means that the window cannot move in front of other windows in its layer.
|
|
ClearAttribute(windAttr_Floating); // clear all the layer bits before we set again - 1997-02-28 mjc
|
|
ClearAttribute(windAttr_Regular);
|
|
ClearAttribute(windAttr_Modal);
|
|
if (inChrome->topmost) // alwaysRaised=yes
|
|
SetAttribute(windAttr_Floating); // javascript under windows doesn't hide a topmost window so we won't either
|
|
else SetAttribute(windAttr_Regular);
|
|
|
|
if (inChrome->z_lock)
|
|
{
|
|
mZLocked = true;
|
|
ClearAttribute(windAttr_DelaySelect);
|
|
// z-locked window must be able to get the select click because it isn't selectable.
|
|
SetAttribute(windAttr_GetSelectClick);
|
|
}
|
|
else
|
|
{
|
|
mZLocked = false;
|
|
SetAttribute(windAttr_DelaySelect);
|
|
}
|
|
|
|
if (inChrome->bottommost && !inChrome->topmost)
|
|
{
|
|
// a bottommost window has to be in the regular layer.
|
|
// if there is more than one regular window, we'll have to send it to the back.
|
|
if (CWindowMediator::GetWindowMediator()->CountOpenWindows(
|
|
WindowType_Browser,
|
|
regularLayerType) > 1)
|
|
{
|
|
if (UDesktop::FetchTopRegular() == this)
|
|
Deactivate();
|
|
::SendBehind(GetMacPort(), NULL); // send to the back
|
|
// The following hack is based on UDesktop::Resume() and fixes a case where the
|
|
// window just sent to the back would be activated, when there is a floating
|
|
// window present.
|
|
LWindow* theTopWindow = UDesktop::FetchTopRegular();
|
|
if (theTopWindow != NULL)
|
|
{
|
|
theTopWindow->Activate();
|
|
LMSetCurActivate(nil); // Suppress any Activate event
|
|
}
|
|
}
|
|
mAlwaysOnBottom = true;
|
|
mZLocked = true; // bottommost implies z-lock
|
|
ClearAttribute(windAttr_DelaySelect); // see z_lock for explanation
|
|
SetAttribute(windAttr_GetSelectClick);
|
|
}
|
|
else
|
|
{
|
|
mAlwaysOnBottom = false;
|
|
if (mZLocked == false) SetAttribute(windAttr_DelaySelect);
|
|
}
|
|
|
|
if (inChrome->hide_title_bar)
|
|
{
|
|
// a titlebar-less window must get the click that selected it because there is
|
|
// little feedback that window is selected.
|
|
SetAttribute(windAttr_GetSelectClick);
|
|
}
|
|
else if (!HasAttribute(windAttr_Floating))
|
|
{
|
|
SetAttribute(windAttr_Targetable); // window which has titlebar and is non-floating, is targetable.
|
|
}
|
|
|
|
// 97-05-08 pkc -- set windAttr_Modal flag appropriately
|
|
if (inChrome->type == MWContextDialog)
|
|
{
|
|
AllowSubviewPopups (false);
|
|
if (!mContext->IsSpecialBrowserContext())
|
|
SetAttribute(windAttr_Modal);
|
|
}
|
|
|
|
mIsRootDocInfo = mContext->IsRootDocInfoContext();
|
|
mIsViewSource = mContext->IsViewSourceContext();
|
|
|
|
// ¥¥¥ TODO: if we have the right security we should be able to set menubar mode to BrWn_Menubar_None
|
|
if (inChrome->show_menu || mIsRootDocInfo || mIsViewSource)
|
|
mMenubarMode = BrWn_Menubar_Default;
|
|
else
|
|
mMenubarMode = BrWn_Menubar_Minimal;
|
|
|
|
// ¥ Broadcast that the menubar mode has changed
|
|
if (inNotifyMenuBarModeChanged)
|
|
NoteWindowMenubarModeChanged();
|
|
|
|
mIsHTMLHelp = (inChrome->type == MWContextHTMLHelp);
|
|
mCommandsDisabled = inChrome->disable_commands && !mIsHTMLHelp;
|
|
|
|
if (inChrome->allow_resize && !HasAttribute(windAttr_Resizable))
|
|
{
|
|
Str255 desc;
|
|
SetAttribute(windAttr_Resizable);
|
|
if (!HasAttribute(windAttr_Floating))
|
|
{
|
|
((WindowPeek)GetMacPort())->spareFlag = true; // enable zoom box
|
|
GetDescriptor(desc); // force titlebar update
|
|
SetDescriptor(desc);
|
|
}
|
|
} else if (!inChrome->allow_resize && HasAttribute(windAttr_Resizable))
|
|
{
|
|
Str255 desc;
|
|
ClearAttribute(windAttr_Resizable);
|
|
if (!HasAttribute(windAttr_Floating))
|
|
{
|
|
((WindowPeek)GetMacPort())->spareFlag = false; // disable zoom box
|
|
GetDescriptor(desc); // force titlebar update
|
|
SetDescriptor(desc);
|
|
}
|
|
}
|
|
|
|
Refresh();
|
|
}
|
|
else
|
|
{
|
|
// reset the window... but how?
|
|
}
|
|
}
|
|
|
|
// Set the chrome structure based on window state - mjc
|
|
void CBrowserWindow::GetChromeInfo(Chrome* inChrome)
|
|
{
|
|
// ¥ controls
|
|
// modified to modified to synchronize with menu items by using mToolbarShown - 1997-02-27 mjc
|
|
// The directory button bar is really the personal toolbar, though the chrome struct has yet to
|
|
// be updated to reflect this change.
|
|
inChrome->show_button_bar = mToolbarShown[eNavigationBar];
|
|
inChrome->show_url_bar = mToolbarShown[eLocationBar];
|
|
inChrome->show_directory_buttons = mToolbarShown[ePersonalToolbar];
|
|
inChrome->show_bottom_status_bar = mToolbarShown[eStatusBar];
|
|
inChrome->show_menu = mMenubarMode == BrWn_Menubar_Default;
|
|
inChrome->show_security_bar = FALSE; // ¥¥¥ always false in javascript?
|
|
|
|
inChrome->hide_title_bar = !HasAttribute(windAttr_TitleBar);
|
|
|
|
// ¥¥¥ NEED SOMETHING HERE FOR THE NAV CENTER
|
|
|
|
// ¥ position and size use window structure bounds
|
|
Rect windowBounds = UWindows::GetWindowStructureRect(GetMacPort());
|
|
// if the window is windowshaded then correct the windowBounds because height of content is zero.
|
|
if (IsVisible() && HasAttribute(windAttr_TitleBar) && ::EmptyRgn(((WindowPeek)GetMacPort())->contRgn))
|
|
windowBounds.bottom = windowBounds.bottom + mMacWindowP->portRect.bottom - mMacWindowP->portRect.top;
|
|
|
|
inChrome->outw_hint = windowBounds.right - windowBounds.left;
|
|
inChrome->outh_hint = windowBounds.bottom - windowBounds.top;
|
|
inChrome->l_hint = windowBounds.left;
|
|
inChrome->t_hint = windowBounds.top - ::GetMBarHeight();
|
|
inChrome->location_is_chrome = TRUE; // set to insure these coordinates are used.
|
|
|
|
// ¥ window properties
|
|
inChrome->topmost = this->HasAttribute(windAttr_Floating);
|
|
//inChrome->bottommost =
|
|
inChrome->z_lock = mZLocked;
|
|
|
|
inChrome->is_modal = FALSE; // always FALSE in javascript
|
|
inChrome->allow_resize = HasAttribute(windAttr_Resizable);
|
|
inChrome->allow_close = TRUE; // always TRUE in javascript
|
|
inChrome->disable_commands = mCommandsDisabled;
|
|
//inChrome->copy_history = FALSE; /* XXX need data tainting */
|
|
|
|
// default values if there is no scroller of HTMLView
|
|
inChrome->w_hint = inChrome->outw_hint;
|
|
inChrome->h_hint = inChrome->outh_hint;
|
|
inChrome->show_scrollbar = FALSE;
|
|
|
|
CHyperScroller* theScroller = (CHyperScroller*)FindPaneByID(Hyper_Scroller_PaneID);
|
|
|
|
if (theScroller == NULL) return;
|
|
|
|
SDimension16 theInnerSize;
|
|
/* if (theScroller != nil) theScroller->GetFrameSize(theInnerSize);
|
|
else */ GetHTMLView()->GetFrameSize(theInnerSize);
|
|
|
|
inChrome->w_hint = theInnerSize.width;
|
|
inChrome->h_hint = theInnerSize.height;
|
|
|
|
inChrome->show_scrollbar = (theScroller != nil) && (GetHTMLView()->GetScrollMode() != LO_SCROLL_NEVER);
|
|
}
|
|
|
|
// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
// ¥
|
|
// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
|
|
void CBrowserWindow::NoteDocTitleChanged(const char* inNewTitle)
|
|
{
|
|
CStr255 netscapeTitle;
|
|
// Get Window title prefix
|
|
::GetIndString( netscapeTitle, ID_STRINGS, APPNAME_STRING_INDEX );
|
|
netscapeTitle += ": ";
|
|
// append title
|
|
netscapeTitle += inNewTitle;
|
|
SetDescriptor( netscapeTitle );
|
|
}
|
|
|
|
|
|
void CBrowserWindow :: NoteInternetKeywordChanged(const char* inTitle)
|
|
{
|
|
if ( inTitle )
|
|
mCurrentKeyword = inTitle;
|
|
else
|
|
mCurrentKeyword = "\p";
|
|
|
|
} // NoteInternetKeywordChanged
|
|
|
|
|
|
// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
// ¥
|
|
// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
|
|
void CBrowserWindow::NoteBeginLayout(void)
|
|
{
|
|
//
|
|
// if (!is_grid) // If we are laying out main new document, adjust the URLs
|
|
// {
|
|
// CStr31 newTitle = CFileMgr::FileNameFromURL (request->address);
|
|
// SetDocTitle( newTitle );
|
|
//
|
|
// if ( fTopWrapper )
|
|
// fTopWrapper->SetLayingOutURLCaption( CStr255( NET_URLStruct_Address( request ) ) , request->is_netsite);
|
|
// fHasTitle = FALSE;
|
|
// }
|
|
// this->UpdateStatusBar();
|
|
|
|
// ¥¥¥ TELL NAVCENTER ABOUT THE CHANGE?
|
|
|
|
// 1997-05-22 brade -- context can be NULL
|
|
if (mContext)
|
|
{
|
|
// 1997-05-02 pkc -- hack to select doc info window if we're laying it out.
|
|
if (mContext->IsRootDocInfoContext())
|
|
Select();
|
|
// 1997-05-09 pkc -- set mSupportsPageServices
|
|
mSupportsPageServices = mContext->SupportsPageServices();
|
|
}
|
|
}
|
|
|
|
// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
// ¥
|
|
// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
|
|
void CBrowserWindow::NoteFinishedLayout(void)
|
|
{
|
|
// Do we need to do anything??
|
|
// ¥ TELL NAVCENTER ABOUT THE CHANGE?
|
|
}
|
|
|
|
// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
// ¥
|
|
// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
|
|
void CBrowserWindow::NoteAllConnectionsComplete(void)
|
|
{
|
|
// NetscapeContext::AllConnectionsComplete();
|
|
//
|
|
// HideProgressBar();
|
|
//
|
|
// if (fProgress)
|
|
// fProgress->SetValue(0);
|
|
//
|
|
// this->SetMessage( CStr255( *GetString(DOCUMENT_DONE_RESID)) );
|
|
// this->UpdateStatusBar();
|
|
// this->StopSpinIcon();
|
|
|
|
// CleanupImagesInTempMemory();
|
|
// fHyperView->RepaginateIfNeeded(); // This is needed for grids. The main view gets
|
|
// done before its subviews are done, so repagination never happens
|
|
|
|
// CPaneEnabler::UpdatePanes(); // moved this to CHTMLView.cp deeje 97-02-10
|
|
}
|
|
|
|
|
|
CBrowserWindow* CBrowserWindow::MakeNewBrowserWindow(Boolean inShow, Boolean inSelect)
|
|
{
|
|
ThrowIf_(Memory_MemoryIsLow());
|
|
|
|
CBrowserWindow* result = nil;
|
|
|
|
try
|
|
{
|
|
CBrowserContext* theContext = new CBrowserContext(MWContextBrowser);
|
|
StSharer theShareLock(theContext);
|
|
|
|
result = dynamic_cast<CBrowserWindow*>(LWindow::CreateWindow(res_ID, LCommander::GetTopCommander()));
|
|
ThrowIfNil_(result);
|
|
result->SetWindowContext(theContext);
|
|
|
|
if (inShow)
|
|
result->Show();
|
|
|
|
if (inSelect)
|
|
result->Select();
|
|
}
|
|
catch(...)
|
|
{
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
CBrowserWindow* CBrowserWindow::FindAndShow(Boolean inMakeNew)
|
|
{
|
|
ThrowIf_(Memory_MemoryIsLow());
|
|
|
|
CBrowserWindow* result = NULL;
|
|
CWindowIterator iter(WindowType_Browser);
|
|
CMediatedWindow* window;
|
|
|
|
iter.Next(window);
|
|
|
|
if (window)
|
|
{
|
|
result = dynamic_cast<CBrowserWindow*>(window);
|
|
}
|
|
else if (inMakeNew)
|
|
{
|
|
try
|
|
{
|
|
// ThrowIfNil_(CURLDispatcher::GetURLDispatcher());
|
|
// CURLDispatcher::GetURLDispatcher()->DispatchToView(nil, nil, FO_CACHE_AND_PRESENT, true);
|
|
result = CURLDispatcher::CreateNewBrowserWindow();
|
|
}
|
|
catch(...)
|
|
{
|
|
}
|
|
|
|
// iter.Next(window);
|
|
//
|
|
// if (window)
|
|
// {
|
|
// result = dynamic_cast<CBrowserWindow*>(window);
|
|
// }
|
|
}
|
|
else
|
|
{
|
|
CWindowMediator* mediator = CWindowMediator::GetWindowMediator();
|
|
CMediatedWindow* topWindow = mediator->FetchTopWindow(WindowType_Browser, dontCareLayerType, false);
|
|
result = dynamic_cast<CBrowserWindow*>(topWindow);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
CBrowserWindow* CBrowserWindow::FindAndPrepareEmpty(Boolean inMakeNew)
|
|
{
|
|
/*
|
|
CWindowIterator iter(WindowType_Browser);
|
|
CMediatedWindow* window;
|
|
CBrowserWindow* result = NULL;
|
|
iter.Next(window);
|
|
*/
|
|
CMediatedWindow* window;
|
|
CBrowserWindow* result = NULL;
|
|
// Find the topmost regular browser window which is not a restricted target
|
|
window = CWindowMediator::GetWindowMediator()->FetchTopWindow(WindowType_Browser, regularLayerType, false);
|
|
|
|
if (window)
|
|
result = dynamic_cast<CBrowserWindow*>(window);
|
|
else if (inMakeNew)
|
|
{
|
|
result = MakeNewBrowserWindow(kShow, kSelect);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
Boolean CBrowserWindow::HandleKeyPress(const EventRecord &inKeyEvent)
|
|
{
|
|
Char16 theChar = inKeyEvent.message & charCodeMask;
|
|
short modifiers = inKeyEvent.modifiers & (cmdKey | shiftKey | optionKey | controlKey);
|
|
|
|
// Command-Key Events
|
|
if ( ( modifiers & cmdKey ) == cmdKey )
|
|
{
|
|
switch ( theChar & charCodeMask )
|
|
{
|
|
case char_LeftArrow:
|
|
ObeyCommand( cmd_GoBack );
|
|
return true;
|
|
|
|
case char_RightArrow:
|
|
ObeyCommand( cmd_GoForward );
|
|
return true;
|
|
}
|
|
}
|
|
|
|
// Passing on the scrolling keys
|
|
|
|
// ¥¥¥ tj - only when modifiers are 0, because
|
|
// we the hyperview may have already passed the key
|
|
// up to us if there are modifiers
|
|
//
|
|
|
|
if ( modifiers == 0 && GetHTMLView())
|
|
{
|
|
if ((theChar == char_UpArrow) ||
|
|
(theChar == char_DownArrow) ||
|
|
(theChar == char_PageUp) ||
|
|
(theChar == char_PageDown) ||
|
|
(theChar == ' ') ||
|
|
(theChar == char_Home) ||
|
|
(theChar == char_End))
|
|
return GetHTMLView()->HandleKeyPress( inKeyEvent );
|
|
}
|
|
|
|
return CNetscapeWindow::HandleKeyPress(inKeyEvent);
|
|
}
|
|
|
|
//
|
|
// WriteWindowStatus
|
|
//
|
|
// Write out status of the toolbars and nav center
|
|
//
|
|
void CBrowserWindow :: WriteWindowStatus ( LStream *outStatusData )
|
|
{
|
|
CSaveWindowStatus::WriteWindowStatus(outStatusData);
|
|
CDragBarContainer* dragContainer = dynamic_cast<CDragBarContainer*>(FindPaneByID('DbCt'));
|
|
if (dragContainer && outStatusData)
|
|
dragContainer->SavePlace(outStatusData);
|
|
|
|
if ( mNavCenterParent )
|
|
mNavCenterParent->SavePlace(outStatusData);
|
|
|
|
} // CBrowserWindow :: WriteWindowStatus
|
|
|
|
|
|
//
|
|
// ReadWindowStatus
|
|
//
|
|
// Read in status of toolbars and nav center
|
|
//
|
|
void CBrowserWindow :: ReadWindowStatus ( LStream *inStatusData )
|
|
{
|
|
CSaveWindowStatus::ReadWindowStatus(inStatusData);
|
|
CDragBarContainer* dragContainer = dynamic_cast<CDragBarContainer*>(FindPaneByID('DbCt'));
|
|
if (dragContainer && inStatusData)
|
|
dragContainer->RestorePlace(inStatusData);
|
|
|
|
if ( mNavCenterParent )
|
|
mNavCenterParent->RestorePlace(inStatusData);
|
|
|
|
} // ReadWindowStatus
|
|
|
|
|
|
//
|
|
// IsPopdownTreeViewVisible
|
|
//
|
|
// Allows anyone to check and see if there is a popdown tree view currently displayed
|
|
// in a browser window
|
|
//
|
|
bool
|
|
CBrowserWindow :: IsPopdownTreeViewVisible ( )
|
|
{
|
|
return sPopdownParent && sPopdownParent->IsVisible();
|
|
|
|
} // IsPopdownTreeViewVisible
|
|
|
|
|
|
//
|
|
// ClipOutPopdown
|
|
//
|
|
// Adds to the current clipRgn the popdown box, if visible. |inView| is needed so we
|
|
// know what view we're drawing in for coordinate adjustments
|
|
//
|
|
void
|
|
CBrowserWindow :: ClipOutPopdown ( LView* inView )
|
|
{
|
|
if ( IsPopdownTreeViewVisible() ) {
|
|
StRegion clip;
|
|
::GetClip(clip);
|
|
|
|
Rect portPopdownFrame;
|
|
sPopdownParent->CalcPortFrameRect(portPopdownFrame);
|
|
Rect localPopdownFrame = PortToLocalRect ( inView, portPopdownFrame ) ;
|
|
StRegion popdownRgn(localPopdownFrame);
|
|
|
|
::DiffRgn ( clip, popdownRgn, clip );
|
|
::SetClip ( clip );
|
|
}
|
|
|
|
} // ClipOutPopdown
|
|
|
|
|
|
//
|
|
// PopDownTreeView
|
|
//
|
|
// Create a popdown Aurora tree view at the given coords (in port coords) from the given
|
|
// HT_Resource. This will dynamically size the height of the tree view.
|
|
//
|
|
void
|
|
CBrowserWindow :: PopDownTreeView ( Uint16 inLeft, Uint16 inTop, HT_Resource inResource )
|
|
{
|
|
// hide the old one if it is around.
|
|
if ( sPopdownParent )
|
|
ClosePopdownTreeView();
|
|
else {
|
|
try {
|
|
mPopdownParent = dynamic_cast<CPopdownRDFCoordinator*>
|
|
(UReanimator::CreateView(CPopdownRDFCoordinator::res_ID, this, this));
|
|
}
|
|
catch ( ... ) {
|
|
mPopdownParent = NULL;
|
|
}
|
|
}
|
|
|
|
if ( mPopdownParent ) {
|
|
// compute the height of tree (80% of the space between top of tree and bottom of browser)
|
|
const Uint16 kMinTreeHeight = 75;
|
|
const Uint16 kMaxTreeHeight = 700;
|
|
const Uint16 kTreeWidth = 250;
|
|
const float kHeightPercentage = 0.8; // 80%
|
|
const Uint16 kExtraPadding = 5;
|
|
|
|
SDimension16 browserFrame;
|
|
GetFrameSize ( browserFrame );
|
|
Uint16 spaceToWorkWith = browserFrame.height - inTop;
|
|
Uint16 newHeight = (Uint16)(spaceToWorkWith * kHeightPercentage);
|
|
if ( newHeight < kMinTreeHeight )
|
|
newHeight = kMinTreeHeight;
|
|
if ( newHeight > kMaxTreeHeight )
|
|
newHeight = kMaxTreeHeight;
|
|
|
|
// make sure we don't allow it to go off the right side of the browser by pulling it
|
|
// back to the left just enough to still fit (like menus)
|
|
if ( inLeft + kTreeWidth > browserFrame.width )
|
|
inLeft = browserFrame.width - kTreeWidth - kExtraPadding;
|
|
|
|
mPopdownParent->ResizeFrameTo ( kTreeWidth, newHeight, false );
|
|
mPopdownParent->PlaceInSuperImageAt ( inLeft, inTop, false );
|
|
mPopdownParent->BuildHTPane ( inResource, *(mHTMLView->GetContext()) );
|
|
|
|
mSavedPopdownTarget = LCommander::GetTarget();
|
|
LCommander::SwitchTarget(mPopdownParent);
|
|
mPopdownParent->AddListener(this); // listen for close messages
|
|
mPopdownParent->Show();
|
|
|
|
// make sure that we draw NOW if this is created in response to a drag
|
|
// and drop.
|
|
if ( ::StillDown() )
|
|
mPopdownParent->Draw(nil);
|
|
}
|
|
|
|
sPopdownParent = mPopdownParent; // make this the globally accessible one
|
|
|
|
} // PopDownTreeView
|
|
|
|
|
|
//
|
|
// ClosePopdownTreeView
|
|
//
|
|
// Closes up the popdown tree view and resets the target to what was active before the
|
|
// popdown was opened.
|
|
//
|
|
void
|
|
CBrowserWindow :: ClosePopdownTreeView ( )
|
|
{
|
|
if ( sPopdownParent ) {
|
|
sPopdownParent->Hide(); // hide it in whatever window it may be in
|
|
|
|
// if it was in this window, redraw things immediately if we're in the middle of
|
|
// a drag and drop and then reset the target commander to what it was before the
|
|
// popdown was activated.
|
|
if ( sPopdownParent == mPopdownParent ) {
|
|
|
|
if ( ::StillDown() ) { // redraw browser window if mouse down
|
|
Rect treePortRect;
|
|
FocusDraw();
|
|
|
|
// set the clip rgn to only redraw the area obscured by the tree
|
|
mPopdownParent->CalcPortFrameRect(treePortRect);
|
|
StRegion redrawArea(treePortRect);
|
|
Draw(nil);
|
|
}
|
|
|
|
LCommander::SwitchTarget(mSavedPopdownTarget);
|
|
|
|
} // if popdown in this window
|
|
} // if a popdown is visible
|
|
|
|
// no tree visible anymore, so clear this out.
|
|
sPopdownParent = NULL;
|
|
|
|
} // ClosePopdownTreeView
|
|
|
|
|
|
//
|
|
// OpenDockedTreeView
|
|
//
|
|
// Make sure the embedded aurora shelf is open and create a new pane to fill it with data
|
|
//
|
|
void
|
|
CBrowserWindow :: OpenDockedTreeView ( HT_Resource inTopNode )
|
|
{
|
|
mNavCenterParent->NavCenterShelf().SetShelfState(true, NULL);
|
|
mNavCenterParent->BuildHTPane ( inTopNode, *mHTMLView->GetContext() );
|
|
|
|
} // OpenDockedTreeView
|
|
|
|
|
|
//
|
|
// Click
|
|
//
|
|
// Override the default behavior to handle when a popdown Aurora tree is showing. If it
|
|
// is and the click is outside of it, dispose of it and throw away the click. Otherwise,
|
|
// just do the normal thing.
|
|
//
|
|
//¥¥¥this should probably not ignore the click when closing up the popdown. It just feels
|
|
//¥¥¥weird.
|
|
void
|
|
CBrowserWindow :: Click( SMouseDownEvent &inMouseDown )
|
|
{
|
|
if ( IsPopdownTreeViewVisible() ) {
|
|
LPane *clickedPane = FindSubPaneHitBy(inMouseDown.wherePort.h, inMouseDown.wherePort.v);
|
|
if ( clickedPane == sPopdownParent )
|
|
clickedPane->Click(inMouseDown);
|
|
else {
|
|
// don't do it on a mouse-down, wait for the mouse up
|
|
while ( ::StillDown() )
|
|
;
|
|
ClosePopdownTreeView();
|
|
}
|
|
}
|
|
else
|
|
CNetscapeWindow::Click(inMouseDown); // process click normally
|
|
}
|
|
|
|
#pragma mark -- I18N Support --
|
|
Int16 CBrowserWindow::DefaultCSIDForNewWindow()
|
|
{
|
|
Int16 default_csid;
|
|
CHTMLView *mainView = GetHTMLView();
|
|
|
|
/* mainView might be zero if the window is still being created (haven't executed
|
|
FinishCreateSelf). (note that in that case, we could still fetch mainView by
|
|
calling FindPaneByID, but again in that case, the pane's context hasn't been set up
|
|
and the view simply returns a 0, so we just skip that step and do the same) */
|
|
default_csid = mainView ? mainView->DefaultCSIDForNewWindow() : 0;
|
|
|
|
// Get it from mContext
|
|
if((0 == default_csid) && mContext)
|
|
default_csid = mContext->GetDefaultCSID();
|
|
|
|
return default_csid;
|
|
}
|
|
|
|
Int16 CBrowserWindow::GetDefaultCSID() const
|
|
{
|
|
if(mContext)
|
|
return mContext->GetDefaultCSID();
|
|
return 0;
|
|
}
|
|
void CBrowserWindow::SetDefaultCSID(Int16 default_csid)
|
|
{
|
|
if(mContext)
|
|
mContext->SetDefaultCSID(default_csid);
|
|
}
|
|
#pragma mark -- AppleEvent Support --
|
|
|
|
// pkc 2/17/97
|
|
// This code copied from mcontext.cp
|
|
// If the event action is long, dispatches it to the proper handler
|
|
// short actions are handled in this loop
|
|
void CBrowserWindow::HandleAppleEvent(const AppleEvent &inAppleEvent,
|
|
AppleEvent &outAEReply,
|
|
AEDesc &outResult,
|
|
long inAENumber)
|
|
{
|
|
switch (inAENumber) {
|
|
case AE_Go:
|
|
{
|
|
StAEDescriptor directionSpec;
|
|
OSErr err = ::AEGetParamDesc(&inAppleEvent,AE_www_go_direction,typeWildCard,&directionSpec.mDesc);
|
|
ThrowIfOSErr_(err);
|
|
OSType direction;
|
|
UExtractFromAEDesc::TheEnum(directionSpec.mDesc, direction);
|
|
DoAEGo((Int32)direction);
|
|
}
|
|
break;
|
|
case AE_GetURL:
|
|
HandleGetURLEvent(inAppleEvent, outAEReply, outResult);
|
|
break;
|
|
case AE_OpenURL:
|
|
HandleOpenURLEvent(inAppleEvent, outAEReply, outResult);
|
|
break;
|
|
case AE_RegisterWinClose:
|
|
Try_
|
|
{
|
|
OSType appSignature;
|
|
Size realSize;
|
|
OSType realType;
|
|
|
|
OSErr err = ::AEGetParamPtr(&inAppleEvent, keyDirectObject, typeApplSignature, &realType,
|
|
&appSignature, sizeof(appSignature), &realSize);
|
|
if (err == noErr) // No parameters, extract the signature from the Apple Event
|
|
fCloseNotifier = GetPSNBySig(appSignature);
|
|
else
|
|
fCloseNotifier = MoreExtractFromAEDesc::ExtractAESender(inAppleEvent);
|
|
break;
|
|
}
|
|
Catch_(inErr)
|
|
{
|
|
fCloseNotifier = MakeNoProcessPSN();
|
|
}
|
|
EndCatch_
|
|
break;
|
|
case AE_UnregisterWinClose:
|
|
fCloseNotifier = MakeNoProcessPSN();
|
|
break;
|
|
default:
|
|
LWindow::HandleAppleEvent( inAppleEvent, outAEReply, outResult, inAENumber );
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
void CBrowserWindow::GetAEProperty(DescType inProperty,
|
|
const AEDesc &inRequestedType,
|
|
AEDesc &outPropertyDesc) const
|
|
{
|
|
switch (inProperty)
|
|
{
|
|
case AE_www_typeWindowURL: // Current URL
|
|
{
|
|
if (!GetWindowContext())
|
|
{
|
|
ThrowOSErr_(errAEDescNotFound);
|
|
}
|
|
|
|
History_entry* theCurrentHistoryEntry = GetWindowContext()->GetCurrentHistoryEntry();
|
|
if (!theCurrentHistoryEntry || !theCurrentHistoryEntry->address)
|
|
{
|
|
ThrowOSErr_(errAEDescNotFound);
|
|
}
|
|
|
|
OSErr err = ::AECreateDesc(typeChar,
|
|
(Ptr) theCurrentHistoryEntry->address,
|
|
strlen(theCurrentHistoryEntry->address),
|
|
&outPropertyDesc);
|
|
ThrowIfOSErr_(err);
|
|
}
|
|
break;
|
|
|
|
case AE_www_typeWindowBusy: // is the window busy?
|
|
{
|
|
if ( !GetWindowContext() )
|
|
{
|
|
ThrowOSErr_(errAEDescNotFound);
|
|
}
|
|
|
|
Uint32 busy = XP_IsContextBusy ( *GetWindowContext() );
|
|
OSErr err = ::AECreateDesc(typeLongInteger,
|
|
&busy,
|
|
sizeof(Uint32),
|
|
&outPropertyDesc);
|
|
ThrowIfOSErr_(err);
|
|
|
|
}
|
|
break;
|
|
|
|
case AE_www_typeWindowID: // get the window ID
|
|
{
|
|
if ( !GetWindowContext() )
|
|
{
|
|
ThrowOSErr_(errAEDescNotFound);
|
|
}
|
|
|
|
Uint32 id = GetWindowContext()->GetContextUniqueID();
|
|
OSErr err = ::AECreateDesc(typeLongInteger,
|
|
& id,
|
|
sizeof(Uint32),
|
|
&outPropertyDesc);
|
|
ThrowIfOSErr_(err);
|
|
|
|
}
|
|
break;
|
|
|
|
|
|
default:
|
|
super::GetAEProperty(inProperty, inRequestedType, outPropertyDesc);
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
// Sends an GetURL event
|
|
void CBrowserWindow::SendAEGetURL(const char* url)
|
|
{
|
|
OSErr anError = noErr;
|
|
try
|
|
{
|
|
AppleEvent getURLEvent;
|
|
UAppleEventsMgr::MakeAppleEvent(AE_url_suite, AE_url_getURL,
|
|
getURLEvent);
|
|
|
|
// URL
|
|
anError = ::AEPutParamPtr(&getURLEvent,
|
|
keyDirectObject,
|
|
typeChar,
|
|
url,
|
|
strlen(url));
|
|
ThrowIfOSErr_(anError);
|
|
|
|
// This window
|
|
StAEDescriptor modelSpec;
|
|
LWindow::MakeSpecifier(modelSpec.mDesc);
|
|
anError = ::AEPutParamDesc(&getURLEvent,
|
|
AE_www_typeWindow,
|
|
&modelSpec.mDesc);
|
|
ThrowIfOSErr_(anError);
|
|
|
|
/*
|
|
// Refererer
|
|
if (strlen(refererer) > 0)
|
|
{
|
|
anError = ::AEPutParamPtr(&getURLEvent,
|
|
AE_url_getURLrefererer,
|
|
typeChar,
|
|
refererer,
|
|
strlen(refererer));
|
|
ThrowIfOSErr_(anError);
|
|
}
|
|
|
|
// Window name
|
|
if (strlen(winName) > 0)
|
|
{
|
|
anError = ::AEPutParamPtr(&getURLEvent,
|
|
AE_url_getURLname,
|
|
typeChar,
|
|
winName,
|
|
strlen(winName));
|
|
ThrowIfOSErr_(anError);
|
|
}
|
|
|
|
// Optional load-to-disk parameter
|
|
if (loadToDisk)
|
|
{
|
|
anError = ::AEPutParamPtr(&getURLEvent,
|
|
AE_url_getURLdestination,
|
|
typeNull,
|
|
NULL,
|
|
0);
|
|
ThrowIfOSErr_(anError);
|
|
}
|
|
*/
|
|
|
|
UAppleEventsMgr::SendAppleEvent(getURLEvent);
|
|
}
|
|
catch(...)
|
|
{
|
|
URL_Struct* theURL = NET_CreateURLStruct(url, NET_DONT_RELOAD);
|
|
mContext->SwitchLoadURL(theURL, FO_CACHE_AND_PRESENT);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Simplify the navigation events to only a single event, Go <direction>
|
|
// Still incomplete, since I have not figured out how to deal with history
|
|
// in an easy way.
|
|
// right now, the possible constants are:
|
|
// kAENext
|
|
// kAEPrevious
|
|
// AE_www_go_again
|
|
// AE_www_super_reload
|
|
void CBrowserWindow::SendAEGo( OSType direction )
|
|
{
|
|
OSErr anError = noErr;
|
|
|
|
try
|
|
{
|
|
AppleEvent goEvent;
|
|
UAppleEventsMgr::MakeAppleEvent(AE_www_suite, AE_www_go, goEvent);
|
|
|
|
// ¥Êthis window
|
|
StAEDescriptor modelSpec;
|
|
LWindow::MakeSpecifier(modelSpec.mDesc);
|
|
anError = ::AEPutParamDesc(&goEvent, keyDirectObject, &modelSpec.mDesc);
|
|
ThrowIfOSErr_(anError);
|
|
|
|
StAEDescriptor directionSpec(typeEnumerated, &direction, sizeof(direction));
|
|
anError = ::AEPutParamDesc(&goEvent, AE_www_go_direction, &directionSpec.mDesc);
|
|
ThrowIfOSErr_(anError);
|
|
|
|
UAppleEventsMgr::SendAppleEvent(goEvent);
|
|
}
|
|
catch(...)
|
|
{
|
|
DoAEGo(direction);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// updated to send an event to javascript, also checks for null context - 1997-02-26 mjc
|
|
// Handles the navigation events
|
|
void CBrowserWindow::DoAEGo( OSType direction )
|
|
{
|
|
switch ( direction )
|
|
{
|
|
case kAENext: // going back in history
|
|
if (mContext != NULL)
|
|
{
|
|
mContext->GoForward();
|
|
CMochaHacks::SendForwardEvent(*mContext);
|
|
}
|
|
break;
|
|
|
|
case kAEPrevious:
|
|
if (mContext != NULL)
|
|
{
|
|
mContext->GoBack();
|
|
CMochaHacks::SendBackEvent(*mContext);
|
|
}
|
|
break;
|
|
|
|
case AE_www_go_again:
|
|
if (mContext != NULL)
|
|
mContext->LoadHistoryEntry(CBrowserContext::index_Reload);
|
|
break;
|
|
|
|
case AE_www_super_reload:
|
|
if (mContext != NULL)
|
|
mContext->LoadHistoryEntry(CBrowserContext::index_Reload, true);
|
|
break;
|
|
|
|
case AE_www_go_home:
|
|
{
|
|
URL_Struct* homeURL =
|
|
NET_CreateURLStruct(CPrefs::GetString(CPrefs::HomePage), NET_DONT_RELOAD);
|
|
if (mContext != NULL)
|
|
mContext->SwitchLoadURL(homeURL, FO_CACHE_AND_PRESENT);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
SysBeep( 1 );
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CBrowserWindow::HandleGetURLEvent(const AppleEvent &inAppleEvent,
|
|
AppleEvent &outAEReply,
|
|
AEDesc &/*outResult*/,
|
|
CBrowserWindow *inBrowserWindow)
|
|
{
|
|
FSSpec fileSpec;
|
|
Boolean hasFileSpec = FALSE;
|
|
Boolean doLoadToDisk = FALSE;
|
|
DescType realType;
|
|
Size actualSize;
|
|
OSErr err;
|
|
char * url = NULL;
|
|
char * refererer = NULL;
|
|
char * winName = NULL;
|
|
|
|
#ifdef DEBUG
|
|
StValueChanger<EDebugAction> changeDebugThrow(UDebugging::gDebugThrow, debugAction_Nothing);
|
|
#endif
|
|
MoreExtractFromAEDesc::GetCString(inAppleEvent, keyDirectObject, url);
|
|
|
|
// Extract the referer, if possible
|
|
MoreExtractFromAEDesc::GetCString(inAppleEvent, AE_url_getURLrefererer, refererer, false);
|
|
MoreExtractFromAEDesc::GetCString(inAppleEvent, AE_url_getURLname, winName, false);
|
|
|
|
// See if we are doing load-to-disk.
|
|
// If the descriptor is of typeNull, we should load to disk
|
|
// but we have to file spec
|
|
{
|
|
StAEDescriptor fileDesc;
|
|
err = ::AEGetParamDesc(&inAppleEvent,AE_url_getURLdestination,typeWildCard,&fileDesc.mDesc);
|
|
if (err == noErr)
|
|
{
|
|
if (fileDesc.mDesc.descriptorType == typeNull)
|
|
doLoadToDisk = TRUE;
|
|
else
|
|
{
|
|
err = ::AEGetParamPtr(&inAppleEvent, AE_url_getURLdestination,
|
|
typeFSS, &realType,
|
|
&fileSpec,
|
|
sizeof(FSSpec), &actualSize);
|
|
if (err == errAECoercionFail)
|
|
{
|
|
char * filePath = NULL;
|
|
Try_
|
|
{
|
|
MoreExtractFromAEDesc::GetCString(inAppleEvent, AE_url_getURLdestination, filePath);
|
|
err = CFileMgr::FSSpecFromPathname(filePath, &fileSpec);
|
|
if (err == fnfErr)
|
|
err = noErr;
|
|
ThrowIfOSErr_(err);
|
|
}
|
|
Catch_(inErr)
|
|
{
|
|
err = fnfErr;
|
|
}
|
|
EndCatch_
|
|
if (filePath)
|
|
XP_FREE(filePath);
|
|
}
|
|
hasFileSpec = (err == noErr);
|
|
doLoadToDisk = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
URL_Struct * request = NET_CreateURLStruct (url, NET_DONT_RELOAD);
|
|
if (winName)
|
|
request->window_target = XP_STRDUP(winName);
|
|
ThrowIfNil_(request);
|
|
request->referer = refererer;
|
|
|
|
if (hasFileSpec && doLoadToDisk)
|
|
{
|
|
CURLDispatcher::DispatchToStorage(request, fileSpec, FO_SAVE_AS, true);
|
|
}
|
|
else if (!hasFileSpec && !doLoadToDisk)
|
|
{
|
|
if (inBrowserWindow)
|
|
{
|
|
ThrowIfNil_(inBrowserWindow->mContext);
|
|
|
|
long windowIndex = inBrowserWindow->mContext->GetContextUniqueID();
|
|
if ( !URDFUtilities::LaunchURL(url, inBrowserWindow) )
|
|
CURLDispatcher::DispatchURL(request, inBrowserWindow->mContext, true);
|
|
|
|
if (outAEReply.descriptorType != typeNull)
|
|
err = ::AEPutParamPtr (&outAEReply, keyAEResult, typeLongInteger, &windowIndex, sizeof(windowIndex));
|
|
}
|
|
else
|
|
{
|
|
if (CFrontApp::GetApplication()->HasProperlyStartedUp())
|
|
{
|
|
// Get a window - but don't show it
|
|
|
|
CBrowserWindow* win = CBrowserWindow::MakeNewBrowserWindow(kDontShow);
|
|
ThrowIfNil_(win);
|
|
|
|
ThrowIfNil_(win->mContext);
|
|
long windowIndex = win->mContext->GetContextUniqueID();
|
|
|
|
if ( !URDFUtilities::LaunchURL(url, win) )
|
|
CURLDispatcher::DispatchURL(request, win->mContext, true);
|
|
|
|
if (outAEReply.descriptorType != typeNull)
|
|
err = ::AEPutParamPtr (&outAEReply, keyAEResult, typeLongInteger, &windowIndex, sizeof(windowIndex));
|
|
}
|
|
else
|
|
{
|
|
// MGY 5/22: If there are multiple profiles and the event is handled before the user selects a profile,
|
|
// then prefs have not been loaded and we will crash trying to restore the position of the browser window.
|
|
// To fix it right, we will have to delay the positioning of the window until it is shown. The mechanism
|
|
// by which the position of windows is restored is not flexible enough to allow this and to make it so now
|
|
// would be too intrusive of a change at this late date. So we just return 0 for the window ID and the
|
|
// window will be created when the delayed URL is handled.
|
|
|
|
if ( !URDFUtilities::LaunchURL(url) )
|
|
CURLDispatcher::DispatchURL(request, nil, true);
|
|
|
|
long windowIndex = 0;
|
|
if (outAEReply.descriptorType != typeNull)
|
|
err = ::AEPutParamPtr (&outAEReply, keyAEResult, typeLongInteger, &windowIndex, sizeof(windowIndex));
|
|
}
|
|
}
|
|
}
|
|
XP_FREE (url);
|
|
if (winName)
|
|
XP_FREE(winName);
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------
|
|
// Spyglass AppleEvent suite
|
|
//--------------------------------------------------------------------------------
|
|
|
|
void CBrowserWindow::HandleOpenURLEvent(const AppleEvent &inAppleEvent,
|
|
AppleEvent &outAEReply,
|
|
AEDesc &/*outResult*/,
|
|
CBrowserWindow *inBrowserWindow)
|
|
{
|
|
char * formData = NULL; // Do not free this
|
|
char * formHeader = NULL; // form headers (MIME type)
|
|
ProcessSerialNumber psn;
|
|
FSSpec fileSpec;
|
|
Boolean hasFileSpec = FALSE;
|
|
Boolean hasFormData = FALSE;
|
|
Boolean hasPSN = FALSE;
|
|
Boolean forceReload = FALSE;
|
|
OSErr err;
|
|
Size actualSize;
|
|
DescType realType;
|
|
|
|
// Get the url
|
|
char* foo;
|
|
MoreExtractFromAEDesc::GetCString(inAppleEvent, keyDirectObject, foo);
|
|
CAutoPtrXP<char> url(foo);
|
|
|
|
{ // See if we are doing load-to-disk
|
|
err = ::AEGetParamPtr(&inAppleEvent, AE_spy_openURL_into,
|
|
typeFSS, &realType,
|
|
&fileSpec,
|
|
sizeof(fileSpec), &actualSize);
|
|
if (err == noErr)
|
|
hasFileSpec = TRUE;
|
|
}
|
|
// Flags
|
|
Try_
|
|
{
|
|
long flags;
|
|
err = ::AEGetParamPtr(&inAppleEvent, AE_spy_openURL_flag, typeLongInteger,
|
|
&realType, &flags, sizeof(flags), &actualSize);
|
|
ThrowIfOSErr_(err);
|
|
if ((flags & 0x1) || (flags & 0x2))
|
|
forceReload = TRUE;
|
|
}
|
|
Catch_(inErr){}
|
|
EndCatch_
|
|
// Form data?
|
|
Try_
|
|
{
|
|
MoreExtractFromAEDesc::GetCString(inAppleEvent, AE_spy_openURL_post, formData);
|
|
hasFormData = TRUE;
|
|
}
|
|
Catch_(inErr){}
|
|
EndCatch_
|
|
// If we have form data, get the form MIME type
|
|
if (formData)
|
|
Try_
|
|
{
|
|
char * newFormHeader = NULL;
|
|
MoreExtractFromAEDesc::GetCString(inAppleEvent, AE_spy_openURL_mime, formHeader);
|
|
StrAllocCat(formHeader, CRLF);
|
|
}
|
|
Catch_(inErr)
|
|
{
|
|
StrAllocCopy(formHeader, "Content-type: application/x-www-form-urlencoded");
|
|
StrAllocCat(formHeader, CRLF);
|
|
}
|
|
EndCatch_
|
|
if (formData && formHeader)
|
|
{
|
|
char buffer[64];
|
|
XP_SPRINTF(buffer, "Content-length: %ld%s", strlen(formData), CRLF);
|
|
StrAllocCat(formHeader, buffer);
|
|
}
|
|
{ // Progress application
|
|
err = ::AEGetParamPtr(&inAppleEvent, AE_spy_openURL_prog,
|
|
typeProcessSerialNumber, &realType,
|
|
&psn,
|
|
sizeof(psn), &actualSize);
|
|
if (err == noErr)
|
|
hasPSN = TRUE;
|
|
}
|
|
|
|
// create a Netlib geturl thread
|
|
URL_Struct * request = NET_CreateURLStruct (url.get(), NET_DONT_RELOAD);
|
|
ThrowIfNil_(request);
|
|
|
|
if (forceReload)
|
|
request->force_reload = NET_NORMAL_RELOAD;
|
|
else
|
|
request->force_reload = NET_DONT_RELOAD;
|
|
if (hasFormData)
|
|
{
|
|
request->method = 1;
|
|
request->post_data = formData;
|
|
request->post_data_size = strlen(formData);
|
|
request->post_headers = formHeader;
|
|
}
|
|
|
|
// service non-interactive request from a different application
|
|
|
|
/*
|
|
¥¥¥ what do we do with this in dobgert, since SetProgressApp no longer exists?
|
|
if (hasPSN)
|
|
mContext->SetProgressApp(psn);
|
|
*/
|
|
|
|
if (hasFileSpec)
|
|
{
|
|
CURLDispatcher::DispatchToStorage(request, fileSpec, FO_SAVE_AS, true);
|
|
}
|
|
else
|
|
{
|
|
if (inBrowserWindow)
|
|
{
|
|
ThrowIfNil_(inBrowserWindow->mContext);
|
|
|
|
long windowID = inBrowserWindow->mContext->GetContextUniqueID();
|
|
/*
|
|
¥¥¥ what is this? deeje 97-03-07
|
|
if (!fHyperView->CanLoad())
|
|
windowID = 0;
|
|
*/
|
|
if (outAEReply.descriptorType != typeNull)
|
|
{
|
|
StAEDescriptor windowIDDesc(windowID);
|
|
err = ::AEPutParamDesc(&outAEReply, keyAEResult, &windowIDDesc.mDesc);
|
|
}
|
|
|
|
if ( !URDFUtilities::LaunchURL(url.get(), inBrowserWindow) )
|
|
CURLDispatcher::DispatchURL(request, inBrowserWindow->mContext, true);
|
|
}
|
|
else
|
|
{
|
|
if (CFrontApp::GetApplication()->HasProperlyStartedUp())
|
|
{
|
|
// Get a window - but don't show it
|
|
|
|
CBrowserWindow* win = CBrowserWindow::MakeNewBrowserWindow(kDontShow);
|
|
ThrowIfNil_(win);
|
|
|
|
ThrowIfNil_(win->mContext);
|
|
long windowIndex = win->mContext->GetContextUniqueID();
|
|
|
|
if ( !URDFUtilities::LaunchURL(url.get(), win) )
|
|
CURLDispatcher::DispatchURL(request, win->mContext, true);
|
|
|
|
if (outAEReply.descriptorType != typeNull)
|
|
err = ::AEPutParamPtr (&outAEReply, keyAEResult, typeLongInteger, &windowIndex, sizeof(windowIndex));
|
|
}
|
|
else
|
|
{
|
|
// MGY 5/22: If there are multiple profiles and the event is handled before the user selects a profile,
|
|
// then prefs have not been loaded and we will crash trying to restore the position of the browser window.
|
|
// To fix it right, we will have to delay the positioning of the window until it is shown. The mechanism
|
|
// by which the position of windows is restored is not flexible enough to allow this and to make it so now
|
|
// would be too intrusive of a change at this late date. So we just return 0 for the window ID and the
|
|
// window will be created when the delayed URL is handled.
|
|
|
|
if ( !URDFUtilities::LaunchURL(url.get()) )
|
|
CURLDispatcher::DispatchURL(request, nil, true);
|
|
|
|
long windowIndex = 0;
|
|
if (outAEReply.descriptorType != typeNull)
|
|
err = ::AEPutParamPtr (&outAEReply, keyAEResult, typeLongInteger, &windowIndex, sizeof(windowIndex));
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
// override to send javascript move events when the user performs the action
|
|
// because ClickInDrag sends an AppleEvent which doesn't come back to the app.
|
|
void
|
|
CBrowserWindow::SendAESetPosition(Point inPosition, Boolean inExecuteAE)
|
|
{
|
|
CNetscapeWindow::SendAESetPosition(inPosition, inExecuteAE);
|
|
if (mContext != NULL)
|
|
{
|
|
Rect bounds;
|
|
bounds = UWindows::GetWindowStructureRect(GetMacPort());
|
|
CMochaHacks::SendMoveEvent(*mContext, bounds.left, bounds.top - ::GetMBarHeight());
|
|
}
|
|
}
|
|
|
|
void CBrowserWindow::DoDefaultPrefs()
|
|
{
|
|
CPrefsDialog::EditPrefs(CPrefsDialog::eExpandBrowser);
|
|
}
|
|
|
|
|
|
|
|
#if 0
|
|
History_entry* CBrowserWindow::GetBookmarksEntry()
|
|
{
|
|
return mContext->GetCurrentHistoryEntry();
|
|
}
|
|
#endif // 0
|
|
|
|
|
|
#pragma mark -- Helper functions for ObeyCommand --
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// ¥ HandleNetSearchCommand
|
|
// ---------------------------------------------------------------------------
|
|
|
|
void
|
|
CBrowserWindow::HandleNetSearchCommand()
|
|
{
|
|
CAutoPtrXP<char> url;
|
|
char* tempURL = 0;
|
|
int rc;
|
|
|
|
rc = PREF_CopyConfigString("internal_url.net_search.url", &tempURL);
|
|
url.reset(tempURL);
|
|
|
|
if (rc == PREF_NOERROR)
|
|
{
|
|
CFrontApp& theApp = dynamic_cast<CFrontApp&>(CApplicationEventAttachment::GetApplication());
|
|
|
|
theApp.DoGetURL(url.get());
|
|
}
|
|
}
|