mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-07 20:17:37 +00:00
7482 lines
213 KiB
C++
7482 lines
213 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
|
*
|
|
* The contents of this file are subject to the Netscape Public License
|
|
* Version 1.0 (the "NPL"); you may not use this file except in
|
|
* compliance with the NPL. You may obtain a copy of the NPL at
|
|
* http://www.mozilla.org/NPL/
|
|
*
|
|
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
|
* for the specific language governing rights and limitations under the
|
|
* NPL.
|
|
*
|
|
* The Initial Developer of this code under the NPL is Netscape
|
|
* Communications Corporation. Portions created by Netscape are
|
|
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
|
* Reserved.
|
|
*/
|
|
|
|
// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
// CHTMLView.cp
|
|
// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
|
|
#include "CHTMLView.h"
|
|
|
|
|
|
#include "CStLayerOriginSetter.h"
|
|
|
|
#include <algorithm>
|
|
#include <CAutoPtrXP.h>
|
|
|
|
#include "CHTMLClickRecord.h"
|
|
#include "BookmarksFile.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"
|
|
|
|
#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 <UDrawingState.h>
|
|
#include <UMemoryMgr.h>
|
|
#include <UCursor.h>
|
|
#include <Sound.h>
|
|
|
|
const Int16 FocusBox_Size = 3;
|
|
|
|
const Int16 TableBorder_TintLevel = 20000;
|
|
|
|
const ResIDT cPaulsMiscStrListID = 16010;
|
|
const Int16 cSendPageIndex = 4;
|
|
const Int16 cSendFrameIndex = 5;
|
|
|
|
|
|
// 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)
|
|
, mDragSelection(false)
|
|
, mFontScaling(eDefaultFontScaling)
|
|
, mTimerURLString(nil)
|
|
, mTimerURLReloadPolicy(NET_SUPER_RELOAD)
|
|
, mTimerURLFireTime(0)
|
|
{
|
|
|
|
// 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;
|
|
|
|
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 );
|
|
|
|
|
|
//mScroller = NULL; // do we need this?
|
|
|
|
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
|
|
|
|
mScroller = dynamic_cast<CHyperScroller*>(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();
|
|
|
|
mOriginalOrigin.v = mOriginalOrigin.h = 0;
|
|
}
|
|
|
|
// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
// ¥
|
|
// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
|
|
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->RemoveListener(this);
|
|
// 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(); // MUST BE LAST, AFTER POSSIBLE DELETION!
|
|
}
|
|
|
|
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 (mCompositor && inNewContext)
|
|
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<Boolean> 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)) {
|
|
SwitchTarget (newTarget);
|
|
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;
|
|
}
|
|
|
|
|
|
// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
// ¥ ScrollBits
|
|
// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
// LView::ScrollBits works by calling ::ScrollRect() which unfortunately paints
|
|
// the invalidated area with the background pattern. This causes lots of ugly
|
|
// flashing and makes us look pretty bad. Instead, we roll our own ::ScrollRect()
|
|
// by using ::CopyBits() to scroll the image in the view and then set the update
|
|
// rgn appropriately so that the compositor can blit it to the screen.
|
|
|
|
void
|
|
CHTMLView :: ScrollBits ( Int32 inLeftDelta, Int32 inTopDelta )
|
|
{
|
|
if (FocusExposed()) {
|
|
|
|
// Get Frame in local coords from clip rect (there might be a border around view)
|
|
StRegion clipRgn;
|
|
Rect frame;
|
|
::GetClip(clipRgn);
|
|
clipRgn.GetBounds(frame);
|
|
|
|
StRegion totalView(frame);
|
|
|
|
// compute the source rect (rect that gets scrolled)
|
|
Rect source = frame;
|
|
if ( inTopDelta > 0 )
|
|
source.top += inTopDelta;
|
|
else if ( inTopDelta < 0 )
|
|
source.bottom -= inTopDelta;
|
|
if ( inLeftDelta > 0 )
|
|
source.left += inLeftDelta;
|
|
else if ( inLeftDelta < 0 )
|
|
source.right -= inLeftDelta;
|
|
|
|
// compute the destination of copybits (post-scroll)
|
|
Rect dest = source;
|
|
if ( inTopDelta ) {
|
|
dest.top -= inTopDelta;
|
|
dest.bottom -= inTopDelta;
|
|
}
|
|
if ( inLeftDelta ) {
|
|
dest.left -= inLeftDelta;
|
|
dest.right -= inLeftDelta;
|
|
}
|
|
|
|
// compute the area that is to be updated by subtracting the dest from the visible area
|
|
StRegion updateRgn(frame);
|
|
StRegion destRgn(dest);
|
|
::DiffRgn ( updateRgn, destRgn, updateRgn );
|
|
|
|
|
|
if(::EmptyRgn(mCachedPort->visRgn))
|
|
{
|
|
::CopyBits (
|
|
&mCachedPort->portBits,
|
|
&mCachedPort->portBits,
|
|
&source,
|
|
&dest,
|
|
srcCopy,
|
|
nil);
|
|
}
|
|
else
|
|
{
|
|
// compute the non-visable region
|
|
StRegion nonVisableRgn;
|
|
::DiffRgn ( totalView, mCachedPort->visRgn, nonVisableRgn );
|
|
|
|
// compute the extra area that may need to be updated
|
|
// scoll the non-visable region to determine what needs updating
|
|
::OffsetRgn ( nonVisableRgn, -inLeftDelta, -inTopDelta );
|
|
|
|
// calculate a mask region to not copy the non-visble portions of the window from the port
|
|
StRegion copyMaskRgn;
|
|
::DiffRgn(totalView, nonVisableRgn, copyMaskRgn);
|
|
|
|
// use copybits to simulate a ScrollRect()
|
|
StColorPenState saved;
|
|
StColorPenState::Normalize();
|
|
|
|
::CopyBits (
|
|
&mCachedPort->portBits,
|
|
&mCachedPort->portBits,
|
|
&source,
|
|
&dest,
|
|
srcCopy,
|
|
copyMaskRgn);
|
|
|
|
// union the update regions together and invalidate them
|
|
::UnionRgn(nonVisableRgn, updateRgn, updateRgn);
|
|
}
|
|
|
|
::OffsetRgn(updateRgn, -mPortOrigin.h, -mPortOrigin.v);
|
|
InvalPortRgn(updateRgn);
|
|
}
|
|
|
|
} // ScrollBits
|
|
|
|
// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
// ¥ 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
|
|
}
|
|
}
|
|
|
|
// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
// ¥
|
|
// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
|
|
Int8 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, mTimerURLReloadPolicy);
|
|
ClearTimerURL(); // ...frees mTimerURLString, so must do this _after_ |NET_CreateURLStruct|.
|
|
if (request)
|
|
{
|
|
// Fix bug: call GetURLForReferral() to set referer field in URL_Struct
|
|
request->referer = XP_STRDUP( mContext->GetURLForReferral() );
|
|
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();
|
|
}
|
|
// If we have auto-detected csid but no corresponding encoding menu item (e.g. JIS),
|
|
// use CS_SJIS_AUTO for CS_JIS, CS_KSC_8BIT_AUTO for CS_2022_KR.
|
|
if (CS_JIS == (~CS_AUTO & csid))
|
|
csid = CS_SJIS_AUTO;
|
|
else if (CS_2022_KR == (~CS_AUTO & csid) || CS_KSC_8BIT == csid)
|
|
csid = CS_KSC_8BIT_AUTO;
|
|
|
|
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;
|
|
|
|
#ifdef SingleSignon
|
|
// Check for a password submission and remember the data if so
|
|
SI_RememberSignonData(pContext, submit);
|
|
#endif
|
|
|
|
URL_Struct* url = NET_CreateURLStruct((char *)submit->action, NET_DONT_RELOAD);
|
|
CBrowserContext* context = ExtractBrowserContext(pContext);
|
|
if (context && url)
|
|
{
|
|
History_entry* current = context->GetCurrentHistoryEntry();
|
|
if (current && current->address)
|
|
{
|
|
// Fix bug -- prefer origin_url to referer
|
|
url->referer = XP_STRDUP(current->origin_url ? current->origin_url : current->address);
|
|
}
|
|
NET_AddLOSubmitDataToURLStruct(submit, url);
|
|
|
|
// Toshok's fix moved over from the XFE code
|
|
if (submit->window_target)
|
|
{
|
|
CBrowserContext* tempContext = ExtractBrowserContext(XP_FindNamedContextInList(pContext, (char *)submit->window_target));
|
|
|
|
if (tempContext)
|
|
{
|
|
submit->window_target = NULL;
|
|
url->window_target = NULL; // don't let window_target get resolved later
|
|
context = tempContext;
|
|
}
|
|
}
|
|
|
|
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<ImageFormSubmitData*>(whatever);
|
|
try
|
|
{
|
|
theSubmit = LO_SubmitImageForm(pContext, data->lo_image, data->x, data->y);
|
|
|
|
#ifdef SingleSignon
|
|
// Check for a password submission and remember the data if so
|
|
SI_RememberSignonData(pContext, theSubmit);
|
|
#endif
|
|
|
|
// 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)
|
|
{
|
|
// Fix bug -- call GetURLForReferral() to set referer field in URL_Struct
|
|
cstring theCurrentURL = theContext->GetURLForReferral();
|
|
if (theCurrentURL.length() > 0)
|
|
theURL->referer = XP_STRDUP(theCurrentURL);
|
|
|
|
if (NET_AddLOSubmitDataToURLStruct(theSubmit, theURL))
|
|
{
|
|
// Toshok's fix moved over from the XFE code
|
|
if (theSubmit->window_target)
|
|
{
|
|
CBrowserContext* tempContext = ExtractBrowserContext(XP_FindNamedContextInList(pContext, (char *)theSubmit->window_target));
|
|
|
|
if (tempContext)
|
|
{
|
|
theSubmit->window_target = NULL;
|
|
theURL->window_target = NULL; // don't let window_target get resolved later
|
|
theContext = tempContext;
|
|
}
|
|
}
|
|
|
|
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<LControl*>(thePane);
|
|
ThrowIfNil_(theControl);
|
|
|
|
formID = (void*) theControl->GetUserCon();
|
|
}
|
|
else
|
|
formID = ((CFormLittleText*)ioParam)->GetLayoutForm();
|
|
|
|
// 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<LControl*>(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<LControl*>(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<CBrowserWindow *>(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;
|
|
/* If a windowless plugin is forcing a redraw, we need to
|
|
account for the scroll position in our origin calculation */
|
|
if(NPL_IsForcingRedraw())
|
|
{
|
|
outPortOrigin.h = mPortOrigin.h - mOriginalOrigin.h;
|
|
outPortOrigin.v = mPortOrigin.v - mOriginalOrigin.v;
|
|
}
|
|
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<RgnHandle>(theImageUpdateRgn));
|
|
else
|
|
DrawBackground((*static_cast<RgnHandle>(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);
|
|
|
|
/* Used in CHTMLView::GetCurrentPort() calculate the origin offset due to scrolling */
|
|
if(mOriginalOrigin.h == 0)
|
|
mOriginalOrigin = mPortOrigin;
|
|
|
|
/* 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<CHTMLView*>(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<LO_EdgeStruct*>::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 );
|
|
|
|
// pinkerton
|
|
// we need a way to prevent images/etc in the HTML area from drawing over the
|
|
// popdown treeView if it is visible. Clip it out.
|
|
StClipRgnState savedClip;
|
|
CBrowserWindow::ClipOutPopdown(this);
|
|
|
|
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->objTag.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<CHTMLView*>(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!
|
|
{
|
|
LCommander::FindCommandStatus(inCommand, outEnabled, outUsesMark, outMark, outName);
|
|
return;
|
|
}
|
|
|
|
CBrowserWindow *browserWindow = dynamic_cast<CBrowserWindow *>(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_FontLarger:
|
|
outEnabled = (mFontScaling < eMaxFontScaling);
|
|
break;
|
|
|
|
case cmd_FontSmaller:
|
|
outEnabled = (mFontScaling > eMinFontScaling);
|
|
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;
|
|
case cmd_FTPUpload: // fix for #313498
|
|
case cmd_PrivDisplayPolicy:
|
|
case cmd_PrivDisplaySiteInfo:
|
|
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
|
|
LCommander::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);
|
|
}
|
|
|
|
|
|
void CHTMLView::NoteFontScalingChanged ( )
|
|
{
|
|
if ( GetContext() ) {
|
|
MWContext* mwContext = *GetContext();
|
|
mwContext->fontScalingPercentage = LO_GetScalingFactor(static_cast<Int32>(mFontScaling));
|
|
GetContext()->Repaginate(NET_SUPER_RELOAD);
|
|
}
|
|
|
|
} // NoteFontScalingChanged
|
|
|
|
|
|
Boolean CHTMLView::ObeyCommand(CommandT inCommand, void* ioParam)
|
|
{
|
|
Boolean cmdHandled = false;
|
|
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:
|
|
URL_Struct* url = CreateURLStructOfCurrent(false);
|
|
if (url) {
|
|
url->history_num = 0;
|
|
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 = CreateURLStructOfCurrent(true);
|
|
if (url)
|
|
mContext->ImmediateLoadURL(url, FO_VIEW_SOURCE);
|
|
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<char*>(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 = CreateURLStructOfCurrent(true);
|
|
|
|
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)
|
|
{
|
|
// Set the type and creator - bug #107708
|
|
url->x_mac_type = (char*)XP_ALLOC(9);
|
|
ThrowIfNil_(url->x_mac_type);
|
|
sprintf(url->x_mac_type, "%X", emTextType);
|
|
url->x_mac_creator = (char*)XP_ALLOC(9);
|
|
ThrowIfNil_(url->x_mac_creator);
|
|
sprintf(url->x_mac_creator, "%X", emSignature);
|
|
|
|
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:
|
|
case cmd_PrivDisplayPolicy:
|
|
case cmd_PrivDisplaySiteInfo:
|
|
cmdHandled = true;
|
|
break;
|
|
|
|
case cmd_MailDocument: // Send Page/Frame
|
|
MSG_MailDocument(*mContext);
|
|
break;
|
|
|
|
|
|
case cmd_FontLarger:
|
|
if ( mFontScaling < eMaxFontScaling ) {
|
|
++mFontScaling;
|
|
NoteFontScalingChanged();
|
|
}
|
|
break;
|
|
|
|
case cmd_FontSmaller:
|
|
if ( mFontScaling > eMinFontScaling ) {
|
|
--mFontScaling;
|
|
NoteFontScalingChanged();
|
|
}
|
|
break;
|
|
|
|
default:
|
|
cmdHandled = LCommander::ObeyCommand(inCommand, ioParam);
|
|
break;
|
|
}
|
|
if (cr && cr->IsAnchor())
|
|
LO_HighlightAnchor(*mContext, cr->mElement, FALSE);
|
|
return cmdHandled;
|
|
} // CHTMLView::ObeyCommand
|
|
|
|
// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
Boolean CHTMLView::SetDefaultCSID(Int16 default_csid, Boolean forceRepaginate /* = false */)
|
|
// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
{
|
|
if (mContext)
|
|
{
|
|
if (default_csid != mContext->GetDefaultCSID())
|
|
{
|
|
mContext->SetDefaultCSID(default_csid);
|
|
mContext->SetWinCSID(INTL_DocToWinCharSetID(default_csid));
|
|
forceRepaginate = true;
|
|
}
|
|
if (forceRepaginate)
|
|
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);
|
|
|
|
LO_SaveFormData(context);
|
|
|
|
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() && SwitchTarget(this))
|
|
{
|
|
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
|
|
class DoExecuteClickInLinkRecord
|
|
{
|
|
public:
|
|
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))
|
|
{
|
|
// Also, check for click in selection first, as it takes precedence over others. If
|
|
// the drag is successful, set |bClickHandled| so we don't try to do anyting else
|
|
// with it.
|
|
if ( cr.IsClickOnSelection() ) {
|
|
// are we dragging? Use a try block to ensure that we set click record back to nil
|
|
mCurrentClickRecord = &cr;
|
|
EClickState theMouseAction = eMouseUndefined;
|
|
try {
|
|
// don't allow context menus here, we'll handle them below. Is this the
|
|
// right thing to do?
|
|
theMouseAction = cr.WaitForMouseAction(inMouseDown, this, GetDblTime(), false);
|
|
}
|
|
catch(...) {}
|
|
mCurrentClickRecord = nil;
|
|
|
|
// if so, drag the selection
|
|
try {
|
|
if ( theMouseAction == eMouseDragging ) {
|
|
StValueChanger<Boolean> val (mDragSelection, true);
|
|
ClickDragSelection(inMouseDown, theElement);
|
|
bClickHandled = true;
|
|
}
|
|
}
|
|
catch ( ... ) { }
|
|
|
|
} // if click on selection
|
|
|
|
// Move check for edge click here; otherwise, if you hold down mouse button over
|
|
// edge, then context menu pops up. Whoops.
|
|
if ( !bClickHandled && cr.IsClickOnEdge())
|
|
ClickTrackEdge(inMouseDown, cr);
|
|
else if ( !bClickHandled && cr.IsClickOnAnchor())
|
|
{
|
|
Int32 theClickStart = inMouseDown.macEvent.when;
|
|
Point thePrevPoint = inMouseDown.whereLocal;
|
|
|
|
LO_HighlightAnchor(*mContext, theElement, true);
|
|
|
|
mCurrentClickRecord = &cr;
|
|
EClickState theMouseAction = eMouseUndefined;
|
|
// 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 eMouseDragging:
|
|
ClickDragLink(inMouseDown, theElement);
|
|
break;
|
|
|
|
case eMouseTimeout:
|
|
/*
|
|
{
|
|
Int16 thePopResult = this->DoPopup(inMouseDown, cr);
|
|
if (thePopResult)
|
|
this->HandlePopupResult(inMouseDown, cr, thePopResult);
|
|
else
|
|
LO_HighlightAnchor(*mContext, cr.mElement, false);
|
|
}
|
|
*/
|
|
break;
|
|
|
|
case eMouseUpEarly:
|
|
ClickSelfLink(inMouseDown, cr, false);
|
|
doUnhighlight = false;
|
|
break;
|
|
|
|
case eMouseHandledByAttachment:
|
|
// Nothing else to do.
|
|
break;
|
|
default:
|
|
SignalPStr_("\pUnhandled click case!!!");
|
|
break;
|
|
}
|
|
|
|
if (doUnhighlight) LO_HighlightAnchor(*mContext, cr.mElement, false);
|
|
bClickHandled = true;
|
|
}
|
|
else if ( !bClickHandled && (theElement != NULL) && (theElement->type == LO_IMAGE))
|
|
{
|
|
// ¥ allow dragging of non-anchor images
|
|
mCurrentClickRecord = &cr;
|
|
EClickState theMouseAction = eMouseUndefined;
|
|
try
|
|
{
|
|
theMouseAction = cr.WaitForMouseAction(inMouseDown.whereLocal, inMouseDown.macEvent.when, GetDblTime());
|
|
}
|
|
catch(...) {}
|
|
mCurrentClickRecord = nil;
|
|
if (theMouseAction == 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<CFormButton*>(thePane);
|
|
CGAFormPushButton* theGAFormPushButton = dynamic_cast<CGAFormPushButton*>(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<CFormRadio*>(thePane);
|
|
CGAFormRadio* theGAFormRadio = dynamic_cast<CGAFormRadio*>(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<CFormCheckbox*>(thePane);
|
|
CGAFormCheckbox* theGAFormCheckbox = dynamic_cast<CGAFormCheckbox*>(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;
|
|
EClickState mouseAction = eMouseUndefined;
|
|
try
|
|
{
|
|
mouseAction = CHTMLClickRecord::WaitForMouseAction(inMouseDown, this, GetDblTime());
|
|
}
|
|
catch (...) {}
|
|
mCurrentClickRecord = nil;
|
|
if ( mouseAction == eMouseHandledByAttachment )
|
|
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);
|
|
|
|
// Fix bug -- call GetURLForReferral() to set referer field in URL_Struct
|
|
cstring theReferer = mContext->GetURLForReferral();
|
|
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
|
|
{
|
|
// 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);
|
|
|
|
// Fix bug -- call GetURLForReferral() to set referer field in URL_Struct
|
|
cstring theReferer = mContext->GetURLForReferral();
|
|
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<Boolean> 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<LO_Element*> theValueChanger(mDragElement, inElement);
|
|
|
|
CDragURLTask theDragTask(inMouseDown.macEvent, theGlobalRect, *this);
|
|
|
|
OSErr theErr = ::SetDragSendProc(theDragTask.GetDragReference(), mSendDataUPP, (LDragAndDrop*)this);
|
|
ThrowIfOSErr_(theErr);
|
|
|
|
theDragTask.DoDrag();
|
|
}
|
|
|
|
// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
// ¥ ClickDragSelection
|
|
// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
// User has clicked somewhere in the current selection. Do the drag
|
|
|
|
void CHTMLView::ClickDragSelection (
|
|
const SMouseDownEvent& inMouseDown,
|
|
LO_Element* inElement)
|
|
{
|
|
FocusDraw();
|
|
|
|
// get the local rect of the element. The drag task will convert it to
|
|
// global coords for it.
|
|
Rect theLocalRect;
|
|
Boolean bVisible = CalcElementPosition(inElement, theLocalRect);
|
|
|
|
StValueChanger<LO_Element*> theValueChanger(mDragElement, inElement);
|
|
|
|
LDragTask theDragTask ( inMouseDown.macEvent, theLocalRect, (unsigned long)this, 'TEXT', NULL,
|
|
0, flavorSenderTranslated );
|
|
OSErr theErr = ::SetDragSendProc(theDragTask.GetDragReference(), mSendDataUPP, (LDragAndDrop*)this);
|
|
ThrowIfOSErr_(theErr);
|
|
|
|
theDragTask.DoDrag();
|
|
|
|
} // ClickDragSelection
|
|
|
|
|
|
// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
// ¥
|
|
// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
|
|
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
|
|
bool shiftDown = (inMouseDown.macEvent.modifiers & shiftKey) != 0;
|
|
|
|
::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 ( GetClickCount() == 2 & !shiftDown )
|
|
LO_DoubleClick ( *mContext, theImagePointStart.h, theImagePointStart.v,
|
|
inClickRecord.GetLayer() ) ;
|
|
else {
|
|
if ( shiftDown && !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 || (modifiers & shiftKey) == shiftKey)
|
|
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:
|
|
if ( mScroller && mScroller->HasVerticalScrollbar())
|
|
mScroller->VertScroll( kControlPageDownPart );
|
|
return TRUE;
|
|
case char_Space:
|
|
if ((modifiers & shiftKey) == shiftKey)
|
|
{
|
|
if ( mScroller && mScroller->HasVerticalScrollbar())
|
|
mScroller->VertScroll( kControlPageUpPart );
|
|
}
|
|
else
|
|
{
|
|
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;
|
|
}
|
|
}
|
|
return LCommander::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
|
|
class AdjustCursorRecord
|
|
{
|
|
public:
|
|
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;
|
|
cstring theText;
|
|
|
|
// 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);
|
|
if ( mDragSelection ) {
|
|
CAutoPtrXP<float> chunk = LO_GetSelectionText(*mContext);
|
|
theText = reinterpret_cast<char*>(chunk.get());
|
|
}
|
|
else {
|
|
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':
|
|
{
|
|
if ( mDragSelection )
|
|
theErr = ::SetDragItemFlavorData(inDragRef, inItemRef, inFlavor, theText, strlen(theText), 0);
|
|
else
|
|
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);
|
|
#ifdef MOZ_MAIL_NEWS
|
|
// For mailto ULRsNetLIB creates a new compose window but passes a bogus parameter( a FileSpec)
|
|
// instead of a mail_action Leads to a lovely crash. Instead we should save a file containing the URL.
|
|
// It could be argued that this should be done in Netlib but I am far too scared to attempt this
|
|
// for a 4.0x release.
|
|
Boolean isMailTo = false;
|
|
isMailTo = XP_STRCASESTR( request->address , "mailto:") ? true : false ;
|
|
if ( isMailTo )
|
|
{
|
|
WriteBookmarksFile( request->address, locationSpec );
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
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(const URL_Struct* inURL)
|
|
{
|
|
if (inURL)
|
|
mTimerURLString = XP_STRDUP(inURL->refresh_url);
|
|
else
|
|
return;
|
|
mTimerURLFireTime = ::TickCount() + inURL->refresh * 60;
|
|
if ( inURL->dont_cache )
|
|
mTimerURLReloadPolicy = NET_SUPER_RELOAD;
|
|
else
|
|
mTimerURLReloadPolicy = inURL->force_reload;
|
|
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<string>::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 ---
|
|
//
|
|
// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
|
|
|
|
//
|
|
// CreateURLStructOfCurrent
|
|
//
|
|
// Get a URL struct for the URL that's being displayed, say for
|
|
// printing, or saving to a file.
|
|
//
|
|
URL_Struct*
|
|
CHTMLView :: CreateURLStructOfCurrent ( Boolean inCopyFormData )
|
|
{
|
|
MWContext* mwcontext = *GetContext();
|
|
if (!mwcontext) return NULL;
|
|
|
|
URL_Struct* url = SHIST_CreateURLStructFromHistoryEntry(mwcontext,
|
|
mContext->GetCurrentHistoryEntry());
|
|
if (!url) return NULL;
|
|
|
|
SHIST_SavedData savedData;
|
|
XP_MEMCPY(&savedData, &url->savedData, sizeof(SHIST_SavedData));
|
|
XP_MEMSET( &url->savedData, 0, sizeof( SHIST_SavedData ) );
|
|
|
|
if (inCopyFormData)
|
|
LO_CloneFormData(&savedData, mwcontext, url);
|
|
|
|
return url;
|
|
}
|
|
|
|
|
|
// 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<LWindow*>(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 (!FocusExposed(false))
|
|
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<CNativeFontReference*>(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->objTag.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->objTag.FE_Data = NULL;
|
|
}
|
|
EndCatch_
|
|
}
|
|
else
|
|
NPL_EmbedSize((NPEmbeddedApp*) inEmbedStruct->objTag.FE_Data);
|
|
}
|
|
|
|
void CHTMLView::FreeEmbedElement(
|
|
LO_EmbedStruct* inEmbedStruct)
|
|
{
|
|
NPL_EmbedDelete(*mContext, inEmbedStruct);
|
|
inEmbedStruct->objTag.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->objTag.x + embed_struct->objTag.x_offset
|
|
/* - CONTEXT_DATA(*mContext)->document_x */;
|
|
yp = embed_struct->objTag.y + embed_struct->objTag.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->objTag.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;
|
|
LWindow* javaCommanderWindow;
|
|
|
|
// 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();
|
|
}
|
|
|
|
// Bug fix -- crash when printing applet window.
|
|
// This routine is in the call chain from ~LPrintout(), and
|
|
// the applet being printed was _not_ in a window. Hence
|
|
// we need the dynamic cast. The basic problem is that
|
|
// LPrintout does not inherit from LCommander, but LWindow
|
|
// does.
|
|
|
|
javaCommanderWindow = dynamic_cast<LWindow*>(previousParentView);
|
|
|
|
javaAppletView->PutInside(javaCommanderWindow);
|
|
javaAppletView->SetSuperCommander(javaCommanderWindow);
|
|
|
|
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<LO_EdgeStruct*>::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
|
|
if (inElement->type != LO_FORM_ELE // coordinates of these types...
|
|
&& inElement->type != LO_EMBED // ... are already document-relative
|
|
&& inElement->type != LO_JAVA)
|
|
{
|
|
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();
|
|
}
|
|
|
|
const char*
|
|
CHTMLView :: GetBuiltInAttribute ( LO_BuiltinStruct *inBuiltinStruct, const char* inAttribute )
|
|
{
|
|
lo_NVList& attributes = inBuiltinStruct->attributes;
|
|
for ( uint16 n = 0; n < attributes.n; n++ ) {
|
|
const char* attName = attributes.names[n];
|
|
const char* attValue = attributes.values[n];
|
|
if ( attName && (XP_STRCASECMP(attName, inAttribute) == 0) )
|
|
return attValue;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
|
|
// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
// ¥ FreeBuiltinElement
|
|
// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
// Dispose of an embedded SHACK widget
|
|
void
|
|
CHTMLView :: FreeBuiltinElement ( LO_BuiltinStruct* inBuiltinStruct )
|
|
{
|
|
LView* tree = static_cast<LView*>(inBuiltinStruct->FE_Data);
|
|
if ( tree ) {
|
|
RemoveSubPane ( tree );
|
|
delete tree;
|
|
inBuiltinStruct->FE_Data = NULL;
|
|
}
|
|
|
|
} // FreeBuiltinElement
|
|
|
|
|
|
// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
// ¥ DisplayBuiltin
|
|
// ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
// Create and display builtin elements like the embedded composer or shack widgets.
|
|
void
|
|
CHTMLView :: DisplayBuiltin ( int /*inLocation*/, LO_BuiltinStruct* inBuiltinStruct )
|
|
{
|
|
// create the widget if it hasn't already been created, else refresh
|
|
if ( ! inBuiltinStruct->FE_Data ) {
|
|
|
|
// get tag attributes
|
|
const char* url = GetBuiltInAttribute(inBuiltinStruct, "data");
|
|
const char* target = GetBuiltInAttribute(inBuiltinStruct, "target");
|
|
|
|
// reanimate the builtin version of Aurora
|
|
CShackRDFCoordinator* tree = dynamic_cast<CShackRDFCoordinator*>
|
|
(UReanimator::CreateView(9503, this, this));
|
|
tree->ResizeFrameTo ( inBuiltinStruct->width, inBuiltinStruct->height, false );
|
|
tree->PlaceInSuperImageAt ( inBuiltinStruct->x, inBuiltinStruct->y, false );
|
|
|
|
// set window target and url
|
|
lo_NVList& attributes = inBuiltinStruct->attributes;
|
|
tree->BuildHTPane ( url, attributes.n, attributes.names, attributes.values);
|
|
tree->SetTargetFrame ( target );
|
|
|
|
tree->Refresh();
|
|
inBuiltinStruct->FE_Data = tree;
|
|
inBuiltinStruct->htPane = tree->HTPane();
|
|
}
|
|
else {
|
|
LView* tree = static_cast<LView*>(inBuiltinStruct->FE_Data);
|
|
tree->Refresh();
|
|
}
|
|
|
|
} // DisplayBuiltin
|
|
|
|
|
|
/*
|
|
// 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<ItemReference>(this));
|
|
}
|
|
|
|
AddFlavorURL(static_cast<ItemReference>(this));
|
|
|
|
AddFlavorBookmark(static_cast<ItemReference>(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) */
|