/* -*- 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. */ // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // CHTMLView.cp // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ #include "CHTMLView.h" #include "CStLayerOriginSetter.h" #include #include "CHTMLClickrecord.h" #include "CBrowserContext.h" #include "CBrowserWindow.h" #include "CURLDispatcher.h" #include "UFormElementFactory.h" #include "RandomFrontEndCrap.h" #include "CDrawable.h" #include "CMochaHacks.h" // this includes libevent.h #include "CHyperScroller.h" #include "UGraphicGizmos.h" #include "CContextMenuAttachment.h" #include "CSharedPatternWorld.h" #include "CApplicationEventAttachment.h" #include "CViewUtils.h" #include "CTargetFramer.h" #include "uapp.h" #include "libimg.h" //#include "allxpstr.h" THE DATA DEFINITION MOVED TO StringLibPPC #include "xlate.h" #include "xp_rect.h" #include "xp_core.h" #include "layers.h" #include "nppriv.h" // FIX ME!!! this is only for SCROLLER_ID remove in favor of xxx::class_ID #include "resgui.h" #include "macgui.h" #include "mimages.h" #include "mplugin.h" #if defined (JAVA) #include "mjava.h" #endif /* defined (JAVA) */ #include "mforms.h" #include "mkutils.h" #include "libi18n.h" #include "prefapi.h" #include "secnav.h" extern "C" { #include "typedefs_md.h" #if defined (JAVA) #include "native.h" #include "sun_awt_macos_MComponentPeer.h" #include "java_awt_Component.h" #include "interpreter.h" #include "exceptions.h" #include "prlog.h" #endif /* defined (JAVA) */ #undef __cplusplus #define IMPLEMENT_netscape_applet_MozillaAppletContext #include "n_applet_MozillaAppletContext.h" // #include "mdmacmem.h" #include "java.h" #include "jri.h" #include "lj.h" } #if defined (JAVA) #include "MToolkit.h" #include "MFramePeer.h" #endif /* defined (JAVA) */ #include "mprint.h" // 97/01/24 jrm #include "ufilemgr.h" // 96-12-16 deeje #include "uerrmgr.h" #include "CBookmarksAttachment.h" #include "Drag.h" #include "macutil.h" #include "UStdDialogs.h" #include "findw.h" #include "CPaneEnabler.h" #include "msgcom.h" // for MSG_MailDocument #include #include #include #include const Int16 FocusBox_Size = 3; const Int16 TableBorder_TintLevel = 20000; const ResIDT cPaulsMiscStrListID = 16010; const Int16 cSendPageIndex = 4; const Int16 cSendFrameIndex = 5; // Explicit Template instantiation for StValueChanger for LO_Element* template StValueChanger::StValueChanger( T &ioVariable, T inNewValue) : mVariable(ioVariable), mOrigValue(ioVariable) { ioVariable = inNewValue; } template StValueChanger::~StValueChanger() { mVariable = mOrigValue; } template class StValueChanger; // Utility function for table borders Uint16 AddWithoutOverflow(Uint16 base, Uint16 addition); Uint16 SubWithoutUnderflow(Uint16 base, Uint16 difference); void ComputeBevelColor(Boolean inRaised, RGBColor inBaseColor, RGBColor& outBevelColor); static void MochaFocusCallback(MWContext * pContext, LO_Element * lo_element, int32 lType, void * whatever, ETEventStatus status); Boolean HasEventHandler(MWContext *context, uint32 events); /* returns true if any of the events specified has a handler in the context and its parents. */ Boolean HasEventHandler(MWContext *context, uint32 events) { if (context == NULL) return false; if (context->event_bit & events) return true; if (context->grid_parent) return HasEventHandler(context->grid_parent, events); return false; } void SafeSetCursor(ResIDT inCursorID) { CursPtr cursorPtr; CursHandle cursorHandle; cursorHandle = ::GetCursor(inCursorID); if (cursorHandle != NULL) { cursorPtr = *cursorHandle; } else { cursorPtr = &UQDGlobals::GetQDGlobals()->arrow; } ::SetCursor(cursorPtr); } UInt32 CHTMLView::sLastFormKeyPressDispatchTime = 0; // to prevent infinite event dispatching loop Boolean CHTMLView::sCachedAlwaysLoadImages = false; // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ CHTMLView::CHTMLView(LStream* inStream) : LView(inStream) , LDragAndDrop(GetMacPort(), this) , mContext(nil) , mSuperHTMLView(nil) , mCompositor(nil) , mPendingDocDimension_IsValid(false) , mCurrentClickRecord(nil) , mDragElement(nil) , mPatternWorld(nil) , mNeedToRepaginate(false) , mDontAddGridEdgeToList(false) , mLoadingURL(false) , mStopEnablerHackExecuted(false) , mInFocusCallAlready(false) { // FIX ME: Use C++. I.e., use mem-initializers where possible (as above) mNoBorder = false; mCachedPort = NULL; mDefaultScrollMode = LO_SCROLL_AUTO; mScrollMode = mDefaultScrollMode; mHasGridCells = false; mShowFocus = false; mElemBaseModel = NULL; mBackgroundImage = NULL; mEraseBackground = TRUE; memset(&mBackgroundColor, 0xFF, sizeof(mBackgroundColor)); // white mCompositor = NULL; mLayerClip = NULL; ::SetEmptyRgn(mSaveLayerClip); mSendDataUPP = NewDragSendDataProc(LDropArea::HandleDragSendData); Assert_(mSendDataUPP != NULL); // FIX ME!!! the scroller dependency needs to be removed mScroller = NULL; mTimerURLString = NULL; mOffscreenDrawable = NULL; mOnscreenDrawable = NULL; mCurrentDrawable = NULL; mWaitMouseUp = false; mLayerOrigin.h = mLayerOrigin.v = 0; RegisterCallBackCalls(); // Sets sCachedAlwaysLoadImages for the first time PrefInvalidateCachedPreference("general.always_load_images", (void *)this); } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ CHTMLView::~CHTMLView() { if (!GetSuperHTMLView()) { UnregisterCallBackCalls(); } if (mPatternWorld) mPatternWorld->RemoveUser(this); if (mSendDataUPP != NULL) DisposeRoutineDescriptor(mSendDataUPP); if ( mOnscreenDrawable != NULL ) mOnscreenDrawable->SetParent ( NULL ); SetContext(NULL); //CL_DestroyCompositor(mCompositor); // brade: check for NULL in case compositor wasn't created yet if ( mCompositor ) mCompositor->RemoveUser(this); } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ void CHTMLView::FinishCreateSelf(void) { LView::FinishCreateSelf(); mCachedPort = GetMacPort(); Assert_(mCachedPort != NULL); // ₯₯₯ Hack, how else do we do this though? // Main view or the frames // FIX ME!!! the scroller dependency need to be removed // if ((mSuperView->GetPaneID() == SCROLLER_ID ) || (mSuperView->GetPaneID() == 1005)) // mScroller = (CHyperScroller*)mSuperView; mScroller = dynamic_cast(mSuperView); // - jrm SDimension16 theFrameSize; GetFrameSize(theFrameSize); /* create our onscreen drawable that will route drawable method calls from the compositor */ /* to this view */ mOnscreenDrawable = new CRouterDrawable(); if ( mOnscreenDrawable != NULL ) { // send all onscreen drawable method calls this way mOnscreenDrawable->SetParent ( this ); CL_Drawable * theDrawable = CL_NewDrawable(theFrameSize.width, theFrameSize.height, CL_WINDOW, &mfe_drawable_vtable, (void *) mOnscreenDrawable); if (theDrawable != NULL) { CL_Drawable* theOffscreen = NULL; // Create our offscreen drawable. If it fails for whatever reason, we don't really care // as we'll just always be onscreen mOffscreenDrawable = COffscreenDrawable::AllocateOffscreen(); if ( mOffscreenDrawable != NULL ) { /* have the offscreen defer all layers calls to us */ mOffscreenDrawable->SetParent ( this ); theOffscreen = CL_NewDrawable(theFrameSize.width, theFrameSize.height, CL_BACKING_STORE, &mfe_drawable_vtable, (void *) mOffscreenDrawable); } // now create our compositor CL_Compositor* c = CL_NewCompositor(theDrawable, theOffscreen, 0, 0, theFrameSize.width, theFrameSize.height, 10); mCompositor = new CSharableCompositor(c); mCompositor->AddUser(this); // shared by context and view. } } // set up background color and pattern // This code is here so that we display default background when // user has blank home page. - no, that's not the only reason. PLEASE // TRY TO REMEMBER THAT THIS CLASS IS USED FOR MAIL MESSAGES AND COMPOSER VIEWS! // ₯ install the user's default solid background color & pattern InstallBackgroundColor(); // now use installed background color to set window background color SetWindowBackgroundColor(); } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ void CHTMLView::SetContext( CBrowserContext* inNewContext) { // jrm - I added these bookend calls to disable the compositor - 97/02/15. // callbacks from timer were crashing! if (!inNewContext && mCompositor) CL_SetCompositorEnabled(*mCompositor, PR_FALSE); if (mContext != NULL) { // mContext->SetCompositor(NULL); // ^^^^^^^^Do NOT do this. If you do, layout will not be able // to clean up properly. This is very bad. // The compositor needs to stick around till the context is deleted. // So the context shares the CSharableCompositor mContext->RemoveUser(this); // set pointer to this view in MWContext to NULL mContext->ClearMWContextViewPtr(); } mContext = inNewContext; if (mContext != NULL) { // Set up the character set stuff SetFontInfo(); mContext->SetCurrentView(this); mContext->SetCompositor(mCompositor); // context will share it. mContext->AddListener(this); mContext->AddUser(this); } if (inNewContext && mCompositor) CL_SetCompositorEnabled(*mCompositor, PR_TRUE); } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // #pragma mark --- ACCESSORS --- // // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ Boolean CHTMLView::IsBorderless(void) const { return (mNoBorder && !IsRootHTMLView()); } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ Boolean CHTMLView::IsRootHTMLView(void) const { return (mSuperHTMLView == NULL); } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ Boolean CHTMLView::IsFocusedFrame(void) const { return (mShowFocus && !mHasGridCells && IsOnDuty()); } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ CHTMLView* CHTMLView::GetSuperHTMLView(void) { return mSuperHTMLView; } // --------------------------------------------------------------------------- // ₯ BeTarget // --------------------------------------------------------------------------- /* since CHTMLView is an LTabGroup, its default behaviour would be to cycle among its subpanes until it found the next one that wanted to be the target. There can be situations, however, where none of our subpanes want to be the target; a silly impasse. Our BeTarget then mimics the behaviour of LTabGroup::BeTarget, but is prepared to accept the focus itself if necessary. An added wrinkle comes from the inability of certain of our subpanes (CPluginView) to correctly preflight whether they will be able to accept the target (in ProcessCommand). When this happens, CPluginView tells its supercommander (us) to be the target and a stack explosion results. Thus the member variable, mTargeting, which detects recursive calls*/ /* Later note: BeTarget was gutted so that CHTMLView _could_ take the focus. This solves problems that happen with simultaneous text selection in the CHTMLView body and in a form edit field. If you wish to reinstate BeTarget(), you must declare a private class boolean called mTargeting, and initialize it to false in the constructor. */ void CHTMLView::BeTarget() { /* // punt if one of our [bleep]ing subcommanders is trying to put the onus back on us if (mTargeting) return; StValueChanger targetMode (mTargeting, true); LCommander *onDutySub = GetOnDutySub(); Int32 pos, // index of the subcommander currently handed the torch subCount = mSubCommanders.GetCount(); pos = subCount; if (onDutySub) pos = mSubCommanders.FetchIndexOf (&onDutySub); // find the next willing subcommander in rotation (a la LTabGroup::BeTarget) if (pos > 0) { Int32 startingPos = pos; LCommander *newTarget; do { // increment and wrap if (++pos > subCount) pos = 1; mSubCommanders.FetchItemAt (pos, &newTarget); if (newTarget->ProcessCommand(msg_TabSelect)) { if (newTarget->IsTarget()) break; } } while (pos != startingPos); } */ } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ Shows the pane by scrolling to it // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ void CHTMLView::ShowView( LPane& pane ) { if (mScroller && mScroller->HasVerticalScrollbar()) // ₯₯₯ FIX ME. We really need to know which way do we want to scroll, // and then constrain it based on whether we have scrollbars { SPoint32 topLeft, botRight; SDimension16 size; pane.GetFrameLocation(topLeft); // This is in window coordinates pane.GetFrameSize(size); topLeft.v -= mImageLocation.v; // Adjust for our view's image position topLeft.h -= mImageLocation.h; botRight.h = topLeft.h + size.width; botRight.v = topLeft.v + size.height; RevealInImage(this, topLeft, botRight); } } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ void CHTMLView::SetRepaginate(Boolean inSetting) { mNeedToRepaginate = inSetting; } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ Boolean CHTMLView::GetRepaginate() { return mNeedToRepaginate; } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ void CHTMLView::SetSuperHTMLView(CHTMLView *inView) { // If we have a SuperHTMLView then we don't want to be called back. if (inView && !mSuperHTMLView) { UnregisterCallBackCalls(); } else if (!inView && mSuperHTMLView) { RegisterCallBackCalls(); } mSuperHTMLView = inView; } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ void CHTMLView::SetFormElemBaseModel(LModelObject* inModel) { mElemBaseModel = inModel; } LModelObject* CHTMLView::GetFormElemBaseModel(void) { LModelObject* theBase; if (mElemBaseModel != NULL) theBase = mElemBaseModel; else theBase = LModelObject::GetDefaultModel(); return theBase; } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ Reset scroll mode to default (LO_SCROLL_AUTO). Use to transition from LO_SCROLL_NEVER. // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ void CHTMLView::ResetScrollMode(Boolean inRefresh) { mScrollMode = LO_SCROLL_YES; SetScrollMode(mScrollMode, inRefresh); mScrollMode = mDefaultScrollMode; } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ Reset scroll mode to default (LO_SCROLL_AUTO). This really resets to // default. // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // 97.12.19 pchen. Add method to *REALLY* reset scroll mode to default scroll mode. void CHTMLView::ResetToDefaultScrollMode() { SetScrollMode(mDefaultScrollMode); mScrollMode = mDefaultScrollMode; } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ LO_SCROLL_NEVER disallows changing the scroll mode until ResetScrollMode() called. // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ void CHTMLView::SetScrollMode( Int8 inScrollMode, Boolean inRefresh) { if (mScrollMode != LO_SCROLL_NEVER) mScrollMode = inScrollMode; if (mScroller != NULL) { if ((mScrollMode == LO_SCROLL_NEVER) || (mScrollMode == LO_SCROLL_NO) || (mScrollMode == LO_SCROLL_AUTO)) mScroller->ShowScrollbars(false, false); else mScroller->ShowScrollbars(true, true); // FIX ME!!! if this is never used, take it out if ( inRefresh ) ;// ₯₯ FIX ME } } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ Boolean CHTMLView::GetScrollMode(void) const { return mScrollMode; } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ void CHTMLView::SpendTime(const EventRecord& /* inMacEvent */) { // // Pagination // if (fLastLedge != NO_LEDGE && fNextLedgeUpdate < TickCount()) // DoSetDocDimension( fLastLedge, fLastWidthDelta, fLastHeightDelta ); // // Refresh timer if (mTimerURLString && (mTimerURLFireTime < LMGetTicks()) && IsEnabled() && ( XP_IsContextBusy(*mContext) == false) && CFrontApp::GetApplication() && CFrontApp::GetApplication()->HasProperlyStartedUp()) { URL_Struct * request = NET_CreateURLStruct (mTimerURLString, NET_NORMAL_RELOAD); ClearTimerURL(); // ...frees mTimerURLString, so must do this _after_ |NET_CreateURLStruct|. if (request) { request->referer = XP_STRDUP( mContext->GetCurrentURL() ); mContext->SwitchLoadURL( request, FO_CACHE_AND_PRESENT ); } } } #pragma mark --- I18N SUPPORT --- // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ Int16 CHTMLView::DefaultCSIDForNewWindow(void) { Int16 csid = 0; if (mContext) { csid = mContext->GetDocCSID(); if(0 == csid) csid = mContext->GetDefaultCSID(); } return csid; } Int16 CHTMLView::GetWinCSID(void) const { if (mContext) return mContext->GetWinCSID(); else return 0; } void CHTMLView::SetFontInfo() { Boolean found; found = CPrefs::GetFont( GetWinCSID(), &mCharSet ); } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // #pragma mark --- NOTIFICATION RESPONSE --- // // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ Mocha submit callback // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ void MochaFormSubmitCallback(MWContext* pContext, LO_Element* lo_element, int32 lType, void* whatever, ETEventStatus status); void MochaFormSubmitCallback(MWContext* pContext, LO_Element* lo_element, int32 /* lType */, void* /* whatever */, ETEventStatus status) { if (status == EVENT_OK) { // Call the LO module to figure out the form's context LO_FormSubmitData* submit = LO_SubmitForm(pContext, (LO_FormElementStruct*)lo_element); if (submit == NULL) return; URL_Struct* url = NET_CreateURLStruct((char *)submit->action, NET_DONT_RELOAD); CBrowserContext* context = ExtractBrowserContext(pContext); if (context) { History_entry* current = context->GetCurrentHistoryEntry(); if (current && current->address) url->referer = XP_STRDUP(current->address); NET_AddLOSubmitDataToURLStruct(submit, url); context->SwitchLoadURL(url, FO_CACHE_AND_PRESENT); } LO_FreeSubmitData(submit); } } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ Mocha image form submit callback // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ struct ImageFormSubmitData { LO_ImageStruct* lo_image; int32 x; int32 y; }; void MochaImageFormSubmitCallback(MWContext* pContext, LO_Element* lo_element, int32 lType, void* whatever, ETEventStatus status); void MochaImageFormSubmitCallback(MWContext* pContext, LO_Element* /* lo_element */, int32 /* lType */, void* whatever, ETEventStatus status) { if (status == EVENT_OK) { LO_FormSubmitData *theSubmit = NULL; ImageFormSubmitData *data = reinterpret_cast(whatever); try { theSubmit = LO_SubmitImageForm(pContext, data->lo_image, data->x, data->y); // ThrowIfNULL_(theSubmit); // 97-06-07 pkc -- NULL is a valid return value from LO_SubmitImageForm if (theSubmit) { URL_Struct* theURL = NET_CreateURLStruct((char*)theSubmit->action, NET_DONT_RELOAD); ThrowIfNULL_(theURL); CBrowserContext* theContext = ExtractBrowserContext(pContext); if (theContext) { cstring theCurrentURL = theContext->GetCurrentURL(); if (theCurrentURL.length() > 0) theURL->referer = XP_STRDUP(theCurrentURL); if (NET_AddLOSubmitDataToURLStruct(theSubmit, theURL)) CURLDispatcher::DispatchURL(theURL, theContext, true); LO_FreeSubmitData(theSubmit); } } } catch (...) { LO_FreeSubmitData(theSubmit); throw; } } } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ void CHTMLView::ListenToMessage( MessageT inMessage, void* ioParam) { switch (inMessage) { case msg_NSCFinishedLayout: NoteFinishedLayout(); break; case msg_NSCAllConnectionsComplete: NoteAllConnectionsComplete(); /* update any commands which might change based on allConnectionsComplete */ LCommander::SetUpdateCommandStatus(true); break; case msg_NSCPEmptyRepagination: NoteEmptyRepagination(); break; case msg_NSCPAboutToRepaginate: NoteStartRepagination(); break; case msg_NSCConfirmLoadNewURL: NoteConfirmLoadNewURL(*(Boolean*)ioParam); break; case msg_NSCStartLoadURL: NoteStartLoadURL(); break; case msg_NSCProgressMessageChanged: // Update Panes to enable the stop button if (!mStopEnablerHackExecuted && mLoadingURL && GetContext() == GetContext()->GetTopContext()) { CPaneEnabler::UpdatePanes(); mStopEnablerHackExecuted = true; } break; case msg_NSCGridContextPreDispose: NoteGridContextPreDispose(*(Boolean*)ioParam); break; case msg_NSCGridContextDisposed: NoteGridContextDisposed(); break; // FORMS case msg_SubmitButton: // submission case msg_SubmitText: { void * formID; StTempFormBlur tempBlur; // see mforms.h for an explanation if (inMessage == msg_SubmitButton) { LPane* thePane = (LPane*)ioParam; LControl* theControl = dynamic_cast(thePane); ThrowIfNil_(theControl); formID = (void*) theControl->GetUserCon(); } else formID = ((CFormLittleText*)ioParam)->GetLayoutForm(); /* if ( true ) // LM_SendOnSubmit(*mContext, (LO_Element*) formID) { // Call the LO module to figure out the form's context submit = LO_SubmitForm(*mContext,( LO_FormElementStruct *)formID); if (submit == NULL) return; URL_Struct * url = NET_CreateURLStruct((char *)submit->action, NET_DONT_RELOAD); History_entry* current = mContext->GetCurrentHistoryEntry(); if (current && current->address) url->referer = XP_STRDUP(current->address); NET_AddLOSubmitDataToURLStruct(submit, url); mContext->SwitchLoadURL(url, FO_CACHE_AND_PRESENT); LO_FreeSubmitData(submit); } */ // ET_SendEvent now takes a JSEvent struct instead of an int type JSEvent* event = XP_NEW_ZAP(JSEvent); if (event) { event->type = EVENT_SUBMIT; // The code above will get executed in MochaFormSubmitCallback ET_SendEvent(*mContext, (LO_Element*)formID, event, MochaFormSubmitCallback, NULL); } } break; case msg_ResetButton: // Reset the form. ioParam is LStdButton { LPane* thePane = (LPane*)ioParam; LControl* theControl = dynamic_cast(thePane); ThrowIfNil_(theControl); LO_ResetForm(*mContext, (LO_FormElementStruct*) theControl->GetUserCon()); } break; case msg_ControlClicked: // Click on the radio button. Change da others { LPane* thePane = (LPane*)ioParam; LControl* theControl = dynamic_cast(thePane); ThrowIfNil_(theControl); LO_FormRadioSet(*mContext, (LO_FormElementStruct*) theControl->GetUserCon()); } break; } } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ void CHTMLView::NoteFinishedLayout(void) { FlushPendingDocResize(); /* Ugly hack: since `asynchronous' layout might have slightly overwritten the scrollbars, get just the scrollbars to redraw. */ if ( mScroller ) mScroller->RefreshSelf(); } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ void CHTMLView::NoteAllConnectionsComplete(void) { // StopRepeating(); // Look to see if my context, or any context enclosing my context, needs to be repaginated. CBrowserContext* contextToRepaginate = 0; if ( mContext ) for ( MWContext* ctx = *mContext; ctx; ctx = ctx->grid_parent ) { CBrowserContext* browserContext = ExtractBrowserContext(ctx); if ( browserContext && browserContext->IsRepagintaitonPending() ) contextToRepaginate = browserContext; } /* Try to repaginate the most enclosing context that needs it. If some busy child stops the repagination, no big deal... that childs |NoteAllConnectionsComplete| will try again. */ if ( contextToRepaginate ) contextToRepaginate->Repaginate(); else ClearDeferredImageQueue(); //Enable(); CPaneEnabler::UpdatePanes(); mLoadingURL = false; } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ void CHTMLView::NoteStartRepagination(void) { SPoint32 theScrollPosition; GetScrollPosition(theScrollPosition); mContext->RememberHistoryPosition(theScrollPosition.h, theScrollPosition.v); // FIX ME!!! may want to reset the size flush timer here } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ void CHTMLView::NoteEmptyRepagination(void) { // Adjust scroll bars AdjustScrollBars(); } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ void CHTMLView::NoteConfirmLoadNewURL(Boolean& ioCanLoad) { // if ( HasDownloads( *mContext ) ) // if (!ErrorManager::PlainConfirm((const char*) GetCString( ABORT_CURR_DOWNLOAD ), nil, nil, nil )) // return; ioCanLoad = true; } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ void CHTMLView::NoteStartLoadURL(void) { //Disable(); // FIX ME!!! we should disable the view. it will be enabled through all connection complete ClearTimerURL(); // jrm 97/08/22 SPoint32 theScrollPosition; GetScrollPosition(theScrollPosition); mContext->RememberHistoryPosition(theScrollPosition.h, theScrollPosition.v); mLoadingURL = true; mStopEnablerHackExecuted = false; } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ void CHTMLView::NoteGridContextPreDispose(Boolean inSavingHistory) { if (inSavingHistory) { SPoint32 theScrollPosition; GetScrollPosition(theScrollPosition); mContext->RememberHistoryPosition(theScrollPosition.h, theScrollPosition.v); } // our grid context is going to be orphaned by it's super context // which is our clue that we aren't supposed to be here anymore. // Deleting outself releases our shared interest in the context. // // FIX ME!!! This needs to change. The assumption here is that the // superview of the HTML view is a scroller and was created at the // same time as this. This will need to go away when the scroller // dependency is removed. delete mSuperView; } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ void CHTMLView::NoteGridContextDisposed(void) { if (mContext->CountGridChildren() == 0) SetScrollMode(mDefaultScrollMode, true); } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // replaces the old fCanLoad Member void CHTMLView::EnableSelf(void) { // for the click code mOldPoint.h = mOldPoint.v = -1; } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ void CHTMLView::DisableSelf(void) { mOldPoint.h = mOldPoint.v = -1; } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // #pragma mark --- DRAWING AND UPDATING --- // // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ void CHTMLView::ResetBackgroundColor() const { UGraphics::SetIfBkColor(mBackgroundColor); } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ ContextMenuPopupsEnabled // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // determine whether context-sensitive popup menus are enabled by querying // the parent browser window Boolean CHTMLView::ContextMenuPopupsEnabled (void) { CBrowserWindow *browserWindow = dynamic_cast(CViewUtils::GetTopMostSuperView (this)); // 8-13-97 context menus disabled when commands are disabled unless the control key is down. // this is mac specific and may go away when we have an xp way to disable context menus from javascript. return browserWindow ? browserWindow->AllowSubviewPopups() && !browserWindow->IsHTMLHelp() && (!browserWindow->CommandsAreDisabled() || CApplicationEventAttachment::CurrentEventHasModifiers(controlKey)) : true; } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ GetCurrentPort // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ CGrafPtr CHTMLView::GetCurrentPort(Point& outPortOrigin) { if ((mCurrentDrawable == NULL) || (mCurrentDrawable == mOnscreenDrawable)) { outPortOrigin = mPortOrigin; return (CGrafPtr) GetMacPort(); } else { outPortOrigin.h = outPortOrigin.v = 0; return mCurrentDrawable->GetDrawableOffscreen(); } } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ FocusDraw // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ Boolean CHTMLView::FocusDraw(LPane* /*inSubPane*/) { Boolean bFocused = true; GWorldPtr gworld = NULL; // I don't really want to write my own FocusDraw, but PowerPlant has this nasty // habit of setting the origin and clip on me... bFocused = (mRevealedRect.left < mRevealedRect.right); // Skip if already in focus if (this != sInFocusView) { // Always set PowerPlant's origin and clip for the onscreen port. if (LView::EstablishPort()) { // Set up local coordinate system ::SetOrigin(mPortOrigin.h, mPortOrigin.v); // Clip to revealed area of View Rect clippingRect = mRevealedRect; PortToLocalPoint( topLeft(clippingRect) ); PortToLocalPoint( botRight(clippingRect) ); // if we're focussed then we need to do some extra stuff if ( bFocused && IsFocusedFrame() ) { ::InsetRect( &clippingRect, FocusBox_Size, FocusBox_Size ); } ::ClipRect( &clippingRect ); } // Set our current Mac Port - could be either onscreen or offscreen if (EstablishPort()) { // If the current drawable is not us, don't screw with the origin and clip. // The drawable is set to nil during normal operation so that's assumed to // also be us. if ( ( mCurrentDrawable != NULL ) && ( mCurrentDrawable != mOnscreenDrawable ) ) { // offscreen Rect theFrame; CalcLocalFrameRect(theFrame); ::SetOrigin(theFrame.left, theFrame.top); } // Cache current Focus sInFocusView = this; // be sure to reset the background color if ( bFocused && ( mRevealedRect.left < mRevealedRect.right ) ) { ResetBackgroundColor(); } } else { SignalPStr_("\pFocus View with no GrafPort"); } } // if we have a current drawable, then we need to do magic with the clip if ( mCurrentDrawable != NULL ) { if ( mCurrentDrawable->HasClipChanged() ) { RgnHandle clip; // // Warning: If the drawable is our offscreen, then we need to make sure // to move the clip into the correct coordinate space. The problem here is that // the drawable has no way of knowing what its coordinate space is. To make // matters worse, Drawables are shared across multiple HTMLViews. // // We could simplify this by keeping one back buffer for the browser as a whole // and then instantiating a COffscreenDrawable per CHTMLView. That way the HTMLView // could notify the offscreen whenever it's origin changes. It could then offset // its clip correctly whenever a new one is set. clip = (RgnHandle) mCurrentDrawable->GetLayerClip(); if ( mCurrentDrawable == mOffscreenDrawable ) { Rect theFrame; CalcLocalFrameRect(theFrame); ::OffsetRgn ( clip, theFrame.left, theFrame.top ); ::SetClip ( clip ); ::OffsetRgn ( clip, -theFrame.left, -theFrame.top ); } else { ::SetClip ( clip ); } } } return bFocused; } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ EstablishPort // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ Boolean CHTMLView::EstablishPort() { Boolean portSet = false; GWorldPtr gworld = NULL; // if the current drawable, is an offscreen one, be sure to set it if ( mCurrentDrawable != NULL ) { gworld = mCurrentDrawable->GetDrawableOffscreen(); } if ( gworld != NULL ) { portSet = true; if ( UQDGlobals::GetCurrentPort() != (GrafPtr) mGWorld ) { SetGWorld ( gworld, NULL ); mOffscreenDrawable->mClipChanged = true; } } else { // make sure to restore the main device SetGDevice ( GetMainDevice() ); portSet = LView::EstablishPort(); } return portSet; } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ DrawSelf // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ void CHTMLView::DrawSelf(void) { if (Memory_MemoryIsLow() || !mContext) return; // A CHTMLView can have a nil mContext, but if it does, it doesn't draw. // update the image display context if we need to. it would be nice to reload the images // on the current page, but we cuurently cannot doing so without other side effects // such as losing form data... VerifyDisplayContextColorSpace ( *mContext ); // this is the new (layered) drawing. It flashes WAY to much. // FIX ME!!! clean up if (GetRepaginate()) { GetContext()->Repaginate(NET_CACHE_ONLY_RELOAD); SetRepaginate(false); } // For layers all drawing is done through the compositor // BUGBUG LAYERS The assumption here is that the cutout region // (including plugins) will be removed from the composited // area...this still needs to be done. // if ( sNoTextUpdateLock ) // return; // Get the update region StRegion theImageUpdateRgn(mUpdateRgnH); if (!mContext || !mContext->GetCurrentHistoryEntry()) { ClearBackground(); } else { /* Convert to frame coordinates */ SPoint32 theFrameLocation; GetFrameLocation(theFrameLocation); ::OffsetRgn(theImageUpdateRgn, -theFrameLocation.h, -theFrameLocation.v); if (mCompositor && CL_GetCompositorEnabled(*mCompositor)) CL_RefreshWindowRegion(*mCompositor, (FE_Region)static_cast(theImageUpdateRgn)); else DrawBackground((*static_cast(theImageUpdateRgn))->rgnBBox); // 07-06-11 pkc -- Update grid edges only if mContext isn't busy which means that // layout isn't running, i.e. calling FE_DisplayEdge directly /* 18.Jun.97 drm -- removed the check so we update grid edges even when layout is already doing that. While layout is creating a new page, the last redraw that goes through tends to happen while the context is busy. This check causes frame edges to not be redrawn, which leaves a bevel line from the enclosing CBevelView running across the end of the frame edge. */ // if (!XP_IsContextBusy(*mContext)) DrawGridEdges(theImageUpdateRgn); } if (IsFocusedFrame()) DrawFrameFocus(); ExecuteAttachments(CTargetFramer::msg_DrawSelfDone, this); /* this is the old drawing code mCalcDontDraw = false; Rect theFrame; CalcLocalFrameRect(theFrame); RgnHandle theLocalUpdateRgn = GetLocalUpdateRgn(); Rect theLocalUpdateFrame = (*theLocalUpdateRgn)->rgnBBox; ::SectRect(&theFrame, &theLocalUpdateFrame, &theLocalUpdateFrame); if (!mHasGridCells) DrawBackground(theLocalUpdateFrame); SPoint32 itl, ibr; Point tl, br; tl = topLeft( theLocalUpdateFrame ); br = botRight( theLocalUpdateFrame ); LocalToImagePoint( tl, itl ); LocalToImagePoint( br, ibr ); LO_RefreshArea(*mContext, itl.h, itl.v, ibr.h - itl.h, ibr.v - itl.v ); if (IsFocusedFrame()) DrawFrameFocus(); ::DisposeRgn(theLocalUpdateRgn); mCalcDontDraw = true; */ } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ DrawFrameFocus // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ void CHTMLView::DrawFrameFocus(void) { StRegion theFocusMask; CalcFrameFocusMask(theFocusMask); Point theLocalOffset = { 0, 0 }; PortToLocalPoint(theLocalOffset); ::OffsetRgn(theFocusMask, theLocalOffset.h, theLocalOffset.v); StClipRgnState theClipSaver(theFocusMask); StColorPenState savePen; ::PenPat(&UQDGlobals::GetQDGlobals()->black); ::PenMode(srcCopy); RGBColor theHiliteColor; LMGetHiliteRGB(&theHiliteColor); ::RGBForeColor(&theHiliteColor); ::PaintRgn(theFocusMask); } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ CalcFrameFocusMask // // This region is in port coordinates // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ void CHTMLView::CalcFrameFocusMask(RgnHandle outFocusMask) { ::SetEmptyRgn(outFocusMask); Rect theFrame; CalcPortFrameRect(theFrame); ::SectRect(&theFrame, &mRevealedRect, &theFrame); ::RectRgn(outFocusMask, &theFrame); StRegion theSubFocus(theFrame); ::InsetRgn(theSubFocus, FocusBox_Size, FocusBox_Size); ::DiffRgn(outFocusMask, theSubFocus, outFocusMask); } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ InvalFocusArea // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ void CHTMLView::InvalFocusArea(void) { if (mShowFocus) { StRegion theFocusMask; CalcFrameFocusMask(theFocusMask); InvalPortRgn(theFocusMask); } } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ AdjustScrollBars // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // FIX ME!!! this needs to be removed when the mScroller is removed void CHTMLView::AdjustScrollBars() { if ((mScroller == NULL) || (GetScrollMode() != LO_SCROLL_AUTO)) return; mScroller->AdjustScrollBars(); /* SDimension16 theFrameSize; GetFrameSize(theFrameSize); SDimension32 theImageSize; GetImageSize(theImageSize); // If we are only showing scrollers when needed, turn them on if we have overgrown mScroller->ShowScrollbars( theImageSize.width > theFrameSize.width, theImageSize.height > theFrameSize.height); */ } void CHTMLView::RegisterCallBackCalls() { PREF_RegisterCallback("intl", PrefUpdateCallback, (void *)this); // At some point we should decide if it makes more sense to register a single // "browser" call back. PREF_RegisterCallback( "browser.underline_anchors", PrefUpdateCallback, (void *)this); PREF_RegisterCallback( "browser.background_color", PrefUpdateCallback, (void *)this); PREF_RegisterCallback( "browser.use_document_fonts", PrefUpdateCallback, (void *)this); PREF_RegisterCallback( "browser.foreground_color", PrefUpdateCallback, (void *)this); PREF_RegisterCallback( "browser.anchor_color", PrefUpdateCallback, (void *)this); PREF_RegisterCallback( "browser.visited_color", PrefUpdateCallback, (void *)this); PREF_RegisterCallback( "browser.use_document_colors", PrefUpdateCallback, (void *)this); PREF_RegisterCallback( "general.always_load_images", PrefInvalidateCachedPreference, (void *)this); } void CHTMLView::UnregisterCallBackCalls() { PREF_UnregisterCallback("intl", PrefUpdateCallback, (void *)this); PREF_UnregisterCallback( "browser.underline_anchors", PrefUpdateCallback, (void *)this); PREF_UnregisterCallback( "browser.background_color", PrefUpdateCallback, (void *)this); PREF_UnregisterCallback( "browser.use_document_fonts", PrefUpdateCallback, (void *)this); PREF_UnregisterCallback( "browser.foreground_color", PrefUpdateCallback, (void *)this); PREF_UnregisterCallback( "browser.anchor_color", PrefUpdateCallback, (void *)this); PREF_UnregisterCallback( "browser.visited_color", PrefUpdateCallback, (void *)this); PREF_UnregisterCallback( "browser.use_document_colors", PrefUpdateCallback, (void *)this); PREF_UnregisterCallback( "general.always_load_images", PrefInvalidateCachedPreference, (void *)this); } int CHTMLView::PrefUpdateCallback(const char * /*inPrefString */, void *inCHTMLView) { CHTMLView *theView = (CHTMLView *)inCHTMLView; theView = dynamic_cast(theView); XP_ASSERT(theView); XP_ASSERT(!theView->GetSuperHTMLView()); if (theView && !theView->GetRepaginate() && // No need to do it again if we have been here before. theView->IsRootHTMLView()) { theView->SetRepaginate(true); Rect paneRect; theView->CalcPortFrameRect(paneRect); theView->InvalPortRect(&paneRect); } return 0; // You don't even want to know my opinion of this! } int CHTMLView::PrefInvalidateCachedPreference(const char *inPrefString, void * /*inCHTMLView */) { int returnValue = 0; if (!XP_STRCMP(inPrefString, "general.always_load_images")) { XP_Bool prefValue; returnValue = PREF_GetBoolPref(inPrefString, &prefValue); if (returnValue != PREF_OK && returnValue != PREF_NOERROR) sCachedAlwaysLoadImages = true; else sCachedAlwaysLoadImages = (Boolean)prefValue; } return returnValue; } // 97-06-11 pkc -- Code to handle redrawing grid edges void CHTMLView::DrawGridEdges(RgnHandle inRgnHandle) { // quick check -- if mGridEdgeList is empty, no grid edges to draw if(!mGridEdgeList.empty()) { // set mDontAddGridEdgeToList to true so that that DisplayEdge does not // to add this LO_EdgeStruct* to mGridEdgeList mDontAddGridEdgeToList = true; // Check each grid edge to see if it intersects the update region vector::iterator iter = mGridEdgeList.begin(); while (iter != mGridEdgeList.end()) { LO_EdgeStruct* edge = *iter; Rect edgeFrame; if (CalcElementPosition((LO_Element*)edge, edgeFrame)) { // grid edge is visible if(::RectInRgn(&edgeFrame, inRgnHandle)) { // grid edge is in update region, draw it DisplayEdge(NULL, edge); } } ++iter; } // set mDontAddGridEdgeToList to false mDontAddGridEdgeToList = false; } } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // #pragma mark --- LAYER DISPATCH --- // // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ void CHTMLView::SetLayerOrigin( Int32 inX, Int32 inY) { mLayerOrigin.h = inX; mLayerOrigin.v = inY; } void CHTMLView::GetLayerOrigin( Int32* outX, Int32* outY) { /* * certain things like images get the current layer origin from the current hyperview. * If they can learn how to get this from the current drawable (through the doc context * then this hack can go away */ if ( mCurrentDrawable != NULL && mCurrentDrawable != mOnscreenDrawable ) { mCurrentDrawable->GetLayerOrigin ( outX, outY ); } else { *outX = mLayerOrigin.h; *outY = mLayerOrigin.v; } } void CHTMLView::SetLayerClip( FE_Region inRegion) { // do we need to restore a magic region? if ( inRegion == NULL ) { mLayerClip = NULL; if (!::EmptyRgn(mSaveLayerClip)) { mClipChanged = true; ::CopyRgn ( mSaveLayerClip, mClipRgn ); ::SetEmptyRgn(mSaveLayerClip); } } else { Point portOrigin, scrollOffset; SPoint32 frameLocation; // do we need to save a magic region? if ( mLayerClip == NULL ) { ::GetClip(mSaveLayerClip); mLayerClip = FE_GetMDRegion(inRegion); } // now, copy this region to our own copy and move it to the correct coordinate // space CopyRgn ( FE_GetMDRegion(inRegion), mClipRgn ); // The region passed in is in frame coordinates. To use it, // we need to convert it to local coordinates. The scrollOffset // represents how much we need to offset the region for this // transformation. GetPortOrigin(portOrigin); GetFrameLocation(frameLocation); scrollOffset.h = portOrigin.h + frameLocation.h; scrollOffset.v = portOrigin.v + frameLocation.v; ::OffsetRgn(mClipRgn, scrollOffset.h, scrollOffset.v); mClipChanged = true; } // because we're lame and don't know how to test if the current // port is us, we save the port, and then focus ourselves. since // we marked the clip as having changed, it will always be set // How can I tell if I'm the current port? GDHandle saveGD; CGrafPtr savePort; GetGWorld ( &savePort, &saveGD ); FocusDraw(); SetGWorld ( savePort, saveGD ); } void CHTMLView::CopyPixels( CDrawable* inSrcDrawable, FE_Region inCopyRgn) { GWorldPtr srcGWorld; FocusDraw(); srcGWorld = inSrcDrawable->GetDrawableOffscreen(); if ( srcGWorld != NULL ) { Rect srcRect; Rect dstRect; GDHandle gdh; CGrafPtr port; GetGWorld ( &port, &gdh ); SetGWorld ( srcGWorld, NULL ); SetOrigin ( 0, 0 ); SetGWorld ( port, gdh ); StColorPenState save; StColorPenState::Normalize(); /* we use the bounding rectangle for the copy rgn as the src/dst rect */ /* for the copy. however, we need to make sure that the onscreen rect is */ /* in the correct coordinate space */ srcRect = (*(RgnHandle) inCopyRgn)->rgnBBox; dstRect = srcRect; Point portOrigin, scrollOffset; SPoint32 frameLocation; // The region passed in is in frame coordinates. To use it, // we need to convert it to local coordinates. The scrollOffset // represents how much we need to offset the region for this // transformation. GetPortOrigin(portOrigin); GetFrameLocation(frameLocation); scrollOffset.h = portOrigin.h + frameLocation.h; scrollOffset.v = portOrigin.v + frameLocation.v; ::OffsetRgn(FE_GetMDRegion(inCopyRgn), scrollOffset.h, scrollOffset.v ); ::OffsetRect ( &dstRect, scrollOffset.h, scrollOffset.v ); CopyBits ( &((GrafPtr) srcGWorld)->portBits, &qd.thePort->portBits, &srcRect, &dstRect, srcCopy, FE_GetMDRegion(inCopyRgn) ); ::OffsetRgn(FE_GetMDRegion(inCopyRgn), -scrollOffset.h, -scrollOffset.v); } } // Dispatcher for events arriving from layers. These events may have originated in // the front end and sent to layers, or they may have been synthesized. PRBool CHTMLView::HandleLayerEvent( CL_Layer* inLayer, CL_Event* inEvent) { CStLayerOriginSetter makeOriginInLayerOrigin(this, inLayer); fe_EventStruct *fe_event = (fe_EventStruct *)inEvent->fe_event; SPoint32 theLayerPoint; theLayerPoint.h = inEvent->x; theLayerPoint.v = inEvent->y; if (!fe_event) // Fill in FE event if the event was synthesized in the backend { EventRecord event; Point whereLocal, wherePort, whereGlobal; ImageToLocalPoint(theLayerPoint, whereLocal); wherePort = whereLocal; LocalToPortPoint(wherePort); whereGlobal = wherePort; PortToLocalPoint(whereGlobal); event.when = ::TickCount(); event.where = whereGlobal; event.modifiers = ((inEvent->modifiers & EVENT_SHIFT_MASK) ? shiftKey : 0) | ((inEvent->modifiers & EVENT_CONTROL_MASK) ? controlKey : 0) | ((inEvent->modifiers & EVENT_ALT_MASK) ? optionKey : 0) | ((inEvent->modifiers & EVENT_META_MASK) ? cmdKey : 0); switch (inEvent->type) { case CL_EVENT_MOUSE_BUTTON_DOWN: case CL_EVENT_MOUSE_BUTTON_MULTI_CLICK: SMouseDownEvent mouseDownEvent; LWindow *window = LWindow::FetchWindowObject(GetMacPort()); event.what = mouseDown; // event.message is undefined mouseDownEvent.wherePort = wherePort; mouseDownEvent.whereLocal = whereLocal; mouseDownEvent.macEvent = event; mouseDownEvent.delaySelect = (window != nil) ? (!UDesktop::WindowIsSelected(window) && window->HasAttribute(windAttr_DelaySelect)) : false; fe_event->event.mouseDownEvent = mouseDownEvent; break; case CL_EVENT_MOUSE_MOVE: event.what = nullEvent; event.message = mouseMovedMessage; fe_event->event.macEvent = event; break; case CL_EVENT_KEY_DOWN: event.what = keyDown; event.message = inEvent->which; fe_event->event.macEvent = event; break; default: return PR_TRUE; // ignore the event } } /* // Make sure this event came from the front-end. // i.e. ignore synthesized events return PR_TRUE; */ // Call the per-layer event handlers switch (inEvent->type) { case CL_EVENT_MOUSE_BUTTON_DOWN: case CL_EVENT_MOUSE_BUTTON_MULTI_CLICK: { //SMouseDownEvent* mouseDown = (SMouseDownEvent *)fe_event->event; //ClickSelfLayer(*mouseDown, inLayer, theLayerPoint); SMouseDownEvent mouseDown = fe_event->event.mouseDownEvent; ClickSelfLayer(mouseDown, inLayer, theLayerPoint); } break; case CL_EVENT_MOUSE_MOVE: { Point portPt = fe_event->portPoint; //EventRecord *macEvent = (EventRecord *)fe_event->event; //AdjustCursorSelfForLayer(portPt, *macEvent, inLayer, theLayerPoint); // modified for new fe_EventStruct typedef 1997-02-25 mjc EventRecord macEvent = fe_event->event.macEvent; AdjustCursorSelfForLayer(portPt, macEvent, inLayer, theLayerPoint); } break; case CL_EVENT_KEY_DOWN: { EventRecord macEvent = fe_event->event.macEvent; HandleKeyPressLayer(macEvent, inLayer, theLayerPoint); break; } case CL_EVENT_KEY_UP: case CL_EVENT_MOUSE_BUTTON_UP: case CL_EVENT_KEY_FOCUS_GAINED: case CL_EVENT_KEY_FOCUS_LOST: // Nothing to do, but grab the event break; default: // Pass the event through return PR_FALSE; } return PR_TRUE; } PRBool CHTMLView::HandleEmbedEvent( LO_EmbedStruct* inEmbed, CL_Event* inEvent) { NPEmbeddedApp* app = (NPEmbeddedApp*) inEmbed->FE_Data; if (app && app->fe_data) { CPluginView* view = (CPluginView*) app->fe_data; return (PRBool)view->HandleEmbedEvent(inEvent); } return PR_FALSE; } void CHTMLView::ScrollImageBy( Int32 inLeftDelta, Int32 inTopDelta, Boolean inRefresh) { if ( ( inLeftDelta == 0 ) && ( inTopDelta == 0 ) ) return; // Get the image coordinates of the frame origin Rect theFrame; CalcLocalFrameRect(theFrame); SPoint32 imageTopLeft; LocalToImagePoint(topLeft(theFrame), imageTopLeft); imageTopLeft.h += inLeftDelta; imageTopLeft.v += inTopDelta; if (mCompositor != NULL) CL_ScrollCompositorWindow(*mCompositor, imageTopLeft.h, imageTopLeft.v); // FIX ME!!! this seems like it might be a bug. The image can be pinned and // not scroll as much as the request. It seems like the commpositor would be out of sync. // Let PowerPlant do the rest Boolean mayAutoScrollLeavingTurds = inRefresh && IsTarget(); //&& mDropRow; // Turds will be left if we call scrollbits in ScrollImageBy if (mayAutoScrollLeavingTurds) { // Notify the CTargetFramer (if any) to erase the frame hilite ExecuteAttachments(CTargetFramer::msg_ResigningTarget, this); } LView::ScrollImageBy(inLeftDelta, inTopDelta, inRefresh); if (mayAutoScrollLeavingTurds && FocusDraw()) { // Turn hiliting back on // Notify the CTargetFramer to draw the border now. ExecuteAttachments(CTargetFramer::msg_BecomingTarget, this); // invert } // normally, the compositor will add forms control subpanes later, during // LPeriodical time. if the subpanes are being displayed now for the first time, // they've never been added to this view, so we need to force the compositor to // add them now, while the update region is still fresh. if (mCompositor) CL_CompositeNow (*mCompositor); } // until flag is turned on... extern "C" { void LO_RelayoutOnResize(MWContext *context, int32 width, int32 height, int32 leftMargin, int32 topMargin); } // This method gets called when window changes size. // Make sure we call mContext->Repaginate() void CHTMLView::AdaptToSuperFrameSize( Int32 inSurrWidthDelta, Int32 inSurrHeightDelta, Boolean inRefresh) { UCursor::SetWatch(); LView::AdaptToSuperFrameSize(inSurrWidthDelta, inSurrHeightDelta, inRefresh); if (IsRootHTMLView()) { if ((mContext != NULL) && ((inSurrWidthDelta != 0) || (inSurrHeightDelta != 0)) && (!mContext->IsViewSourceContext())) { SDimension16 theFrameSize; Rect theFrame; int32 leftMargin; int32 topMargin; GetFrameSize(theFrameSize); leftMargin = 8; topMargin = 8; CalcLocalFrameRect(theFrame); if ( theFrame.right - theFrame.left > 0 ) { if (leftMargin > (theFrame.right / 2 )) leftMargin = MAX( theFrame.right / 2 - 50, 0); } if ( theFrame.bottom - theFrame.top > 0 ) { if ( topMargin > (theFrame.bottom / 2 ) ) topMargin = MAX(theFrame.bottom / 2 -50, 0); } // set the image size to the current frame size SDimension16 curFrameSize; GetFrameSize(curFrameSize); ResizeImageTo ( curFrameSize.width, curFrameSize.height, false ); // If the vertical scrollbar might be shown, // tell layout that we already have it, so that it does // the correct wrapping of text. // If we do not do this, when vertical scrollbar only is // shown, some text might be hidden if (GetScrollMode() == LO_SCROLL_AUTO) theFrameSize.width -= 15; LO_RelayoutOnResize ( *mContext, theFrameSize.width, theFrameSize.height, leftMargin, topMargin ); AdjustScrollBars(); } } UCursor::SetArrow(); } void CHTMLView::ResizeFrameBy( Int16 inWidthDelta, Int16 inHeightDelta, Boolean inRefresh) { // are we on drugs? if ( ( inWidthDelta == 0 ) && ( inHeightDelta == 0 ) ) return; SDimension16 theFrameSize; GetFrameSize(theFrameSize); theFrameSize.width += inWidthDelta; theFrameSize.height += inHeightDelta; // Let PowerPlant do the rest LView::ResizeFrameBy(inWidthDelta, inHeightDelta, inRefresh); // We need to adjust the compositor before the inherited call in case // in refresh is true (immediate draw). if (mCompositor != NULL) CL_ResizeCompositorWindow(*mCompositor, theFrameSize.width, theFrameSize.height); // We now call Repaginate in AdaptToSuperFrameSize } void CHTMLView::SetCurrentDrawable( CDrawable* inDrawable) { if ( inDrawable != NULL ) { mCurrentDrawable = inDrawable; /* make sure this new drawable calls us */ mCurrentDrawable->SetParent ( this ); } else { mCurrentDrawable = NULL; } /* Our focus has most likely changed */ OutOfFocus ( nil ); FocusDraw(); } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // #pragma mark --- COMMANDER OVERRIDES --- // // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ void MochaFocusCallback( MWContext * /* pContext */, LO_Element * /* lo_element */, int32 /* lType */, void * whatever, ETEventStatus status ) { if (status == EVENT_OK && whatever) { CHTMLView* htmlView = reinterpret_cast(whatever); htmlView->ClearInFocusCallAlready(); } } void CHTMLView::PutOnDuty(LCommander*) { if (IsFocusedFrame() && FocusDraw()) DrawFrameFocus(); // javascript onFocus callback - 1997-02-27 mjc if (mContext != NULL && !mInFocusCallAlready) { JSEvent* event = XP_NEW_ZAP(JSEvent); if (event) { event->type = EVENT_FOCUS; event->layer_id = LO_DOCUMENT_LAYER_ID; mInFocusCallAlready = true; ET_SendEvent( *mContext, NULL, event, MochaFocusCallback, this ); } } } void CHTMLView::TakeOffDuty(void) { if (FocusDraw()) InvalFocusArea(); // javascript onBlur callback - 1997-02-27 mjc if (mContext != NULL && !mInFocusCallAlready) { JSEvent* event = XP_NEW_ZAP(JSEvent); if (event) { event->type = EVENT_BLUR; event->layer_id = LO_DOCUMENT_LAYER_ID; mInFocusCallAlready = true; ET_SendEvent( *mContext, NULL, event, MochaFocusCallback, this ); } } } void CHTMLView::FindCommandStatus(CommandT inCommand, Boolean &outEnabled, Boolean &outUsesMark, Char16 &outMark, Str255 outName) { outUsesMark = false; if (!mContext) // yes, this can happen. It happened to me! { LTabGroup::FindCommandStatus(inCommand, outEnabled, outUsesMark, outMark, outName); return; } CBrowserWindow *browserWindow = dynamic_cast(CViewUtils::GetTopMostSuperView(this)); Boolean isRootDocInfo = browserWindow ? browserWindow->IsRootDocInfo() : false; Boolean isHTMLHelp = browserWindow ? browserWindow->IsHTMLHelp() : false; Boolean isViewSource = browserWindow ? browserWindow->IsViewSource() : false; // Disable commands which don't apply to restricted targets, at the request of javascript. // No special distinction needed for floaters here. if (browserWindow && browserWindow->CommandsAreDisabled() && ( inCommand == cmd_AddToBookmarks || inCommand == cmd_ViewSource || inCommand == cmd_DocumentInfo || inCommand == cmd_Find || inCommand == cmd_FindAgain || inCommand == cmd_MailDocument || inCommand == cmd_LoadImages || inCommand == cmd_Reload || inCommand == cmd_SaveAs)) { outEnabled = false; return; } switch (inCommand) { case cmd_LoadImages: if (mContext && !isViewSource) { outEnabled = !sCachedAlwaysLoadImages; } break; case cmd_Reload: { if (GetContext()) { CBrowserContext* theTopContext = GetContext()->GetTopContext(); if ((theTopContext != nil) && (theTopContext->GetCurrentHistoryEntry() != nil) && !XP_IsContextBusy(*theTopContext)) { outEnabled = true; if (CApplicationEventAttachment::CurrentEventHasModifiers(optionKey) || CApplicationEventAttachment::CurrentEventHasModifiers(shiftKey)) { LString::CopyPStr(::GetPString(MENU_SUPER_RELOAD), outName); } else { LString::CopyPStr(::GetPString(MENU_RELOAD), outName); } } } } break; case cmd_SecurityInfo: { outEnabled = !UDesktop::FrontWindowIsModal(); break; } case cmd_ViewSource: case cmd_DocumentInfo: { outEnabled = !isHTMLHelp; break; } case cmd_AddToBookmarks: outUsesMark = false; outEnabled = mContext && mContext->GetCurrentHistoryEntry() && !(isRootDocInfo || isHTMLHelp); break; case cmd_SaveAs: { if ((mContext->GetCurrentHistoryEntry() != nil) && !XP_IsContextBusy(*mContext)) { outEnabled = !isHTMLHelp; } break; } case cmd_Copy: { outEnabled = LO_HaveSelection(*mContext); break; } case cmd_SelectAll: { outEnabled = (mContext->GetCurrentHistoryEntry() != NULL); break; } case cmd_Find: { outEnabled = (mContext->GetCurrentHistoryEntry() != NULL); break; } case cmd_FindAgain: { outEnabled = ((mContext->GetCurrentHistoryEntry() != NULL) && CFindWindow::CanFindAgain()); break; } case cmd_PageSetup: if (CanPrint()) outEnabled = TRUE; break; case cmd_Print: case cmd_PrintOne: { if (CanPrint()) outEnabled = TRUE; if (mContext && (MWContext (*mContext)).is_grid_cell) LString::CopyPStr( GetPString( MENU_PRINT_FRAME ), outName); else LString::CopyPStr( GetPString( MENU_PRINT ), outName); break; } case cmd_MailDocument: // Send Page/Frame if (mContext->IsGridCell()) { // frame view, set menu command to "Send Frame..." LStr255 sendFrameStr(cPaulsMiscStrListID, cSendFrameIndex); LString::CopyPStr(sendFrameStr, outName); outEnabled = !isHTMLHelp; } else if (!mContext->HasGridChildren() && !mContext->HasGridParent()) { // non-frame view LStr255 sendPageStr(cPaulsMiscStrListID, cSendPageIndex); LString::CopyPStr(sendPageStr, outName); outEnabled = !isHTMLHelp; } else { // frame container view LStr255 sendFrameStr(cPaulsMiscStrListID, cSendFrameIndex); LString::CopyPStr(sendFrameStr, outName); outEnabled = false; } break; default: if(inCommand >= ENCODING_BASE && inCommand < ENCODING_CEILING) { outEnabled = true; outUsesMark = true; int16 csid = CPrefs::CmdNumToDocCsid( inCommand ); outMark = (csid == mContext->GetDefaultCSID()) ? checkMark : ' '; } else LTabGroup::FindCommandStatus(inCommand, outEnabled, outUsesMark, outMark, outName); } } // CHTMLView::FindCommandStatus void CHTMLView::GetDefaultFileNameForSaveAs(URL_Struct* url, CStr31& defaultName) { // Overridden by CMessageView to use the message subject instead. fe_FileNameFromContext(*mContext, url->address, defaultName); } Boolean CHTMLView::ObeyCommand(CommandT inCommand, void* ioParam) { Boolean cmdHandled = false; // CURLDispatcher* theDispatcher = CURLDispatcher::GetURLDispatcher(); CHTMLClickRecord* cr = mCurrentClickRecord; // for brevity. // cr will be non-null when handling a context menu command. mCurrentClickRecord = nil; // set it back. LClipboard* clip = LClipboard::GetClipboard(); switch (inCommand) { case cmd_NEW_WINDOW_WITH_FRAME: History_entry* history = mContext->GetCurrentHistoryEntry(); if (!history) break; URL_Struct* url = SHIST_CreateURLStructFromHistoryEntry(*mContext, history); if (url) { url->history_num = 0; XP_MEMSET(&url->savedData, 0, sizeof(SHIST_SavedData)); } DispatchURL(url, mContext, false, true); cmdHandled = true; break; case cmd_OPEN_LINK: if (cr) { if (cr->mClickKind == eImageIcon) { // Make sure that we follow the link, and not load the image cr->mClickKind = eImageAnchor; } ClickSelfLink(*(SMouseDownEvent*)ioParam, *cr, FALSE); } cmdHandled = true; break; case cmd_NEW_WINDOW: if (cr) { ClickSelfLink(*(SMouseDownEvent*)ioParam, *cr, TRUE);// case C cmdHandled = true; } break; case cmd_COPY_LINK_LOC: if (cr) { try //Κcase D { if (cr->IsAnchor() && (cr->mClickURL.length() > 0)) clip->SetData('TEXT', cr->mClickURL.data(), cr->mClickURL.length(), TRUE); else // case E { cstring urlString = mContext->GetCurrentURL(); clip->SetData('TEXT', urlString.data(), urlString.length(), TRUE); } } catch(...) {} cmdHandled = true; } break; case cmd_VIEW_IMAGE: if (cr) { cstring urlString = GetURLFromImageElement(mContext, (LO_ImageStruct*) cr->mElement); if (urlString != "") { URL_Struct* url = NET_CreateURLStruct(urlString, NET_DONT_RELOAD); DispatchURL(url, mContext); } cmdHandled = true; } break; case cmd_SAVE_IMAGE_AS: if (cr) { StandardFileReply reply; cstring urlString = GetURLFromImageElement(mContext, (LO_ImageStruct*) cr->mElement); if (urlString == "") break; CStr31 fileName = CFileMgr::FileNameFromURL( urlString ); Boolean isMailAttachment = false; #ifdef MOZ_MAIL_NEWS isMailAttachment = XP_STRSTR( urlString, "?part=") || XP_STRSTR(urlString, "&part="); if( isMailAttachment ) { fe_FileNameFromContext(*mContext, urlString, fileName); } #endif // MOZ_MAIL_NEWS StandardPutFile(GetPString(MCLICK_SAVE_IMG_AS), fileName, &reply); if (reply.sfGood) { URL_Struct* url = NET_CreateURLStruct(urlString, NET_DONT_RELOAD); XP_MEMSET(&url->savedData, 0, sizeof(SHIST_SavedData)); CURLDispatcher::DispatchToStorage(url, reply.sfFile); } cmdHandled = true; } break; case cmd_COPY_IMAGE: if (cr) { PicHandle pict = ConvertImageElementToPICT((LO_ImageStruct*) cr->mElement); if (pict != NULL) { try { clip->SetData('PICT', (Handle) pict, TRUE); } catch(...) { } KillPicture(pict); } cmdHandled = true; } break; case cmd_COPY_IMAGE_LOC: if (cr) { cstring urlString = GetURLFromImageElement(mContext, (LO_ImageStruct*) cr->mElement); if (urlString != "") { try { clip->SetData('TEXT', urlString, strlen(urlString), TRUE ); } catch(...) {} } cmdHandled = true; } break; case cmd_LOAD_IMAGE: if (cr) { PostDeferredImage(cr->mImageURL); cmdHandled = true; } break; case cmd_LoadImages: { // Load images for the top-most browser context cmdHandled = true; if (GetContext()) { CBrowserContext* theTopContext = GetContext()->GetTopContext(); if (theTopContext) { LO_SetForceLoadImage(NULL, TRUE); theTopContext->Repaginate(); } } } break; case cmd_ViewSource: { URL_Struct* url = NET_CreateURLStruct(mContext->GetCurrentURL(), NET_DONT_RELOAD); mContext->ImmediateLoadURL(url, FO_VIEW_SOURCE); NET_FreeURLStruct ( url ); cmdHandled = true; break; } case cmd_AddToBookmarks: { // two cases: is this the "Add URL to bookmarks" from context menu or // using "Add Bookmarks" from the bookmark menu. if ( cr && cr->IsAnchor() ) { // strip off the protocol then truncate the middle char trunkedAddress[HIST_MAX_URL_LEN + 1]; string url = cr->GetClickURL(); const char* strippedAddr = SHIST_StripProtocol( const_cast(url.c_str()) ); INTL_MidTruncateString( 0, strippedAddr, trunkedAddress, HIST_MAX_URL_LEN ); CBookmarksAttachment::AddToBookmarks( cr->GetClickURL(), trunkedAddress); } else { History_entry *entry = mContext->GetCurrentHistoryEntry(); if ( entry ) CBookmarksAttachment::AddToBookmarks(entry->address, entry->title); } break; } case cmd_SAVE_LINK_AS: case cmd_SaveAs: { URL_Struct* url = nil; if (cr && cr->IsAnchor() && inCommand == cmd_SAVE_LINK_AS ) url = NET_CreateURLStruct(cr->mClickURL, NET_DONT_RELOAD); else url = NET_CreateURLStruct(mContext->GetCurrentURL(), NET_DONT_RELOAD); CStr31 fileName; Boolean isMailAttachment = false; #ifdef MOZ_MAIL_NEWS isMailAttachment = XP_STRSTR( url->address, "?part=") || XP_STRSTR(url->address, "&part="); if( isMailAttachment ) { CHTMLView::GetDefaultFileNameForSaveAs(url, fileName); } else #endif // MOZ_MAIL_NEWS { if (inCommand == cmd_SAVE_LINK_AS) { fileName = CFileMgr::FileNameFromURL( url->address ); } else { GetDefaultFileNameForSaveAs(url, fileName); } } StandardFileReply reply; short format; if (cr && cr->IsAnchor() && (!strncasecomp(url->address, "ftp://", 6) || isMailAttachment ) ) (void) UStdDialogs::AskSaveAsSource(reply, fileName, format); else (void) UStdDialogs::AskSaveAsTextOrSource(reply, fileName, format); if (reply.sfGood) { short saveType = (format == 2) ? FO_SAVE_AS : FO_SAVE_AS_TEXT; CURLDispatcher::DispatchToStorage(url, reply.sfFile, saveType, isMailAttachment ); } cmdHandled = true; break; } case cmd_Copy: { char* realText; XP_Block copyText = LO_GetSelectionText(*mContext); OSErr err = ::ZeroScrap(); XP_LOCK_BLOCK(realText, char*, copyText); err = ::PutScrap(strlen(realText), 'TEXT', (Ptr)realText); ::TEFromScrap(); XP_UNLOCK_BLOCK(copyText); XP_FREE_BLOCK(copyText); break; } case cmd_SelectAll: { (void) LO_SelectAll(*mContext); break; } case cmd_Find: { CFindWindow::DoFind(this); break; } case cmd_FindAgain: { DoFind(); break; } case cmd_Print: case cmd_PrintOne: { DoPrintCommand(inCommand); cmdHandled = true; break; } case cmd_SecurityInfo: { MWContext* mwcontext = *GetContext(); if (mwcontext) { URL_Struct* url = SHIST_CreateURLStructFromHistoryEntry( mwcontext, GetContext()->GetCurrentHistoryEntry() ); // It's OK if we call SECNAV_SecurityAdvisor with a NULL URL // which is the case when the user has a blank page as their startup // BUG #66435 //if (url) SECNAV_SecurityAdvisor(mwcontext,url); } break; } case cmd_DocumentInfo: URL_Struct* aboutURL = NET_CreateURLStruct( "about:document", NET_DONT_RELOAD ); if ( aboutURL ) { // about:document is displayed in the doc info window, so we don't need to call CURLDispatcher. // Just call SwitchLoadURL on mContext mContext->SwitchLoadURL(aboutURL, FO_CACHE_AND_PRESENT); } break; case cmd_FTPUpload: case msg_TabSelect: cmdHandled = true; break; case cmd_MailDocument: // Send Page/Frame MSG_MailDocument(*mContext); break; default: cmdHandled = LTabGroup::ObeyCommand(inCommand, ioParam); break; } if (cr && cr->IsAnchor()) LO_HighlightAnchor(*mContext, cr->mElement, FALSE); return cmdHandled; } // CHTMLView::ObeyCommand // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ Boolean CHTMLView::SetDefaultCSID(Int16 default_csid) // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ { if (mContext && default_csid != mContext->GetDefaultCSID()) { mContext->SetDefaultCSID(default_csid); mContext->SetWinCSID(INTL_DocToWinCharSetID(default_csid)); mContext->Repaginate(); } return true; } // CHTMLView::SetDefaultCSID // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ Boolean CHTMLView::CanPrint() const // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ { // ₯ in order to be able to print we must // not already be printing, // not be busy loading, // not be busy repaginating, // have a page loaded, // not be low on memory, // and have a print record to print with return mContext && !XP_IsContextBusy(*mContext) && !mContext->IsRepaginating() && (mContext->GetCurrentHistoryEntry() != nil) && !Memory_MemoryIsLow(); // && CPrefs::GetPrintRecord(); /* We no longer checking for a print record; now we allow the user to make the menu selection and then provide feedback about its failure) */ } // CHTMLView::CanPrint() const // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ URL_Struct *CHTMLView::GetURLForPrinting(Boolean& outSuppressURLCaption, MWContext * /* context */) // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ { MWContext *context = *GetContext(); History_entry* current = SHIST_GetCurrent(&context->hist); ThrowIfNil_(current); URL_Struct* url = SHIST_CreateWysiwygURLStruct(context, current); ThrowIfNil_(url); outSuppressURLCaption = false; return url; } // CHTMLView::GetURLForPrinting() // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ void CHTMLView::DoPrintCommand(CommandT inCommand) // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ { THPrint hp; hp = CPrefs::GetPrintRecord(); if ( !hp ) { FE_Alert( *GetContext(), GetPString ( NO_PRINTER_RESID ) ); return; } UPrintingMgr::ValidatePrintRecord( hp ); Boolean printOne = ( inCommand == cmd_PrintOne ); // // If this page is a single fullscreen plugin, give the // plugin a chance to handle the entire print process. If // it returns false, it doesnΥt want to take over printing, // so we should print as normal. // Boolean doPrint = true; NPEmbeddedApp* app = ((MWContext*)*mContext)->pluginList; if (app != NULL && app->next == NULL && app->pagePluginType == NP_FullPage) { CPluginView* plugin = (CPluginView*) app->fe_data; if ( plugin ) doPrint = ( plugin->PrintFullScreen( printOne, hp ) != TRUE ); } // // There wasnΥt a fullscreen plugin, or there was a plugin // but it wants us to take care of printing. In this case // we should show the normal dialog if necessary and print. // if ( doPrint ) { if ( printOne ) { (**hp).prJob.iFstPage = 1; (**hp).prJob.iLstPage = max_Pages; (**hp).prJob.iCopies = 1; UHTMLPrinting::BeginPrint( hp, this ); } else { if ( UPrintingMgr::AskPrintJob( hp ) ) UHTMLPrinting::BeginPrint( hp, this ); } } } // CHTMLView::DoPrintCommand // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // #pragma mark --- FIND SUPPORT --- // // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ void CHTMLView::CreateFindWindow() { LWindow::CreateWindow(6000, LCommander::GetTopCommander()); } // history code, I am not sure what does it do static void SelectionToImage(LO_Element* startElement, int32 /*startPos*/, LO_Element* /*endElement*/, int32 /*endPos*/, SPoint32* topLeft, SPoint32* botRight) { /* Calculate an image rectangle which is good enough to display some portion of a selection. Since selections can wrap around and do other wierd stuff, we'll make it big enough to cover the first "element" of the selection. */ topLeft->h = startElement->lo_any.x; topLeft->v = startElement->lo_any.y; botRight->h = startElement->lo_any.x + 64 /*endPos*/; botRight->v = startElement->lo_any.y + 20; } // Returns whether the search string was found - 1997-02-27 mjc Boolean CHTMLView::DoFind() { int32 start_position; int32 end_position; LO_Element* start_ele_loc = NULL; LO_Element* end_ele_loc = NULL; CL_Layer* layer; MWContext* gridContext; MWContext* currentContext = *mContext; Boolean found = false; char* lookFor = CFindWindow::sLastSearch; Boolean caseless = CFindWindow::sCaseless; Boolean backward = CFindWindow::sBackward; Boolean doWrap = CFindWindow::sWrap; /* I didn't like doing that, that being "grabbing statics from a class" but it's a lot cleaner than before, and it works. Mail gets this for free, and only need a few overrides to provide their own search dialog deeje 1997-01-22 */ // work within the current selection LO_GetSelectionEndpoints(currentContext, &start_ele_loc, &end_ele_loc, &start_position, &end_position, &layer); do { gridContext = currentContext; found = LO_FindGridText(currentContext, &gridContext, lookFor, &start_ele_loc, &start_position, &end_ele_loc, &end_position, !caseless, !backward); if (found) break; if (doWrap) { /* try again from the beginning. these are the values LO_GetSelectionEndpoints returns if there was no selection */ start_ele_loc = NULL; end_ele_loc = NULL; start_position = 0; end_position = 0; doWrap = false; } else { SysBeep(1); return false; } } while (true); /* 6.6.97: set target even if we didn't switch cells. do this in case the CHTMLView isn't the target at all. this is entirely possible after the first Find on a new window. */ // if (currentContext != gridContext) // Text was found in a different cell // { SwitchTarget(gridContext->fe.newView); // } SPoint32 selTopLeft, selBotRight; int32 tlx, tly; // Scroll before selecting because otherwise hilighting gets screwed up SelectionToImage(start_ele_loc, start_position, end_ele_loc, end_position, &selTopLeft, &selBotRight); RevealInImage(gridContext->fe.newView, selTopLeft, selBotRight); LO_SelectText(gridContext, start_ele_loc, start_position, end_ele_loc, end_position, &tlx, &tly); return true; } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // #pragma mark --- MOUSING AND KEYING --- // // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ Converts image point to offset from the origin of the available screen rect. // That is, the screen origin + menubar height. // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ void CHTMLView::ImageToAvailScreenPoint(const SPoint32 &inImagePoint, Point &outPoint) const { ImageToLocalPoint(inImagePoint, outPoint); LocalToPortPoint(outPoint); PortToGlobalPoint(outPoint); outPoint.v -= ::GetMBarHeight(); } void CHTMLView::ClickSelf(const SMouseDownEvent& inMouseDown) { // With LAYERS, the original method gets the compositor to dispatch // the event, which is then dealt with (in this method) on a per-layer // basis. if ((mContext != NULL) && FocusDraw()) { Int16 clickCount = GetClickCount(); SPoint32 theImageClick; LocalToImagePoint(inMouseDown.whereLocal, theImageClick); if (mCompositor != NULL) { fe_EventStruct fe_event; fe_event.portPoint = inMouseDown.wherePort; //fe_event.event = (void *)&inMouseDown; fe_event.event.mouseDownEvent = inMouseDown; // 1997-02-25 mjc CL_Event event; if (clickCount > 2) return; // ignore triple (or more) clicks event.type = CL_EVENT_MOUSE_BUTTON_DOWN; event.fe_event = (void *)&fe_event; event.fe_event_size = sizeof(fe_EventStruct); // 1997-02-25 mjc event.x = theImageClick.h; event.y = theImageClick.v; event.which = 1; event.data = clickCount; event.modifiers = CMochaHacks::MochaModifiers(inMouseDown.macEvent.modifiers); // 1997-02-27 mjc // set a wait flag that gives ClickSelfLink and EventMouseUp a chance to execute, // and prevents the possibility of two mouse ups occurring for one mouse down. // ALERT: // This approach may have to be revised if we need to handle double clicks in JS. // This is because there seem to be some cases in which a double click might cause // EventMouseUp to be called when ClickSelfLink should be called instead. While this // has no adverse affect on the browser, a script may not expect that the mouse up // is not followed by a click. mWaitMouseUp = true; CL_DispatchEvent(*mCompositor, &event); } else { mWaitMouseUp = true; ClickSelfLayer(inMouseDown, NULL, theImageClick); } } } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ Callback for click handling for new mocha event stuff // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // DoExecuteClickInLinkRecord // Used as a Mocha callback structure // holds all the information needed to call ReallyDoExecuteClickInLink struct DoExecuteClickInLinkRecord { SMouseDownEvent mWhere; CHTMLClickRecord mCr; Boolean mMakeNewWindow; Boolean mSaveToDisk; LO_AnchorData* mMouseOverMapArea; // for click event handling in image maps CHTMLView * mView; int32 mEventType; DoExecuteClickInLinkRecord( CHTMLView * view, const SMouseDownEvent& where, CHTMLClickRecord cr, Boolean makeNewWindow, Boolean saveToDisk, LO_AnchorData* mouseOverMapArea, int32 eventType) : mCr(cr) // do we really want to use default copy contructor? { mView = view; mWhere = where; mMakeNewWindow = makeNewWindow; mSaveToDisk = saveToDisk; mMouseOverMapArea = mouseOverMapArea; mEventType = eventType; } void ExecuteClickInLink() { Assert_(mView != NULL); mView->PostProcessClickSelfLink(mWhere, mCr, mMakeNewWindow, mSaveToDisk, false); } }; // Mocha callback for DoExecuteClickInLink // Click preceded by mouse up - 1997-03-08 mjc void MochaDoExecuteClickInLinkCallback(MWContext * pContext, LO_Element * lo_element, int32 lType, void * whatever, ETEventStatus status); void MochaDoExecuteClickInLinkCallback(MWContext * pContext, LO_Element * lo_element, int32 /* lType */, void * whatever, ETEventStatus status) { DoExecuteClickInLinkRecord * p = (DoExecuteClickInLinkRecord*)whatever; if (status == EVENT_OK) { if (p->mEventType == EVENT_MOUSEUP) { try { DoExecuteClickInLinkRecord* clickRecord = new DoExecuteClickInLinkRecord(p->mView, p->mWhere, p->mCr, p->mMakeNewWindow, p->mSaveToDisk, p->mMouseOverMapArea, EVENT_CLICK); JSEvent* event = XP_NEW_ZAP(JSEvent); if (event) { if (p->mMouseOverMapArea != NULL) { lo_element = XP_NEW_ZAP(LO_Element); // Need to fake the element, ask chouck for details lo_element->type = LO_TEXT; lo_element->lo_text.anchor_href = p->mMouseOverMapArea; if (lo_element->lo_text.anchor_href->anchor) lo_element->lo_text.text = lo_element->lo_text.anchor_href->anchor; // to pass js freed element check } CL_Layer* layer = p->mCr.GetLayer(); event->type = EVENT_CLICK; event->which = 1; event->x = p->mCr.GetImageWhere().h; event->y = p->mCr.GetImageWhere().v; event->docx = event->x + CL_GetLayerXOrigin(layer); event->docy = event->y + CL_GetLayerYOrigin(layer); Point screenPt = { event->docy, event->docx }; SPoint32 imagePt; p->mView->LocalToImagePoint(screenPt, imagePt); p->mView->ImageToAvailScreenPoint(imagePt, screenPt); event->screenx = screenPt.h; event->screeny = screenPt.v; event->layer_id = LO_GetIdFromLayer(pContext, layer); event->modifiers = CMochaHacks::MochaModifiers(p->mWhere.macEvent.modifiers); ET_SendEvent(pContext, lo_element, event, MochaDoExecuteClickInLinkCallback, clickRecord); } } catch (...) { } } else if (p->mEventType == EVENT_CLICK && p->mCr.IsClickOnAnchor()) p->ExecuteClickInLink(); } // Free faked element after click if (p->mEventType == EVENT_CLICK && p->mMouseOverMapArea != NULL) XP_FREE(lo_element); delete p; } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // Mouse tracking. // On click if it is an anchor, track it. If the mouse does not move, load the anchor. // If it is not an anchor, continue the selection. void CHTMLView::ClickSelfLayer( const SMouseDownEvent& inMouseDown, CL_Layer* inLayer, SPoint32 inLayerWhere) { SPoint32 theElementWhere = inLayerWhere; LO_Element* theElement = LO_XYToElement(*mContext, theElementWhere.h, theElementWhere.v, inLayer); CHTMLClickRecord cr(inMouseDown.whereLocal, inLayerWhere, mContext, theElement, inLayer); cr.Recalc(); Boolean bClickHandled = false; // ₯ with shift key, just track selection if ((inMouseDown.macEvent.modifiers & shiftKey) == 0) { if ((theElement != NULL) && cr.PixelReallyInElement(theElementWhere, theElement)) { // Move check for edge click here; otherwise, if you hold down mouse button over // edge, then context menu pops up. Whoops. if (cr.IsClickOnEdge()) ClickTrackEdge(inMouseDown, cr); else if (cr.IsClickOnAnchor()) { Int32 theClickStart = inMouseDown.macEvent.when; Point thePrevPoint = inMouseDown.whereLocal; LO_HighlightAnchor(*mContext, theElement, true); mCurrentClickRecord = &cr; CHTMLClickRecord::EClickState theMouseAction = CHTMLClickRecord::eUndefined; // Use a try block to ensure that we set it back to nil try { theMouseAction = cr.WaitForMouseAction(inMouseDown, this, GetDblTime(), ContextMenuPopupsEnabled()); } catch(...) {} mCurrentClickRecord = nil; // Whether we need to unhighlight after handling the click. // In the mouse up early case, unhighlighting must be done before the // content changes, not afterwards, otherwise we would crash because the // element is no longer there. Boolean doUnhighlight = true; switch (theMouseAction) { case CHTMLClickRecord::eMouseDragging: ClickDragLink(inMouseDown, theElement); break; case CHTMLClickRecord::eMouseTimeout: /* { Int16 thePopResult = this->DoPopup(inMouseDown, cr); if (thePopResult) this->HandlePopupResult(inMouseDown, cr, thePopResult); else LO_HighlightAnchor(*mContext, cr.mElement, false); } */ break; case CHTMLClickRecord::eMouseUpEarly: ClickSelfLink(inMouseDown, cr, false); doUnhighlight = false; break; case CHTMLClickRecord::eHandledByAttachment: // Nothing else to do. break; default: SignalPStr_("\pUnhandled click case!!!"); break; } if (doUnhighlight) LO_HighlightAnchor(*mContext, cr.mElement, false); bClickHandled = true; } else if ((theElement != NULL) && (theElement->type == LO_IMAGE)) { // ₯ allow dragging of non-anchor images mCurrentClickRecord = &cr; CHTMLClickRecord::EClickState theMouseAction = CHTMLClickRecord::eUndefined; try { theMouseAction = cr.WaitForMouseAction(inMouseDown.whereLocal, inMouseDown.macEvent.when, GetDblTime()); } catch(...) {} mCurrentClickRecord = nil; if (theMouseAction == CHTMLClickRecord::eMouseDragging) { ClickDragLink(inMouseDown, theElement); bClickHandled = true; } } } } // callback for form elements - mjc if (!bClickHandled) { if ((theElement != NULL) && (theElement->type == LO_FORM_ELE) && (inLayerWhere.h - theElement->lo_form.x - theElement->lo_form.x_offset <= theElement->lo_form.width) && (inLayerWhere.h - theElement->lo_form.x - theElement->lo_form.x_offset >= 0) && (inLayerWhere.v - theElement->lo_form.y - theElement->lo_form.y_offset <= theElement->lo_form.height) && (inLayerWhere.v - theElement->lo_form.y - theElement->lo_form.y_offset >= 0)) { switch (theElement->lo_form.element_data->type) { case FORM_TYPE_SUBMIT: case FORM_TYPE_RESET: case FORM_TYPE_BUTTON: { LPane* thePane = ((FormFEData *)theElement->lo_form.element_data->ele_minimal.FE_Data)->fPane; CFormButton* theFormButton = dynamic_cast(thePane); CGAFormPushButton* theGAFormPushButton = dynamic_cast(thePane); if (theFormButton) { theFormButton->ClickSelfLayer(inMouseDown); } else if (theGAFormPushButton) { theGAFormPushButton->ClickSelfLayer(inMouseDown); } else { Assert_(false); } bClickHandled = true; } break; case FORM_TYPE_RADIO: { LPane* thePane = ((FormFEData *)theElement->lo_form.element_data->ele_minimal.FE_Data)->fPane; CFormRadio* theFormRadio = dynamic_cast(thePane); CGAFormRadio* theGAFormRadio = dynamic_cast(thePane); if (theFormRadio) { theFormRadio->ClickSelfLayer(inMouseDown); } else if (theGAFormRadio) { theGAFormRadio->ClickSelfLayer(inMouseDown); } else { Assert_(false); } bClickHandled = true; } break; case FORM_TYPE_CHECKBOX: { LPane* thePane = ((FormFEData *)theElement->lo_form.element_data->ele_minimal.FE_Data)->fPane; CFormCheckbox* theFormCheckbox = dynamic_cast(thePane); CGAFormCheckbox* theGAFormCheckbox = dynamic_cast(thePane); if (theFormCheckbox) { theFormCheckbox->ClickSelfLayer(inMouseDown); } else if (theGAFormCheckbox) { theGAFormCheckbox->ClickSelfLayer(inMouseDown); } else { Assert_(false); } bClickHandled = true; } break; } } } // ₯₯₯Κthere must be a better way... // // this is just about the same code as above for handling a click // but it's repeated here because the code above handles clicks on graphical elements? // // also, I see two version of WaitForMouseAction being called, one global and one inside cr // which is appropriate? // // 96-12-18 deeje if (!bClickHandled && ContextMenuPopupsEnabled()) { mCurrentClickRecord = &cr; CHTMLClickRecord::EClickState mouseAction = CHTMLClickRecord::eUndefined; try { mouseAction = CHTMLClickRecord::WaitForMouseAction( inMouseDown, this, GetDblTime()); } catch (...) {} mCurrentClickRecord = nil; if ( mouseAction == CHTMLClickRecord::eHandledByAttachment ) bClickHandled = TRUE; /* if ( mouseAction == CHTMLClickRecord::eMouseTimeout ) // No popup when we have grids { Int16 thePopResult = this->DoPopup(inMouseDown, cr); if (thePopResult) this->HandlePopupResult(inMouseDown, cr, thePopResult); bClickHandled = TRUE; } */ } if (!bClickHandled) { Boolean didTrackSelection = ClickTrackSelection(inMouseDown, cr); // if no selection, and we're not over an element, // send a mouse up and click to the document if (!didTrackSelection && (cr.mClickKind == eNone)) { EventRecord macEvent; GetOSEvent(mUpMask, &macEvent); // grab the mouse up event so LEventDispatcher never sees it mWaitMouseUp = false; try { DoExecuteClickInLinkRecord* clickRecord = new DoExecuteClickInLinkRecord(this, inMouseDown, cr, false, false, NULL, EVENT_MOUSEUP); JSEvent* event = XP_NEW_ZAP(JSEvent); if (event) { // 97-06-10 pkc -- Turn off grab mouse events here because we don't call // compositor for mouse ups. MWContext* mwContext = *mContext; if (mwContext->js_dragging==TRUE) { CL_GrabMouseEvents(mwContext->compositor, NULL); mwContext->js_dragging = 0; } event->type = EVENT_MOUSEUP; event->which = 1; event->x = cr.mImageWhere.h; event->y = cr.mImageWhere.v; event->docx = event->x + CL_GetLayerXOrigin(cr.mLayer); event->docy = event->y + CL_GetLayerYOrigin(cr.mLayer); Point screenPt = { event->docy, event->docx }; SPoint32 imagePt; LocalToImagePoint(screenPt, imagePt); ImageToAvailScreenPoint(imagePt, screenPt); event->screenx = screenPt.h; event->screeny = screenPt.v; event->layer_id = LO_GetIdFromLayer(*mContext, cr.mLayer); event->modifiers = CMochaHacks::MochaModifiers(inMouseDown.macEvent.modifiers); ET_SendEvent(*mContext, NULL, event, MochaDoExecuteClickInLinkCallback, clickRecord); } } catch (...) { } } } } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ void CHTMLView::ClickSelfLink( const SMouseDownEvent& inMouseDown, CHTMLClickRecord& inClickRecord, Boolean inMakeNewWindow) { // Execute this only if there was a previous mouse down which did not have a corresponding // mouse up. if (mWaitMouseUp) { EventRecord macEvent; GetOSEvent(mUpMask, &macEvent); // grab the mouse up event so LEventDispatcher never sees it mWaitMouseUp = false; // got a mouse up so clear the wait flag. Boolean bSaveToDisk = ((inMouseDown.macEvent.modifiers & optionKey) == optionKey) && !inMakeNewWindow; // do we also have to use a StTempFormBlur in PostProcessClickSelfLink? StTempFormBlur tempBlur; // mforms.h for an explanation // check for event handler in containing contexts or on anchor for the events // we are about to send. LO_Element* element = inClickRecord.GetLayoutElement(); if (HasEventHandler(*mContext, (EVENT_MOUSEUP | EVENT_CLICK)) || // map area anchor with an event handler (CMochaHacks::GetMouseOverMapArea() && CMochaHacks::GetMouseOverMapArea()->event_handler_present) || (element && // ALERT: event_handler_present doesn't seem to be initialized properly so test against TRUE. ((element->type == LO_TEXT && element->lo_text.anchor_href && (element->lo_text.anchor_href->event_handler_present == TRUE)) || (element->type == LO_IMAGE && element->lo_image.anchor_href && (element->lo_image.anchor_href->event_handler_present == TRUE)) || // a plain image without an anchor could have event handlers, but there is no bit to tell us that. ((element->type == LO_IMAGE) && (element->lo_image.anchor_href == NULL) && (element->lo_image.image_attr->usemap_name == NULL) && // not a client-side image map !(element->lo_image.image_attr->attrmask & LO_ATTR_ISMAP))))) // not a server-side image map { try { DoExecuteClickInLinkRecord* clickRecord = new DoExecuteClickInLinkRecord(this, inMouseDown, inClickRecord, inMakeNewWindow, bSaveToDisk, CMochaHacks::GetMouseOverMapArea(), EVENT_MOUSEUP); // ET_SendEvent now takes a JSEvent struct instead of an int type JSEvent* event = XP_NEW_ZAP(JSEvent); if (event) { // 97-06-10 pkc -- Turn off grab mouse events here because we don't call // compositor for mouse ups. MWContext* mwContext = *mContext; if (mwContext->js_dragging==TRUE) { CL_GrabMouseEvents(mwContext->compositor, NULL); mwContext->js_dragging = 0; } event->type = EVENT_MOUSEUP; event->which = 1; // send layer relative position info to mocha - mjc event->x = inClickRecord.mImageWhere.h; event->y = inClickRecord.mImageWhere.v; event->docx = event->x + CL_GetLayerXOrigin(inClickRecord.mLayer); event->docy = event->y + CL_GetLayerYOrigin(inClickRecord.mLayer); Point screenPt; ImageToAvailScreenPoint(inClickRecord.mImageWhere, screenPt); event->screenx = screenPt.h; event->screeny = screenPt.v; event->layer_id = LO_GetIdFromLayer(*mContext, inClickRecord.mLayer); // 1997-03-02 mjc event->modifiers = CMochaHacks::MochaModifiers(inMouseDown.macEvent.modifiers); // 1997-02-27 mjc ET_SendEvent(*mContext, inClickRecord.mElement, event, MochaDoExecuteClickInLinkCallback, clickRecord); } } catch (...) { } } // We delay DispatchToView because we're completely handling the mouse // down in the front end, so the compositor needs to unwind before we switch content. else PostProcessClickSelfLink(inMouseDown, inClickRecord, inMakeNewWindow, bSaveToDisk, true); } } // PostProcessClickSelfLink // Mocha callback routine, post processes DoExecuteClickInLink // Because of the new threaded mocha, we have to wait for a call back // after mocha calls, this code used to come after the call to LM_SendOnClick in ClickSelfLink. // Now, this code gets executed after the call to ET_SendEvent calls us back through // MochaDoExecuteClickInLinkCallback. // // inDelay - set to true if there is a possibility that the content will change before the compositor // has finished unwinding from the mouse down event dispatch. If there were intervening // javascript or compositor calls, for example, there is no need to delay. void CHTMLView::PostProcessClickSelfLink( const SMouseDownEvent& /* inMouseDown */, CHTMLClickRecord& inClickRecord, Boolean inMakeNewWindow, Boolean inSaveToDisk, Boolean inDelay) { // Sniff the URL to detect mail attachment. Set inSaveToDisk accordingly before // dispatching. Note that in Constellation, mail messages may be viewed in a browser // view! /* Boolean isMailAttachment = false; const char* url = inClickRecord.GetClickURL(); if (!strncasecomp (url, "mailbox:", 8)) { if (XP_STRSTR(url, "?part=") || XP_STRSTR(url, "&part=")) isMailAttachment = true; // Yep, mail attachment. } */ CBrowserContext* theSponsorContext = (inMakeNewWindow) ? NULL : mContext; EClickKind oldClickKind = inClickRecord.mClickKind; inClickRecord.Recalc(); switch (inClickRecord.mClickKind) { case eTextAnchor: case eImageAnchor: case eImageIsmap: case eImageAltText: { // unhighlight the anchor while it is still around (before content is switched) LO_HighlightAnchor(*mContext, inClickRecord.mElement, false); FO_Present_Types theType = (inSaveToDisk) ? FO_SAVE_AS : FO_CACHE_AND_PRESENT; URL_Struct* theURL = NET_CreateURLStruct(inClickRecord.mClickURL, NET_DONT_RELOAD); ThrowIfNULL_(theURL); cstring theReferer = mContext->GetCurrentURL(); if (theReferer.length() > 0) theURL->referer = XP_STRDUP(theReferer); if (inMakeNewWindow) theURL->window_target = XP_STRDUP(""); else { if (XP_STRCMP(inClickRecord.mWindowTarget, "") != 0) theURL->window_target = XP_STRDUP(inClickRecord.mWindowTarget); else theURL->window_target = NULL; } if (FO_SAVE_AS == theType) { // See also the code for popup stuff. Combine these later. FIX ME. CStr31 fileName = CFileMgr::FileNameFromURL( theURL->address ); //fe_FileNameFromContext(*mContext, theURL->address, fileName); StandardFileReply reply; /* if (isMailAttachment) { // ad decoder will prompt for the name. reply.sfGood = true; ::FSMakeFSSpec(0, 0, fileName, &reply.sfFile); } else */ ::StandardPutFile(GetPString(SAVE_AS_RESID), fileName, &reply); if (reply.sfGood) { CURLDispatcher::DispatchToStorage(theURL, reply.sfFile, FO_SAVE_AS, false); } } else if (FO_CACHE_AND_PRESENT == theType) { DispatchURL(theURL, theSponsorContext, inDelay, inMakeNewWindow); } break; } case eImageForm: // Image that is an ISMAP form { /* LO_FormSubmitData *theSubmit = NULL; try { theSubmit = LO_SubmitImageForm(*mContext, &inClickRecord.mElement->lo_image, inClickRecord.mImageWhere.h, inClickRecord.mImageWhere.v); ThrowIfNULL_(theSubmit); URL_Struct* theURL = NET_CreateURLStruct((char*)theSubmit->action, NET_DONT_RELOAD); ThrowIfNULL_(theURL); cstring theCurrentURL = mContext->GetCurrentURL(); if (theCurrentURL.length() > 0) theURL->referer = XP_STRDUP(theCurrentURL); if (NET_AddLOSubmitDataToURLStruct(theSubmit, theURL)) theDispatcher->DispatchToView(theSponsorContext, theURL, FO_CACHE_AND_PRESENT, inMakeNewWindow, 1010, inDelay); LO_FreeSubmitData(theSubmit); } catch (...) { LO_FreeSubmitData(theSubmit); throw; }*/ // ET_SendEvent now takes a JSEvent struct instead of an int type ImageFormSubmitData* data = new ImageFormSubmitData; LO_ImageStruct* image = &inClickRecord.mElement->lo_image; data->lo_image = image; // set the coordinates relative to the image (not the document), taking into account the border. data->x = inClickRecord.mImageWhere.h - (image->x + image->x_offset + image->border_width); data->y = inClickRecord.mImageWhere.v - (image->y + image->y_offset + image->border_width); JSEvent* event = XP_NEW_ZAP(JSEvent); if (event) { event->type = EVENT_SUBMIT; // The code above will get executed in MochaFormSubmitCallback ET_SendEvent(*mContext, inClickRecord.mElement, event, MochaImageFormSubmitCallback, data); } } break; case eImageIcon: { if (!inSaveToDisk) { HandleImageIconClick(inClickRecord); } else { URL_Struct* theURL = NET_CreateURLStruct(inClickRecord.mClickURL, NET_DONT_RELOAD); if (theURL == NULL) break; cstring theReferer = theURL->address; if (theReferer.length() > 0) theURL->referer = XP_STRDUP(theReferer); if (inMakeNewWindow) { theURL->window_target = XP_STRDUP(""); if (XP_STRCMP(inClickRecord.mWindowTarget, "") != 0) theURL->window_target = XP_STRDUP(inClickRecord.mWindowTarget); else theURL->window_target = NULL; } DispatchURL(theURL, theSponsorContext, false, inMakeNewWindow); } } break; case eNone: { // 97-06-10 pkc -- Hack to dispatch URL's after mocha is done loading image. // If oldClickKind is eImageAnchor, then we're in the case where mocha is loading // an image over a current image. if (oldClickKind == eImageAnchor && (((char*)inClickRecord.mClickURL) != NULL)) { URL_Struct* theURL = NET_CreateURLStruct(inClickRecord.mClickURL, NET_DONT_RELOAD); ThrowIfNULL_(theURL); cstring theReferer = mContext->GetCurrentURL(); if (theReferer.length() > 0) theURL->referer = XP_STRDUP(theReferer); if (inMakeNewWindow) theURL->window_target = XP_STRDUP(""); else { if (XP_STRCMP(inClickRecord.mWindowTarget, "") != 0) theURL->window_target = XP_STRDUP(inClickRecord.mWindowTarget); else theURL->window_target = NULL; } // Call DispatchToView with inDelay = true and inWaitingForMochaImageLoad = true // theDispatcher->DispatchToView(theSponsorContext, theURL, FO_CACHE_AND_PRESENT, inMakeNewWindow, 1010, true, true, true); CURLDispatcher::DispatchURL(theURL, theSponsorContext, true, inMakeNewWindow, BrowserWindow_ResID, true, FO_CACHE_AND_PRESENT, true); } } break; default: case eWaiting: Assert_(false); break; } } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ void CHTMLView::Click(SMouseDownEvent &inMouseDown) // Special processing for drag-n-drop stuff, not to select the window until mouse up. // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ { LPane *clickedPane = FindSubPaneHitBy(inMouseDown.wherePort.h, inMouseDown.wherePort.v); if ( clickedPane != nil ) clickedPane->Click(inMouseDown); else { if ( !inMouseDown.delaySelect ) LCommander::SwitchTarget(this); StValueChanger change(inMouseDown.delaySelect, false); // For drag-n-drop functionality LPane::Click(inMouseDown); // will process click on this View } } // CHTMLView::Click // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ void CHTMLView::HandleImageIconClick(CHTMLClickRecord& inClickRecord) { char* url = inClickRecord.mImageURL; // check to see if the click was on the attachment or SMime icon if (!XP_STRNCMP(url, "internal-smime", 14) || !XP_STRNCMP(url, "internal-attachment-icon", 24) ) { URL_Struct* theURL = NET_CreateURLStruct(inClickRecord.mClickURL, NET_DONT_RELOAD); mContext->SwitchLoadURL(theURL, FO_CACHE_AND_PRESENT); } else PostDeferredImage(url); } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // void CHTMLView::ClickDragLink( const SMouseDownEvent& inMouseDown, LO_Element* inElement) { FocusDraw(); Rect theGlobalRect; Boolean bVisible = CalcElementPosition(inElement, theGlobalRect); ::LocalToGlobal(&topLeft(theGlobalRect)); ::LocalToGlobal(&botRight(theGlobalRect)); // account for image border Int32 borderWidth = 0; if (inElement->type == LO_IMAGE) borderWidth = inElement->lo_image.border_width; ::OffsetRect(&theGlobalRect, borderWidth, borderWidth); StValueChanger theValueChanger(mDragElement, inElement); CDragURLTask theDragTask(inMouseDown.macEvent, theGlobalRect, *this); OSErr theErr = ::SetDragSendProc(theDragTask.GetDragReference(), mSendDataUPP, (LDragAndDrop*)this); ThrowIfOSErr_(theErr); theDragTask.DoDrag(); } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ void CHTMLView::ClickTrackEdge( const SMouseDownEvent& inMouseDown, CHTMLClickRecord& inClickRecord) { // ₯₯₯ FIX ME!!! we need to stop the blinkers Rect limitRect, slopRect; Int16 axis; // Figure out the outline of the region. This should come from layout somehow Point topRgn = inMouseDown.whereLocal; Point bottomRgn = inMouseDown.whereLocal; if ( inClickRecord.mIsVerticalEdge ) // Edge is vertical, we can drag horizontally. { topRgn.v = inClickRecord.mElement->lo_edge.y; bottomRgn.v = topRgn.v + inClickRecord.mElement->lo_edge.height; topRgn.h = inClickRecord.mElement->lo_edge.x; bottomRgn.h = topRgn.h + inClickRecord.mElement->lo_edge.width; limitRect.left = inClickRecord.mEdgeLowerBound; limitRect.right = inClickRecord.mEdgeUpperBound; limitRect.top = topRgn.v; limitRect.bottom = bottomRgn.v; slopRect = limitRect; axis = hAxisOnly; } else { topRgn.h = inClickRecord.mElement->lo_edge.x; bottomRgn.h = topRgn.h + inClickRecord.mElement->lo_edge.width; topRgn.v = inClickRecord.mElement->lo_edge.y; bottomRgn.v = topRgn.v + inClickRecord.mElement->lo_edge.height; limitRect.top = inClickRecord.mEdgeLowerBound; limitRect.bottom = inClickRecord.mEdgeUpperBound; limitRect.left = topRgn.h; limitRect.right = bottomRgn.h; slopRect = limitRect; axis = vAxisOnly; } Rect tmp; tmp.top = topRgn.v; tmp.left = topRgn.h; tmp.right = bottomRgn.h; tmp.bottom = bottomRgn.v; StRegion rgn(tmp); FocusDraw(); long movedBy = ::DragGrayRgn(rgn, inMouseDown.whereLocal, &limitRect, &slopRect, axis, NULL); if ( HiWord( movedBy ) != -32768 ) // We have a valid movement { // We set a null clip so we don't flicker and flash StClipRgnState theSavedClip(NULL); LocalToPortPoint(topLeft(tmp)); LocalToPortPoint(botRight(tmp)); ::InsetRect(&tmp, -2, -2); InvalPortRect(&tmp); Point newPoint; Rect newRect = tmp; if ( axis == vAxisOnly ) { newPoint.v = inMouseDown.whereLocal.v + HiWord(movedBy); ::OffsetRect(&newRect, 0, HiWord(movedBy)); } else { newPoint.h = inMouseDown.whereLocal.h + LoWord( movedBy ); ::OffsetRect(&newRect, LoWord(movedBy), 0); } if (inClickRecord.mIsVerticalEdge) ::InsetRect(&newRect, -RectWidth(limitRect), -3); else ::InsetRect(&newRect, -3, -RectHeight(limitRect)); ::UnionRect(&tmp, &newRect, &tmp); { StClipRgnState theClipSaver(NULL); // 97-06-11 pkc -- Set mDontAddGridEdgeToList to true so that DisplayEdge // doesn't add this grid edge into list and DrawGridEdge doesn't draw // because LO_MoveGridEdge will call DisplayEdge mDontAddGridEdgeToList = true; LO_MoveGridEdge(*mContext, (LO_EdgeStruct*)inClickRecord.mElement, newPoint.h, newPoint.v ); mDontAddGridEdgeToList = false; } InvalPortRect( &tmp ); } // FIX ME!!! we need to start the blinkers } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ inline void CHTMLView::LocalToLayerCoordinates( const XP_Rect& inBoundingBox, Point inWhereLocal, SPoint32& outWhereLayer) const // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ { LocalToImagePoint(inWhereLocal, outWhereLayer); // Convert from image to layer coordinates outWhereLayer.h -= inBoundingBox.left; outWhereLayer.v -= inBoundingBox.top; } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ Boolean CHTMLView::ClickTrackSelection( const SMouseDownEvent& inMouseDown, CHTMLClickRecord& inClickRecord) // ₯ Returns true if a selection was started and extended. // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ { // FIX ME!!! we need to stop the blinkers ::SetCursor(*GetCursor(iBeamCursor)); XP_Rect theBoundingBox; CL_GetLayerBboxAbsolute(inClickRecord.mLayer, &theBoundingBox); // Convert from image to layer coordinates SPoint32 theImagePointStart; LocalToLayerCoordinates(theBoundingBox, inMouseDown.whereLocal, theImagePointStart); SPoint32 theImagePointEnd = theImagePointStart; if ((inMouseDown.macEvent.modifiers & shiftKey) && !inClickRecord.IsClickOnAnchor()) LO_ExtendSelection(*mContext, theImagePointStart.h, theImagePointStart.v); else LO_StartSelection(*mContext, theImagePointStart.h, theImagePointStart.v, inClickRecord.mLayer); // track mouse till we are done Boolean didTrackSelection = false; while (::StillDown()) { Point qdWhere; FocusDraw(); // so that we get coordinates right ::GetMouse(&qdWhere); if (AutoScrollImage(qdWhere)) { Rect theFrame; CalcLocalFrameRect(theFrame); if (qdWhere.v < theFrame.top) qdWhere.v = theFrame.top; else if (qdWhere.v > theFrame.bottom) qdWhere.v = theFrame.bottom; } SPoint32 theTrackImagePoint; LocalToLayerCoordinates(theBoundingBox, qdWhere, theTrackImagePoint); if (theTrackImagePoint.v != theImagePointEnd.v || theTrackImagePoint.h != theImagePointEnd.h) { didTrackSelection = true; LO_ExtendSelection(*mContext, theTrackImagePoint.h, theTrackImagePoint.v); } theImagePointEnd = theTrackImagePoint; // ₯Κidling ::SystemTask(); EventRecord dummy; ::WaitNextEvent(0, &dummy, 5, NULL); } LO_EndSelection(*mContext); return didTrackSelection; // FIX ME!!! we need to restart the blinkers } // CHTMLView::ClickTrackSelection // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ void CHTMLView::EventMouseUp(const EventRecord& inMouseUp) // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ { // FocusDraw() && SwitchTarget(this) appears to be a copy/paste error from ClickSelf. // We will dispatch a mouse up only if a mouse down has been dispatched. Otherwise there // would be a possibility of this getting called if a click selects the window containing // this view but does not perform a mouse down. if (mContext != NULL && mWaitMouseUp) /* && FocusDraw() && SwitchTarget(this) */ { SPoint32 firstP; Point localPt = inMouseUp.where; mWaitMouseUp = false; GlobalToPortPoint( localPt); // 1997-02-27 mjc PortToLocalPoint( localPt ); LocalToImagePoint( localPt, firstP ); if (mCompositor != NULL) { fe_EventStruct fe_event; fe_event.portPoint = inMouseUp.where; //fe_event.event = (void *)&inMouseUp; fe_event.event.macEvent = inMouseUp; // 1997-02-27 mjc CL_Event event; event.type = CL_EVENT_MOUSE_BUTTON_UP; event.fe_event = (void *)&fe_event; event.fe_event_size = sizeof(fe_EventStruct); // 1997-02-27 mjc event.x = firstP.h; event.y = firstP.v; event.which = 1; event.modifiers = CMochaHacks::MochaModifiers(inMouseUp.modifiers); CL_DispatchEvent(*mCompositor, &event); } } } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ Boolean CHTMLView::HandleKeyPress( const EventRecord& inKeyEvent ) { Char16 theChar = inKeyEvent.message & charCodeMask; short modifiers = inKeyEvent.modifiers & (cmdKey | shiftKey | optionKey | controlKey); SPoint32 firstP; Point localPt = inKeyEvent.where; GlobalToPortPoint(localPt); PortToLocalPoint( localPt ); LocalToImagePoint( localPt, firstP ); #ifdef LAYERS if (mCompositor) { // If no one has key event focus, set event focus to the main document. if (CL_IsKeyEventGrabber(*mCompositor, NULL) && CL_GetCompositorRoot(*mCompositor)) { CL_GrabKeyEvents( *mCompositor, CL_GetLayerChildByName( CL_GetCompositorRoot(*mCompositor), LO_BODY_LAYER_NAME)); } // If there's a compositor and someone has keyboard focus, dispatch the event. if (!CL_IsKeyEventGrabber(*mCompositor, NULL) && (sLastFormKeyPressDispatchTime != inKeyEvent.when)) { CL_Event event; fe_EventStruct fe_event; fe_event.event.macEvent = inKeyEvent; // 1997-02-25 mjc event.data = 0; switch (inKeyEvent.what) { case keyDown: event.type = CL_EVENT_KEY_DOWN; break; case autoKey: event.type = CL_EVENT_KEY_DOWN; event.data = 1; // repeating break; case keyUp: event.type = CL_EVENT_KEY_UP; break; } event.fe_event = (void *)&fe_event; event.fe_event_size = sizeof(fe_EventStruct); event.x = firstP.h; event.y = firstP.v; event.which = theChar; event.modifiers = CMochaHacks::MochaModifiers(inKeyEvent.modifiers); // 1997-02-27 mjc CL_DispatchEvent(*mCompositor, &event); return true; } else return HandleKeyPressLayer(inKeyEvent, NULL, firstP); } else #endif // LAYERS return HandleKeyPressLayer(inKeyEvent, NULL, firstP); } Boolean CHTMLView::HandleKeyPressLayer(const EventRecord& inKeyEvent, CL_Layer *inLayer, SPoint32 inLayerWhere ) { Char16 theChar = inKeyEvent.message & charCodeMask; short modifiers = inKeyEvent.modifiers & (cmdKey | shiftKey | optionKey | controlKey); Boolean handled = false; #ifdef LAYERS if ((inLayer != NULL) && (sLastFormKeyPressDispatchTime != inKeyEvent.when)) { SPoint32 theElementWhere = inLayerWhere; LO_Element* theElement = LO_XYToElement(*mContext, theElementWhere.h, theElementWhere.v, inLayer); if ((theElement != NULL) && (theElement->type == LO_FORM_ELE)) { switch (theElement->lo_form.element_data->type) { case FORM_TYPE_TEXTAREA: CFormBigText *bigText = (CFormBigText *)((FormFEData *)theElement->lo_form.element_data->ele_minimal.FE_Data)->fPane->FindPaneByID(formBigTextID); sLastFormKeyPressDispatchTime = inKeyEvent.when; handled = bigText->HandleKeyPress(inKeyEvent); break; case FORM_TYPE_TEXT: case FORM_TYPE_PASSWORD: CFormLittleText *text = (CFormLittleText *)((FormFEData *)theElement->lo_form.element_data->ele_minimal.FE_Data)->fPane; sLastFormKeyPressDispatchTime = inKeyEvent.when; handled = text->HandleKeyPress(inKeyEvent); break; } } } #endif // forms didn't handle the event if (!handled) { // we may get keyUp events (javascript needs them) but just ignore them - 1997-02-27 mjc if (keyUp == inKeyEvent.what) return TRUE; if ( modifiers == 0 ) switch ( theChar & charCodeMask ) { case char_UpArrow: if ( mScroller && mScroller->HasVerticalScrollbar()) mScroller->VertScroll( kControlUpButtonPart ); return TRUE; case char_DownArrow: if ( mScroller && mScroller->HasVerticalScrollbar() ) mScroller->VertScroll( kControlDownButtonPart ); return TRUE; // Seems only fair to allow scrolling left and right like the other platforms case char_LeftArrow: if ( mScroller && mScroller->HasHorizontalScrollbar()) mScroller->HorizScroll( kControlUpButtonPart ); return TRUE; case char_RightArrow: if ( mScroller && mScroller->HasHorizontalScrollbar() ) mScroller->HorizScroll( kControlDownButtonPart ); return TRUE; case char_PageUp: case char_Backspace: if ( mScroller && mScroller->HasVerticalScrollbar()) mScroller->VertScroll( kControlPageUpPart ); return TRUE; case char_PageDown: case char_Space: if ( mScroller && mScroller->HasVerticalScrollbar()) mScroller->VertScroll( kControlPageDownPart ); return TRUE; case char_Home: ScrollImageTo( 0, 0, TRUE ); return TRUE; case char_End: int32 y; y = mImageSize.height - mFrameSize.height; if ( y < 0) y = 0; ScrollImageTo( 0, y, TRUE ); return TRUE; } if ( ( modifiers & cmdKey ) == cmdKey ) switch ( theChar & charCodeMask ) { case char_UpArrow: if ( mScroller && mScroller->HasVerticalScrollbar() ) mScroller->VertScroll( kControlPageUpPart ); return TRUE; case char_DownArrow: if ( mScroller && mScroller->HasVerticalScrollbar() ) mScroller->VertScroll( kControlPageDownPart ); return TRUE; } if ( ( modifiers & (controlKey | optionKey ) ) == ( controlKey | optionKey ) ) switch ( theChar & charCodeMask ) { case 'h' - 96: if ( mScroller ) { mScroller->ShowScrollbars( FALSE, FALSE ); return TRUE; } case 'j' - 96: if ( mScroller ) { mScroller->ShowScrollbars( TRUE, TRUE ); return TRUE; } case 'k' - 96: if ( mScroller ) { mScroller->ShowScrollbars( FALSE, TRUE ); return TRUE; } case 'l' - 96: if ( mScroller ) { mScroller->ShowScrollbars( TRUE, FALSE ); return TRUE; } } // Tabbing. We want to shift hyperviews, and not form elements, if we // are going backward from the first form element, or forward from the last one if (theChar == char_Tab) { Boolean retVal; if (mSubCommanders.GetCount() == 0) // no tabbing, nothing to switch retVal = LCommander::HandleKeyPress(inKeyEvent); else { // ₯₯₯ 98/03/26: Because of the new implementation of LTabGroup in Pro2, we get // stuck in the deepest commander hierarchy and can never get back to the // toplevel tab group to get to the location bar. This needs to be fixed, but // not before 3/31. I'm not sure what the right fix is (pinkerton). LCommander *onDutySub = GetTarget(); if (onDutySub == NULL) { LCommander *newTarget; mSubCommanders.FetchItemAt(1, newTarget); SwitchTarget(newTarget); retVal = TRUE; } else { Int32 pos = mSubCommanders.FetchIndexOf(onDutySub); Boolean backward = (inKeyEvent.modifiers & shiftKey) != 0; if ((pos == mSubCommanders.GetCount() && !backward) // If we are the last field, || (--pos <= 0 && backward)) // // Do not wrap within the view, use the commander retVal = LCommander::HandleKeyPress(inKeyEvent); else retVal = LTabGroup::HandleKeyPress( inKeyEvent ); } } return retVal; } return LTabGroup::HandleKeyPress( inKeyEvent ); } return handled; } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ Callback for cursor handling for new mocha event stuff // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // AdjustCursorRecord // Used as a Mocha callback structure // holds all the information needed to call MochaExecuteClickInLink struct AdjustCursorRecord { char * mMessage; AdjustCursorRecord(const char * message) { if (message) mMessage = XP_STRDUP( message ); else mMessage = NULL; } ~AdjustCursorRecord() { FREEIF( mMessage ); } }; // Mocha callback for MochaAdjustCursorRecord void MochaAdjustCursorCallback(MWContext * pContext, LO_Element * lo_element, int32 lType, void * whatever, ETEventStatus status); void MochaAdjustCursorCallback(MWContext * pContext, LO_Element * /* lo_element */, int32 /* lType */, void * whatever, ETEventStatus status) { AdjustCursorRecord * p = (AdjustCursorRecord*)whatever; if (status == EVENT_CANCEL) { CNSContext* nsContext = ExtractNSContext(pContext); nsContext->SetStatus(p->mMessage); } delete p; } // Mocha callback for MochaAdjustCursorRecord // Also frees the layout record. Layout record needs to be allocated // because of a hack for map areas void MochaAdjustCursorCallbackLayoutFree(MWContext * pContext, LO_Element * lo_element, int32 lType, void * whatever, ETEventStatus status); void MochaAdjustCursorCallbackLayoutFree(MWContext * pContext, LO_Element * lo_element, int32 lType, void * whatever, ETEventStatus status) { MochaAdjustCursorCallback( pContext, lo_element, lType, whatever, status); XP_FREE( lo_element ); } void CHTMLView::AdjustCursorSelf( Point inPortPt, const EventRecord& inMacEvent ) { // if this page is tied-up, display a watch if ( !IsEnabled() ) { ::SafeSetCursor( watchCursor ); return; } // bail if we did not move, saves time and flickering if ( ( inPortPt.h == mOldPoint.h ) && ( inPortPt.v == mOldPoint.v ) ) return; mOldPoint.h = inPortPt.h; mOldPoint.v = inPortPt.v; Point localPt = inPortPt; SPoint32 firstP; PortToLocalPoint( localPt ); LocalToImagePoint( localPt, firstP ); if (mCompositor != NULL) { CL_Event event; fe_EventStruct fe_event; fe_event.portPoint = inPortPt; //fe_event.event = (void *)&inMacEvent; fe_event.event.macEvent = inMacEvent; // 1997-02-27 mjc event.type = CL_EVENT_MOUSE_MOVE; event.fe_event = (void *)&fe_event; event.fe_event_size = sizeof(fe_EventStruct); // 1997-02-27 mjc event.x = firstP.h; event.y = firstP.v; event.which = 1; event.modifiers = 0; CL_DispatchEvent(*mCompositor, &event); } else AdjustCursorSelfForLayer(inPortPt, inMacEvent, NULL, firstP); } void CHTMLView::AdjustCursorSelfForLayer( Point inPortPt, const EventRecord& inMacEvent, CL_Layer *layer, SPoint32 inLayerPt ) { // With LAYERS, the original method gets the compositor to dispatch // the event, which is then dealt with (in this method) on a per-layer // basis. // find the element the cursor is above, SPoint32 firstP; LO_Element* element; PortToLocalPoint( inPortPt ); firstP = inLayerPt; FocusDraw(); // Debugging only element = LO_XYToElement( *mContext, firstP.h, firstP.v, layer ); // // Send MouseLeave events for layout elements // and areas of client-side image maps. // if (!CMochaHacks::IsMouseOverElement(element)) CMochaHacks::SendOutOfElementEvent(*mContext, layer, firstP); // add where parameter - mjc // // If cursor is over blank space, reset and bail // // pkc (6/5/96) If there is a defaultStatus string, don't clear status area if ( element == NULL && mContext->GetDefaultStatus() == NULL ) { CMochaHacks::SetMouseOverElement(NULL); CMochaHacks::ResetMochaMouse(); ::SetCursor( &UQDGlobals::GetQDGlobals()->arrow ); mContext->SetStatus(CStr255::sEmptyString); mOldEleID = -1; return; } // // If cursor is over same element as last time and that element // is not a client-side image map (sMouseOverMapArea != NULL), then // we're done // if (element && element->lo_any.ele_id == mOldEleID && !CMochaHacks::GetMouseOverMapArea() ) return; cstring anchor, location; CHTMLClickRecord cr(inPortPt, firstP, mContext, element, layer); if ( cr.IsAnchor() && !( inMacEvent.modifiers & shiftKey ) ) { // tj (4/29/96): I belive this code forces us to recompute // every time in the case of images // // (5/2/96): Don't set the element to NULL if its an image. // We need to absolutely know if we're over the same image // the next time through this call. // // We can use mOldEleID to force a redisplay of status for // images (image map coords). // if ( ( element->type == LO_IMAGE && ( element->lo_image.image_attr->attrmask & LO_ATTR_ISMAP ) ) || ( cr.mClickKind == eImageIcon ) ) mOldEleID = -1; else mOldEleID = element->lo_any.ele_id; // 97-06-21 pkc -- Also save MWContext along with element because if we mouse out // and we switch frames, the mContext when we send the mouseout event is NOT the same // one that contains the LO_Element. CMochaHacks::SetMouseOverElement(element, *mContext); location = (cr.mClickKind == eImageAnchor) ? cr.mImageURL : cr.mClickURL; // // Handle changes in client-side map area // if (!CMochaHacks::IsMouseOverMapArea(cr.mAnchorData)) { // leave the old area // if ( CFrontApp::sMouseOverMapArea ) // LM_SendMouseOutOfAnchor( *mContext, CFrontApp::sMouseOverMapArea ); CMochaHacks::SendOutOfMapAreaEvent(*mContext, layer, firstP); // add where parameter - mjc CMochaHacks::SetMouseOverMapArea(cr.mAnchorData); // If the mouseover handler returns true, then // we don't change the location in the status filed // // if ( CFrontApp::sMouseOverMapArea ) // showLocation = ! LM_SendMouseOverAnchor( *mContext, CFrontApp::sMouseOverMapArea ); if (CMochaHacks::GetMouseOverMapArea()) { LO_Element * el = XP_NEW_ZAP(LO_Element); // Need to fake the element, ask chouck for details el->type = LO_TEXT; el->lo_text.anchor_href = CMochaHacks::GetMouseOverMapArea(); el->lo_text.text = el->lo_text.anchor_href->anchor; // for js freed element test AdjustCursorRecord * r = new AdjustCursorRecord(location); // ET_SendEvent now takes a JSEvent struct instead of a int type JSEvent* event = XP_NEW_ZAP(JSEvent); if (event) { event->type = EVENT_MOUSEOVER; event->x = firstP.h; // layer-relative coordinates - mjc event->y = firstP.v; event->docx = event->x + CL_GetLayerXOrigin(layer); event->docy = event->y + CL_GetLayerYOrigin(layer); Point screenPt; ImageToAvailScreenPoint(firstP, screenPt); event->screenx = screenPt.h; event->screeny = screenPt.v; event->layer_id = LO_GetIdFromLayer(*mContext, layer); // 1997-03-02 mjc ET_SendEvent( *mContext, el, event, MochaAdjustCursorCallbackLayoutFree, r ); } } } // // Only send mouseover for the layout element if the cursor // is not over a client-side map area // if ( !CMochaHacks::GetMouseOverMapArea() ) { // showLocation = !LM_SendMouseOver( *mContext, element ); AdjustCursorRecord * r = new AdjustCursorRecord(location); // ET_SendEvent now takes a JSEvent struct instead of a int type JSEvent* event = XP_NEW_ZAP(JSEvent); if (event) { event->type = EVENT_MOUSEOVER; event->x = firstP.h; // layer-relative coordinates - mjc event->y = firstP.v; event->docx = event->x + CL_GetLayerXOrigin(layer); event->docy = event->y + CL_GetLayerYOrigin(layer); Point screenPt; ImageToAvailScreenPoint(firstP, screenPt); event->screenx = screenPt.h; event->screeny = screenPt.v; event->layer_id = LO_GetIdFromLayer(*mContext, layer); // 1997-03-02 mjc ET_SendEvent( *mContext, element, event, MochaAdjustCursorCallback, r ); } } ::SafeSetCursor(curs_Hand); return; } else if ( cr.IsEdge() ) { ::SafeSetCursor( (cr.mIsVerticalEdge) ? curs_HoriDrag : curs_VertDrag ); /* 97-06-11 pkc -- what in blue blazes is all this code for? mOldEleID = -1; { FocusDraw(); // Debugging only Rect limitRect, slopRect; int axis; StRegion rgn; // Figure out the outline of the region. This should come from layout somehow Point topRgn = inPortPt; Point bottomRgn = inPortPt; if ( cr.mIsVerticalEdge ) // Edge is vertical, we can drag horizontally. { topRgn.v = element->lo_edge.y; bottomRgn.v = topRgn.v + element->lo_edge.height; topRgn.h = element->lo_edge.x; bottomRgn.h = topRgn.h + element->lo_edge.width; limitRect.left = cr.mEdgeLowerBound; limitRect.right = cr.mEdgeUpperBound; limitRect.top = topRgn.v; limitRect.bottom = bottomRgn.v; slopRect = limitRect; axis = hAxisOnly; } else { topRgn.h = element->lo_edge.x; bottomRgn.h = topRgn.h + element->lo_edge.width; topRgn.v = element->lo_edge.y; bottomRgn.v = topRgn.v + element->lo_edge.height; limitRect.top = cr.mEdgeLowerBound; limitRect.bottom = cr.mEdgeUpperBound; limitRect.left = topRgn.h; limitRect.right = bottomRgn.h; slopRect = limitRect; axis = vAxisOnly; } OpenRgn(); // ShowPen(); MoveTo(topRgn.h, topRgn.v); LineTo(bottomRgn.h, topRgn.v); // Framing of the rect LineTo(bottomRgn.h, bottomRgn.v); LineTo(topRgn.h, bottomRgn.v); LineTo(topRgn.h, topRgn.v); CloseRgn(rgn.mRgn); // FillRgn(rgn.mRgn, &qd.black); // FrameRect(&limitRect); }*/ return; } // // The cursor is over blank space // // If we were previously over a map area, leave the old area if (CMochaHacks::GetMouseOverMapArea() != NULL) { // LM_SendMouseOutOfAnchor(*mContext, CFrontApp::sMouseOverMapArea); LO_Element * el = XP_NEW_ZAP(LO_Element); // Need to fake the element, ask chouck for details el->type = LO_TEXT; el->lo_text.anchor_href = CMochaHacks::GetMouseOverMapArea(); if (el->lo_text.anchor_href->anchor) el->lo_text.text = el->lo_text.anchor_href->anchor; // to pass js freed element check AdjustCursorRecord * r = new AdjustCursorRecord(location); // ET_SendEvent now takes a JSEvent struct instead of a int type JSEvent* event = XP_NEW_ZAP(JSEvent); if (event) { event->type = EVENT_MOUSEOUT; event->x = firstP.h; // layer-relative coordinates - mjc event->y = firstP.v; event->docx = event->x + CL_GetLayerXOrigin(layer); event->docy = event->y + CL_GetLayerYOrigin(layer); Point screenPt; ImageToAvailScreenPoint(firstP, screenPt); event->screenx = screenPt.h; event->screeny = screenPt.v; event->layer_id = LO_GetIdFromLayer(*mContext, layer); // 1997-03-02 mjc ET_SendEvent( *mContext, el, event, MochaAdjustCursorCallbackLayoutFree, r ); } CMochaHacks::SetMouseOverMapArea(NULL); } ::SetCursor( &UQDGlobals::GetQDGlobals()->arrow ); mOldEleID = -1; mContext->SetStatus( ( mContext->GetDefaultStatus() != NULL) ? mContext->GetDefaultStatus() : CStr255::sEmptyString ); } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // #pragma mark --- DRAG AND DROP --- // // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ void CHTMLView::DoDragSendData(FlavorType inFlavor, ItemReference inItemRef, DragReference inDragRef) { OSErr theErr; cstring theUrl; // Get the URL of the thing we're dragging... if (mDragElement->type == LO_IMAGE) { theUrl = GetURLFromImageElement(mContext, (LO_ImageStruct*) mDragElement); // do this so we can get name of non-anchor images } else { PA_Block anchor; XP_ASSERT(mDragElement->type == LO_TEXT); anchor = mDragElement->lo_text.anchor_href->anchor; PA_LOCK (theUrl, char*, anchor); PA_UNLOCK(anchor); } // Now send the data switch (inFlavor) { // Just send the URL text case 'TEXT': { theErr = ::SetDragItemFlavorData(inDragRef, inItemRef, inFlavor, theUrl, strlen(theUrl), 0); ThrowIfOSErr_ (theErr); break; } // Send the image as a PICT case 'PICT': { Assert_(mDragElement->type == LO_IMAGE); PicHandle thePicture = ConvertImageElementToPICT((LO_ImageStruct_struct*) mDragElement); ThrowIfNULL_(thePicture); { StHandleLocker theLock((Handle)thePicture); theErr = ::SetDragItemFlavorData(inDragRef, inItemRef, inFlavor, *thePicture, GetHandleSize((Handle)thePicture), 0); ThrowIfOSErr_(theErr); } ::KillPicture(thePicture); break; } case emBookmarkFileDrag: { // Get the target drop location AEDesc dropLocation; theErr = ::GetDropLocation(inDragRef, &dropLocation); //ThrowIfOSErr_(theErr); if (theErr != noErr) return; // Get the directory ID and volume reference number from the drop location SInt16 volume; SInt32 directory; theErr = GetDropLocationDirectory(&dropLocation, &directory, &volume); //ThrowIfOSErr_(theErr); // Ok, this is a hack, and here's why: This flavor type is sent with the FlavorFlag 'flavorSenderTranslated' which // means that this send data routine will get called whenever someone accepts this flavor. The problem is that // it is also called whenever someone calls GetFlavorDataSize(). This routine assumes that the drop location is // something HFS related, but it's perfectly valid for something to query the data size, and not be a HFS // derrivative (like the text widget for example). // So, if the coercion to HFS thingy fails, then we just punt to the textual representation. if (theErr == errAECoercionFail) { theErr = ::SetDragItemFlavorData(inDragRef, inItemRef, inFlavor, theUrl, strlen(theUrl), 0); return; } if (theErr != noErr) return; if (mDragElement->type == LO_IMAGE && theUrl == "") break; URL_Struct* request; request = NET_CreateURLStruct(theUrl, NET_DONT_RELOAD); // Combine with the unique name to make an FSSpec to the new file FSSpec prototypeFilespec; FSSpec locationSpec; prototypeFilespec.vRefNum = volume; prototypeFilespec.parID = directory; CStr31 filename; Boolean isMailAttachment = false; #ifdef MOZ_MAIL_NEWS isMailAttachment = XP_STRSTR( request->address , "?part=") || XP_STRSTR( request->address, "&part="); if ( isMailAttachment ) { CHTMLView::GetDefaultFileNameForSaveAs( request, filename); } else #endif // MOZ_MAIL_NEWS { filename = CFileMgr::FileNameFromURL( request->address ); //GetDefaultFileNameForSaveAs( request , filename ); } //theErr = CFileMgr::NewFileSpecFromURLStruct(filename, prototypeFilespec, locationSpec); theErr = CFileMgr::UniqueFileSpec( prototypeFilespec,filename, locationSpec ); if (theErr && theErr != fnfErr) // need a unique name, so we want fnfErr! ThrowIfOSErr_(theErr); // Set the flavor data to our emBookmarkFileDrag flavor with an FSSpec to the new file. theErr = ::SetDragItemFlavorData (inDragRef, inItemRef, inFlavor, &locationSpec, sizeof(FSSpec), 0); ThrowIfOSErr_(theErr); XP_MEMSET(&request->savedData, 0, sizeof(SHIST_SavedData)); CURLDispatcher::DispatchToStorage(request, locationSpec, FO_SAVE_AS, isMailAttachment); // ₯₯₯ both blocks of the if/then/else above call break, so does this get called? 96-12-17 deeje //CFileMgr::UpdateFinderDisplay(locationSpec); } case emBookmarkDrag: { cstring urlAndTitle(theUrl); if (mDragElement->type == LO_IMAGE) urlAndTitle += "\r[Image]"; else if (mDragElement->type == LO_TEXT) { urlAndTitle += "\r"; cstring title; PA_LOCK(title, char *, mDragElement->lo_text.text); PA_UNLOCK(mDragElement->lo_text.text); urlAndTitle += title; } theErr = ::SetDragItemFlavorData(inDragRef, inItemRef, inFlavor, urlAndTitle, strlen(urlAndTitle), 0); break; } default: { Throw_(cantGetFlavorErr); // caught by PP handler break; } } } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // #pragma mark --- TIMER URL --- // // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ void CHTMLView::SetTimerURL(Uint32 inSeconds, const char* inURL) { if (inURL) mTimerURLString = XP_STRDUP(inURL); else return; mTimerURLFireTime = ::TickCount() + inSeconds * 60; StartRepeating(); } void CHTMLView::ClearTimerURL(void) { if (mTimerURLString) XP_FREE(mTimerURLString); mTimerURLString = NULL; StopRepeating(); } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // #pragma mark --- DEFERRED LOADING --- // // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ void CHTMLView::PostDeferredImage(const char* inImageURL) { Assert_(inImageURL != NULL); LO_SetForceLoadImage((char *)inImageURL, FALSE); string theURL(inImageURL); mImageQueue.push_back(theURL); mContext->Repaginate(); } Boolean CHTMLView::IsImageInDeferredQueue(const char* inImageURL) const { Boolean bFound = false; if (mImageQueue.size() > 0) { vector::const_iterator theIter = mImageQueue.begin(); while (theIter != mImageQueue.end()) { if (*theIter == inImageURL) { bFound = true; break; } ++theIter; } } return bFound; } void CHTMLView::ClearDeferredImageQueue(void) { mImageQueue.erase(mImageQueue.begin(), mImageQueue.end()); } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // #pragma mark --- URL DISPATCHING --- // // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // 97-05-30 pkc -- These methods are here so that subclasses can alter the // CURLDispatchInfo struct as necessary before we call CURLDispatcher::DispatchURL void CHTMLView::DispatchURL( URL_Struct* inURLStruct, CNSContext* inTargetContext, Boolean inDelay, Boolean inForceCreate, FO_Present_Types inOutputFormat) { CURLDispatchInfo* info = new CURLDispatchInfo(inURLStruct, inTargetContext, inOutputFormat, inDelay, inForceCreate); DispatchURL(info); } void CHTMLView::DispatchURL(CURLDispatchInfo* inDispatchInfo) { CURLDispatcher::DispatchURL(inDispatchInfo); } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // #pragma mark --- CONTEXT CALLBACK IMPLEMENTATION --- // // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // XXX CALLBACK void CHTMLView::LayoutNewDocument( URL_Struct* /* inURL */, Int32* ioWidth, Int32* ioHeight, Int32* ioMarginWidth, Int32* ioMarginHeight) { if (IsRootHTMLView()) { //Assert_(mScroller != NULL); Don't HAVE to have scrollers, as long as we check for 'em. if (mScroller) { mScroller->ResetExpansion(); mScroller->AdjustHyperViewBounds(); } } // clear these so we don't send JavaScript mouseover/exit // events for deleted elements // ₯₯₯ FIX ME!!! CMochaHacks::ResetMochaMouse(); // FIX ME!!! determine why we need this here // Answer: // Because the we may load a docuemnt in different CharSet (eg. Japanese, Korean ) // ftang SetFontInfo(); mHasGridCells = FALSE; *ioWidth = *ioHeight = 0; if (*ioMarginWidth == 0) { *ioMarginWidth = 8; *ioMarginHeight = 8; } Assert_(mContext != NULL); if (IsRootHTMLView()) SetScrollMode(mDefaultScrollMode); // Clear the previous page ScrollImageTo(0, 0, false); if (mEraseBackground) ClearView(); Rect theFrame; CalcLocalFrameRect(theFrame); *ioWidth = theFrame.right; *ioHeight = theFrame.bottom; // Resize the images from the _current_ document size to the _preferred_ size. // Resize directly, because SetDocDimension does not decrease the size for main view ResizeImageTo(*ioWidth, *ioHeight, false); // 97-06-18 pkc -- Fix bug #70661. Don't do this margin altering code if frame width // and/or height is zero. if (theFrame.right - theFrame.left > 0) { if (*ioMarginWidth > (theFrame.right / 2 )) *ioMarginWidth = MAX( theFrame.right / 2 - 50, 0); } if (theFrame.bottom - theFrame.top > 0) { if (*ioMarginHeight > (theFrame.bottom / 2 )) *ioMarginHeight = MAX(theFrame.bottom / 2 -50, 0); } // If the vertical scrollbar might be shown, // tell layout that we already have it, so that it does // the correct wrapping of text. // If we do not do this, when vertical scrollbar only is // shown, some text might be hidden if (GetScrollMode() == LO_SCROLL_AUTO) *ioWidth -= 15; } // XXX CALLBACK void CHTMLView::ClearView( int /* inWhich */) { ClearBackground(); StopRepeating(); } void CHTMLView::InstallBackgroundColor(void) { // ₯ install the user's default solid background color & pattern mBackgroundColor = CPrefs::GetColor(CPrefs::TextBkgnd); } void CHTMLView::GetDefaultBackgroundColor(LO_Color* outColor) const { *outColor = UGraphics::MakeLOColor(mBackgroundColor); } void CHTMLView::SetWindowBackgroundColor() { // Danger! Port is not necessarily a window. // To fix, compare LWindow::FetchWindowObject result versus LWindow // found by going up view hierarchy. LWindow* portWindow = LWindow::FetchWindowObject(GetMacPort()); LWindow* ourWindow = NULL; LView* view = this; while( view != NULL ) { view = view->GetSuperView(); if (view) { ourWindow = dynamic_cast(view); if (ourWindow) break; } } if (portWindow == ourWindow) UGraphics::SetWindowColor(GetMacPort(), wContentColor, mBackgroundColor); } void CHTMLView::ClearBackground(void) { if (!FocusDraw()) return; // ₯ dispose of the current background mBackgroundImage = NULL; // ₯ install the user's default solid background color & pattern InstallBackgroundColor(); // Danger! Port is not necessarily a window. // if (LWindow::FetchWindowObject(GetMacPort())) // UGraphics::SetWindowColor(GetMacPort(), wContentColor, mBackgroundColor); SetWindowBackgroundColor(); ::RGBBackColor(&mBackgroundColor); // erase the widget to the user's default background Rect theFrame; if (CalcLocalFrameRect(theFrame)) DrawBackground(theFrame, nil); } void CHTMLView::DrawBackground( const Rect& inArea, LO_ImageStruct* inBackdrop) { if (!FocusDraw()) return; // We're using this to denote that we _do_ have an outline Rect theFrame; //, theEraseArea; CalcLocalFrameRect(theFrame); ::SectRect(&theFrame, &inArea, &theFrame); // // Get our default clip from the port so that we use the correct clip // from layers // StRegion theUpdateMask; ::GetClip(theUpdateMask); // // Never erase the plug-in area -- the plug-ins // will take care of that for us, and we donΥt // want to cause flicker with redundant drawing. // StRegion thePluginMask; ::SetEmptyRgn(thePluginMask); CalcPluginMask(thePluginMask); if (!::EmptyRgn(thePluginMask)) { Point theLocalOffset = { 0, 0 }; PortToLocalPoint(theLocalOffset); ::OffsetRgn(thePluginMask, theLocalOffset.h, theLocalOffset.v); ::DiffRgn(theUpdateMask, thePluginMask, theUpdateMask); } StClipRgnState theClipState(theUpdateMask); DrawBackgroundSelf(theFrame, inBackdrop); } void CHTMLView::DrawBackgroundSelf( const Rect& inArea, LO_ImageStruct* inBackdrop) { LO_ImageStruct *backdrop; if (inBackdrop) backdrop = inBackdrop; else if (mBackgroundImage) backdrop = mBackgroundImage; else backdrop = NULL; // ₯ if we can't draw the image then fall back on the pattern/solid if ( backdrop ) { } else ::EraseRect(&inArea); } void CHTMLView::EraseBackground( int /* inLocation */, Int32 inX, Int32 inY, Uint32 inWidth, Uint32 inHeight, LO_Color* inColor) { if (!FocusDraw()) return; // Convert draw rect from image coordinate system to local SPoint32 imageTopLeft; imageTopLeft.h = inX; imageTopLeft.v = inY; SPoint32 imageBottomRight; imageBottomRight.h = inX + inWidth; imageBottomRight.v = inY + inHeight; Rect theLocalEraseArea; ImageToLocalPoint(imageTopLeft, topLeft(theLocalEraseArea)); ImageToLocalPoint(imageBottomRight, botRight(theLocalEraseArea)); if (inColor != NULL) { // Make sure we don't erase the scrollbars. // NOTE: don't call StClipRgnState() here: // it messes up with the text selection. Rect frame; CalcLocalFrameRect(frame); // StClipRgnState tempClip(frame); if (theLocalEraseArea.right > frame.right) theLocalEraseArea.right = frame.right; if (theLocalEraseArea.bottom > frame.bottom) theLocalEraseArea.bottom = frame.bottom; RGBColor theBackColor = UGraphics::MakeRGBColor(inColor->red, inColor->green, inColor->blue); ::RGBBackColor(&theBackColor); ::EraseRect(&theLocalEraseArea); } else DrawBackground(theLocalEraseArea); } int CHTMLView::SetColormap( IL_IRGB* /* inMap */, int /* inRequested */) { return 0; } void CHTMLView::SetBackgroundColor( Uint8 inRed, Uint8 inGreen, Uint8 inBlue) { RGBColor theBackground = UGraphics::MakeRGBColor(inRed, inGreen, inBlue); GrafPtr thePort = GetMacPort(); if (thePort != NULL && mContext != NULL && IsRootHTMLView() && LWindow::FetchWindowObject(GetMacPort())) { UGraphics::SetWindowColor(thePort, wContentColor, theBackground); } if (!UGraphics::EqualColor(mBackgroundColor, theBackground)) { mBackgroundColor = theBackground; Refresh(); } /* now, call the image code to setup this new background color in the color map */ SetImageContextBackgroundColor ( *GetContext(), inRed, inGreen, inBlue ); } void CHTMLView::SetBackgroundImage( LO_ImageStruct* inImageStruct, Boolean inRefresh) { mBackgroundImage = inImageStruct; if (inRefresh) { Rect theFrame; CalcLocalFrameRect(theFrame); DrawBackground(theFrame); } } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ CalcPluginMask // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // // The following code calculates the union of all exposed plugin areas. The // result is added to ioPluginRgn. It is assumed that ioPluginRgn is a // valid region (already constructed with NewRgn()). The region is port // relative. // // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // REGION IS BASED ON PORT COORDINATES void CHTMLView::CalcPluginMask(RgnHandle ioPluginRgn) { Assert_(ioPluginRgn != NULL); if (mSubPanes.GetCount() == 0) // Any subpanes? return; LArrayIterator iter(mSubPanes); LPane* pane = NULL; while (iter.Next(&pane )) // Check each subpane { if ((pane->GetPaneID() == CPluginView::class_ID) || (pane->GetPaneID() == 'java')) // Is it a plug-in or a java pane? { CPluginView* plugin = (CPluginView*)pane; if (plugin->IsPositioned() && // Position is valid? NPL_IsEmbedWindowed(plugin->GetNPEmbeddedApp())) { Rect theRevealedFrame; plugin->GetRevealedRect(theRevealedFrame); if (!EmptyRect(&theRevealedFrame)) // Plug-in visible in page? { StRegion thePluginFrameRgn(theRevealedFrame); ::UnionRgn(ioPluginRgn, thePluginFrameRgn, ioPluginRgn); } } } } } Boolean CHTMLView::IsGrowCachingEnabled() const /* ...only derived classes with special needs would need better control than this. See |CEditView|. */ { return true; } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ SetDocDimension // // This evidently gets called a bazillion times from within layout. We need // to cache the calls so that the image is not resized all the time. // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // XXX CALLBACK void CHTMLView::SetDocDimension( int /* inLocation */, Int32 inWidth, Int32 inHeight) { SDimension32 oldImageSize; GetImageSize(oldImageSize); SDimension32 newImageSize; newImageSize.width = inWidth; newImageSize.height = inHeight; // If we can cache `grows' to enhance performance... if ( IsGrowCachingEnabled() ) { // ...then we only need to grow if we ran out of space... if ( (oldImageSize.width < inWidth) || (oldImageSize.height < inHeight) ) { SDimension16 curFrameSize; GetFrameSize(curFrameSize); // Warning: in some funky Java cases, |curFrameSize| can be 0,0. // Start doubling from which ever is greater, the frame height or the old image height. newImageSize.height = ((curFrameSize.height >= oldImageSize.height) ? curFrameSize.height : oldImageSize.height); // Ensure that doubling the height will terminate the doubling-loop. if ( newImageSize.height < 1 ) newImageSize.height = 1; // Now, double the current height until it's greater than the requested height do newImageSize.height += newImageSize.height; while ( newImageSize.height < inHeight ); // That ought to hold 'em for a while... } else // ...else, we'll grow later, what we have now is good enough. newImageSize = oldImageSize; } // Resize the image, if we need to... if ( (newImageSize.height != oldImageSize.height) || (newImageSize.width != oldImageSize.width) ) ResizeImageTo(newImageSize.width, newImageSize.height, true); // If we didn't exactly satisfy the request, then we'll have to later... if ( (mPendingDocDimension_IsValid = ((newImageSize.height != inHeight) || (newImageSize.width != inWidth))) == true ) { mPendingDocDimension.width = inWidth; mPendingDocDimension.height = inHeight; } } void CHTMLView::FlushPendingDocResize(void) { if ( mPendingDocDimension_IsValid ) { mPendingDocDimension_IsValid = false; SDimension32 imageSize; GetImageSize(imageSize); if ( (imageSize.width != mPendingDocDimension.width) || (imageSize.height != mPendingDocDimension.height) ) ResizeImageTo(mPendingDocDimension.width, mPendingDocDimension.height, true); } } // XXX CALLBACK // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ SetDocPosition // // Scrolls the image to (inX, inY), limited to the image size minus the frame size. The x position is // left unchanged if it is already visible. // // inLocation: ignored // inX, inY: new position. Negative values will be converted to zero. // inScrollEvenIfVisible: if true, will cause the html view to scroll even if the x position is already // visible (defaults to false, which is the historical behavior). // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ void CHTMLView::SetDocPosition( int /* inLocation */, Int32 inX, Int32 inY, Boolean inScrollEvenIfVisible) { // // If we're displaying a full-page plug-in, ignore the // request to position the document. When displaying // a full-page plug-in, we don't show scroll bars and // all positioning is handled by the plug-in itself. // if (mContext->HasFullPagePlugin()) return; // Make sure our size is not our of sync, flush any pending resize FlushPendingDocResize(); //Κ₯Κlocation is the variable affecting which view are we in // Make sure that the view is big enough so that we do not get // auto-cropped with PPlant when we auto-scroll SDimension16 theFrameSize; GetFrameSize(theFrameSize); SPoint32 theFrameLocation; GetFrameLocation(theFrameLocation); SDimension32 theImageSize; GetImageSize(theImageSize); SPoint32 theImageLocation; GetImageLocation(theImageLocation); theImageLocation.h -= theFrameLocation.h; theImageLocation.v -= theFrameLocation.v; // ₯ΚCalculate proper position. Int32 scrollToX = inX; Int32 scrollToY = inY; if ((scrollToY + theFrameSize.height) > theImageSize.height) { scrollToY = theImageSize.height - theFrameSize.height; } // rebracket this test so it's done all the time (not only when we exceed image height) - mjc 97-9-12 // Sometimes the image height is 0 and scrollToY goes negative. It // seems stupid that image height should ever be 0 - oh well. if (scrollToY < 0) { scrollToY = 0; } // If x is visible, do not change it. if (!inScrollEvenIfVisible && (inX >= theImageLocation.h) && (inX + 10 <= (theImageLocation.h + theFrameSize.width ))) { scrollToX = theImageLocation.h; } // limit the x position as we do with the y position - mjc 97-9-12 scrollToX = MIN(scrollToX, theImageSize.width - theFrameSize.width); if (scrollToX < 0) scrollToX = 0; ScrollImageTo(scrollToX, scrollToY, true); } // XXX CALLBACK void CHTMLView::GetDocPosition( int /* inLocation */, Int32* outX, Int32* outY) { // Make sure our size is not our of sync, flush any pending resize FlushPendingDocResize(); SPoint32 theScrollPosition; GetScrollPosition(theScrollPosition); *outX = theScrollPosition.h; *outY = theScrollPosition.v; } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ int CHTMLView::GetTextInfo( LO_TextStruct* inText, LO_TextInfo* outTextInfo) { Assert_(inText != NULL); Assert_(outTextInfo != NULL); Assert_(mContext != NULL); LO_TextAttr* theTextAttr = inText->text_attr; Assert_(theTextAttr != NULL); if (theTextAttr == NULL) return 1; // FIX ME!!! need to optimize the getting of the port (cache it) // No, don't. This is open to error, and the amount of time saved is minimal. GrafPtr theSavePort = NULL; if (GetCachedPort() != qd.thePort) { theSavePort = qd.thePort; ::SetPort(GetCachedPort()); } { HyperStyle theStyle(*mContext, &mCharSet, theTextAttr, true); theStyle.Apply(); theStyle.GetFontInfo(); outTextInfo->ascent = theStyle.fFontInfo.ascent; outTextInfo->descent = theStyle.fFontInfo.descent; outTextInfo->lbearing = 0; char* theText; PA_LOCK(theText, char*, inText->text); // ₯Κmeasure the text Int16 theWidth = theStyle.TextWidth(theText, 0, inText->text_len); // **** Don't know which of these is better; the first only works for native single byte scritps // The second will always work, but produces different results... // Probably need to Add a function to HyperStyle to handle this... /* if (theTextAttr->fontmask & LO_FONT_ITALIC ) outTextInfo->rbearing = theWidth + (::CharWidth(theText[inText->text_len - 1]) / 2); else outTextInfo->rbearing = 0; */ if (theTextAttr->fontmask & LO_FONT_ITALIC ) outTextInfo->rbearing = theWidth + (theStyle.fFontInfo.widMax / 2); else outTextInfo->rbearing = 0; PA_UNLOCK(inText->text); outTextInfo->max_width = theWidth; } //so that theStyle goes out of scope and resets the text traits in the correct port if (theSavePort != NULL) ::SetPort(theSavePort); return 1; } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ MeasureText // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ int CHTMLView::MeasureText( LO_TextStruct* inText, short* outCharLocs) { Assert_(inText != NULL); Assert_(outCharLocs != NULL); Assert_(mContext != NULL); LO_TextAttr* theTextAttr = inText->text_attr; Assert_(theTextAttr != NULL); if (theTextAttr == NULL) return 0; // FIX ME!!! need to optimize the getting of the port (cache it) GrafPtr theSavePort = NULL; if (GetCachedPort() != qd.thePort) { theSavePort = qd.thePort; ::SetPort(GetCachedPort()); } Int16 measuredBytes = 0; { HyperStyle theStyle(*mContext, &mCharSet, theTextAttr, true); theStyle.Apply(); // FIX ME!!! we only work with Native font references for now CNativeFontReference* nativeFontReference = dynamic_cast(theStyle.fFontReference); if (nativeFontReference != NULL) { // measure the text measuredBytes = nativeFontReference->MeasureText( (char*)inText->text, 0, inText->text_len, outCharLocs); } } //so that theStyle goes out of scope and resets the text traits in the correct port if (theSavePort != NULL) ::SetPort(theSavePort); return measuredBytes; } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ void CHTMLView::GetTextFrame( LO_TextStruct* inTextStruct, Int32 inStartPos, Int32 inEndPos, XP_Rect* outFrame) { Assert_(inTextStruct != NULL); Assert_(outFrame != NULL); GrafPtr theSavePort = NULL; if (GetCachedPort() != qd.thePort) { theSavePort = qd.thePort; ::SetPort(GetCachedPort()); } { LO_TextAttr* theTextAttr = inTextStruct->text_attr; HyperStyle theStyle(*mContext, &mCharSet, theTextAttr, true, inTextStruct); Point theLocalTopLeft = { 0, 0 }; char* theText; PA_LOCK(theText, char*, inTextStruct->text); Rect theLocalFrame = theStyle.InvalBackground(theLocalTopLeft, theText, inStartPos, inEndPos, false); PA_UNLOCK(inTextStruct->text); // Convert to layer coordinates outFrame->left = theLocalFrame.left + inTextStruct->x + inTextStruct->x_offset; outFrame->top = theLocalFrame.top + inTextStruct->y + inTextStruct->y_offset; outFrame->right = theLocalFrame.right + inTextStruct->x + inTextStruct->x_offset; outFrame->bottom = theLocalFrame.bottom + inTextStruct->y + inTextStruct->y_offset; } //so that theStyle goes out of scope and resets the text traits in the correct port if (theSavePort != NULL) ::SetPort(theSavePort); } void CHTMLView::DisplaySubtext( int /* inLocation */, LO_TextStruct* inText, Int32 inStartPos, Int32 inEndPos, XP_Bool inNeedBG) { // ₯ if we can't focus, don't do anything if (!FocusDraw()) return; // ₯Κif we're not visible, don't do anything Rect theTextFrame; if (!CalcElementPosition((LO_Element*)inText, theTextFrame)) return; LO_TextAttr* theTextAttr = inText->text_attr; // FIX ME!!! this needs to do the right thing in the editor // Boolean bBlinks = (attr->attrmask & LO_ATTR_BLINK) && (!EDT_IS_EDITOR(*mContext)); // no blinking in the editor because of problems with moving text which is blinking HyperStyle style(*mContext, &mCharSet, theTextAttr, false, inText); char *theTextPtr; PA_LOCK(theTextPtr, char*, inText->text); if (inNeedBG) // ₯Κerase the background { Rect theInvalRect = style.InvalBackground( topLeft(theTextFrame), theTextPtr, inStartPos, inEndPos, false); if ( theTextAttr->no_background ) { StClipRgnState theClipSaver; theClipSaver.ClipToIntersection(theInvalRect); DrawBackground(theInvalRect); } else { ::PenPat(&qd.black ); UGraphics::SetIfColor( UGraphics::MakeRGBColor(theTextAttr->bg.red, theTextAttr->bg.green, theTextAttr->bg.blue)); ::FillRect(&theInvalRect, &qd.black); } } style.DrawText(topLeft(theTextFrame), theTextPtr, inStartPos, inEndPos); PA_UNLOCK(inText->text); } void CHTMLView::DisplayText( int inLocation, LO_TextStruct* inText, XP_Bool inNeedBG) { DisplaySubtext(inLocation, inText, 0, inText->text_len - 1, inNeedBG); } void CHTMLView::DisplayLineFeed( int /* inLocation */, LO_LinefeedStruct* /* inLinefeedStruct */, XP_Bool /* inNeedBG */) { #ifdef LAYERS #else Rect frame; Boolean doDraw; // BUGBUG LAYERS: Linefeed drawing causes problems with layers (the problem // is not in FE code - the selection code needs to do the same special casing // it did for text in the case of line feeds and hrules). The temporary fix is // to not draw linefeeds. if ( !FocusDraw() ) return; if ( needBg ) { doDraw = CalcElementPosition( (LO_Element*)lineFeed, frame ); if ( !doDraw ) return; // ₯Κfill the background in the color given by layout if ( lineFeed->text_attr->no_background == FALSE ) { UGraphics::SetIfColor( UGraphics::MakeRGBColor( lineFeed->text_attr->bg.red, lineFeed->text_attr->bg.green, lineFeed->text_attr->bg.blue ) ); ::FillRect( &frame, &qd.black ); } else this->DrawBackground( frame ); } Boolean selected = lineFeed->ele_attrmask & LO_ELE_SELECTED; if ( selected ) { if ( CalcElementPosition( (LO_Element*)lineFeed, frame ) ) { RGBColor color; LMGetHiliteRGB( &color ); ::RGBBackColor( &color ); ::EraseRect( &frame ); } } #endif } void CHTMLView::DisplayHR( int /* inLocation */, LO_HorizRuleStruct* inRuleStruct) { if (!FocusDraw()) return; Rect theFrame; if (!CalcElementPosition( (LO_Element*)inRuleStruct, theFrame)) return; // FIX ME!!! remove lame drawing if (((inRuleStruct->ele_attrmask & LO_ELE_SHADED)== 0) || ( theFrame.top + 1 >= theFrame.bottom ) ) // No shading, or 1 pixel rect { UGraphics::SetFore(CPrefs::Black); FillRect(&theFrame, &UQDGlobals::GetQDGlobals()->black); } else UGraphics::FrameRectShaded(theFrame, TRUE); } void CHTMLView::DisplayBullet( int /* inLocation */, LO_BullettStruct* inBulletStruct) { if (!FocusDraw()) return; Rect theFrame; if (!CalcElementPosition((LO_Element*)inBulletStruct, theFrame)) return; if (inBulletStruct->text_attr) UGraphics::SetIfColor( UGraphics::MakeRGBColor( inBulletStruct->text_attr->fg.red, inBulletStruct->text_attr->fg.green, inBulletStruct->text_attr->fg.blue )); else UGraphics::SetFore(CPrefs::Black); switch ( inBulletStruct->bullet_type ) { case BULLET_ROUND: ::PenPat(&qd.black); ::FrameOval(&theFrame); break; case BULLET_SQUARE: ::PenPat(&qd.black); ::FrameRect(&theFrame); break; case BULLET_BASIC: ::FillOval(&theFrame, &UQDGlobals::GetQDGlobals()->black); break; case BULLET_MQUOTE: ::PenPat(&qd.black); ::MoveTo(theFrame.left, theFrame.top); ::LineTo(theFrame.left, theFrame.bottom); break; default: // Should not happen ::MoveTo(theFrame.left, theFrame.bottom); ::DrawChar('?'); break; } } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ void CHTMLView::GetEmbedSize( LO_EmbedStruct* inEmbedStruct, NET_ReloadMethod /* inReloadMethod */) { if (inEmbedStruct->FE_Data == NULL) // Creating plugin from scratch { Try_ { NPEmbeddedApp* app = NPL_EmbedCreate(*mContext, inEmbedStruct); ThrowIfNil_(app); // XXX This is so bogus. Figure out how to pull the junk in // EmbedCreate() up here or at least rework it so it's cleaner. CPluginView* newPlugin = (CPluginView*) app->fe_data; newPlugin->EmbedCreate(*mContext, inEmbedStruct); } Catch_(inErr) { inEmbedStruct->FE_Data = NULL; } EndCatch_ } else NPL_EmbedSize((NPEmbeddedApp*) inEmbedStruct->FE_Data); } void CHTMLView::FreeEmbedElement( LO_EmbedStruct* inEmbedStruct) { NPL_EmbedDelete(*mContext, inEmbedStruct); inEmbedStruct->FE_Data = NULL; } void CHTMLView::CreateEmbedWindow( NPEmbeddedApp* inEmbeddedApp) { // Ensure that we have a layout struct so that we can size // the plugin properly. ThrowIfNil_(inEmbeddedApp->np_data); LO_EmbedStruct* embed_struct = ((np_data*) inEmbeddedApp->np_data)->lo_struct; ThrowIfNil_(embed_struct); LCommander::SetDefaultCommander(LWindow::FetchWindowObject(GetMacPort())); LPane::SetDefaultView(NULL); CPluginView* newPlugin = NULL; newPlugin = (CPluginView*) UReanimator::ReadObjects('PPob', 4010); ThrowIfNil_(newPlugin); newPlugin->FinishCreate(); newPlugin->PutInside(this); newPlugin->SetSuperCommander(this); SDimension16 hyperSize; this->GetFrameSize(hyperSize); // Get the size of the hyperView newPlugin->EmbedSize(embed_struct, hyperSize); // XXX Don't we need to create the NPWindow struct here, too? // Ugh. Actually that's done in CPluginView::EmbedCreate(), which we // call after NPL_EmbedCreate(). That probably needs some massaging... inEmbeddedApp->fe_data = (void*) newPlugin; } void CHTMLView::SaveEmbedWindow( NPEmbeddedApp* inEmbeddedApp) { ThrowIfNil_(inEmbeddedApp); CPluginView *view = (CPluginView*) inEmbeddedApp->fe_data; ThrowIfNil_(view); // Make sure that we are not targeting the plugin view // // XXX Note that this will be overly aggressive in removing the // focus. Probably what we really want to do is check to see if // some sub-pane of the view has focus, and if so, reset it to // a well-known safe place. LCommander::SwitchTarget(NULL); // Un-intsall the plugin view, hide it, and re-target // it to the owning window. view->Hide(); // PCB: clear the plugin's knowledge that it has been positioned, so it will be layed out correctly. view->SetPositioned(false); LView *previousParentView = NULL; LView *currentParentView = view->GetSuperView(); while (currentParentView != NULL) { previousParentView = currentParentView; currentParentView = currentParentView->GetSuperView(); } view->PutInside((LWindow *)previousParentView); view->SetSuperCommander((LWindow *)previousParentView); // XXX This should probably move to the Stop() method of the JVM plugin. //FlushEventHierarchy(view); } void CHTMLView::RestoreEmbedWindow( NPEmbeddedApp* inEmbeddedApp) { CPluginView* view = (CPluginView*) inEmbeddedApp->fe_data; LView* parentView = view->GetSuperView(); // If we are parented inside the outermost window, then // reparent us to the hyperview. if (parentView->GetSuperView() == NULL) { view->PutInside(this); view->SetSuperCommander(this); int32 xp = 0; int32 yp = 0; if (XP_OK_ASSERT(inEmbeddedApp->np_data)) { LO_EmbedStruct* embed_struct = ((np_data*) inEmbeddedApp->np_data)->lo_struct; if (XP_OK_ASSERT(embed_struct)) { xp = embed_struct->x + embed_struct->x_offset /* - CONTEXT_DATA(*mContext)->document_x */; yp = embed_struct->y + embed_struct->y_offset /* - CONTEXT_DATA(*mContext)->document_y */; } } view->PlaceInSuperImageAt(xp, yp, TRUE); } LCommander::SetDefaultCommander(LWindow::FetchWindowObject(GetMacPort())); LPane::SetDefaultView(NULL); } void CHTMLView::DestroyEmbedWindow( NPEmbeddedApp* inEmbeddedApp) { if (inEmbeddedApp && inEmbeddedApp->fe_data) { // XXX Why does EmbedFree need the LO_EmbedStruct? ThrowIfNil_(inEmbeddedApp->np_data); LO_EmbedStruct* embed_struct = ((np_data*) inEmbeddedApp->np_data)->lo_struct; // XXX The following check crashes (why?) when embed_struct is NULL, which it always is. // ThrowIfNil_(embed_struct); CPluginView* view = (CPluginView*) inEmbeddedApp->fe_data; view->EmbedFree(*mContext, embed_struct); delete view; inEmbeddedApp->fe_data = NULL; } } void CHTMLView::DisplayEmbed( int /* inLocation */, LO_EmbedStruct* inEmbedStruct) { NPEmbeddedApp* app = (NPEmbeddedApp*) inEmbedStruct->FE_Data; if (app && app->fe_data) { if ( !FocusDraw() ) return; CPluginView* view = (CPluginView*) app->fe_data; view->EmbedDisplay(inEmbedStruct, false); } } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ void CHTMLView::GetJavaAppSize( LO_JavaAppStruct* inJavaAppStruct, NET_ReloadMethod inReloadMethod) { LJ_GetJavaAppSize(*mContext, inJavaAppStruct, inReloadMethod); } static void PR_CALLBACK FE_SaveJavaWindow(MWContext * /* context */, LJAppletData* /* ad */, void* window) { #if defined (JAVA) CJavaView* javaAppletView = (CJavaView *)window; // Make sure that we are not targeting this // java applet. LCommander::SwitchTarget(GetContainerWindow(javaAppletView)); // Un-intsall the java view, hide it, and re-target // it to the owning window. javaAppletView->Hide(); LView *currentParentView, *previousParentView = NULL; currentParentView = javaAppletView->GetSuperView(); while (currentParentView != NULL) { previousParentView = currentParentView; currentParentView = currentParentView->GetSuperView(); } javaAppletView->PutInside((LWindow *)previousParentView); javaAppletView->SetSuperCommander((LWindow *)previousParentView); FlushEventHierarchy(javaAppletView); #endif /* defined (JAVA) */ } void CHTMLView::HideJavaAppElement( LJAppletData* inAppletData) { LJ_HideJavaAppElement(*mContext, inAppletData, FE_SaveJavaWindow); } static void PR_CALLBACK FE_DisplayNoJavaIcon(MWContext *, LO_JavaAppStruct *) { /* write me */ } static void* PR_CALLBACK FE_CreateJavaWindow(MWContext *context, LO_JavaAppStruct * /* inJavaAppStruct */, int32 xp, int32 yp, int32 xs, int32 ys) { #if defined (JAVA) CNSContext* theNSContext = ExtractNSContext(context); Assert_(theNSContext != NULL); CHTMLView* theCurrentView = ExtractHyperView(*theNSContext); Assert_(theCurrentView != NULL); CJavaView *newJavaView = NULL; Try_ { LCommander::SetDefaultCommander(LWindow::FetchWindowObject(theCurrentView->GetMacPort())); LPane::SetDefaultView(NULL); newJavaView = (CJavaView *)UReanimator::ReadObjects('PPob', 2090); newJavaView->FinishCreate(); newJavaView->PutInside(theCurrentView); newJavaView->SetSuperCommander(theCurrentView); newJavaView->PlaceInSuperImageAt(xp, yp, TRUE); newJavaView->SetPositioned(); /* // If the plugin size is 1x1, this really means that the plugin is // full-screen, and that we should set up the pluginΥs real width // for XP since it doesnΥt know how big to make it. Since a full- // screen plugin should resize when its enclosing view (the hyperview) // resizes, we bind the plugin view on all sides to its superview. // -bing 11/16/95 // if (inJavaAppStruct->width == 1 && inJavaAppStruct->height == 1) { SBooleanRect binding = {true, true, true, true}; newJavaView->SetFrameBinding(binding); SDimension16 hyperSize; this->GetFrameSize(hyperSize); // Get the size of the hyperView inJavaAppStruct->width = hyperSize.width - 1; inJavaAppStruct->height = hyperSize.height - 1; const short kLeftMargin = 8; // ₯₯₯ These should be defined in mhyper.h!!! const short kTopMargin = 8; inJavaAppStruct->x -= kLeftMargin; // Allow the plugin to use ALL the screen space inJavaAppStruct->y -= kTopMargin; } */ } Catch_(inErr) { } EndCatch_ // Resize the image if (newJavaView != NULL) { newJavaView->ResizeImageTo(xs, ys, FALSE); newJavaView->ResizeFrameTo(xs, ys, FALSE); } return (void*)newJavaView; #else return (void*)NULL; #endif /* defined (JAVA) */ } static void* PR_CALLBACK FE_GetAwtWindow(MWContext * /* context */, LJAppletData* ad) { #if defined (JAVA) CJavaView* newJavaView = (CJavaView *)ad->window; return (void*)newJavaView->GetUserCon(); #else return (void*)NULL; #endif /* defined (JAVA) */ } static void PR_CALLBACK FE_RestoreJavaWindow(MWContext *context, LJAppletData* ad, int32 xp, int32 yp, int32 /* xs */, int32 /* ys */) { #if defined (JAVA) CNSContext* theNSContext = ExtractNSContext(context); Assert_(theNSContext != NULL); CHTMLView* theCurrentView = ExtractHyperView(*theNSContext); Assert_(theCurrentView != NULL); CJavaView* newJavaView = (CJavaView *)ad->window; LView *parentView = newJavaView->GetSuperView(); // If we are parented inside the outermost window, then // reparent us to the hyperview. if (parentView->GetSuperView() == NULL) { newJavaView->PutInside(theCurrentView); newJavaView->SetSuperCommander(theCurrentView); newJavaView->PlaceInSuperImageAt(xp, yp, TRUE); } LCommander::SetDefaultCommander(LWindow::FetchWindowObject(theCurrentView->GetMacPort())); LPane::SetDefaultView(NULL); #endif /* defined (JAVA) */ } static void PR_CALLBACK FE_SetJavaWindowPos(MWContext * /* context */, void* window, int32 xp, int32 yp, int32 /* xs */, int32 /* ys */) { #if defined (JAVA) CJavaView* newJavaView = (CJavaView *)window; newJavaView->PlaceInSuperImageAt(xp, yp, TRUE); #endif /* defined (JAVA) */ } static void PR_CALLBACK FE_SetJavaWindowVisibility(MWContext *context, void* window, PRBool visible) { #if defined (JAVA) CNSContext* theNSContext = ExtractNSContext(context); Assert_(theNSContext != NULL); CHTMLView* theCurrentView = ExtractHyperView(*theNSContext); Assert_(theCurrentView != NULL); CJavaView* newJavaView = (CJavaView *)window; Boolean isComponentVisible = TRUE; Hsun_awt_macos_MComponentPeer *componentPeer = PaneToPeer(newJavaView); if (componentPeer != NULL) { if (unhand(unhand(componentPeer)->target)->visible) isComponentVisible = TRUE; else isComponentVisible = FALSE; } if (newJavaView != NULL) { // This call could mean that either the visibility or the position of the // applet has changed, so we make the appropriate changes to the view. if ((newJavaView->IsVisible() && !visible) || (isComponentVisible == FALSE)) newJavaView->Hide(); if ((!newJavaView->IsVisible() && visible) && isComponentVisible) newJavaView->Show(); } #endif /* defined (JAVA) */ } void CHTMLView::DisplayJavaApp( int /* inLocation */, LO_JavaAppStruct* inJavaAppStruct) { LJ_DisplayJavaApp(*mContext, inJavaAppStruct, FE_DisplayNoJavaIcon, FE_GetFullWindowSize, FE_CreateJavaWindow, FE_GetAwtWindow, FE_RestoreJavaWindow, FE_SetJavaWindowPos, FE_SetJavaWindowVisibility); } static void PR_CALLBACK FE_FreeJavaWindow(MWContext * /* context */, struct LJAppletData * /* appletData */, void* window) { #if defined (JAVA) CJavaView* javaAppletView = (CJavaView *)window; delete javaAppletView; #endif /* defined (JAVA) */ } void CHTMLView::FreeJavaAppElement( LJAppletData* inAppletData) { LJ_FreeJavaAppElement(*mContext, inAppletData, FE_SaveJavaWindow, FE_FreeJavaWindow); } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ void CHTMLView::DrawJavaApp( int /*inLocation*/, LO_JavaAppStruct* ) { } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ void CHTMLView::HandleClippingView( struct LJAppletData* , int /*x*/, int /*y*/, int /*width*/, int /*height*/) { } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ void CHTMLView::GetFormElementInfo( LO_FormElementStruct* inElement) { UFormElementFactory::MakeFormElem(this, mContext, inElement); } void CHTMLView::ResetFormElementData( LO_FormElementStruct* inElement, Boolean inRefresh, Boolean inFromDefaults) { UFormElementFactory::ResetFormElementData(inElement, inRefresh, inFromDefaults, true); } void CHTMLView::DisplayFormElement( int /* inLocation */, LO_FormElementStruct* inFormElement) { CDrawable *currentDrawable = mCurrentDrawable; // When we're drawing form elements, we force our current drawable to be onscreen SetCurrentDrawable(nil); UFormElementFactory::DisplayFormElement(mContext, inFormElement); SetCurrentDrawable(currentDrawable); } void CHTMLView::DisplayBorder( int /* inLocation */, int inX, int inY, int inWidth, int inHeight, int inBW, LO_Color* inColor, LO_LineStyle inStyle) { if (!FocusDraw() || (inBW == 0)) return; SPoint32 topLeftImage; Point topLeft; int32 layerOriginX, layerOriginY; Rect borderRect; RGBColor borderColor; if ( mCurrentDrawable != NULL ) { mCurrentDrawable->GetLayerOrigin(&layerOriginX, &layerOriginY); } else { layerOriginX = mLayerOrigin.h; layerOriginY = mLayerOrigin.v; } topLeftImage.h = inX + layerOriginX; topLeftImage.v = inY + layerOriginY; ImageToLocalPoint(topLeftImage, topLeft); borderRect.left = topLeft.h; borderRect.top = topLeft.v; borderRect.right = borderRect.left + inWidth; borderRect.bottom = borderRect.top + inHeight; borderColor = UGraphics::MakeRGBColor(inColor->red, inColor->green, inColor->blue); RGBForeColor(&borderColor); ::PenSize(inBW, inBW); switch (inStyle) { case LO_SOLID: ::FrameRect(&borderRect); break; case LO_BEVEL: ::UGraphics::FrameRectShaded(borderRect, FALSE); break; default: break; } ::PenSize(1, 1); } void CHTMLView::UpdateEnableStates() { // this is a Composer function so that the state of buttons can change(enabled/disabled) } void CHTMLView::DisplayFeedback( int /*inLocation*/, LO_Element* ) { // this is a Composer function for showing selection of Images } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ void CHTMLView::FreeEdgeElement( LO_EdgeStruct* inEdgeStruct) { if (FocusDraw()) { Rect theEdgeFrame; if (CalcElementPosition((LO_Element*)inEdgeStruct, theEdgeFrame)) { ::InsetRect(&theEdgeFrame, -1, -1); ::InvalRect(&theEdgeFrame); } } // 97-06-11 pkc -- delete inEdgeStruct from edge list // NOTE: This line assumes that inEdgeStruct is in the list. vector::iterator found = find(mGridEdgeList.begin(), mGridEdgeList.end(), inEdgeStruct); if (found != mGridEdgeList.end()) mGridEdgeList.erase(found); } void CHTMLView::DisplayEdge( int /* inLocation */, LO_EdgeStruct* inEdgeStruct) { if ( !FocusDraw() ) return; // 97-06-21 pkc -- In some instances, like when the Security Advisor brings the Page Info // window to the front, FocusDraw won't call SetPort on the window port for some reason. // Use an StPortOriginState to make sure the port is set correctly. StPortOriginState theOriginSaver((GrafPtr)GetMacPort()); if (IsRootHTMLView()) mShowFocus = FALSE; // 97-06-11 pkc -- If we're not redrawing a grid edge via DrawSelf, and we're also not // drawing because the user dragged an edge, then add this LO_EdgeStruct* to list if (!mDontAddGridEdgeToList) { mGridEdgeList.push_back(inEdgeStruct); } Rect docFrame; Boolean isVisible; isVisible = CalcElementPosition( (LO_Element*)inEdgeStruct, docFrame ); int32 size; if ( !isVisible ) return; SBooleanRect thePartialBevels = { true, true, true, true }; if ( inEdgeStruct->is_vertical ) { size = inEdgeStruct->width; /* top - 2 ? Try anything else and look closely at the top of the frame edge, where it abutts the enclosing bevel view. -2 seems to be only benevolent; if you find otherwise, more tweaking may be necessary. I suspect the unexpected extra pixel correction has something to do with the unfortunate circumstance that the first time an edge is drawn, while the frame is being laid out, the port origin is often one pixel off (both vertically and horizontally) from its final position after layout is complete. */ docFrame.top -= 2; docFrame.bottom++; thePartialBevels.top = thePartialBevels.bottom = false; } else { size = inEdgeStruct->height; ::InsetRect( &docFrame, -1, 0 ); thePartialBevels.left = thePartialBevels.right = false; } StClipRgnState theClipSaver(docFrame); SBevelColorDesc theBevelColors; if ( inEdgeStruct->bg_color ) { UGraphics::SetIfColor( UGraphics::MakeRGBColor( inEdgeStruct->bg_color->red, inEdgeStruct->bg_color->green, inEdgeStruct->bg_color->blue ) ); ::FillRect( &docFrame, &qd.black ); } else { // Cinco de Mayo '97 pkc // Added code to draw using background pattern like our pattern bevel views if (!mPatternWorld) { mPatternWorld = CSharedPatternWorld::CreateSharedPatternWorld(10000); if (mPatternWorld) { mPatternWorld->AddUser(this); } } if (mPatternWorld) { Point theAlignment; CSharedPatternWorld::CalcRelativePoint(this, CSharedPatternWorld::eOrientation_Port, theAlignment); CGrafPtr thePort = (CGrafPtr)GetMacPort(); mPatternWorld->Fill(thePort, docFrame, theAlignment); } else { UGraphicGizmos::LoadBevelTraits(10000, theBevelColors); ::PmForeColor(theBevelColors.fillColor); ::PaintRect(&docFrame); } } if ( size > 2 ) { // shrink the beveled edges rect back to the original size specified if ( inEdgeStruct->is_vertical ) ::InsetRect( &docFrame, 0, 1 ); else ::InsetRect( &docFrame, 1, 0 ); if ( inEdgeStruct->bg_color ) { UGraphics::FrameRectShaded( docFrame, FALSE ); } else { // Cinco de Mayo '97 pkc // Use BevelTintPartialRect if we're drawing using a pattern if (mPatternWorld) { UGraphicGizmos::BevelTintPartialRect(docFrame, 1, 0x2000, 0x2000, thePartialBevels); } else { UGraphicGizmos::BevelPartialRect(docFrame, 1, theBevelColors.topBevelColor, theBevelColors.bottomBevelColor, thePartialBevels); } } if ( inEdgeStruct->movable ) { Rect theDotFrame = { 0, 0, 2, 2 }; UGraphicGizmos::CenterRectOnRect(theDotFrame, docFrame); UGraphics::FrameCircleShaded( theDotFrame, TRUE ); } } } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ void CHTMLView::DisplayTable( int /* inLocation */, LO_TableStruct* inTableStruct) { if (!FocusDraw() || ((inTableStruct->border_width == 0) && (inTableStruct->border_top_width == 0) && (inTableStruct->border_right_width == 0) && (inTableStruct->border_bottom_width == 0) && (inTableStruct->border_left_width == 0))) return; // Retain akbar (3.0) functionality -- we used to call UGraphics::FrameRectShaded // which set a light rgb pin color of { 60000, 60000, 60000 }. By default, // UGraphicGizmos has a light pin color of { 0xFFFF, 0xFFFF, 0xFFFF }. So as // not to diverge from akbar, set UGraphicGizmos::sLighter then restore its value RGBColor savedLighter = UGraphicGizmos::sLighter; UGraphicGizmos::sLighter.red = 0xFFFF; UGraphicGizmos::sLighter.green = 0xFFFF; UGraphicGizmos::sLighter.blue = 0xFFFF; // ₯Κelement->width + borderWidth, element->height + borderWidth); Rect theFrame; if (CalcElementPosition( (LO_Element*)inTableStruct, theFrame )) { RGBColor borderColor = UGraphics::MakeRGBColor((inTableStruct->border_color).red, (inTableStruct->border_color).green, (inTableStruct->border_color).blue); switch (inTableStruct->border_style) { case BORDER_NONE: break; case BORDER_DOTTED: case BORDER_DASHED: case BORDER_SOLID: DisplaySolidBorder(theFrame, borderColor, inTableStruct->border_top_width, inTableStruct->border_left_width, inTableStruct->border_bottom_width, inTableStruct->border_right_width); break; case BORDER_DOUBLE: { Int32 borderTopWidth = inTableStruct->border_top_width / 3; Int32 borderLeftWidth = inTableStruct->border_left_width / 3; Int32 borderBottomWidth = inTableStruct->border_bottom_width / 3; Int32 borderRightWidth = inTableStruct->border_right_width / 3; // draw outer border DisplaySolidBorder(theFrame, borderColor, borderTopWidth, borderLeftWidth, borderBottomWidth, borderRightWidth); // adjust frame theFrame.top += (inTableStruct->border_top_width - borderTopWidth); theFrame.left += (inTableStruct->border_left_width - borderLeftWidth); theFrame.bottom -= (inTableStruct->border_bottom_width - borderBottomWidth); theFrame.right -= (inTableStruct->border_right_width - borderRightWidth); // draw inner border DisplaySolidBorder(theFrame, borderColor, borderTopWidth, borderLeftWidth, borderBottomWidth, borderRightWidth); } break; case BORDER_GROOVE: // Groove border has sunken outer border with a raised inner border DisplayGrooveRidgeBorder(theFrame, borderColor, true, inTableStruct->border_top_width, inTableStruct->border_left_width, inTableStruct->border_bottom_width, inTableStruct->border_right_width); break; case BORDER_RIDGE: // Ridge border has raised outer border with a sunken inner border DisplayGrooveRidgeBorder(theFrame, borderColor, false, inTableStruct->border_top_width, inTableStruct->border_left_width, inTableStruct->border_bottom_width, inTableStruct->border_right_width); break; case BORDER_INSET: // sunken border DisplayBevelBorder(theFrame, borderColor, false, inTableStruct->border_top_width, inTableStruct->border_left_width, inTableStruct->border_bottom_width, inTableStruct->border_right_width); break; case BORDER_OUTSET: // raised border DisplayBevelBorder(theFrame, borderColor, true, inTableStruct->border_top_width, inTableStruct->border_left_width, inTableStruct->border_bottom_width, inTableStruct->border_right_width); break; default: Assert_(false); } // restore UGraphicGizmos::sLighter UGraphicGizmos::sLighter = savedLighter; } } void CHTMLView::DisplaySolidBorder( const Rect& inFrame, const RGBColor& inBorderColor, Int32 inTopWidth, Int32 inLeftWidth, Int32 inBottomWidth, Int32 inRightWidth) { StColorPenState state; state.Normalize(); ::RGBForeColor(&inBorderColor); // Check for easy case -- all border widths equal if (inTopWidth == inLeftWidth && inTopWidth == inBottomWidth && inTopWidth == inRightWidth) { ::PenSize(inTopWidth, inTopWidth); ::FrameRect(&inFrame); } else { // Otherwise manually draw each side if (inTopWidth > 0) { ::PenSize(1, inTopWidth); ::MoveTo(inFrame.left, inFrame.top); ::LineTo(inFrame.right, inFrame.top); } if (inLeftWidth > 0) { ::PenSize(inLeftWidth, 1); ::MoveTo(inFrame.left, inFrame.top); ::LineTo(inFrame.left, inFrame.bottom); } if (inBottomWidth > 0) { ::PenSize(1, inBottomWidth); // Don't forget, pen draws down and to the right ::MoveTo(inFrame.left, inFrame.bottom - inBottomWidth); ::LineTo(inFrame.right, inFrame.bottom - inBottomWidth); } if (inRightWidth > 0) { ::PenSize(inRightWidth, 1); // Don't forget, pen draws down and to the right ::MoveTo(inFrame.right - inRightWidth, inFrame.bottom); ::LineTo(inFrame.right - inRightWidth, inFrame.top); } } } Uint16 AddWithoutOverflow(Uint16 base, Uint16 addition) { if ((base + addition) > 0xFFFF) { // overflow, return max Uint16 value return 0xFFFF; } else return base + addition; } Uint16 SubWithoutUnderflow(Uint16 base, Uint16 difference) { if ((base - difference) < 0x0000) { // underflow, return 0 return 0x0000; } else return base - difference; } void ComputeBevelColor(Boolean inRaised, RGBColor inBaseColor, RGBColor& outBevelColor) { if (inRaised) { outBevelColor.red = AddWithoutOverflow(inBaseColor.red, TableBorder_TintLevel); outBevelColor.green = AddWithoutOverflow(inBaseColor.green, TableBorder_TintLevel); outBevelColor.blue = AddWithoutOverflow(inBaseColor.blue, TableBorder_TintLevel); } else { outBevelColor.red = SubWithoutUnderflow(inBaseColor.red, TableBorder_TintLevel); outBevelColor.green = SubWithoutUnderflow(inBaseColor.green, TableBorder_TintLevel); outBevelColor.blue = SubWithoutUnderflow(inBaseColor.blue, TableBorder_TintLevel); } } void CHTMLView::DisplayBevelBorder( const Rect& inFrame, const RGBColor& inBorderColor, Boolean inRaised, Int32 inTopWidth, Int32 inLeftWidth, Int32 inBottomWidth, Int32 inRightWidth) { // 97-06-10 pkc -- No longer use UGraphicGizmos::BevelRect StColorPenState state; state.Normalize(); PolyHandle poly = NULL; RGBColor raisedBevelColor, loweredBevelColor; ComputeBevelColor(true, inBorderColor, raisedBevelColor); ComputeBevelColor(false, inBorderColor, loweredBevelColor); // First do top and left sides if (inTopWidth > 0 || inLeftWidth > 0) { poly = OpenPoly(); if (inRaised) ::RGBForeColor(&raisedBevelColor); else ::RGBForeColor(&loweredBevelColor); ::MoveTo(inFrame.left, inFrame.top); if (inTopWidth > 0) { ::LineTo(inFrame.right, inFrame.top); ::LineTo(inFrame.right - inRightWidth, inFrame.top + inTopWidth); ::LineTo(inFrame.left + inLeftWidth, inFrame.top + inTopWidth); } if (inLeftWidth > 0) { if (inTopWidth == 0) ::LineTo(inFrame.left + inLeftWidth, inFrame.top + inTopWidth); ::LineTo(inFrame.left + inLeftWidth, inFrame.bottom - inBottomWidth); ::LineTo(inFrame.left, inFrame.bottom); } ::ClosePoly(); ::PaintPoly(poly); ::KillPoly(poly); poly = NULL; } if (inRightWidth > 0 || inBottomWidth > 0) { poly = OpenPoly(); // Then do bottom and right sides if (inRaised) ::RGBForeColor(&loweredBevelColor); else ::RGBForeColor(&raisedBevelColor); ::MoveTo(inFrame.right, inFrame.bottom); if (inRightWidth > 0) { ::LineTo(inFrame.right, inFrame.top); ::LineTo(inFrame.right - inRightWidth, inFrame.top + inTopWidth); ::LineTo(inFrame.right - inRightWidth, inFrame.bottom - inBottomWidth); } if (inBottomWidth > 0) { if (inRightWidth == 0) ::LineTo(inFrame.right - inRightWidth, inFrame.bottom - inBottomWidth); ::LineTo(inFrame.left + inLeftWidth, inFrame.bottom - inBottomWidth); ::LineTo(inFrame.left, inFrame.bottom); } ::ClosePoly(); ::PaintPoly(poly); ::KillPoly(poly); poly = NULL; } } void CHTMLView::DisplayGrooveRidgeBorder( const Rect& inFrame, const RGBColor& inBorderColor, Boolean inIsGroove, Int32 inTopWidth, Int32 inLeftWidth, Int32 inBottomWidth, Int32 inRightWidth) { Rect theFrame = inFrame; Int32 borderTopWidth = inTopWidth / 2; Int32 borderLeftWidth = inLeftWidth / 2; Int32 borderBottomWidth = inBottomWidth / 2; Int32 borderRightWidth = inRightWidth / 2; // draw outer border DisplayBevelBorder(theFrame, inBorderColor, inIsGroove ? false : true, borderTopWidth, borderLeftWidth, borderBottomWidth, borderRightWidth); // adjust frame theFrame.top += borderTopWidth; theFrame.left += borderLeftWidth; theFrame.bottom -= borderBottomWidth; theFrame.right -= borderRightWidth; // draw inner border DisplayBevelBorder(theFrame, inBorderColor, inIsGroove ? true : false, borderTopWidth, borderLeftWidth, borderBottomWidth, borderRightWidth); } void CHTMLView::DisplayCell( int /* inLocation */, LO_CellStruct* inCellStruct) { if (!FocusDraw() ) return; // ₯ subdoc->width + borderWidth, subdoc->height + borderWidth); Rect theFrame; if (CalcElementPosition( (LO_Element*)inCellStruct, theFrame )) { // ₯Κthis is really slow LAM for ( int i = 1; i <= inCellStruct->border_width; i++ ) { UGraphics::FrameRectShaded( theFrame, true ); ::InsetRect( &theFrame, 1, 1 ); } } } void CHTMLView::InvalidateEntireTableOrCell(LO_Element*) { /* composer only */ } void CHTMLView::DisplayAddRowOrColBorder(XP_Rect*, XP_Bool /*inDoErase*/) { /* composer only */ } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ Boolean CHTMLView::CalcElementPosition( LO_Element* inElement, Rect& outFrame) { // This function takes the real position of a layout element, // .. and returns the local position and whether it is visible. // the calculated position is valid, even if the element is not currently visible XP_Rect absoluteFrame; Point portOrigin; SPoint32 frameLocation; SDimension16 frameSize; SPoint32 imageLocation; Boolean isVisible; portOrigin.h = 0; portOrigin.v = 0; PortToLocalPoint (portOrigin); GetFrameLocation (frameLocation); GetFrameSize (frameSize); GetImageLocation (imageLocation); long realFrameLeft = frameLocation.h - imageLocation.h; long realFrameRight = realFrameLeft + frameSize.width; long realFrameTop = frameLocation.v - imageLocation.v; long realFrameBottom = realFrameTop + frameSize.height; CalcAbsoluteElementPosition (inElement, absoluteFrame); isVisible = realFrameRight > absoluteFrame.left && realFrameLeft < absoluteFrame.right && realFrameBottom > absoluteFrame.top && realFrameTop < absoluteFrame.bottom; outFrame.left = absoluteFrame.left + portOrigin.h + imageLocation.h; outFrame.top = absoluteFrame.top + portOrigin.v + imageLocation.v; outFrame.right = outFrame.left + inElement->lo_any.width; outFrame.bottom = outFrame.top + inElement->lo_any.height; return isVisible; } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ void CHTMLView::CalcAbsoluteElementPosition( LO_Element* inElement, XP_Rect& outFrame) { // calculates the position of a layout element within the document, disregarding // scroll positions and whatnot // make sure we have the actual element position long elementPosLeft = inElement->lo_any.x + inElement->lo_any.x_offset; long elementPosTop = inElement->lo_any.y + inElement->lo_any.y_offset; #ifdef LAYERS int32 layerOriginX,layerOriginY; if (mCurrentDrawable != NULL) mCurrentDrawable->GetLayerOrigin ( &layerOriginX, &layerOriginY ); else { layerOriginX = mLayerOrigin.h; layerOriginY = mLayerOrigin.v; } elementPosLeft += layerOriginX; elementPosTop += layerOriginY; #endif outFrame.left = elementPosLeft; outFrame.top = elementPosTop; outFrame.right = outFrame.left + inElement->lo_any.width; outFrame.bottom = outFrame.top + inElement->lo_any.height; } // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ // ₯ // ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ void CHTMLView::CreateGridView( CBrowserContext* inGridContext, Int32 inX, Int32 inY, Int32 inWidth, Int32 inHeight, Int8 inScrollMode, Bool inNoEdge) { CHyperScroller* theContainer = NULL; try { // URL_Struct* request = NULL; // CHyperScroller* theContainer; // MWContext* newContext; // CHyperView* newView; SetScrollMode(LO_SCROLL_NO); mShowFocus = false; FocusDraw(); LCommander::SetDefaultCommander( this ); LPane::SetDefaultView( this ); theContainer = (CHyperScroller*)UReanimator::ReadObjects('PPob', 1005); ThrowIfNULL_(theContainer); theContainer->FinishCreate(); CHTMLView* theNewView = (CHTMLView*)theContainer->FindPaneByID(2005); ThrowIfNULL_(theNewView); // ₯ position it theNewView->mNoBorder = inNoEdge; theNewView->SetSuperHTMLView(this); Rect theOwningFrame; CalcLocalFrameRect(theOwningFrame); Rect theNewFrame; CropFrameToContainer(inX, inY, inWidth, inHeight, theNewFrame); CHyperScroller* theSuperScroller = mScroller; if (!theNewView->mNoBorder) { // for each side that intersects the container, // expand the container out one if (inX == 0) if (theSuperScroller) theSuperScroller->ExpandLeft(); if (inY == 0) if (theSuperScroller) theSuperScroller->ExpandTop(); if (theNewFrame.right == theOwningFrame.right) if (theSuperScroller) theSuperScroller->ExpandRight(); if (theNewFrame.bottom == theOwningFrame.bottom) if (theSuperScroller) theSuperScroller->ExpandBottom(); if (theSuperScroller) theSuperScroller->AdjustHyperViewBounds(); } else { theContainer->ExpandLeft(); theContainer->ExpandTop(); theContainer->ExpandRight(); theContainer->ExpandBottom(); theContainer->AdjustHyperViewBounds(); } CropFrameToContainer(inX, inY, inWidth, inHeight, theNewFrame); theContainer->PlaceInSuperFrameAt(theNewFrame.left, theNewFrame.top, true); theContainer->ResizeFrameTo(RectWidth(theNewFrame), RectHeight(theNewFrame), false); if (theSuperScroller) theSuperScroller->AdjustHyperViewBounds(); theContainer->AdjustHyperViewBounds(); theNewView->SetScrollMode(inScrollMode); // 97-05-07 pkc -- if inNoEdge is true, we've got a borderless frame, don't // display frame focus if (!inNoEdge) theNewView->mShowFocus = true; // ₯ so that we call scroller's activate, and it actually enables the scrollbars // theContainer->ActivateSelf(); // FIX ME!!! this used to be the line above. I hope this still works theContainer->Activate(); if (theSuperScroller) theSuperScroller->Refresh(); theNewView->SetContext(inGridContext); mHasGridCells = true; // give the grid context the same listeners as the root context mContext->CopyListenersToContext(inGridContext); } catch (...) { delete theContainer; throw; } } void CHTMLView::CropFrameToContainer( Int32 inImageLeft, Int32 inImageTop, Int32 inImageWidth, Int32 inImageHeight, Rect& outLocalFrame) const { Rect theOwningFrame; CalcLocalFrameRect(theOwningFrame); SPoint32 theImageTopLeft; theImageTopLeft.h = inImageLeft; theImageTopLeft.v = inImageTop; SPoint32 theImageBotRight; theImageBotRight.h = inImageLeft + inImageWidth; theImageBotRight.v = inImageTop + inImageHeight; ImageToLocalPoint(theImageTopLeft, topLeft(outLocalFrame)); ImageToLocalPoint(theImageBotRight, botRight(outLocalFrame)); ::SectRect(&theOwningFrame, &outLocalFrame, &outLocalFrame); } // --------------------------------------------------------------------------- // ₯ CalcStandardSizeForWindowForScreen // --------------------------------------------------------------------------- void CHTMLView::CalcStandardSizeForWindowForScreen( CHTMLView* inTopMostHTMLView, const LWindow& inWindow, const Rect& inScreenBounds, SDimension16& outStandardSize) { bool haveAnHTMLView = false; Rect minMaxSize; SDimension16 htmlFrameSize; SDimension16 windowContentSize; SDimension32 htmlImageSize; CBrowserContext* theTopContext = nil; Boolean puntToADefaultStandardSize = false; if (CApplicationEventAttachment::CurrentEventHasModifiers(optionKey)) { outStandardSize.width = max_Int16; outStandardSize.height = max_Int16; return; } inWindow.GetMinMaxSize(minMaxSize); inWindow.GetFrameSize(windowContentSize); // Note: If inTopMostHTMLView is nil, then we use the punt size if (inTopMostHTMLView) { theTopContext = inTopMostHTMLView->GetContext(); // Get the image size of the html view inTopMostHTMLView->GetImageSize(htmlImageSize); htmlImageSize.width = MIN(htmlImageSize.width, max_Int16); htmlImageSize.height = MIN(htmlImageSize.height, max_Int16); if (htmlImageSize.width != 0 && htmlImageSize.height != 0) { haveAnHTMLView = true; } } // Calculate standard size if (theTopContext && haveAnHTMLView) { CBrowserContext* theTopContext = inTopMostHTMLView->GetContext(); ThrowIfNil_(theTopContext); if (!theTopContext->CountGridChildren()) { // Get the frame size of the html view inTopMostHTMLView->GetFrameSize(htmlFrameSize); outStandardSize.width = ((windowContentSize.width - htmlFrameSize.width) + htmlImageSize.width); outStandardSize.height = ((windowContentSize.height - htmlFrameSize.height) + htmlImageSize.height); // Shrink the standard size in each dimension if the other dimension has a scroll bar // which will disappear at the new standard size. We attempt to adjust the standard // size height first. If the standard width for the screen does cause a previous // horizontal scrollbar to disappear then we adjust the height. We remember whether // it was adjusted. Then we attempt to adjust the width. Then we try once more on the // height if it wasn't already adjusted. Boolean heightAdjusted = false; if (inTopMostHTMLView->GetScroller() && inTopMostHTMLView->GetScroller()->HasHorizontalScrollbar() && outStandardSize.width < (inScreenBounds.right - inScreenBounds.left)) { outStandardSize.height -= (ScrollBar_Size - 1); heightAdjusted = true; } if (inTopMostHTMLView->GetScroller() && inTopMostHTMLView->GetScroller()->HasVerticalScrollbar() && outStandardSize.height < (inScreenBounds.bottom - inScreenBounds.top)) { outStandardSize.width -= (ScrollBar_Size - 1); } if (inTopMostHTMLView->GetScroller() && inTopMostHTMLView->GetScroller()->HasHorizontalScrollbar() && outStandardSize.width < (inScreenBounds.right - inScreenBounds.left) && !heightAdjusted) { outStandardSize.height -= (ScrollBar_Size - 1); heightAdjusted = true; } // Don't shrink window smaller than the minimum size if (outStandardSize.width < minMaxSize.left) outStandardSize.width = minMaxSize.left; if (outStandardSize.height < minMaxSize.top) outStandardSize.height = minMaxSize.top; } else { // We have frames. // // We will pick a "reasonable" size out of our... Note that Akbar would // simply reuse the mStandardSize for the previously viewed page (which // produces inconsistent results when zooming a given frames page). At least // this method will produce consistent results. // // It would be cool, of course, if we could figure out which frames should // contribute to the calculation of the new width and height of the window // to miminize scrolling and do that instead. That would produce a better // standard size for frame documents. puntToADefaultStandardSize = true; } } else { // No context or top-most context is not and html view or the user held // down the optionKey, so we just punt puntToADefaultStandardSize = true; } if (puntToADefaultStandardSize) { Int16 height = 850; Int16 width = 0.85 * height; // If the punt height is greater than the screen height then // recalculate with a punt height equal to the screen height. if ((inScreenBounds.bottom - inScreenBounds.top) < height) { height = inScreenBounds.bottom - inScreenBounds.top; width = 0.85 * height; } outStandardSize.width = width; outStandardSize.height = height; } } void CHTMLView::GetFullGridSize( Int32& outWidth, Int32& outHeight) { // FIX ME!!! here's another thing that will need to change // when the scroller dependency is removed. if (mScroller != NULL) { SDimension16 theContainerSize; mScroller->GetFrameSize(theContainerSize); outWidth = theContainerSize.width; outHeight = theContainerSize.height; } else { Assert_(false); outWidth = outHeight = 0; } } void CHTMLView::RestructureGridView( Int32 inX, Int32 inY, Int32 inWidth, Int32 inHeight) { mSuperHTMLView->FocusDraw(); if (mScroller != NULL) { CHyperScroller* theSuperScroller = mScroller; Rect theNewFrame; mSuperHTMLView->CropFrameToContainer(inX, inY, inWidth, inHeight, theNewFrame); theSuperScroller->PlaceInSuperFrameAt(theNewFrame.left, theNewFrame.top, false); theSuperScroller->ResizeFrameTo(RectWidth(theNewFrame), RectHeight(theNewFrame), false); theSuperScroller->AdjustHyperViewBounds(); } // if ( mContext ) // { // History_entry* he = SHIST_GetCurrent( &fHContext->hist ); // if ( !he || he->is_binary ) // { // this->Refresh(); // this->ReadjustScrollbars( TRUE ); // this->Refresh(); // return; // } // } // ₯ causes repositioning of the scrollbars SetScrollMode(mDefaultScrollMode, true); ClearBackground(); mContext->Repaginate(); } /* // MAY WANT TO ADD HERE AS BSE IMPLEMENTATION void CHTMLView::BeginPreSection(void) { // Empty NS_xxx implementation } void CHTMLView::EndPreSection(void) { // Empty NS_xxx implementation } */ #pragma mark - // --------------------------------------------------------------------------- // ₯ CDragURLTask // --------------------------------------------------------------------------- CDragURLTask::CDragURLTask( const EventRecord& inEventRecord, const Rect& inGlobalFrame, CHTMLView& inHTMLView) : mGlobalFrame(inGlobalFrame), mHTMLView(inHTMLView), super(inEventRecord) { } // --------------------------------------------------------------------------- // ₯ AddFlavors // --------------------------------------------------------------------------- void CDragURLTask::AddFlavors( DragReference /* inDragRef */) { OSErr theErr; // If the option-key is down and the element is an image, we drag as a PICT, even to the finder.. // If not, we drag real image data (JPEF or GIF).. Boolean isOptionDown = ((mEventRecord.modifiers & optionKey) != 0); if (mHTMLView.mDragElement->type != LO_IMAGE || !isOptionDown) { AddFlavorBookmarkFile(static_cast(this)); } AddFlavorURL(static_cast(this)); AddFlavorBookmark(static_cast(this)); // Add a PICT flavor for images if (mHTMLView.mDragElement->type == LO_IMAGE) { LO_ImageStruct* imageElement = (LO_ImageStruct*)mHTMLView.mDragElement; if (!IsInternalTypeLink((char*)imageElement->image_url) || IsMailNewsReconnect((char*)imageElement->image_url)) { // flavorSenderTranslated will prevent us from being saved as a PICT clipping // in the Finder. When the option key is down, this is exactly what we want FlavorFlags flavorFlags = (isOptionDown) ? 0 : flavorSenderTranslated; theErr = ::AddDragItemFlavor (mDragRef, (ItemReference) this, 'PICT', nil, 0, flavorFlags); ThrowIfOSErr_(theErr); } } } // --------------------------------------------------------------------------- // ₯ MakeDragRegion // --------------------------------------------------------------------------- void CDragURLTask::MakeDragRegion( DragReference /* inDragRef */, RgnHandle /* inDragRegion */) { AddRectDragItem((ItemReference)mHTMLView.mDragElement, mGlobalFrame); } #pragma mark - #if defined (JAVA) void FlushEventHierarchyRecursive(LPane *currentPane) { Hsun_awt_macos_MComponentPeer *componentPeerHandle = PaneToPeer(currentPane); // Flush the events associated with the component; if (componentPeerHandle != NULL) { // Clear the interface queue of events related to the component to help garbage collection. ClassClass *interfaceEventClass; interfaceEventClass = FindClass(EE(), "sun/awt/macos/InterfaceEvent", (PRBool)TRUE); if (interfaceEventClass != NULL) { MToolkitExecutJavaStaticMethod(interfaceEventClass, "flushInterfaceQueue", "(Lsun/awt/macos/MComponentPeer;)V", componentPeerHandle); } // Recurse on the sub-panes if (unhand(componentPeerHandle)->mIsContainer) { LArrayIterator iterator(((LView *)currentPane)->GetSubPanes()); LPane *theSub; while (iterator.Next(&theSub)) FlushEventHierarchyRecursive(theSub); } } } void FlushEventHierarchy(LView *javaAppletView) { LPane *canvas = javaAppletView->FindPaneByID('cvpr'); FlushEventHierarchyRecursive(canvas); } #endif /* defined (JAVA) */