/* -*- 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 #include #include // 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(FindPaneByID(CHTMLView::pane_ID)); ThrowIfNil_(mHTMLView); mNavCenterParent = dynamic_cast(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(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(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(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(FindPaneByID(CProxyPane::class_ID)); if (browserPageProxy) mContext->AddListener(browserPageProxy); // now hook up CURLCaption to listen to context CURLCaption* urlCaption = dynamic_cast(FindPaneByID(CURLCaption::class_ID)); if (urlCaption) mContext->AddListener(urlCaption); // now hook up CURLEditField to listen to context CURLEditField* urlField = dynamic_cast(FindPaneByID(CURLEditField::class_ID)); if (urlField) { mContext->AddListener(urlField); urlField->AddListener(this); if (urlCaption) urlField->AddListener(urlCaption); } CSpinningN* theN = dynamic_cast(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(FindPaneByID(CBrowserSecurityButton::class_ID)); if (securityButton) mContext->AddListener(securityButton); CMiniSecurityButton* miniSecurityButton = dynamic_cast(FindPaneByID(CMiniSecurityButton::class_ID)); if (miniSecurityButton) mContext->AddListener(miniSecurityButton); #ifdef MOZ_OFFLINE // hook up the offline icon LBroadcaster* offlineButton = dynamic_cast(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(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(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 changeStandardWidth(mStandardSize.width, max_Int16); StValueChanger 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(mContext->GetTopContext()); if (theTopContext) { theHTMLView = ::ExtractHyperView((MWContext*)(*theTopContext)); } StValueChanger saveStandardWidth(const_cast(this)->mStandardSize.width, max_Int16); StValueChanger saveStandardHeight(const_cast(this)->mStandardSize.height, max_Int16); CHTMLView::CalcStandardSizeForWindowForScreen( theHTMLView, *this, inScreenBounds, const_cast(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(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(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(FindPaneByID('StBv')); if (statusArea) statusArea->DontBevelGrowIcon(); } void CBrowserWindow::SetSystemGrowIconBevel() { CBevelView* statusArea = dynamic_cast(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(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(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(window); // } } else { CWindowMediator* mediator = CWindowMediator::GetWindowMediator(); CMediatedWindow* topWindow = mediator->FetchTopWindow(WindowType_Browser, dontCareLayerType, false); result = dynamic_cast(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(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(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(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 (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 // 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 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 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 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(CApplicationEventAttachment::GetApplication()); theApp.DoGetURL(url.get()); } }