1999-08-04 07:39:34 +04:00
|
|
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
2001-12-06 08:45:07 +03:00
|
|
|
* vim:cindent:ts=2:et:sw=2:
|
1999-08-04 07:39:34 +04:00
|
|
|
*
|
1999-11-06 06:40:37 +03:00
|
|
|
* The contents of this file are subject to the Netscape Public
|
|
|
|
* License Version 1.1 (the "License"); you may not use this file
|
|
|
|
* except in compliance with the License. You may obtain a copy of
|
|
|
|
* the License at http://www.mozilla.org/NPL/
|
1999-08-04 07:39:34 +04:00
|
|
|
*
|
1999-11-06 06:40:37 +03:00
|
|
|
* Software distributed under the License is distributed on an "AS
|
|
|
|
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
|
|
|
* implied. See the License for the specific language governing
|
|
|
|
* rights and limitations under the License.
|
1999-08-04 07:39:34 +04:00
|
|
|
*
|
1999-11-06 06:40:37 +03:00
|
|
|
* The Original Code is mozilla.org code.
|
|
|
|
*
|
|
|
|
* The Initial Developer of the Original Code is Netscape
|
1999-08-04 07:39:34 +04:00
|
|
|
* Communications Corporation. Portions created by Netscape are
|
1999-11-06 06:40:37 +03:00
|
|
|
* Copyright (C) 1998 Netscape Communications Corporation. All
|
|
|
|
* Rights Reserved.
|
|
|
|
*
|
|
|
|
* Contributor(s):
|
2000-02-03 01:24:56 +03:00
|
|
|
* Pierre Phaneuf <pp@ludusdesign.com>
|
2000-05-03 03:07:11 +04:00
|
|
|
*
|
|
|
|
* This Original Code has been modified by IBM Corporation. Modifications made by IBM
|
|
|
|
* described herein are Copyright (c) International Business Machines Corporation, 2000.
|
|
|
|
* Modifications to Mozilla code or documentation identified per MPL Section 3.3
|
|
|
|
*
|
|
|
|
* Date Modified by Description of modification
|
|
|
|
* 04/20/2000 IBM Corp. OS/2 VisualAge build.
|
1999-08-04 07:39:34 +04:00
|
|
|
*/
|
2001-08-14 11:59:59 +04:00
|
|
|
#include "nscore.h"
|
1999-08-04 07:39:34 +04:00
|
|
|
#include "nsIFrameManager.h"
|
|
|
|
#include "nsIFrame.h"
|
|
|
|
#include "nsIPresContext.h"
|
|
|
|
#include "nsIPresShell.h"
|
2004-01-08 01:30:53 +03:00
|
|
|
#include "nsStyleSet.h"
|
|
|
|
#include "nsIStyleFrameConstruction.h"
|
2003-02-22 03:32:13 +03:00
|
|
|
#include "nsStyleContext.h"
|
1999-09-21 11:53:14 +04:00
|
|
|
#include "nsStyleChangeList.h"
|
1999-08-06 00:17:44 +04:00
|
|
|
#include "nsIEventQueueService.h"
|
|
|
|
#include "nsIServiceManager.h"
|
1999-08-04 07:39:34 +04:00
|
|
|
#include "nsCOMPtr.h"
|
1999-08-06 00:17:44 +04:00
|
|
|
#include "prthread.h"
|
1999-08-04 07:39:34 +04:00
|
|
|
#include "plhash.h"
|
2001-12-06 08:45:07 +03:00
|
|
|
#include "pldhash.h"
|
1999-08-04 07:39:34 +04:00
|
|
|
#include "nsPlaceholderFrame.h"
|
|
|
|
#include "nsLayoutAtoms.h"
|
2002-11-17 18:37:56 +03:00
|
|
|
#include "nsCSSAnonBoxes.h"
|
2003-01-05 08:05:17 +03:00
|
|
|
#include "nsCSSPseudoElements.h"
|
2000-05-17 02:05:47 +04:00
|
|
|
#include "nsHTMLAtoms.h"
|
1999-09-21 11:53:14 +04:00
|
|
|
#ifdef NS_DEBUG
|
|
|
|
#include "nsISupportsArray.h"
|
|
|
|
#include "nsIStyleRule.h"
|
1999-08-04 07:39:34 +04:00
|
|
|
#endif
|
1999-08-31 18:35:50 +04:00
|
|
|
#include "nsILayoutHistoryState.h"
|
|
|
|
#include "nsIStatefulFrame.h"
|
2000-01-14 12:28:54 +03:00
|
|
|
#include "nsIPresState.h"
|
1999-08-31 18:35:50 +04:00
|
|
|
#include "nsIContent.h"
|
1999-10-16 03:14:44 +04:00
|
|
|
#include "nsINameSpaceManager.h"
|
2001-12-18 01:51:39 +03:00
|
|
|
#include "nsIXBLBinding.h"
|
2000-11-28 01:00:33 +03:00
|
|
|
#include "nsIDocument.h"
|
|
|
|
#include "nsIBindingManager.h"
|
|
|
|
#include "nsIScrollableFrame.h"
|
1999-08-04 07:39:34 +04:00
|
|
|
|
2001-05-30 15:26:21 +04:00
|
|
|
#include "nsIHTMLDocument.h"
|
|
|
|
#include "nsIDOMHTMLDocument.h"
|
|
|
|
#include "nsIDOMNodeList.h"
|
|
|
|
#include "nsIDOMHTMLCollection.h"
|
|
|
|
#include "nsIFormControl.h"
|
|
|
|
#include "nsIDOMElement.h"
|
|
|
|
#include "nsIDOMHTMLFormElement.h"
|
|
|
|
#include "nsIForm.h"
|
|
|
|
#include "nsIContentList.h"
|
2003-05-30 04:21:01 +04:00
|
|
|
#include "nsContentUtils.h"
|
2001-08-16 11:18:24 +04:00
|
|
|
#include "nsReadableUtils.h"
|
2001-10-26 21:51:22 +04:00
|
|
|
#include "nsUnicharUtils.h"
|
2002-03-31 14:14:01 +04:00
|
|
|
#include "nsPrintfCString.h"
|
2002-07-26 07:48:24 +04:00
|
|
|
#include "nsDummyLayoutRequest.h"
|
2002-11-25 14:21:22 +03:00
|
|
|
#include "nsLayoutErrors.h"
|
2003-01-05 08:05:17 +03:00
|
|
|
#include "nsLayoutUtils.h"
|
2003-02-22 03:32:13 +03:00
|
|
|
#include "nsAutoPtr.h"
|
2001-05-30 15:26:21 +04:00
|
|
|
|
2000-09-13 02:47:09 +04:00
|
|
|
#ifdef DEBUG
|
2002-04-03 01:14:43 +04:00
|
|
|
//#define NOISY_DEBUG
|
|
|
|
//#define DEBUG_UNDISPLAYED_MAP
|
2000-09-13 02:47:09 +04:00
|
|
|
#else
|
|
|
|
#undef NOISY_DEBUG
|
2002-04-03 01:14:43 +04:00
|
|
|
#undef DEBUG_UNDISPLAYED_MAP
|
2000-09-13 02:47:09 +04:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef NOISY_DEBUG
|
|
|
|
#define NOISY_TRACE(_msg) \
|
2000-10-29 02:17:53 +04:00
|
|
|
printf("%s",_msg);
|
2000-09-13 02:47:09 +04:00
|
|
|
#define NOISY_TRACE_FRAME(_msg,_frame) \
|
2000-10-29 02:17:53 +04:00
|
|
|
printf("%s ",_msg); nsFrame::ListTag(stdout,_frame); printf("\n");
|
2000-09-13 02:47:09 +04:00
|
|
|
#else
|
|
|
|
#define NOISY_TRACE(_msg);
|
|
|
|
#define NOISY_TRACE_FRAME(_msg,_frame);
|
|
|
|
#endif
|
|
|
|
|
1999-08-06 00:17:44 +04:00
|
|
|
// Class IID's
|
2001-10-25 05:08:40 +04:00
|
|
|
static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
|
1999-08-04 07:39:34 +04:00
|
|
|
|
1999-08-06 00:17:44 +04:00
|
|
|
// IID's
|
1999-08-04 07:39:34 +04:00
|
|
|
|
1999-08-06 00:17:44 +04:00
|
|
|
//----------------------------------------------------------------------
|
1999-08-04 07:39:34 +04:00
|
|
|
|
2001-12-06 08:45:07 +03:00
|
|
|
struct PlaceholderMapEntry : public PLDHashEntryHdr {
|
|
|
|
// key (the out of flow frame) can be obtained through placeholder frame
|
|
|
|
nsPlaceholderFrame *placeholderFrame;
|
|
|
|
};
|
1999-08-04 07:39:34 +04:00
|
|
|
|
2001-12-06 08:45:07 +03:00
|
|
|
PR_STATIC_CALLBACK(const void *)
|
|
|
|
PlaceholderMapGetKey(PLDHashTable *table, PLDHashEntryHdr *hdr)
|
|
|
|
{
|
|
|
|
PlaceholderMapEntry *entry = NS_STATIC_CAST(PlaceholderMapEntry*, hdr);
|
|
|
|
return entry->placeholderFrame->GetOutOfFlowFrame();
|
|
|
|
}
|
1999-08-04 07:39:34 +04:00
|
|
|
|
2001-12-06 08:45:07 +03:00
|
|
|
PR_STATIC_CALLBACK(PRBool)
|
|
|
|
PlaceholderMapMatchEntry(PLDHashTable *table, const PLDHashEntryHdr *hdr,
|
|
|
|
const void *key)
|
|
|
|
{
|
|
|
|
const PlaceholderMapEntry *entry =
|
|
|
|
NS_STATIC_CAST(const PlaceholderMapEntry*, hdr);
|
|
|
|
return entry->placeholderFrame->GetOutOfFlowFrame() == key;
|
|
|
|
}
|
1999-08-04 07:39:34 +04:00
|
|
|
|
2001-12-06 08:45:07 +03:00
|
|
|
static PLDHashTableOps PlaceholderMapOps = {
|
|
|
|
PL_DHashAllocTable,
|
|
|
|
PL_DHashFreeTable,
|
|
|
|
PlaceholderMapGetKey,
|
|
|
|
PL_DHashVoidPtrKeyStub,
|
|
|
|
PlaceholderMapMatchEntry,
|
|
|
|
PL_DHashMoveEntryStub,
|
|
|
|
PL_DHashClearEntryStub,
|
|
|
|
PL_DHashFinalizeStub,
|
|
|
|
NULL
|
|
|
|
};
|
1999-08-04 07:39:34 +04:00
|
|
|
|
2001-12-06 08:45:07 +03:00
|
|
|
//----------------------------------------------------------------------
|
1999-08-04 07:39:34 +04:00
|
|
|
|
2001-12-06 08:45:07 +03:00
|
|
|
struct PropertyListMapEntry : public PLDHashEntryHdr {
|
|
|
|
nsIFrame *key;
|
|
|
|
void *value;
|
|
|
|
};
|
1999-08-04 07:39:34 +04:00
|
|
|
|
2001-12-06 08:45:07 +03:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
|
|
|
|
struct PrimaryFrameMapEntry : public PLDHashEntryHdr {
|
2002-01-05 18:22:52 +03:00
|
|
|
// key (the content node) can almost always be obtained through the
|
|
|
|
// frame. If it weren't for the way image maps (mis)used the primary
|
|
|
|
// frame map, we'd be able to have a 2 word entry instead of a 3 word
|
|
|
|
// entry.
|
|
|
|
nsIContent *content;
|
2001-12-06 08:45:07 +03:00
|
|
|
nsIFrame *frame;
|
|
|
|
};
|
|
|
|
|
2002-01-05 18:22:52 +03:00
|
|
|
// These ops should be used if/when we switch back to a 2-word entry.
|
|
|
|
// See comment in |PrimaryFrameMapEntry| above.
|
|
|
|
#if 0
|
2001-12-06 08:45:07 +03:00
|
|
|
PR_STATIC_CALLBACK(const void *)
|
|
|
|
PrimaryFrameMapGetKey(PLDHashTable *table, PLDHashEntryHdr *hdr)
|
|
|
|
{
|
|
|
|
PrimaryFrameMapEntry *entry = NS_STATIC_CAST(PrimaryFrameMapEntry*, hdr);
|
2003-06-29 07:43:05 +04:00
|
|
|
return entry->frame->GetContent();
|
2001-12-06 08:45:07 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
PR_STATIC_CALLBACK(PRBool)
|
|
|
|
PrimaryFrameMapMatchEntry(PLDHashTable *table, const PLDHashEntryHdr *hdr,
|
|
|
|
const void *key)
|
|
|
|
{
|
|
|
|
const PrimaryFrameMapEntry *entry =
|
|
|
|
NS_STATIC_CAST(const PrimaryFrameMapEntry*, hdr);
|
2003-06-29 07:43:05 +04:00
|
|
|
return entry->frame->GetContent() == key;
|
2001-12-06 08:45:07 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static PLDHashTableOps PrimaryFrameMapOps = {
|
|
|
|
PL_DHashAllocTable,
|
|
|
|
PL_DHashFreeTable,
|
|
|
|
PrimaryFrameMapGetKey,
|
|
|
|
PL_DHashVoidPtrKeyStub,
|
|
|
|
PrimaryFrameMapMatchEntry,
|
|
|
|
PL_DHashMoveEntryStub,
|
|
|
|
PL_DHashClearEntryStub,
|
|
|
|
PL_DHashFinalizeStub,
|
|
|
|
NULL
|
1999-08-04 07:39:34 +04:00
|
|
|
};
|
2002-01-05 18:22:52 +03:00
|
|
|
#endif /* 0 */
|
1999-08-04 07:39:34 +04:00
|
|
|
|
2001-12-06 08:45:07 +03:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
|
|
|
|
// XXXldb This seems too complicated for what I think it's doing, and it
|
|
|
|
// should also be using pldhash rather than plhash to use less memory.
|
2001-01-28 02:06:33 +03:00
|
|
|
MOZ_DECL_CTOR_COUNTER(UndisplayedNode)
|
1999-10-09 00:41:19 +04:00
|
|
|
|
2000-03-25 00:50:40 +03:00
|
|
|
class UndisplayedNode {
|
|
|
|
public:
|
2003-02-22 03:32:13 +03:00
|
|
|
UndisplayedNode(nsIContent* aContent, nsStyleContext* aStyle)
|
2003-01-21 03:47:14 +03:00
|
|
|
: mContent(aContent),
|
|
|
|
mStyle(aStyle),
|
|
|
|
mNext(nsnull)
|
1999-10-02 08:25:29 +04:00
|
|
|
{
|
1999-10-09 00:41:19 +04:00
|
|
|
MOZ_COUNT_CTOR(UndisplayedNode);
|
1999-10-02 08:25:29 +04:00
|
|
|
}
|
2003-01-21 03:47:14 +03:00
|
|
|
|
|
|
|
~UndisplayedNode()
|
1999-10-02 08:25:29 +04:00
|
|
|
{
|
1999-10-09 00:41:19 +04:00
|
|
|
MOZ_COUNT_DTOR(UndisplayedNode);
|
2003-01-21 03:47:14 +03:00
|
|
|
delete mNext;
|
1999-10-02 08:25:29 +04:00
|
|
|
}
|
|
|
|
|
2003-01-21 03:47:14 +03:00
|
|
|
nsCOMPtr<nsIContent> mContent;
|
2003-02-22 03:32:13 +03:00
|
|
|
nsRefPtr<nsStyleContext> mStyle;
|
2003-01-21 03:47:14 +03:00
|
|
|
UndisplayedNode* mNext;
|
1999-10-02 08:25:29 +04:00
|
|
|
};
|
|
|
|
|
|
|
|
class UndisplayedMap {
|
|
|
|
public:
|
|
|
|
UndisplayedMap(PRUint32 aNumBuckets = 16);
|
|
|
|
~UndisplayedMap(void);
|
|
|
|
|
|
|
|
UndisplayedNode* GetFirstNode(nsIContent* aParentContent);
|
|
|
|
|
2003-02-22 03:32:13 +03:00
|
|
|
nsresult AddNodeFor(nsIContent* aParentContent, nsIContent* aChild, nsStyleContext* aStyle);
|
1999-10-02 08:25:29 +04:00
|
|
|
|
|
|
|
nsresult RemoveNodeFor(nsIContent* aParentContent, UndisplayedNode* aNode);
|
|
|
|
nsresult RemoveNodesFor(nsIContent* aParentContent);
|
|
|
|
|
|
|
|
// Removes all entries from the hash table
|
|
|
|
void Clear(void);
|
|
|
|
|
|
|
|
protected:
|
|
|
|
PLHashEntry** GetEntryFor(nsIContent* aParentContent);
|
|
|
|
nsresult AppendNodeFor(UndisplayedNode* aNode, nsIContent* aParentContent);
|
|
|
|
|
|
|
|
PLHashTable* mTable;
|
|
|
|
PLHashEntry** mLastLookup;
|
|
|
|
};
|
|
|
|
|
1999-08-06 00:17:44 +04:00
|
|
|
//----------------------------------------------------------------------
|
1999-08-04 07:39:34 +04:00
|
|
|
|
1999-08-06 00:17:44 +04:00
|
|
|
class FrameManager;
|
1999-08-04 07:39:34 +04:00
|
|
|
|
2001-03-06 04:46:03 +03:00
|
|
|
// A CantRenderReplacedElementEvent has a weak pointer to the frame
|
|
|
|
// manager, and the frame manager has a weak pointer to the event.
|
|
|
|
// The event queue owns the event and the FrameManager will delete
|
|
|
|
// the event if it's going to go away.
|
1999-08-06 00:17:44 +04:00
|
|
|
struct CantRenderReplacedElementEvent : public PLEvent {
|
2002-07-26 07:48:24 +04:00
|
|
|
CantRenderReplacedElementEvent(FrameManager* aFrameManager, nsIFrame* aFrame, nsIPresShell* aPresShell);
|
|
|
|
~CantRenderReplacedElementEvent();
|
2003-01-21 03:47:14 +03:00
|
|
|
// XXXldb Should the pres shell maintain a reference count on a single
|
|
|
|
// dummy layout request instead of doing creation of a separate one
|
|
|
|
// here (and per-event!)?
|
2002-07-26 07:48:24 +04:00
|
|
|
nsresult AddLoadGroupRequest(nsIPresShell* aPresShell);
|
|
|
|
nsresult RemoveLoadGroupRequest();
|
1999-08-04 07:39:34 +04:00
|
|
|
|
1999-08-06 00:17:44 +04:00
|
|
|
nsIFrame* mFrame; // the frame that can't be rendered
|
|
|
|
CantRenderReplacedElementEvent* mNext; // next event in the list
|
2002-07-26 07:48:24 +04:00
|
|
|
nsCOMPtr<nsIRequest> mDummyLayoutRequest; // load group request
|
|
|
|
nsWeakPtr mPresShell; // for removing load group request later
|
1999-08-06 00:17:44 +04:00
|
|
|
};
|
1999-08-04 07:39:34 +04:00
|
|
|
|
|
|
|
class FrameManager : public nsIFrameManager
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
FrameManager();
|
|
|
|
virtual ~FrameManager();
|
|
|
|
|
|
|
|
NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW
|
|
|
|
|
|
|
|
// nsISupports
|
|
|
|
NS_DECL_ISUPPORTS
|
|
|
|
|
|
|
|
// nsIFrameManager
|
2004-01-08 01:30:53 +03:00
|
|
|
NS_IMETHOD Init(nsIPresShell* aPresShell, nsStyleSet* aStyleSet);
|
2001-03-06 04:46:03 +03:00
|
|
|
NS_IMETHOD Destroy();
|
1999-08-04 07:39:34 +04:00
|
|
|
|
1999-10-19 02:20:37 +04:00
|
|
|
// Gets and sets the root frame
|
|
|
|
NS_IMETHOD GetRootFrame(nsIFrame** aRootFrame) const;
|
|
|
|
NS_IMETHOD SetRootFrame(nsIFrame* aRootFrame);
|
|
|
|
|
2000-06-01 02:33:12 +04:00
|
|
|
// Get the canvas frame: searches from the Root frame down, may be null
|
2003-06-20 03:52:58 +04:00
|
|
|
NS_IMETHOD GetCanvasFrame(nsIFrame** aCanvasFrame) const;
|
2000-06-01 02:33:12 +04:00
|
|
|
|
1999-08-04 07:39:34 +04:00
|
|
|
// Primary frame functions
|
2003-06-20 03:52:58 +04:00
|
|
|
NS_IMETHOD GetPrimaryFrameFor(nsIContent* aContent,
|
|
|
|
nsIFrame** aPrimaryFrame);
|
1999-08-04 07:39:34 +04:00
|
|
|
NS_IMETHOD SetPrimaryFrameFor(nsIContent* aContent,
|
|
|
|
nsIFrame* aPrimaryFrame);
|
|
|
|
NS_IMETHOD ClearPrimaryFrameMap();
|
|
|
|
|
|
|
|
// Placeholder frame functions
|
|
|
|
NS_IMETHOD GetPlaceholderFrameFor(nsIFrame* aFrame,
|
|
|
|
nsIFrame** aPlaceholderFrame) const;
|
2001-12-06 08:45:07 +03:00
|
|
|
NS_IMETHOD RegisterPlaceholderFrame(nsPlaceholderFrame* aPlaceholderFrame);
|
|
|
|
NS_IMETHOD UnregisterPlaceholderFrame(nsPlaceholderFrame* aPlaceholderFrame);
|
1999-08-04 07:39:34 +04:00
|
|
|
NS_IMETHOD ClearPlaceholderFrameMap();
|
|
|
|
|
1999-10-02 08:25:29 +04:00
|
|
|
// Undisplayed content functions
|
2003-02-22 03:32:13 +03:00
|
|
|
virtual nsStyleContext* GetUndisplayedContent(nsIContent* aContent);
|
2003-06-20 03:52:58 +04:00
|
|
|
virtual void SetUndisplayedContent(nsIContent* aContent,
|
|
|
|
nsStyleContext* aStyleContext);
|
|
|
|
virtual void ChangeUndisplayedContent(nsIContent* aContent,
|
|
|
|
nsStyleContext* aStyleContext);
|
|
|
|
NS_IMETHOD ClearUndisplayedContentIn(nsIContent* aContent,
|
|
|
|
nsIContent* aParentContent);
|
1999-10-02 08:25:29 +04:00
|
|
|
NS_IMETHOD ClearAllUndisplayedContentIn(nsIContent* aParentContent);
|
|
|
|
NS_IMETHOD ClearUndisplayedContentMap();
|
|
|
|
|
1999-08-04 07:39:34 +04:00
|
|
|
// Functions for manipulating the frame model
|
2003-06-20 03:52:58 +04:00
|
|
|
NS_IMETHOD AppendFrames(nsIFrame* aParentFrame,
|
1999-08-04 07:39:34 +04:00
|
|
|
nsIAtom* aListName,
|
|
|
|
nsIFrame* aFrameList);
|
2003-06-20 03:52:58 +04:00
|
|
|
NS_IMETHOD InsertFrames(nsIFrame* aParentFrame,
|
1999-08-04 07:39:34 +04:00
|
|
|
nsIAtom* aListName,
|
|
|
|
nsIFrame* aPrevFrame,
|
|
|
|
nsIFrame* aFrameList);
|
2003-06-20 03:52:58 +04:00
|
|
|
NS_IMETHOD RemoveFrame(nsIFrame* aParentFrame,
|
1999-08-04 07:39:34 +04:00
|
|
|
nsIAtom* aListName,
|
|
|
|
nsIFrame* aOldFrame);
|
2003-06-20 03:52:58 +04:00
|
|
|
NS_IMETHOD ReplaceFrame(nsIFrame* aParentFrame,
|
1999-08-04 07:39:34 +04:00
|
|
|
nsIAtom* aListName,
|
|
|
|
nsIFrame* aOldFrame,
|
|
|
|
nsIFrame* aNewFrame);
|
1999-08-06 00:17:44 +04:00
|
|
|
|
2003-06-20 03:52:58 +04:00
|
|
|
NS_IMETHOD CantRenderReplacedElement(nsIFrame* aFrame);
|
1999-08-06 00:17:44 +04:00
|
|
|
|
|
|
|
NS_IMETHOD NotifyDestroyingFrame(nsIFrame* aFrame);
|
1999-08-04 07:39:34 +04:00
|
|
|
|
2003-06-20 03:52:58 +04:00
|
|
|
NS_IMETHOD ReParentStyleContext(nsIFrame* aFrame,
|
2003-02-22 03:32:13 +03:00
|
|
|
nsStyleContext* aNewParentContext);
|
2003-06-20 03:52:58 +04:00
|
|
|
NS_IMETHOD ComputeStyleChangeFor(nsIFrame* aFrame,
|
1999-10-16 03:14:44 +04:00
|
|
|
PRInt32 aAttrNameSpaceID,
|
|
|
|
nsIAtom* aAttribute,
|
1999-09-21 11:53:14 +04:00
|
|
|
nsStyleChangeList& aChangeList,
|
2002-08-24 18:41:28 +04:00
|
|
|
nsChangeHint aMinChange,
|
|
|
|
nsChangeHint& aTopLevelChange);
|
2003-06-20 03:52:58 +04:00
|
|
|
NS_IMETHOD HasAttributeDependentStyle(nsIContent *aContent,
|
2003-02-22 19:10:53 +03:00
|
|
|
nsIAtom *aAttribute,
|
|
|
|
PRInt32 aModType,
|
2004-01-14 04:36:35 +03:00
|
|
|
nsReStyleHint *aResult);
|
1999-09-04 03:35:41 +04:00
|
|
|
|
2000-06-15 04:35:46 +04:00
|
|
|
// Capture state from the entire frame heirarchy and store in aState
|
2003-06-20 03:52:58 +04:00
|
|
|
NS_IMETHOD CaptureFrameState(nsIFrame* aFrame,
|
1999-10-26 08:44:41 +04:00
|
|
|
nsILayoutHistoryState* aState);
|
2003-06-20 03:52:58 +04:00
|
|
|
NS_IMETHOD RestoreFrameState(nsIFrame* aFrame,
|
1999-10-26 08:44:41 +04:00
|
|
|
nsILayoutHistoryState* aState);
|
2000-06-15 04:35:46 +04:00
|
|
|
// Add/restore state for one frame (special, global type, like scroll position)
|
2003-06-20 03:52:58 +04:00
|
|
|
NS_IMETHOD CaptureFrameStateFor(nsIFrame* aFrame,
|
|
|
|
nsILayoutHistoryState* aState,
|
|
|
|
nsIStatefulFrame::SpecialStateID aID = nsIStatefulFrame::eNoID);
|
|
|
|
NS_IMETHOD RestoreFrameStateFor(nsIFrame* aFrame,
|
|
|
|
nsILayoutHistoryState* aState,
|
|
|
|
nsIStatefulFrame::SpecialStateID aID = nsIStatefulFrame::eNoID);
|
1999-10-16 04:55:48 +04:00
|
|
|
// Gets and sets properties on a given frame
|
|
|
|
NS_IMETHOD GetFrameProperty(nsIFrame* aFrame,
|
|
|
|
nsIAtom* aPropertyName,
|
1999-10-19 08:52:33 +04:00
|
|
|
PRUint32 aOptions,
|
1999-10-16 04:55:48 +04:00
|
|
|
void** aPropertyValue);
|
2002-12-04 03:58:52 +03:00
|
|
|
NS_IMETHOD SetFrameProperty(nsIFrame* aFrame,
|
|
|
|
nsIAtom* aPropertyName,
|
|
|
|
void* aPropertyValue,
|
|
|
|
NSFramePropertyDtorFunc aPropDtorFunc);
|
1999-10-16 04:55:48 +04:00
|
|
|
NS_IMETHOD RemoveFrameProperty(nsIFrame* aFrame,
|
|
|
|
nsIAtom* aPropertyName);
|
|
|
|
|
1999-09-21 11:53:14 +04:00
|
|
|
#ifdef NS_DEBUG
|
2003-06-20 03:52:58 +04:00
|
|
|
NS_IMETHOD DebugVerifyStyleTree(nsIFrame* aFrame);
|
1999-09-21 11:53:14 +04:00
|
|
|
#endif
|
|
|
|
|
1999-10-16 04:55:48 +04:00
|
|
|
struct PropertyList {
|
2002-12-04 03:58:52 +03:00
|
|
|
nsCOMPtr<nsIAtom> mName; // property name
|
|
|
|
PLDHashTable mFrameValueMap; // map of frame/value pairs
|
|
|
|
NSFramePropertyDtorFunc mDtorFunc; // property specific value dtor function
|
|
|
|
PropertyList* mNext;
|
1999-10-21 09:11:43 +04:00
|
|
|
|
2002-12-04 03:58:52 +03:00
|
|
|
PropertyList(nsIAtom* aName,
|
|
|
|
NSFramePropertyDtorFunc aDtorFunc);
|
1999-10-16 04:55:48 +04:00
|
|
|
~PropertyList();
|
|
|
|
|
|
|
|
// Removes the property associated with the given frame, and destroys
|
|
|
|
// the property value
|
1999-10-21 09:11:43 +04:00
|
|
|
PRBool RemovePropertyForFrame(nsIPresContext* aPresContext, nsIFrame* aFrame);
|
1999-10-19 18:41:55 +04:00
|
|
|
|
2001-12-06 08:45:07 +03:00
|
|
|
// Destroy all remaining properties (without removing them)
|
|
|
|
void Destroy(nsIPresContext* aPresContext);
|
1999-10-16 04:55:48 +04:00
|
|
|
};
|
2001-12-06 08:45:07 +03:00
|
|
|
private:
|
1999-10-16 04:55:48 +04:00
|
|
|
|
2003-06-20 03:52:58 +04:00
|
|
|
nsIPresShell* GetPresShell() const { return mPresShell; }
|
|
|
|
nsIPresContext* GetPresContext() const {
|
|
|
|
return mPresShell->GetPresContext();
|
|
|
|
}
|
|
|
|
|
1999-10-18 23:02:09 +04:00
|
|
|
nsIPresShell* mPresShell; // weak link, because the pres shell owns us
|
2004-01-08 01:30:53 +03:00
|
|
|
nsStyleSet* mStyleSet; // weak link. pres shell holds a reference
|
1999-10-19 02:20:37 +04:00
|
|
|
nsIFrame* mRootFrame;
|
2001-12-06 08:45:07 +03:00
|
|
|
PLDHashTable mPrimaryFrameMap;
|
|
|
|
PLDHashTable mPlaceholderMap;
|
1999-10-02 08:25:29 +04:00
|
|
|
UndisplayedMap* mUndisplayedMap;
|
1999-08-06 00:17:44 +04:00
|
|
|
CantRenderReplacedElementEvent* mPostedEvents;
|
1999-10-16 04:55:48 +04:00
|
|
|
PropertyList* mPropertyList;
|
2002-03-10 09:47:42 +03:00
|
|
|
PRBool mIsDestroyingFrames;
|
1999-10-02 08:25:29 +04:00
|
|
|
|
1999-11-24 09:03:41 +03:00
|
|
|
void ReResolveStyleContext(nsIPresContext* aPresContext,
|
1999-09-21 11:53:14 +04:00
|
|
|
nsIFrame* aFrame,
|
|
|
|
nsIContent* aParentContent,
|
1999-10-16 03:14:44 +04:00
|
|
|
PRInt32 aAttrNameSpaceID,
|
|
|
|
nsIAtom* aAttribute,
|
1999-09-21 11:53:14 +04:00
|
|
|
nsStyleChangeList& aChangeList,
|
2002-08-24 18:41:28 +04:00
|
|
|
nsChangeHint aMinChange,
|
|
|
|
nsChangeHint& aResultChange);
|
1999-09-21 11:53:14 +04:00
|
|
|
|
2001-03-06 04:46:03 +03:00
|
|
|
nsresult RevokePostedEvents();
|
1999-08-06 00:17:44 +04:00
|
|
|
CantRenderReplacedElementEvent** FindPostedEventFor(nsIFrame* aFrame);
|
|
|
|
void DequeuePostedEventFor(nsIFrame* aFrame);
|
1999-10-19 18:41:55 +04:00
|
|
|
void DestroyPropertyList(nsIPresContext* aPresContext);
|
1999-10-16 04:55:48 +04:00
|
|
|
PropertyList* GetPropertyListFor(nsIAtom* aPropertyName) const;
|
1999-10-19 18:41:55 +04:00
|
|
|
void RemoveAllPropertiesFor(nsIPresContext* aPresContext, nsIFrame* aFrame);
|
1999-08-06 00:17:44 +04:00
|
|
|
|
1999-08-06 18:34:32 +04:00
|
|
|
friend struct CantRenderReplacedElementEvent;
|
|
|
|
static void HandlePLEvent(CantRenderReplacedElementEvent* aEvent);
|
|
|
|
static void DestroyPLEvent(CantRenderReplacedElementEvent* aEvent);
|
1999-08-04 07:39:34 +04:00
|
|
|
};
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
|
2003-03-05 18:08:41 +03:00
|
|
|
nsresult
|
1999-08-04 07:39:34 +04:00
|
|
|
NS_NewFrameManager(nsIFrameManager** aInstancePtrResult)
|
|
|
|
{
|
1999-10-21 09:11:43 +04:00
|
|
|
NS_ENSURE_ARG_POINTER(aInstancePtrResult);
|
1999-08-06 18:34:32 +04:00
|
|
|
if (!aInstancePtrResult) {
|
1999-08-04 07:39:34 +04:00
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
}
|
|
|
|
FrameManager* it = new FrameManager;
|
1999-08-06 18:34:32 +04:00
|
|
|
if (!it) {
|
1999-08-04 07:39:34 +04:00
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
}
|
2000-02-03 01:24:56 +03:00
|
|
|
return it->QueryInterface(NS_GET_IID(nsIFrameManager), (void **)aInstancePtrResult);
|
1999-08-04 07:39:34 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
FrameManager::FrameManager()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
FrameManager::~FrameManager()
|
|
|
|
{
|
2001-03-06 04:46:03 +03:00
|
|
|
NS_ASSERTION(!mPresShell, "FrameManager::Destroy never called");
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMPL_ISUPPORTS1(FrameManager, nsIFrameManager)
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
FrameManager::Init(nsIPresShell* aPresShell,
|
2004-01-08 01:30:53 +03:00
|
|
|
nsStyleSet* aStyleSet)
|
2001-03-06 04:46:03 +03:00
|
|
|
{
|
|
|
|
NS_ASSERTION(aPresShell, "null aPresShell");
|
|
|
|
NS_ASSERTION(aStyleSet, "null aStyleSet");
|
|
|
|
|
|
|
|
mPresShell = aPresShell;
|
|
|
|
mStyleSet = aStyleSet;
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
FrameManager::Destroy()
|
|
|
|
{
|
|
|
|
NS_ASSERTION(mPresShell, "Frame manager already shut down.");
|
|
|
|
|
1999-10-19 18:41:55 +04:00
|
|
|
nsCOMPtr<nsIPresContext> presContext;
|
|
|
|
mPresShell->GetPresContext(getter_AddRefs(presContext));
|
|
|
|
|
1999-10-19 02:20:37 +04:00
|
|
|
// Destroy the frame hierarchy. Don't destroy the property lists until after
|
|
|
|
// we've destroyed the frame hierarchy because some frames may expect to be
|
|
|
|
// able to retrieve their properties during destruction
|
2001-12-01 03:22:00 +03:00
|
|
|
mPresShell->SetIgnoreFrameDestruction(PR_TRUE);
|
2002-03-10 09:47:42 +03:00
|
|
|
|
|
|
|
mIsDestroyingFrames = PR_TRUE; // This flag prevents GetPrimaryFrameFor from returning pointers to destroyed frames
|
|
|
|
|
1999-10-19 02:20:37 +04:00
|
|
|
if (mRootFrame) {
|
1999-11-24 09:03:41 +03:00
|
|
|
mRootFrame->Destroy(presContext);
|
1999-10-19 02:20:37 +04:00
|
|
|
mRootFrame = nsnull;
|
|
|
|
}
|
|
|
|
|
2001-12-06 08:45:07 +03:00
|
|
|
if (mPrimaryFrameMap.ops) {
|
|
|
|
PL_DHashTableFinish(&mPrimaryFrameMap);
|
|
|
|
mPrimaryFrameMap.ops = nsnull;
|
|
|
|
}
|
|
|
|
if (mPlaceholderMap.ops) {
|
|
|
|
PL_DHashTableFinish(&mPlaceholderMap);
|
|
|
|
mPlaceholderMap.ops = nsnull;
|
|
|
|
}
|
1999-10-19 23:06:37 +04:00
|
|
|
delete mUndisplayedMap;
|
1999-10-19 18:41:55 +04:00
|
|
|
DestroyPropertyList(presContext);
|
1999-08-04 07:39:34 +04:00
|
|
|
|
2001-03-06 04:46:03 +03:00
|
|
|
// If we're not going to be used anymore, we should revoke the
|
|
|
|
// pending |CantRenderReplacedElementEvent|s being sent to us.
|
|
|
|
nsresult rv = RevokePostedEvents();
|
|
|
|
NS_ASSERTION(NS_SUCCEEDED(rv), "RevokePostedEvents failed: might crash");
|
1999-10-18 23:02:09 +04:00
|
|
|
|
2001-03-06 04:46:03 +03:00
|
|
|
mPresShell = nsnull; // mPresShell isn't valid anymore. We
|
|
|
|
// won't use it, either, but we check it
|
|
|
|
// at the start of every function so that we'll
|
|
|
|
// be OK when nsIPresShell is converted to IDL.
|
1999-10-18 23:02:09 +04:00
|
|
|
|
2001-03-06 04:46:03 +03:00
|
|
|
return rv;
|
1999-08-04 07:39:34 +04:00
|
|
|
}
|
|
|
|
|
1999-10-19 02:20:37 +04:00
|
|
|
NS_IMETHODIMP
|
|
|
|
FrameManager::GetRootFrame(nsIFrame** aRootFrame) const
|
|
|
|
{
|
2001-03-06 04:46:03 +03:00
|
|
|
NS_ENSURE_TRUE(mPresShell, NS_ERROR_NOT_AVAILABLE);
|
1999-10-19 02:20:37 +04:00
|
|
|
NS_ENSURE_ARG_POINTER(aRootFrame);
|
|
|
|
*aRootFrame = mRootFrame;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
FrameManager::SetRootFrame(nsIFrame* aRootFrame)
|
|
|
|
{
|
2001-03-06 04:46:03 +03:00
|
|
|
NS_ENSURE_TRUE(mPresShell, NS_ERROR_NOT_AVAILABLE);
|
1999-10-19 02:20:37 +04:00
|
|
|
NS_PRECONDITION(!mRootFrame, "already have a root frame");
|
|
|
|
if (mRootFrame) {
|
|
|
|
return NS_ERROR_UNEXPECTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
mRootFrame = aRootFrame;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2000-06-01 02:33:12 +04:00
|
|
|
NS_IMETHODIMP
|
2003-06-20 03:52:58 +04:00
|
|
|
FrameManager::GetCanvasFrame(nsIFrame** aCanvasFrame) const
|
2000-06-01 02:33:12 +04:00
|
|
|
{
|
2001-03-06 04:46:03 +03:00
|
|
|
NS_ENSURE_TRUE(mPresShell, NS_ERROR_NOT_AVAILABLE);
|
2000-06-01 02:33:12 +04:00
|
|
|
NS_PRECONDITION(aCanvasFrame, "aCanvasFrame argument cannot be null");
|
|
|
|
|
|
|
|
*aCanvasFrame = nsnull;
|
|
|
|
if (mRootFrame) {
|
|
|
|
// walk the children of the root frame looking for a frame with type==canvas
|
|
|
|
// start at the root
|
|
|
|
nsIFrame* childFrame = mRootFrame;
|
|
|
|
while (childFrame) {
|
|
|
|
// get each sibling of the child and check them, startig at the child
|
|
|
|
nsIFrame *siblingFrame = childFrame;
|
|
|
|
while (siblingFrame) {
|
2003-10-31 23:19:18 +03:00
|
|
|
if (siblingFrame->GetType() == nsLayoutAtoms::canvasFrame) {
|
2000-06-01 02:33:12 +04:00
|
|
|
// this is it: set the out-arg and stop looking
|
|
|
|
*aCanvasFrame = siblingFrame;
|
|
|
|
break;
|
|
|
|
} else {
|
2003-06-29 07:43:05 +04:00
|
|
|
siblingFrame = siblingFrame->GetNextSibling();
|
2000-06-01 02:33:12 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
// move on to the child's child
|
2004-01-09 17:20:53 +03:00
|
|
|
childFrame = childFrame->GetFirstChild(nsnull);
|
2000-06-01 02:33:12 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
1999-08-06 00:17:44 +04:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
|
1999-08-04 07:39:34 +04:00
|
|
|
// Primary frame functions
|
|
|
|
NS_IMETHODIMP
|
1999-08-05 07:09:22 +04:00
|
|
|
FrameManager::GetPrimaryFrameFor(nsIContent* aContent, nsIFrame** aResult)
|
1999-08-04 07:39:34 +04:00
|
|
|
{
|
2002-03-19 03:32:41 +03:00
|
|
|
NS_ASSERTION(aResult, "null out-param not supported");
|
|
|
|
*aResult = nsnull; // initialize out param (before possibly returning due to null args/members)
|
|
|
|
|
2001-03-06 04:46:03 +03:00
|
|
|
NS_ENSURE_TRUE(mPresShell, NS_ERROR_NOT_AVAILABLE);
|
1999-10-21 09:11:43 +04:00
|
|
|
NS_ENSURE_ARG_POINTER(aContent);
|
1999-08-04 07:39:34 +04:00
|
|
|
|
2002-03-10 09:47:42 +03:00
|
|
|
if (mIsDestroyingFrames) {
|
|
|
|
#ifdef DEBUG
|
|
|
|
printf("GetPrimaryFrameFor() called while FrameManager is being destroyed!\n");
|
|
|
|
#endif
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
2001-12-06 08:45:07 +03:00
|
|
|
if (mPrimaryFrameMap.ops) {
|
|
|
|
PrimaryFrameMapEntry *entry = NS_STATIC_CAST(PrimaryFrameMapEntry*,
|
|
|
|
PL_DHashTableOperate(&mPrimaryFrameMap, aContent, PL_DHASH_LOOKUP));
|
|
|
|
if (PL_DHASH_ENTRY_IS_BUSY(entry)) {
|
|
|
|
*aResult = entry->frame;
|
|
|
|
} else {
|
2001-01-17 01:10:04 +03:00
|
|
|
// XXX: todo: Add a lookup into the undisplay map to skip searches
|
|
|
|
// if we already know the content has no frame.
|
|
|
|
// nsCSSFrameConstructor calls SetUndisplayedContent() for every
|
|
|
|
// content node that has display: none.
|
|
|
|
// Today, the undisplay map doesn't quite support what we need.
|
|
|
|
// We need to see if we can add a method to make a search for aContent
|
|
|
|
// very fast in the embedded hash table.
|
|
|
|
// This would almost completely remove the lookup penalty for things
|
|
|
|
// like <SCRIPT> and comments in very large documents.
|
1999-08-04 07:39:34 +04:00
|
|
|
nsCOMPtr<nsIPresContext> presContext;
|
|
|
|
|
|
|
|
// Give the frame construction code the opportunity to return the
|
|
|
|
// frame that maps the content object
|
|
|
|
mPresShell->GetPresContext(getter_AddRefs(presContext));
|
2001-01-17 01:10:04 +03:00
|
|
|
NS_ASSERTION(presContext, "bad presContext");
|
2004-01-08 01:30:53 +03:00
|
|
|
if (!presContext) {
|
2001-01-17 01:10:04 +03:00
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
}
|
|
|
|
|
|
|
|
// if the prev sibling of aContent has a cached primary frame,
|
|
|
|
// pass that data in to the style set to speed things up
|
|
|
|
// if any methods in here fail, don't report that failure
|
|
|
|
// we're just trying to enhance performance here, not test for correctness
|
|
|
|
nsFindFrameHint hint;
|
2003-07-29 01:25:13 +04:00
|
|
|
nsIContent* parent = aContent->GetParent();
|
|
|
|
if (parent)
|
2001-01-17 01:10:04 +03:00
|
|
|
{
|
2003-09-27 08:18:26 +04:00
|
|
|
PRInt32 index = parent->IndexOf(aContent);
|
|
|
|
if (index > 0) // no use looking if it's the first child
|
2001-01-17 01:10:04 +03:00
|
|
|
{
|
2003-09-27 08:18:26 +04:00
|
|
|
nsIContent *prevSibling;
|
2003-11-19 04:20:56 +03:00
|
|
|
nsIAtom *tag;
|
2002-01-11 23:10:46 +03:00
|
|
|
do {
|
2003-09-27 08:18:26 +04:00
|
|
|
prevSibling = parent->GetChildAt(--index);
|
2003-11-19 04:20:56 +03:00
|
|
|
tag = prevSibling->Tag();
|
2002-01-11 23:10:46 +03:00
|
|
|
} while (index &&
|
|
|
|
(tag == nsLayoutAtoms::textTagName ||
|
|
|
|
tag == nsLayoutAtoms::commentTagName ||
|
|
|
|
tag == nsLayoutAtoms::processingInstructionTagName));
|
|
|
|
if (prevSibling) {
|
2001-12-06 08:45:07 +03:00
|
|
|
entry = NS_STATIC_CAST(PrimaryFrameMapEntry*,
|
2003-09-27 08:18:26 +04:00
|
|
|
PL_DHashTableOperate(&mPrimaryFrameMap, prevSibling,
|
2001-12-06 08:45:07 +03:00
|
|
|
PL_DHASH_LOOKUP));
|
|
|
|
if (PL_DHASH_ENTRY_IS_BUSY(entry))
|
|
|
|
hint.mPrimaryFrameForPrevSibling = entry->frame;
|
2001-01-17 01:10:04 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// walk the frame tree to find the frame that maps aContent.
|
|
|
|
// Use the hint if we have it.
|
2004-01-08 01:30:53 +03:00
|
|
|
mPresShell->FrameConstructor()->
|
|
|
|
FindPrimaryFrameFor(presContext, this, aContent, aResult,
|
|
|
|
hint.mPrimaryFrameForPrevSibling ? &hint : nsnull);
|
2001-01-17 01:10:04 +03:00
|
|
|
|
1999-08-04 07:39:34 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
FrameManager::SetPrimaryFrameFor(nsIContent* aContent,
|
|
|
|
nsIFrame* aPrimaryFrame)
|
|
|
|
{
|
2001-03-06 04:46:03 +03:00
|
|
|
NS_ENSURE_TRUE(mPresShell, NS_ERROR_NOT_AVAILABLE);
|
1999-10-21 09:11:43 +04:00
|
|
|
NS_ENSURE_ARG_POINTER(aContent);
|
2001-01-17 01:10:04 +03:00
|
|
|
// it's ok if aPrimaryFrame is null
|
1999-08-04 07:39:34 +04:00
|
|
|
|
|
|
|
// If aPrimaryFrame is NULL, then remove the mapping
|
|
|
|
if (!aPrimaryFrame) {
|
2001-12-06 08:45:07 +03:00
|
|
|
if (mPrimaryFrameMap.ops) {
|
|
|
|
PL_DHashTableOperate(&mPrimaryFrameMap, aContent, PL_DHASH_REMOVE);
|
1999-08-04 07:39:34 +04:00
|
|
|
}
|
|
|
|
} else {
|
2002-01-05 18:22:52 +03:00
|
|
|
// This code should be used if/when we switch back to a 2-word entry
|
|
|
|
// in the primary frame map.
|
|
|
|
#if 0
|
2003-06-29 07:43:05 +04:00
|
|
|
NS_PRECONDITION(aPrimaryFrame->GetContent() == aContent, "wrong content");
|
2001-12-06 08:45:07 +03:00
|
|
|
#endif
|
|
|
|
|
|
|
|
// Create a new hashtable if necessary
|
|
|
|
if (!mPrimaryFrameMap.ops) {
|
2002-01-05 18:22:52 +03:00
|
|
|
if (!PL_DHashTableInit(&mPrimaryFrameMap, PL_DHashGetStubOps(), nsnull,
|
2001-12-06 08:45:07 +03:00
|
|
|
sizeof(PrimaryFrameMapEntry), 16)) {
|
|
|
|
mPrimaryFrameMap.ops = nsnull;
|
1999-08-04 07:39:34 +04:00
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add a mapping to the hash table
|
2001-12-06 08:45:07 +03:00
|
|
|
PrimaryFrameMapEntry *entry = NS_STATIC_CAST(PrimaryFrameMapEntry*,
|
|
|
|
PL_DHashTableOperate(&mPrimaryFrameMap, aContent, PL_DHASH_ADD));
|
2001-12-06 22:53:37 +03:00
|
|
|
#ifdef DEBUG_dbaron
|
2001-12-06 08:45:07 +03:00
|
|
|
if (entry->frame) {
|
|
|
|
NS_WARNING("already have primary frame for content");
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
entry->frame = aPrimaryFrame;
|
2002-01-05 18:22:52 +03:00
|
|
|
entry->content = aContent;
|
1999-08-04 07:39:34 +04:00
|
|
|
}
|
2001-01-17 01:10:04 +03:00
|
|
|
|
1999-08-04 07:39:34 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
FrameManager::ClearPrimaryFrameMap()
|
|
|
|
{
|
2001-03-06 04:46:03 +03:00
|
|
|
NS_ENSURE_TRUE(mPresShell, NS_ERROR_NOT_AVAILABLE);
|
2001-12-06 08:45:07 +03:00
|
|
|
if (mPrimaryFrameMap.ops) {
|
|
|
|
PL_DHashTableFinish(&mPrimaryFrameMap);
|
|
|
|
mPrimaryFrameMap.ops = nsnull;
|
1999-08-04 07:39:34 +04:00
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Placeholder frame functions
|
|
|
|
NS_IMETHODIMP
|
|
|
|
FrameManager::GetPlaceholderFrameFor(nsIFrame* aFrame,
|
|
|
|
nsIFrame** aResult) const
|
|
|
|
{
|
2001-03-06 04:46:03 +03:00
|
|
|
NS_ENSURE_TRUE(mPresShell, NS_ERROR_NOT_AVAILABLE);
|
2001-12-06 08:45:07 +03:00
|
|
|
NS_PRECONDITION(aFrame, "null param unexpected");
|
|
|
|
NS_PRECONDITION(aResult, "null out param unexpected");
|
1999-08-04 07:39:34 +04:00
|
|
|
|
2001-12-06 08:45:07 +03:00
|
|
|
if (mPlaceholderMap.ops) {
|
|
|
|
PlaceholderMapEntry *entry = NS_STATIC_CAST(PlaceholderMapEntry*,
|
|
|
|
PL_DHashTableOperate(NS_CONST_CAST(PLDHashTable*, &mPlaceholderMap),
|
|
|
|
aFrame, PL_DHASH_LOOKUP));
|
|
|
|
if (PL_DHASH_ENTRY_IS_BUSY(entry)) {
|
|
|
|
*aResult = entry->placeholderFrame;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
1999-08-04 07:39:34 +04:00
|
|
|
}
|
|
|
|
|
2001-12-06 08:45:07 +03:00
|
|
|
*aResult = nsnull;
|
1999-08-04 07:39:34 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2001-12-06 08:45:07 +03:00
|
|
|
FrameManager::RegisterPlaceholderFrame(nsPlaceholderFrame* aPlaceholderFrame)
|
1999-08-04 07:39:34 +04:00
|
|
|
{
|
2001-03-06 04:46:03 +03:00
|
|
|
NS_ENSURE_TRUE(mPresShell, NS_ERROR_NOT_AVAILABLE);
|
2001-12-06 08:45:07 +03:00
|
|
|
NS_PRECONDITION(aPlaceholderFrame, "null param unexpected");
|
2003-10-31 23:19:18 +03:00
|
|
|
NS_PRECONDITION(nsLayoutAtoms::placeholderFrame == aPlaceholderFrame->GetType(),
|
2001-12-06 08:45:07 +03:00
|
|
|
"unexpected frame type");
|
|
|
|
if (!mPlaceholderMap.ops) {
|
|
|
|
if (!PL_DHashTableInit(&mPlaceholderMap, &PlaceholderMapOps, nsnull,
|
|
|
|
sizeof(PlaceholderMapEntry), 16)) {
|
|
|
|
mPlaceholderMap.ops = nsnull;
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
1999-08-04 07:39:34 +04:00
|
|
|
}
|
|
|
|
}
|
2001-12-06 08:45:07 +03:00
|
|
|
PlaceholderMapEntry *entry = NS_STATIC_CAST(PlaceholderMapEntry*,
|
|
|
|
PL_DHashTableOperate(&mPlaceholderMap,
|
|
|
|
aPlaceholderFrame->GetOutOfFlowFrame(),
|
|
|
|
PL_DHASH_ADD));
|
|
|
|
if (!entry)
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
2002-11-12 06:30:13 +03:00
|
|
|
|
|
|
|
NS_ASSERTION(!entry->placeholderFrame, "Registering a placeholder for a frame that already has a placeholder!");
|
2001-12-06 08:45:07 +03:00
|
|
|
entry->placeholderFrame = aPlaceholderFrame;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
FrameManager::UnregisterPlaceholderFrame(nsPlaceholderFrame* aPlaceholderFrame)
|
|
|
|
{
|
|
|
|
NS_ENSURE_TRUE(mPresShell, NS_ERROR_NOT_AVAILABLE);
|
|
|
|
NS_PRECONDITION(aPlaceholderFrame, "null param unexpected");
|
2003-10-31 23:19:18 +03:00
|
|
|
NS_PRECONDITION(nsLayoutAtoms::placeholderFrame == aPlaceholderFrame->GetType(),
|
2001-12-06 08:45:07 +03:00
|
|
|
"unexpected frame type");
|
|
|
|
|
2002-06-29 03:25:57 +04:00
|
|
|
/*
|
|
|
|
* nsCSSFrameConstructor::ReconstructDocElementHierarchy calls
|
|
|
|
* ClearPlaceholderFrameMap and _then_ removes the fixed-positioned
|
|
|
|
* frames one by one. As these are removed they call
|
|
|
|
* UnregisterPlaceholderFrame on their placeholders, but this is all
|
|
|
|
* happening when mPlaceholderMap is already finished, so there is
|
|
|
|
* nothing to do here. See bug 144479.
|
|
|
|
*/
|
|
|
|
if (mPlaceholderMap.ops) {
|
|
|
|
PL_DHashTableOperate(&mPlaceholderMap,
|
|
|
|
aPlaceholderFrame->GetOutOfFlowFrame(),
|
|
|
|
PL_DHASH_REMOVE);
|
|
|
|
}
|
|
|
|
|
1999-08-04 07:39:34 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
FrameManager::ClearPlaceholderFrameMap()
|
|
|
|
{
|
2001-03-06 04:46:03 +03:00
|
|
|
NS_ENSURE_TRUE(mPresShell, NS_ERROR_NOT_AVAILABLE);
|
2001-12-06 08:45:07 +03:00
|
|
|
if (mPlaceholderMap.ops) {
|
|
|
|
PL_DHashTableFinish(&mPlaceholderMap);
|
|
|
|
mPlaceholderMap.ops = nsnull;
|
1999-08-04 07:39:34 +04:00
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
1999-08-06 00:17:44 +04:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
|
2003-02-22 03:32:13 +03:00
|
|
|
nsStyleContext*
|
|
|
|
FrameManager::GetUndisplayedContent(nsIContent* aContent)
|
2001-06-01 02:19:43 +04:00
|
|
|
{
|
2003-02-22 03:32:13 +03:00
|
|
|
if (!aContent || !mUndisplayedMap)
|
|
|
|
return nsnull;
|
2002-05-01 04:36:50 +04:00
|
|
|
|
2003-07-29 01:25:13 +04:00
|
|
|
nsIContent* parent = aContent->GetParent();
|
2002-05-01 04:36:50 +04:00
|
|
|
if (!parent)
|
2003-02-22 03:32:13 +03:00
|
|
|
return nsnull;
|
2002-05-01 04:36:50 +04:00
|
|
|
|
|
|
|
for (UndisplayedNode* node = mUndisplayedMap->GetFirstNode(parent);
|
|
|
|
node; node = node->mNext) {
|
2003-02-22 03:32:13 +03:00
|
|
|
if (node->mContent == aContent)
|
|
|
|
return node->mStyle;
|
2002-05-01 04:36:50 +04:00
|
|
|
}
|
2003-02-22 03:32:13 +03:00
|
|
|
|
|
|
|
return nsnull;
|
2001-06-01 02:19:43 +04:00
|
|
|
}
|
|
|
|
|
2003-02-22 03:32:13 +03:00
|
|
|
void
|
1999-10-02 08:25:29 +04:00
|
|
|
FrameManager::SetUndisplayedContent(nsIContent* aContent,
|
2003-02-22 03:32:13 +03:00
|
|
|
nsStyleContext* aStyleContext)
|
1999-10-02 08:25:29 +04:00
|
|
|
{
|
2003-02-22 03:32:13 +03:00
|
|
|
if (!mPresShell)
|
|
|
|
return;
|
2002-04-03 01:14:43 +04:00
|
|
|
|
|
|
|
#ifdef DEBUG_UNDISPLAYED_MAP
|
|
|
|
static int i = 0;
|
|
|
|
printf("SetUndisplayedContent(%d): p=%p \n", i++, (void *)aContent);
|
|
|
|
#endif
|
|
|
|
|
1999-10-02 08:25:29 +04:00
|
|
|
if (! mUndisplayedMap) {
|
|
|
|
mUndisplayedMap = new UndisplayedMap;
|
|
|
|
}
|
|
|
|
if (mUndisplayedMap) {
|
2003-07-29 01:25:13 +04:00
|
|
|
nsIContent* parent = aContent->GetParent();
|
2002-04-03 01:14:43 +04:00
|
|
|
NS_ASSERTION(parent, "undisplayed content must have a parent");
|
1999-10-02 08:25:29 +04:00
|
|
|
if (parent) {
|
2003-02-22 03:32:13 +03:00
|
|
|
mUndisplayedMap->AddNodeFor(parent, aContent, aStyleContext);
|
1999-10-02 08:25:29 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-06-19 01:54:51 +04:00
|
|
|
void
|
|
|
|
FrameManager::ChangeUndisplayedContent(nsIContent* aContent,
|
|
|
|
nsStyleContext* aStyleContext)
|
|
|
|
{
|
|
|
|
if (!mPresShell)
|
|
|
|
return;
|
|
|
|
NS_ASSERTION(mUndisplayedMap, "no existing undisplayed content");
|
|
|
|
|
|
|
|
#ifdef DEBUG_UNDISPLAYED_MAP
|
|
|
|
static int i = 0;
|
|
|
|
printf("ChangeUndisplayedContent(%d): p=%p \n", i++, (void *)aContent);
|
|
|
|
#endif
|
|
|
|
|
2003-07-29 01:25:13 +04:00
|
|
|
for (UndisplayedNode* node = mUndisplayedMap->GetFirstNode(aContent->GetParent());
|
2003-06-19 01:54:51 +04:00
|
|
|
node; node = node->mNext) {
|
|
|
|
if (node->mContent == aContent) {
|
|
|
|
node->mStyle = aStyleContext;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_NOTREACHED("no existing undisplayed content");
|
|
|
|
}
|
|
|
|
|
1999-10-02 08:25:29 +04:00
|
|
|
NS_IMETHODIMP
|
|
|
|
FrameManager::ClearUndisplayedContentIn(nsIContent* aContent, nsIContent* aParentContent)
|
|
|
|
{
|
2001-03-06 04:46:03 +03:00
|
|
|
NS_ENSURE_TRUE(mPresShell, NS_ERROR_NOT_AVAILABLE);
|
2002-04-03 01:14:43 +04:00
|
|
|
|
|
|
|
#ifdef DEBUG_UNDISPLAYED_MAP
|
|
|
|
static int i = 0;
|
|
|
|
printf("ClearUndisplayedContent(%d): content=%p parent=%p --> ", i++, (void *)aContent, (void*)aParentContent);
|
|
|
|
#endif
|
|
|
|
|
1999-10-02 08:25:29 +04:00
|
|
|
if (mUndisplayedMap) {
|
|
|
|
UndisplayedNode* node = mUndisplayedMap->GetFirstNode(aParentContent);
|
|
|
|
while (node) {
|
|
|
|
if (node->mContent == aContent) {
|
2002-04-03 01:14:43 +04:00
|
|
|
nsresult rv = mUndisplayedMap->RemoveNodeFor(aParentContent, node);
|
|
|
|
|
|
|
|
#ifdef DEBUG_UNDISPLAYED_MAP
|
|
|
|
printf( "REMOVED! (rv=%d)\n", (int)rv);
|
|
|
|
#endif
|
|
|
|
#ifdef DEBUG
|
|
|
|
// make sure that there are no more entries for the same content
|
2003-02-22 03:32:13 +03:00
|
|
|
nsStyleContext *context = GetUndisplayedContent(aContent);
|
2002-04-03 01:14:43 +04:00
|
|
|
NS_ASSERTION(context == nsnull, "Found more undisplayed content data after removal");
|
|
|
|
#endif
|
|
|
|
return rv;
|
1999-10-02 08:25:29 +04:00
|
|
|
}
|
|
|
|
node = node->mNext;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
FrameManager::ClearAllUndisplayedContentIn(nsIContent* aParentContent)
|
|
|
|
{
|
2001-03-06 04:46:03 +03:00
|
|
|
NS_ENSURE_TRUE(mPresShell, NS_ERROR_NOT_AVAILABLE);
|
2002-04-03 01:14:43 +04:00
|
|
|
|
|
|
|
#ifdef DEBUG_UNDISPLAYED_MAP
|
|
|
|
static int i = 0;
|
|
|
|
printf("ClearAllUndisplayedContentIn(%d): parent=%p \n", i++, (void*)aParentContent);
|
|
|
|
#endif
|
|
|
|
|
1999-10-02 08:25:29 +04:00
|
|
|
if (mUndisplayedMap) {
|
|
|
|
return mUndisplayedMap->RemoveNodesFor(aParentContent);
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
FrameManager::ClearUndisplayedContentMap()
|
|
|
|
{
|
2001-03-06 04:46:03 +03:00
|
|
|
NS_ENSURE_TRUE(mPresShell, NS_ERROR_NOT_AVAILABLE);
|
2002-04-03 01:14:43 +04:00
|
|
|
|
|
|
|
#ifdef DEBUG_UNDISPLAYED_MAP
|
|
|
|
static int i = 0;
|
|
|
|
printf("ClearUndisplayedContentMap(%d)\n", i++);
|
|
|
|
#endif
|
|
|
|
|
1999-10-02 08:25:29 +04:00
|
|
|
if (mUndisplayedMap) {
|
|
|
|
mUndisplayedMap->Clear();
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
|
1999-08-04 07:39:34 +04:00
|
|
|
NS_IMETHODIMP
|
2003-06-20 03:52:58 +04:00
|
|
|
FrameManager::AppendFrames(nsIFrame* aParentFrame,
|
1999-08-04 07:39:34 +04:00
|
|
|
nsIAtom* aListName,
|
|
|
|
nsIFrame* aFrameList)
|
|
|
|
{
|
2001-03-06 04:46:03 +03:00
|
|
|
NS_ENSURE_TRUE(mPresShell, NS_ERROR_NOT_AVAILABLE);
|
2003-06-20 03:52:58 +04:00
|
|
|
return aParentFrame->AppendFrames(GetPresContext(), *GetPresShell(),
|
|
|
|
aListName, aFrameList);
|
1999-08-04 07:39:34 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2003-06-20 03:52:58 +04:00
|
|
|
FrameManager::InsertFrames(nsIFrame* aParentFrame,
|
1999-08-04 07:39:34 +04:00
|
|
|
nsIAtom* aListName,
|
|
|
|
nsIFrame* aPrevFrame,
|
|
|
|
nsIFrame* aFrameList)
|
|
|
|
{
|
2001-03-06 04:46:03 +03:00
|
|
|
NS_ENSURE_TRUE(mPresShell, NS_ERROR_NOT_AVAILABLE);
|
2001-03-09 06:29:00 +03:00
|
|
|
#ifdef IBMBIDI
|
|
|
|
if (aPrevFrame) {
|
|
|
|
// Insert aFrameList after the last bidi continuation of aPrevFrame.
|
|
|
|
nsIFrame* nextBidi;
|
|
|
|
for (; ;) {
|
|
|
|
GetFrameProperty(aPrevFrame, nsLayoutAtoms::nextBidi, 0, (void**) &nextBidi);
|
|
|
|
if (!nextBidi) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
aPrevFrame = nextBidi;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif // IBMBIDI
|
|
|
|
|
2003-06-20 03:52:58 +04:00
|
|
|
return aParentFrame->InsertFrames(GetPresContext(), *GetPresShell(),
|
|
|
|
aListName, aPrevFrame, aFrameList);
|
1999-08-04 07:39:34 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2003-06-20 03:52:58 +04:00
|
|
|
FrameManager::RemoveFrame(nsIFrame* aParentFrame,
|
1999-08-04 07:39:34 +04:00
|
|
|
nsIAtom* aListName,
|
|
|
|
nsIFrame* aOldFrame)
|
|
|
|
{
|
2001-03-06 04:46:03 +03:00
|
|
|
NS_ENSURE_TRUE(mPresShell, NS_ERROR_NOT_AVAILABLE);
|
2000-11-28 01:00:33 +03:00
|
|
|
|
2001-03-09 06:29:00 +03:00
|
|
|
#ifdef IBMBIDI
|
|
|
|
// Don't let the parent remove next bidi. In the other cases the it should NOT be removed.
|
|
|
|
nsIFrame* nextBidi;
|
|
|
|
GetFrameProperty(aOldFrame, nsLayoutAtoms::nextBidi, 0, (void**) &nextBidi);
|
|
|
|
if (nextBidi) {
|
2003-06-20 03:52:58 +04:00
|
|
|
RemoveFrame(aParentFrame, aListName, nextBidi);
|
2001-03-09 06:29:00 +03:00
|
|
|
}
|
|
|
|
#endif // IBMBIDI
|
|
|
|
|
2003-06-20 03:52:58 +04:00
|
|
|
return aParentFrame->RemoveFrame(GetPresContext(), *GetPresShell(),
|
|
|
|
aListName, aOldFrame);
|
1999-08-04 07:39:34 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2003-06-20 03:52:58 +04:00
|
|
|
FrameManager::ReplaceFrame(nsIFrame* aParentFrame,
|
1999-08-04 07:39:34 +04:00
|
|
|
nsIAtom* aListName,
|
|
|
|
nsIFrame* aOldFrame,
|
|
|
|
nsIFrame* aNewFrame)
|
|
|
|
{
|
2001-03-06 04:46:03 +03:00
|
|
|
NS_ENSURE_TRUE(mPresShell, NS_ERROR_NOT_AVAILABLE);
|
2003-06-20 03:52:58 +04:00
|
|
|
return aParentFrame->ReplaceFrame(GetPresContext(), *GetPresShell(),
|
|
|
|
aListName, aOldFrame, aNewFrame);
|
1999-08-04 07:39:34 +04:00
|
|
|
}
|
|
|
|
|
1999-08-06 00:17:44 +04:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
FrameManager::NotifyDestroyingFrame(nsIFrame* aFrame)
|
|
|
|
{
|
2001-03-06 04:46:03 +03:00
|
|
|
NS_ENSURE_TRUE(mPresShell, NS_ERROR_NOT_AVAILABLE);
|
1999-08-06 00:17:44 +04:00
|
|
|
// Dequeue and destroy and posted events for this frame
|
|
|
|
DequeuePostedEventFor(aFrame);
|
1999-10-16 04:55:48 +04:00
|
|
|
|
|
|
|
// Remove all properties associated with the frame
|
1999-10-19 18:41:55 +04:00
|
|
|
nsCOMPtr<nsIPresContext> presContext;
|
|
|
|
mPresShell->GetPresContext(getter_AddRefs(presContext));
|
|
|
|
|
|
|
|
RemoveAllPropertiesFor(presContext, aFrame);
|
2001-12-11 08:39:36 +03:00
|
|
|
|
|
|
|
#ifdef DEBUG
|
2001-12-11 22:16:15 +03:00
|
|
|
if (mPrimaryFrameMap.ops) {
|
|
|
|
PrimaryFrameMapEntry *entry = NS_STATIC_CAST(PrimaryFrameMapEntry*,
|
2003-06-29 07:43:05 +04:00
|
|
|
PL_DHashTableOperate(&mPrimaryFrameMap, aFrame->GetContent(), PL_DHASH_LOOKUP));
|
2001-12-11 22:16:15 +03:00
|
|
|
NS_ASSERTION(!PL_DHASH_ENTRY_IS_BUSY(entry) || entry->frame != aFrame,
|
2002-01-05 18:22:52 +03:00
|
|
|
"frame was not removed from primary frame map before "
|
2001-12-11 22:16:15 +03:00
|
|
|
"destruction or was readded to map after being removed");
|
|
|
|
}
|
2001-12-11 08:39:36 +03:00
|
|
|
#endif
|
|
|
|
|
1999-08-06 00:17:44 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2001-03-06 04:46:03 +03:00
|
|
|
nsresult
|
1999-08-06 00:17:44 +04:00
|
|
|
FrameManager::RevokePostedEvents()
|
|
|
|
{
|
2001-03-06 04:46:03 +03:00
|
|
|
nsresult rv = NS_OK;
|
2000-06-05 07:37:33 +04:00
|
|
|
#ifdef NOISY_EVENTS
|
2000-10-29 02:17:53 +04:00
|
|
|
printf("%p ~RevokePostedEvents() start\n", this);
|
2000-06-05 07:37:33 +04:00
|
|
|
#endif
|
1999-08-06 00:17:44 +04:00
|
|
|
if (mPostedEvents) {
|
|
|
|
mPostedEvents = nsnull;
|
|
|
|
|
|
|
|
// Revoke any events in the event queue that are owned by us
|
|
|
|
nsIEventQueueService* eventService;
|
|
|
|
|
|
|
|
rv = nsServiceManager::GetService(kEventQueueServiceCID,
|
2001-01-04 23:44:42 +03:00
|
|
|
NS_GET_IID(nsIEventQueueService),
|
1999-08-06 00:17:44 +04:00
|
|
|
(nsISupports **)&eventService);
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
nsCOMPtr<nsIEventQueue> eventQueue;
|
1999-11-30 03:32:43 +03:00
|
|
|
rv = eventService->GetThreadEventQueue(NS_CURRENT_THREAD,
|
1999-08-06 00:17:44 +04:00
|
|
|
getter_AddRefs(eventQueue));
|
|
|
|
nsServiceManager::ReleaseService(kEventQueueServiceCID, eventService);
|
|
|
|
|
|
|
|
if (NS_SUCCEEDED(rv) && eventQueue) {
|
2001-03-06 04:46:03 +03:00
|
|
|
rv = eventQueue->RevokeEvents(this);
|
1999-08-06 00:17:44 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2000-06-05 07:37:33 +04:00
|
|
|
#ifdef NOISY_EVENTS
|
2000-10-29 02:17:53 +04:00
|
|
|
printf("%p ~RevokePostedEvents() end\n", this);
|
2000-06-05 07:37:33 +04:00
|
|
|
#endif
|
2001-03-06 04:46:03 +03:00
|
|
|
return rv;
|
1999-08-06 00:17:44 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
CantRenderReplacedElementEvent**
|
|
|
|
FrameManager::FindPostedEventFor(nsIFrame* aFrame)
|
|
|
|
{
|
|
|
|
CantRenderReplacedElementEvent** event = &mPostedEvents;
|
|
|
|
|
|
|
|
while (*event) {
|
|
|
|
if ((*event)->mFrame == aFrame) {
|
|
|
|
return event;
|
|
|
|
}
|
|
|
|
event = &(*event)->mNext;
|
|
|
|
}
|
|
|
|
|
|
|
|
return event;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
FrameManager::DequeuePostedEventFor(nsIFrame* aFrame)
|
|
|
|
{
|
|
|
|
// If there's a posted event for this frame, then remove it
|
|
|
|
CantRenderReplacedElementEvent** event = FindPostedEventFor(aFrame);
|
|
|
|
if (*event) {
|
|
|
|
CantRenderReplacedElementEvent* tmp = *event;
|
|
|
|
|
|
|
|
// Remove it from our linked list of posted events
|
|
|
|
*event = (*event)->mNext;
|
|
|
|
|
|
|
|
// Dequeue it from the event queue
|
|
|
|
nsIEventQueueService* eventService;
|
|
|
|
nsresult rv;
|
|
|
|
|
|
|
|
rv = nsServiceManager::GetService(kEventQueueServiceCID,
|
2001-01-04 23:44:42 +03:00
|
|
|
NS_GET_IID(nsIEventQueueService),
|
1999-08-06 00:17:44 +04:00
|
|
|
(nsISupports **)&eventService);
|
2001-03-06 04:46:03 +03:00
|
|
|
NS_ASSERTION(NS_SUCCEEDED(rv),
|
|
|
|
"will crash soon due to event holding dangling pointer to frame");
|
1999-08-06 00:17:44 +04:00
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
nsCOMPtr<nsIEventQueue> eventQueue;
|
1999-11-30 03:32:43 +03:00
|
|
|
rv = eventService->GetThreadEventQueue(NS_CURRENT_THREAD,
|
1999-08-06 00:17:44 +04:00
|
|
|
getter_AddRefs(eventQueue));
|
|
|
|
nsServiceManager::ReleaseService(kEventQueueServiceCID, eventService);
|
|
|
|
|
2001-03-06 04:46:03 +03:00
|
|
|
NS_ASSERTION(NS_SUCCEEDED(rv) && eventQueue,
|
|
|
|
"will crash soon due to event holding dangling pointer to frame");
|
1999-08-06 00:17:44 +04:00
|
|
|
if (NS_SUCCEEDED(rv) && eventQueue) {
|
|
|
|
PLEventQueue* plqueue;
|
|
|
|
|
|
|
|
eventQueue->GetPLEventQueue(&plqueue);
|
2001-03-06 04:46:03 +03:00
|
|
|
NS_ASSERTION(plqueue,
|
|
|
|
"will crash soon due to event holding dangling pointer to frame");
|
1999-08-06 00:17:44 +04:00
|
|
|
if (plqueue) {
|
2003-05-17 05:10:50 +04:00
|
|
|
// Remove the event and then destroy it
|
1999-08-06 00:17:44 +04:00
|
|
|
PL_DequeueEvent(tmp, plqueue);
|
2003-05-17 05:10:50 +04:00
|
|
|
PL_DestroyEvent(tmp);
|
1999-08-06 00:17:44 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2001-03-06 04:46:03 +03:00
|
|
|
FrameManager::HandlePLEvent(CantRenderReplacedElementEvent* aEvent)
|
|
|
|
{
|
2000-06-05 07:37:33 +04:00
|
|
|
#ifdef NOISY_EVENTS
|
2000-10-29 02:17:53 +04:00
|
|
|
printf("FrameManager::HandlePLEvent() start for FM %p\n", aEvent->owner);
|
2000-06-05 07:37:33 +04:00
|
|
|
#endif
|
1999-08-06 18:34:32 +04:00
|
|
|
FrameManager* frameManager = (FrameManager*)aEvent->owner;
|
2001-03-06 04:46:03 +03:00
|
|
|
NS_ASSERTION(frameManager, "null frame manager");
|
2000-03-28 05:08:36 +04:00
|
|
|
|
2001-03-06 04:46:03 +03:00
|
|
|
if (!frameManager->mPresShell) {
|
|
|
|
NS_ASSERTION(frameManager->mPresShell,
|
|
|
|
"event not removed from queue on shutdown");
|
|
|
|
return;
|
|
|
|
}
|
1999-08-06 00:17:44 +04:00
|
|
|
|
2001-03-06 04:46:03 +03:00
|
|
|
// Remove the posted event from the linked list
|
|
|
|
CantRenderReplacedElementEvent** events = &frameManager->mPostedEvents;
|
|
|
|
while (*events) {
|
|
|
|
if (*events == aEvent) {
|
|
|
|
*events = (*events)->mNext;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
events = &(*events)->mNext;
|
|
|
|
NS_ASSERTION(*events, "event not in queue");
|
2000-03-28 05:08:36 +04:00
|
|
|
}
|
2001-03-06 04:46:03 +03:00
|
|
|
|
|
|
|
// Notify the style system and then process any reflow commands that
|
|
|
|
// are generated
|
|
|
|
nsCOMPtr<nsIPresContext> presContext;
|
|
|
|
frameManager->mPresShell->GetPresContext(getter_AddRefs(presContext));
|
2004-01-08 01:30:53 +03:00
|
|
|
frameManager->mPresShell->FrameConstructor()->
|
|
|
|
CantRenderReplacedElement(frameManager->mPresShell, presContext,
|
|
|
|
aEvent->mFrame);
|
|
|
|
|
2000-06-05 07:37:33 +04:00
|
|
|
#ifdef NOISY_EVENTS
|
2000-10-29 02:17:53 +04:00
|
|
|
printf("FrameManager::HandlePLEvent() end for FM %p\n", aEvent->owner);
|
2000-06-05 07:37:33 +04:00
|
|
|
#endif
|
1999-08-06 00:17:44 +04:00
|
|
|
}
|
|
|
|
|
1999-08-06 18:34:32 +04:00
|
|
|
void
|
|
|
|
FrameManager::DestroyPLEvent(CantRenderReplacedElementEvent* aEvent)
|
1999-08-06 00:17:44 +04:00
|
|
|
{
|
|
|
|
delete aEvent;
|
|
|
|
}
|
|
|
|
|
|
|
|
CantRenderReplacedElementEvent::CantRenderReplacedElementEvent(FrameManager* aFrameManager,
|
2002-07-26 07:48:24 +04:00
|
|
|
nsIFrame* aFrame,
|
|
|
|
nsIPresShell* aPresShell)
|
1999-08-06 00:17:44 +04:00
|
|
|
{
|
2001-03-06 04:46:03 +03:00
|
|
|
PL_InitEvent(this, aFrameManager,
|
|
|
|
(PLHandleEventProc)&FrameManager::HandlePLEvent,
|
1999-08-06 18:34:32 +04:00
|
|
|
(PLDestroyEventProc)&FrameManager::DestroyPLEvent);
|
1999-08-06 00:17:44 +04:00
|
|
|
mFrame = aFrame;
|
2002-07-26 07:48:24 +04:00
|
|
|
|
2003-10-31 23:19:18 +03:00
|
|
|
if (nsLayoutAtoms::objectFrame == aFrame->GetType()) {
|
2002-07-26 07:48:24 +04:00
|
|
|
AddLoadGroupRequest(aPresShell);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
CantRenderReplacedElementEvent::~CantRenderReplacedElementEvent()
|
|
|
|
{
|
|
|
|
RemoveLoadGroupRequest();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add a load group request in order to delay the onLoad handler when we have
|
|
|
|
// pending replacements
|
|
|
|
nsresult CantRenderReplacedElementEvent::AddLoadGroupRequest(nsIPresShell* aPresShell)
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIDocument> doc;
|
|
|
|
aPresShell->GetDocument(getter_AddRefs(doc));
|
|
|
|
if (!doc) return NS_ERROR_FAILURE;
|
|
|
|
|
|
|
|
nsresult rv = nsDummyLayoutRequest::Create(getter_AddRefs(mDummyLayoutRequest), aPresShell);
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
if (!mDummyLayoutRequest) return NS_ERROR_FAILURE;
|
|
|
|
|
2003-10-22 10:09:48 +04:00
|
|
|
nsCOMPtr<nsILoadGroup> loadGroup = doc->GetDocumentLoadGroup();
|
2002-07-26 07:48:24 +04:00
|
|
|
if (!loadGroup) return NS_ERROR_FAILURE;
|
|
|
|
|
|
|
|
rv = mDummyLayoutRequest->SetLoadGroup(loadGroup);
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
|
2003-07-25 23:06:59 +04:00
|
|
|
mPresShell = do_GetWeakReference(aPresShell);
|
2002-07-26 07:48:24 +04:00
|
|
|
|
|
|
|
return loadGroup->AddRequest(mDummyLayoutRequest, nsnull);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Remove the load group request added above
|
|
|
|
nsresult CantRenderReplacedElementEvent::RemoveLoadGroupRequest()
|
|
|
|
{
|
|
|
|
nsresult rv = NS_OK;
|
|
|
|
|
|
|
|
if (mDummyLayoutRequest) {
|
|
|
|
nsCOMPtr<nsIRequest> request = mDummyLayoutRequest;
|
|
|
|
mDummyLayoutRequest = nsnull;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIPresShell> presShell = do_QueryReferent(mPresShell);
|
|
|
|
if (!presShell) return NS_ERROR_FAILURE;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDocument> doc;
|
|
|
|
presShell->GetDocument(getter_AddRefs(doc));
|
|
|
|
if (!doc) return NS_ERROR_FAILURE;;
|
|
|
|
|
2003-10-22 10:09:48 +04:00
|
|
|
nsCOMPtr<nsILoadGroup> loadGroup = doc->GetDocumentLoadGroup();
|
2002-07-26 07:48:24 +04:00
|
|
|
if (!loadGroup) return NS_ERROR_FAILURE;
|
|
|
|
|
|
|
|
rv = loadGroup->RemoveRequest(request, nsnull, NS_OK);
|
|
|
|
}
|
|
|
|
return rv;
|
1999-08-06 00:17:44 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2003-06-20 03:52:58 +04:00
|
|
|
FrameManager::CantRenderReplacedElement(nsIFrame* aFrame)
|
1999-08-06 00:17:44 +04:00
|
|
|
{
|
2001-03-06 04:46:03 +03:00
|
|
|
NS_ENSURE_TRUE(mPresShell, NS_ERROR_NOT_AVAILABLE);
|
2000-06-05 07:37:33 +04:00
|
|
|
#ifdef NOISY_EVENTS
|
2000-10-29 02:17:53 +04:00
|
|
|
printf("%p FrameManager::CantRenderReplacedElement called\n", this);
|
2000-06-05 07:37:33 +04:00
|
|
|
#endif
|
1999-08-06 00:17:44 +04:00
|
|
|
|
|
|
|
// We need to notify the style stystem, but post the notification so it
|
|
|
|
// doesn't happen now
|
2001-04-24 04:05:33 +04:00
|
|
|
nsresult rv;
|
|
|
|
nsCOMPtr<nsIEventQueueService> eventService = do_GetService(kEventQueueServiceCID, &rv);
|
|
|
|
|
|
|
|
if (eventService) {
|
1999-08-06 00:17:44 +04:00
|
|
|
nsCOMPtr<nsIEventQueue> eventQueue;
|
1999-11-30 03:32:43 +03:00
|
|
|
rv = eventService->GetThreadEventQueue(NS_CURRENT_THREAD,
|
1999-08-06 00:17:44 +04:00
|
|
|
getter_AddRefs(eventQueue));
|
|
|
|
|
|
|
|
if (NS_SUCCEEDED(rv) && eventQueue) {
|
|
|
|
// Verify that there isn't already a posted event associated with
|
2001-04-24 04:05:33 +04:00
|
|
|
// this frame.
|
|
|
|
if (*FindPostedEventFor(aFrame))
|
|
|
|
return NS_OK;
|
|
|
|
|
1999-08-06 00:17:44 +04:00
|
|
|
CantRenderReplacedElementEvent* ev;
|
|
|
|
|
|
|
|
// Create a new event
|
2002-07-26 07:48:24 +04:00
|
|
|
ev = new CantRenderReplacedElementEvent(this, aFrame, mPresShell);
|
1999-08-06 00:17:44 +04:00
|
|
|
|
|
|
|
// Post the event
|
2003-10-06 05:46:31 +04:00
|
|
|
rv = eventQueue->PostEvent(ev);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
NS_ERROR("failed to post event");
|
|
|
|
PL_DestroyEvent(ev);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// Add the event to our linked list of posted events
|
|
|
|
ev->mNext = mPostedEvents;
|
|
|
|
mPostedEvents = ev;
|
|
|
|
}
|
1999-08-06 00:17:44 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
1999-09-21 11:53:14 +04:00
|
|
|
#ifdef NS_DEBUG
|
|
|
|
static void
|
2003-02-22 03:32:13 +03:00
|
|
|
DumpContext(nsIFrame* aFrame, nsStyleContext* aContext)
|
1999-09-21 11:53:14 +04:00
|
|
|
{
|
|
|
|
if (aFrame) {
|
|
|
|
fputs("frame: ", stdout);
|
|
|
|
nsAutoString name;
|
1999-11-02 01:12:45 +03:00
|
|
|
nsIFrameDebug* frameDebug;
|
|
|
|
|
2000-02-03 01:24:56 +03:00
|
|
|
if (NS_SUCCEEDED(aFrame->QueryInterface(NS_GET_IID(nsIFrameDebug), (void**)&frameDebug))) {
|
1999-11-02 01:12:45 +03:00
|
|
|
frameDebug->GetFrameName(name);
|
2001-10-16 07:53:44 +04:00
|
|
|
fputs(NS_LossyConvertUCS2toASCII(name).get(), stdout);
|
1999-11-02 01:12:45 +03:00
|
|
|
}
|
2001-03-06 04:46:03 +03:00
|
|
|
fprintf(stdout, " (%p)", NS_STATIC_CAST(void*, aFrame));
|
1999-09-21 11:53:14 +04:00
|
|
|
}
|
|
|
|
if (aContext) {
|
2001-03-06 04:46:03 +03:00
|
|
|
fprintf(stdout, " style: %p ", NS_STATIC_CAST(void*, aContext));
|
1999-09-21 11:53:14 +04:00
|
|
|
|
2003-10-17 06:38:37 +04:00
|
|
|
nsIAtom* pseudoTag = aContext->GetPseudoType();
|
1999-09-21 11:53:14 +04:00
|
|
|
if (pseudoTag) {
|
|
|
|
nsAutoString buffer;
|
|
|
|
pseudoTag->ToString(buffer);
|
2001-10-16 07:53:44 +04:00
|
|
|
fputs(NS_LossyConvertUCS2toASCII(buffer).get(), stdout);
|
1999-09-21 11:53:14 +04:00
|
|
|
fputs(" ", stdout);
|
|
|
|
}
|
|
|
|
|
2001-10-24 04:01:09 +04:00
|
|
|
/* XXXdwh fix debugging here. Need to add a List method to nsRuleNode
|
2001-06-01 02:19:43 +04:00
|
|
|
and have the context call list on its rule node.
|
1999-09-21 11:53:14 +04:00
|
|
|
PRInt32 count = aContext->GetStyleRuleCount();
|
|
|
|
if (0 < count) {
|
|
|
|
fputs("{\n", stdout);
|
|
|
|
nsISupportsArray* rules = aContext->GetStyleRules();
|
|
|
|
PRInt32 ix;
|
|
|
|
for (ix = 0; ix < count; ix++) {
|
|
|
|
nsIStyleRule* rule = (nsIStyleRule*)rules->ElementAt(ix);
|
|
|
|
rule->List(stdout, 1);
|
|
|
|
NS_RELEASE(rule);
|
|
|
|
}
|
|
|
|
NS_RELEASE(rules);
|
|
|
|
fputs("}\n", stdout);
|
|
|
|
}
|
2001-06-01 02:19:43 +04:00
|
|
|
else
|
|
|
|
*/
|
|
|
|
{
|
1999-09-21 11:53:14 +04:00
|
|
|
fputs("{}\n", stdout);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-03-16 18:26:56 +03:00
|
|
|
static void
|
2003-02-22 03:32:13 +03:00
|
|
|
VerifySameTree(nsStyleContext* aContext1, nsStyleContext* aContext2)
|
2002-03-16 18:26:56 +03:00
|
|
|
{
|
2003-02-22 03:32:13 +03:00
|
|
|
nsStyleContext* top1 = aContext1;
|
|
|
|
nsStyleContext* top2 = aContext2;
|
|
|
|
nsStyleContext* parent;
|
2002-03-16 18:26:56 +03:00
|
|
|
for (;;) {
|
2002-10-09 05:46:15 +04:00
|
|
|
parent = top1->GetParent();
|
2002-03-16 18:26:56 +03:00
|
|
|
if (!parent)
|
|
|
|
break;
|
|
|
|
top1 = parent;
|
|
|
|
}
|
|
|
|
for (;;) {
|
2002-10-09 05:46:15 +04:00
|
|
|
parent = top2->GetParent();
|
2002-03-16 18:26:56 +03:00
|
|
|
if (!parent)
|
|
|
|
break;
|
|
|
|
top2 = parent;
|
|
|
|
}
|
|
|
|
if (top1 != top2)
|
|
|
|
printf("Style contexts are not in the same style context tree.\n");
|
|
|
|
}
|
|
|
|
|
2000-09-13 02:47:09 +04:00
|
|
|
static void
|
|
|
|
VerifyContextParent(nsIPresContext* aPresContext, nsIFrame* aFrame,
|
2003-02-22 03:32:13 +03:00
|
|
|
nsStyleContext* aContext, nsStyleContext* aParentContext)
|
2000-09-13 02:47:09 +04:00
|
|
|
{
|
|
|
|
// get the contexts not provided
|
|
|
|
if (!aContext) {
|
2003-02-22 03:32:13 +03:00
|
|
|
aContext = aFrame->GetStyleContext();
|
2000-09-13 02:47:09 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!aParentContext) {
|
|
|
|
// Get the correct parent context from the frame
|
|
|
|
// - if the frame is a placeholder, we get the out of flow frame's context
|
|
|
|
// as the parent context instead of asking the frame
|
2002-03-27 05:38:13 +03:00
|
|
|
|
|
|
|
// get the parent context from the frame (indirectly)
|
|
|
|
nsIFrame* providerFrame = nsnull;
|
|
|
|
PRBool providerIsChild;
|
|
|
|
aFrame->GetParentStyleContextFrame(aPresContext,
|
|
|
|
&providerFrame, &providerIsChild);
|
|
|
|
if (providerFrame)
|
2003-02-22 03:32:13 +03:00
|
|
|
aParentContext = providerFrame->GetStyleContext();
|
2002-03-27 05:38:13 +03:00
|
|
|
// aParentContext could still be null
|
2000-09-13 02:47:09 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_ASSERTION(aContext, "Failure to get required contexts");
|
2003-02-22 03:32:13 +03:00
|
|
|
nsStyleContext* actualParentContext = aContext->GetParent();
|
2000-09-13 02:47:09 +04:00
|
|
|
|
|
|
|
if (aParentContext) {
|
|
|
|
if (aParentContext != actualParentContext) {
|
|
|
|
DumpContext(aFrame, aContext);
|
|
|
|
if (aContext == aParentContext) {
|
|
|
|
fputs("Using parent's style context\n\n", stdout);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
fputs("Wrong parent style context: ", stdout);
|
|
|
|
DumpContext(nsnull, actualParentContext);
|
|
|
|
fputs("should be using: ", stdout);
|
|
|
|
DumpContext(nsnull, aParentContext);
|
2002-03-16 18:26:56 +03:00
|
|
|
VerifySameTree(actualParentContext, aParentContext);
|
2000-09-13 02:47:09 +04:00
|
|
|
fputs("\n", stdout);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (actualParentContext) {
|
|
|
|
DumpContext(aFrame, aContext);
|
|
|
|
fputs("Has parent context: ", stdout);
|
|
|
|
DumpContext(nsnull, actualParentContext);
|
|
|
|
fputs("Should be null\n\n", stdout);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2003-02-22 03:32:13 +03:00
|
|
|
VerifyStyleTree(nsIPresContext* aPresContext, nsIFrame* aFrame, nsStyleContext* aParentContext)
|
2000-09-13 02:47:09 +04:00
|
|
|
{
|
2003-02-22 03:32:13 +03:00
|
|
|
nsStyleContext* context = aFrame->GetStyleContext();
|
2002-03-27 05:38:13 +03:00
|
|
|
VerifyContextParent(aPresContext, aFrame, context, nsnull);
|
2000-09-13 02:47:09 +04:00
|
|
|
|
|
|
|
PRInt32 listIndex = 0;
|
|
|
|
nsIAtom* childList = nsnull;
|
|
|
|
nsIFrame* child;
|
|
|
|
|
|
|
|
do {
|
2004-01-09 17:20:53 +03:00
|
|
|
child = aFrame->GetFirstChild(childList);
|
|
|
|
while (child) {
|
2003-06-29 07:43:05 +04:00
|
|
|
if (NS_FRAME_OUT_OF_FLOW != (child->GetStateBits() & NS_FRAME_OUT_OF_FLOW)) {
|
2000-09-13 02:47:09 +04:00
|
|
|
// only do frames that are in flow
|
2003-10-31 23:19:18 +03:00
|
|
|
if (nsLayoutAtoms::placeholderFrame == child->GetType()) {
|
2000-09-13 02:47:09 +04:00
|
|
|
// placeholder: first recirse and verify the out of flow frame,
|
|
|
|
// then verify the placeholder's context
|
|
|
|
nsIFrame* outOfFlowFrame = ((nsPlaceholderFrame*)child)->GetOutOfFlowFrame();
|
|
|
|
NS_ASSERTION(outOfFlowFrame, "no out-of-flow frame");
|
|
|
|
|
|
|
|
// recurse to out of flow frame, letting the parent context get resolved
|
|
|
|
VerifyStyleTree(aPresContext, outOfFlowFrame, nsnull);
|
|
|
|
|
2002-03-27 05:38:13 +03:00
|
|
|
// verify placeholder using the parent frame's context as
|
|
|
|
// parent context
|
|
|
|
VerifyContextParent(aPresContext, child, nsnull, nsnull);
|
2000-09-13 02:47:09 +04:00
|
|
|
}
|
|
|
|
else { // regular frame
|
|
|
|
VerifyStyleTree(aPresContext, child, nsnull);
|
|
|
|
}
|
|
|
|
}
|
2003-06-29 07:43:05 +04:00
|
|
|
child = child->GetNextSibling();
|
2000-09-13 02:47:09 +04:00
|
|
|
}
|
|
|
|
|
2004-01-09 17:20:53 +03:00
|
|
|
childList = aFrame->GetAdditionalChildListName(listIndex++);
|
2000-09-13 02:47:09 +04:00
|
|
|
} while (childList);
|
|
|
|
|
|
|
|
// do additional contexts
|
|
|
|
PRInt32 contextIndex = -1;
|
2003-02-22 03:32:13 +03:00
|
|
|
while (1) {
|
|
|
|
nsStyleContext* extraContext = aFrame->GetAdditionalStyleContext(++contextIndex);
|
2000-09-13 02:47:09 +04:00
|
|
|
if (extraContext) {
|
|
|
|
VerifyContextParent(aPresContext, aFrame, extraContext, context);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2003-06-20 03:52:58 +04:00
|
|
|
FrameManager::DebugVerifyStyleTree(nsIFrame* aFrame)
|
2000-09-13 02:47:09 +04:00
|
|
|
{
|
2001-03-06 04:46:03 +03:00
|
|
|
NS_ENSURE_TRUE(mPresShell, NS_ERROR_NOT_AVAILABLE);
|
2000-09-13 02:47:09 +04:00
|
|
|
if (aFrame) {
|
2003-02-22 03:32:13 +03:00
|
|
|
nsStyleContext* context = aFrame->GetStyleContext();
|
|
|
|
nsStyleContext* parentContext = context->GetParent();
|
2003-06-20 03:52:58 +04:00
|
|
|
VerifyStyleTree(GetPresContext(), aFrame, parentContext);
|
2000-09-13 02:47:09 +04:00
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif // DEBUG
|
1999-09-21 11:53:14 +04:00
|
|
|
|
1999-09-04 03:35:41 +04:00
|
|
|
NS_IMETHODIMP
|
2003-06-20 03:52:58 +04:00
|
|
|
FrameManager::ReParentStyleContext(nsIFrame* aFrame,
|
2003-02-22 03:32:13 +03:00
|
|
|
nsStyleContext* aNewParentContext)
|
1999-09-04 03:35:41 +04:00
|
|
|
{
|
2001-03-06 04:46:03 +03:00
|
|
|
NS_ENSURE_TRUE(mPresShell, NS_ERROR_NOT_AVAILABLE);
|
1999-09-04 03:35:41 +04:00
|
|
|
nsresult result = NS_ERROR_NULL_POINTER;
|
|
|
|
if (aFrame) {
|
2003-11-13 07:31:04 +03:00
|
|
|
// DO NOT verify the style tree before reparenting. The frame
|
|
|
|
// tree has already been changed, so this check would just fail.
|
2003-02-22 03:32:13 +03:00
|
|
|
nsStyleContext* oldContext = aFrame->GetStyleContext();
|
1999-09-04 03:35:41 +04:00
|
|
|
if (oldContext) {
|
2003-06-20 03:52:58 +04:00
|
|
|
nsIPresContext *presContext = GetPresContext();
|
2003-02-22 03:32:13 +03:00
|
|
|
nsRefPtr<nsStyleContext> newContext;
|
|
|
|
result = NS_OK;
|
2003-06-20 03:52:58 +04:00
|
|
|
newContext = mStyleSet->ReParentStyleContext(presContext, oldContext,
|
2003-02-22 03:32:13 +03:00
|
|
|
aNewParentContext);
|
|
|
|
if (newContext) {
|
1999-09-04 03:35:41 +04:00
|
|
|
if (newContext != oldContext) {
|
|
|
|
PRInt32 listIndex = 0;
|
|
|
|
nsIAtom* childList = nsnull;
|
|
|
|
nsIFrame* child;
|
2003-11-13 07:11:38 +03:00
|
|
|
|
|
|
|
aFrame->SetStyleContext(presContext, newContext);
|
1999-09-04 03:35:41 +04:00
|
|
|
|
|
|
|
do {
|
2004-01-09 17:20:53 +03:00
|
|
|
child = aFrame->GetFirstChild(childList);
|
|
|
|
while (child) {
|
2003-06-29 07:43:05 +04:00
|
|
|
if (NS_FRAME_OUT_OF_FLOW != (child->GetStateBits() & NS_FRAME_OUT_OF_FLOW)) {
|
1999-09-21 11:53:14 +04:00
|
|
|
// only do frames that are in flow
|
2003-10-31 23:19:18 +03:00
|
|
|
if (nsLayoutAtoms::placeholderFrame == child->GetType()) {
|
1999-09-21 11:53:14 +04:00
|
|
|
// get out of flow frame and recurse there
|
|
|
|
nsIFrame* outOfFlowFrame = ((nsPlaceholderFrame*)child)->GetOutOfFlowFrame();
|
|
|
|
NS_ASSERTION(outOfFlowFrame, "no out-of-flow frame");
|
|
|
|
|
2003-06-20 03:52:58 +04:00
|
|
|
result = ReParentStyleContext(outOfFlowFrame, newContext);
|
1999-09-21 11:53:14 +04:00
|
|
|
|
|
|
|
// reparent placeholder's context under out of flow frame
|
2003-02-22 03:32:13 +03:00
|
|
|
nsStyleContext* outOfFlowContext = outOfFlowFrame->GetStyleContext();
|
2003-06-20 03:52:58 +04:00
|
|
|
ReParentStyleContext(child, outOfFlowContext);
|
1999-09-21 11:53:14 +04:00
|
|
|
}
|
|
|
|
else { // regular frame
|
2003-06-20 03:52:58 +04:00
|
|
|
result = ReParentStyleContext(child, newContext);
|
1999-09-21 11:53:14 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-06-29 07:43:05 +04:00
|
|
|
child = child->GetNextSibling();
|
1999-09-04 03:35:41 +04:00
|
|
|
}
|
|
|
|
|
2004-01-09 17:20:53 +03:00
|
|
|
childList = aFrame->GetAdditionalChildListName(listIndex++);
|
1999-09-04 03:35:41 +04:00
|
|
|
} while (childList);
|
|
|
|
|
|
|
|
// do additional contexts
|
|
|
|
PRInt32 contextIndex = -1;
|
2003-02-22 03:32:13 +03:00
|
|
|
while (1) {
|
|
|
|
nsStyleContext* oldExtraContext = aFrame->GetAdditionalStyleContext(++contextIndex);
|
|
|
|
if (oldExtraContext) {
|
|
|
|
nsRefPtr<nsStyleContext> newExtraContext;
|
2003-06-20 03:52:58 +04:00
|
|
|
newExtraContext = mStyleSet->ReParentStyleContext(presContext,
|
2003-02-22 03:32:13 +03:00
|
|
|
oldExtraContext,
|
|
|
|
newContext);
|
|
|
|
if (newExtraContext) {
|
|
|
|
aFrame->SetAdditionalStyleContext(contextIndex, newExtraContext);
|
1999-09-04 03:35:41 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
1999-09-21 11:53:14 +04:00
|
|
|
result = NS_OK; // ok not to have extras (or run out)
|
1999-09-04 03:35:41 +04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2003-11-13 07:31:04 +03:00
|
|
|
#ifdef DEBUG
|
2003-06-20 04:54:57 +04:00
|
|
|
VerifyStyleTree(GetPresContext(), aFrame, aNewParentContext);
|
1999-09-21 11:53:14 +04:00
|
|
|
#endif
|
1999-09-04 03:35:41 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
1999-10-16 03:14:44 +04:00
|
|
|
static PRBool
|
2003-02-22 03:32:13 +03:00
|
|
|
HasAttributeContent(nsStyleContext* aStyleContext,
|
1999-10-16 03:14:44 +04:00
|
|
|
PRInt32 aNameSpaceID,
|
|
|
|
nsIAtom* aAttribute)
|
|
|
|
{
|
|
|
|
PRBool result = PR_FALSE;
|
|
|
|
if (aStyleContext) {
|
2003-05-15 07:42:21 +04:00
|
|
|
const nsStyleContent* content = aStyleContext->GetStyleContent();
|
1999-10-16 03:14:44 +04:00
|
|
|
PRUint32 count = content->ContentCount();
|
|
|
|
while ((0 < count) && (! result)) {
|
2003-10-02 02:53:56 +04:00
|
|
|
const nsStyleContentData &data = content->ContentAt(--count);
|
|
|
|
if (eStyleContentType_Attr == data.mType) {
|
1999-10-16 03:14:44 +04:00
|
|
|
nsIAtom* attrName = nsnull;
|
|
|
|
PRInt32 attrNameSpace = kNameSpaceID_None;
|
2003-10-02 02:53:56 +04:00
|
|
|
nsAutoString contentString(data.mContent.mString);
|
1999-10-16 03:14:44 +04:00
|
|
|
PRInt32 barIndex = contentString.FindChar('|'); // CSS namespace delimiter
|
|
|
|
if (-1 != barIndex) {
|
|
|
|
nsAutoString nameSpaceVal;
|
|
|
|
contentString.Left(nameSpaceVal, barIndex);
|
|
|
|
PRInt32 error;
|
|
|
|
attrNameSpace = nameSpaceVal.ToInteger(&error, 10);
|
|
|
|
contentString.Cut(0, barIndex + 1);
|
2003-05-24 01:34:47 +04:00
|
|
|
if (!contentString.IsEmpty()) {
|
1999-10-16 03:14:44 +04:00
|
|
|
attrName = NS_NewAtom(contentString);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
attrName = NS_NewAtom(contentString);
|
|
|
|
}
|
|
|
|
if ((attrName == aAttribute) &&
|
|
|
|
((attrNameSpace == aNameSpaceID) ||
|
|
|
|
(attrNameSpace == kNameSpaceID_Unknown))) {
|
|
|
|
result = PR_TRUE;
|
|
|
|
}
|
|
|
|
NS_IF_RELEASE(attrName);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2002-08-24 18:41:28 +04:00
|
|
|
static nsChangeHint
|
2003-02-22 03:32:13 +03:00
|
|
|
CaptureChange(nsStyleContext* aOldContext, nsStyleContext* aNewContext,
|
1999-10-02 08:25:29 +04:00
|
|
|
nsIFrame* aFrame, nsIContent* aContent,
|
2002-08-24 18:41:28 +04:00
|
|
|
nsStyleChangeList& aChangeList, nsChangeHint aMinChange)
|
1999-09-21 11:53:14 +04:00
|
|
|
{
|
2002-08-24 18:41:28 +04:00
|
|
|
nsChangeHint ourChange = NS_STYLE_HINT_NONE;
|
2003-02-22 03:32:13 +03:00
|
|
|
ourChange = aOldContext->CalcStyleDifference(aNewContext);
|
2002-08-24 18:41:28 +04:00
|
|
|
if (NS_UpdateHint(aMinChange, ourChange)) {
|
1999-10-02 08:25:29 +04:00
|
|
|
aChangeList.AppendChange(aFrame, aContent, ourChange);
|
1999-09-21 11:53:14 +04:00
|
|
|
}
|
|
|
|
return aMinChange;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
1999-11-24 09:03:41 +03:00
|
|
|
FrameManager::ReResolveStyleContext(nsIPresContext* aPresContext,
|
1999-09-21 11:53:14 +04:00
|
|
|
nsIFrame* aFrame,
|
|
|
|
nsIContent* aParentContent,
|
1999-10-16 03:14:44 +04:00
|
|
|
PRInt32 aAttrNameSpaceID,
|
|
|
|
nsIAtom* aAttribute,
|
1999-09-21 11:53:14 +04:00
|
|
|
nsStyleChangeList& aChangeList,
|
2002-08-24 18:41:28 +04:00
|
|
|
nsChangeHint aMinChange,
|
|
|
|
nsChangeHint& aResultChange)
|
1999-09-21 11:53:14 +04:00
|
|
|
{
|
2002-03-16 18:26:56 +03:00
|
|
|
// XXXldb get new context from prev-in-flow if possible, to avoid
|
|
|
|
// duplication. (Or should we just let |GetContext| handle that?)
|
|
|
|
// Getting the hint would be nice too, but that's harder.
|
|
|
|
|
2003-02-22 03:32:13 +03:00
|
|
|
// XXXbryner we may be able to avoid some of the refcounting goop here.
|
|
|
|
// We do need a reference to oldContext for the lifetime of this function, and it's possible
|
|
|
|
// that the frame has the last reference to it, so AddRef it here.
|
|
|
|
|
|
|
|
nsStyleContext* oldContext = aFrame->GetStyleContext();
|
|
|
|
|
|
|
|
if (oldContext) {
|
|
|
|
oldContext->AddRef();
|
2003-10-17 06:38:37 +04:00
|
|
|
nsIAtom* pseudoTag = oldContext->GetPseudoType();
|
2003-06-29 07:43:05 +04:00
|
|
|
nsIContent* localContent = aFrame->GetContent();
|
|
|
|
nsIContent* content = localContent ? localContent : aParentContent;
|
|
|
|
|
1999-10-16 03:14:44 +04:00
|
|
|
if (aParentContent && aAttribute) { // attribute came from parent, we don't care about it here when recursing
|
2003-06-29 07:43:05 +04:00
|
|
|
if (!(aFrame->GetStateBits() & NS_FRAME_GENERATED_CONTENT)) { // keep it for generated content
|
1999-10-16 03:14:44 +04:00
|
|
|
aAttribute = nsnull;
|
|
|
|
}
|
|
|
|
}
|
1999-09-21 11:53:14 +04:00
|
|
|
|
2003-02-22 03:32:13 +03:00
|
|
|
nsStyleContext* parentContext;
|
2002-03-27 05:38:13 +03:00
|
|
|
nsIFrame* resolvedChild = nsnull;
|
|
|
|
// Get the frame providing the parent style context. If it is a
|
|
|
|
// child, then resolve the provider first.
|
2002-03-12 18:21:35 +03:00
|
|
|
nsIFrame* providerFrame = nsnull;
|
2002-03-27 05:38:13 +03:00
|
|
|
PRBool providerIsChild = PR_FALSE;
|
|
|
|
aFrame->GetParentStyleContextFrame(aPresContext,
|
|
|
|
&providerFrame, &providerIsChild);
|
|
|
|
if (!providerIsChild) {
|
|
|
|
if (providerFrame)
|
2003-02-22 03:32:13 +03:00
|
|
|
parentContext = providerFrame->GetStyleContext();
|
|
|
|
else
|
|
|
|
parentContext = nsnull;
|
2002-03-12 18:21:35 +03:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
// resolve the provider here (before aFrame below)
|
2002-03-27 05:38:13 +03:00
|
|
|
ReResolveStyleContext(aPresContext, providerFrame, content,
|
|
|
|
aAttrNameSpaceID, aAttribute, aChangeList,
|
|
|
|
aMinChange, aResultChange);
|
|
|
|
// The provider's new context becomes the parent context of
|
|
|
|
// aFrame's context.
|
2003-02-22 03:32:13 +03:00
|
|
|
parentContext = providerFrame->GetStyleContext();
|
2002-03-27 05:38:13 +03:00
|
|
|
// Set |resolvedChild| so we don't bother resolving the
|
|
|
|
// provider again.
|
|
|
|
resolvedChild = providerFrame;
|
2000-09-13 02:47:09 +04:00
|
|
|
}
|
2001-12-18 01:51:39 +03:00
|
|
|
|
1999-09-21 11:53:14 +04:00
|
|
|
// do primary context
|
2003-02-22 03:32:13 +03:00
|
|
|
nsStyleContext* newContext = nsnull;
|
2002-11-17 18:37:56 +03:00
|
|
|
if (pseudoTag == nsCSSAnonBoxes::mozNonElement) {
|
2002-03-27 05:38:13 +03:00
|
|
|
NS_ASSERTION(localContent,
|
|
|
|
"non pseudo-element frame without content node");
|
2003-02-22 03:32:13 +03:00
|
|
|
newContext = aPresContext->ResolveStyleContextForNonElement(parentContext).get();
|
2002-03-27 05:38:13 +03:00
|
|
|
}
|
|
|
|
else if (pseudoTag) {
|
|
|
|
nsIContent* pseudoContent =
|
|
|
|
aParentContent ? aParentContent : localContent;
|
2003-01-05 08:05:17 +03:00
|
|
|
if (pseudoTag == nsCSSPseudoElements::before ||
|
|
|
|
pseudoTag == nsCSSPseudoElements::after) {
|
|
|
|
// XXX what other pseudos do we need to treat like this?
|
2003-02-22 03:32:13 +03:00
|
|
|
newContext = aPresContext->ProbePseudoStyleContextFor(pseudoContent,
|
|
|
|
pseudoTag,
|
|
|
|
parentContext).get();
|
2003-01-05 08:05:17 +03:00
|
|
|
if (!newContext) {
|
|
|
|
// This pseudo should no longer exist; gotta reframe
|
|
|
|
NS_UpdateHint(aMinChange, nsChangeHint_ReconstructFrame);
|
|
|
|
aChangeList.AppendChange(aFrame, pseudoContent,
|
|
|
|
nsChangeHint_ReconstructFrame);
|
|
|
|
// We're reframing anyway; just keep the same context
|
|
|
|
newContext = oldContext;
|
2003-02-22 03:32:13 +03:00
|
|
|
newContext->AddRef();
|
2003-01-05 08:05:17 +03:00
|
|
|
}
|
|
|
|
} else {
|
2003-02-22 03:32:13 +03:00
|
|
|
newContext = aPresContext->ResolvePseudoStyleContextFor(pseudoContent,
|
|
|
|
pseudoTag,
|
|
|
|
parentContext).get();
|
2003-01-05 08:05:17 +03:00
|
|
|
}
|
1999-09-21 11:53:14 +04:00
|
|
|
}
|
|
|
|
else {
|
2001-11-02 07:14:58 +03:00
|
|
|
NS_ASSERTION(localContent,
|
|
|
|
"non pseudo-element frame without content node");
|
2003-02-22 03:32:13 +03:00
|
|
|
newContext = aPresContext->ResolveStyleContextFor(content, parentContext).get();
|
1999-09-21 11:53:14 +04:00
|
|
|
}
|
|
|
|
NS_ASSERTION(newContext, "failed to get new style context");
|
|
|
|
if (newContext) {
|
2002-03-31 20:59:00 +04:00
|
|
|
if (!parentContext) {
|
2003-06-20 05:22:44 +04:00
|
|
|
if (oldContext->GetRuleNode() == newContext->GetRuleNode()) {
|
2002-03-31 20:59:00 +04:00
|
|
|
// We're the root of the style context tree and the new style
|
|
|
|
// context returned has the same rule node. This means that
|
|
|
|
// we can use FindChildWithRules to keep a lot of the old
|
|
|
|
// style contexts around. However, we need to start from the
|
|
|
|
// same root.
|
2003-02-22 03:32:13 +03:00
|
|
|
newContext->Release();
|
2002-03-31 20:59:00 +04:00
|
|
|
newContext = oldContext;
|
2003-02-22 03:32:13 +03:00
|
|
|
newContext->AddRef();
|
2002-03-31 20:59:00 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-09-21 11:53:14 +04:00
|
|
|
if (newContext != oldContext) {
|
1999-10-02 08:25:29 +04:00
|
|
|
aMinChange = CaptureChange(oldContext, newContext, aFrame, content, aChangeList, aMinChange);
|
2004-01-15 06:32:06 +03:00
|
|
|
if (!(aMinChange & nsChangeHint_ReconstructFrame)) {
|
2002-08-24 18:41:28 +04:00
|
|
|
// if frame gets regenerated, let it keep old context
|
1999-11-24 09:03:41 +03:00
|
|
|
aFrame->SetStyleContext(aPresContext, newContext);
|
1999-09-25 09:00:41 +04:00
|
|
|
}
|
2000-02-16 05:49:01 +03:00
|
|
|
// if old context had image and new context does not have the same image,
|
|
|
|
// stop the image load for the frame
|
2003-05-15 07:42:21 +04:00
|
|
|
const nsStyleBackground* oldColor = oldContext->GetStyleBackground();
|
|
|
|
const nsStyleBackground* newColor = newContext->GetStyleBackground();
|
2001-06-01 02:19:43 +04:00
|
|
|
|
2003-10-02 02:53:56 +04:00
|
|
|
PRBool equal;
|
|
|
|
if (oldColor->mBackgroundImage &&
|
|
|
|
(!newColor->mBackgroundImage ||
|
|
|
|
NS_FAILED(oldColor->mBackgroundImage->Equals(
|
|
|
|
newColor->mBackgroundImage, &equal)) ||
|
|
|
|
!equal)) {
|
2000-02-16 05:49:01 +03:00
|
|
|
// stop the image loading for the frame, the image has changed
|
2001-08-10 00:22:39 +04:00
|
|
|
aPresContext->StopImagesFor(aFrame);
|
2000-02-16 05:49:01 +03:00
|
|
|
}
|
1999-09-21 11:53:14 +04:00
|
|
|
}
|
1999-09-29 07:32:19 +04:00
|
|
|
else {
|
2002-11-17 18:37:56 +03:00
|
|
|
if (pseudoTag && pseudoTag != nsCSSAnonBoxes::mozNonElement &&
|
2002-08-24 18:41:28 +04:00
|
|
|
aAttribute &&
|
|
|
|
(!(aMinChange &
|
2004-01-15 06:32:06 +03:00
|
|
|
(nsChangeHint_ReflowFrame | nsChangeHint_ReconstructFrame))) &&
|
1999-10-16 03:14:44 +04:00
|
|
|
HasAttributeContent(oldContext, aAttrNameSpaceID, aAttribute)) {
|
1999-12-02 12:19:16 +03:00
|
|
|
aChangeList.AppendChange(aFrame, content, NS_STYLE_HINT_REFLOW);
|
1999-10-16 03:14:44 +04:00
|
|
|
}
|
1999-09-29 07:32:19 +04:00
|
|
|
}
|
2003-02-22 03:32:13 +03:00
|
|
|
oldContext->Release();
|
1999-09-21 11:53:14 +04:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
NS_ERROR("resolve style context failed");
|
|
|
|
newContext = oldContext; // new context failed, recover... (take ref)
|
2002-03-31 20:59:00 +04:00
|
|
|
oldContext = nsnull;
|
1999-09-21 11:53:14 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// do additional contexts
|
|
|
|
PRInt32 contextIndex = -1;
|
|
|
|
while (1 == 1) {
|
2003-02-22 03:32:13 +03:00
|
|
|
nsStyleContext* oldExtraContext = nsnull;
|
|
|
|
oldExtraContext = aFrame->GetAdditionalStyleContext(++contextIndex);
|
|
|
|
if (oldExtraContext) {
|
|
|
|
nsStyleContext* newExtraContext = nsnull;
|
|
|
|
pseudoTag = oldExtraContext->GetPseudoType();
|
|
|
|
NS_ASSERTION(pseudoTag &&
|
|
|
|
pseudoTag != nsCSSAnonBoxes::mozNonElement,
|
|
|
|
"extra style context is not pseudo element");
|
|
|
|
newExtraContext = aPresContext->ResolvePseudoStyleContextFor(content,
|
|
|
|
pseudoTag,
|
|
|
|
newContext).get();
|
|
|
|
if (newExtraContext) {
|
|
|
|
if (oldExtraContext != newExtraContext) {
|
|
|
|
aMinChange = CaptureChange(oldExtraContext, newExtraContext, aFrame,
|
|
|
|
content, aChangeList, aMinChange);
|
2004-01-15 06:32:06 +03:00
|
|
|
if (!(aMinChange & nsChangeHint_ReconstructFrame)) {
|
2003-02-22 03:32:13 +03:00
|
|
|
aFrame->SetAdditionalStyleContext(contextIndex, newExtraContext);
|
1999-09-21 11:53:14 +04:00
|
|
|
}
|
2003-02-22 03:32:13 +03:00
|
|
|
}
|
|
|
|
else {
|
2002-08-24 18:41:28 +04:00
|
|
|
#if 0
|
2003-02-22 03:32:13 +03:00
|
|
|
// XXXldb |oldContext| is null by this point, so this will
|
|
|
|
// never do anything.
|
|
|
|
if (pseudoTag && pseudoTag != nsCSSAnonBoxes::mozNonElement &&
|
|
|
|
aAttribute && (aMinChange < NS_STYLE_HINT_REFLOW) &&
|
|
|
|
HasAttributeContent(oldContext, aAttrNameSpaceID, aAttribute)) {
|
|
|
|
aChangeList.AppendChange(aFrame, content, NS_STYLE_HINT_REFLOW);
|
1999-10-02 08:25:29 +04:00
|
|
|
}
|
2003-02-22 03:32:13 +03:00
|
|
|
#endif
|
1999-09-21 11:53:14 +04:00
|
|
|
}
|
2003-02-22 03:32:13 +03:00
|
|
|
newExtraContext->Release();
|
1999-09-21 11:53:14 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-10-02 08:25:29 +04:00
|
|
|
// now look for undisplayed child content and pseudos
|
1999-10-02 23:45:18 +04:00
|
|
|
if (localContent && mUndisplayedMap) {
|
2003-01-21 03:47:14 +03:00
|
|
|
for (UndisplayedNode* undisplayed =
|
|
|
|
mUndisplayedMap->GetFirstNode(localContent);
|
|
|
|
undisplayed; undisplayed = undisplayed->mNext) {
|
2003-02-22 03:32:13 +03:00
|
|
|
nsRefPtr<nsStyleContext> undisplayedContext;
|
|
|
|
pseudoTag = undisplayed->mStyle->GetPseudoType();
|
2002-05-16 17:30:57 +04:00
|
|
|
if (pseudoTag == nsnull) { // child content
|
2003-02-22 03:32:13 +03:00
|
|
|
undisplayedContext = aPresContext->ResolveStyleContextFor(undisplayed->mContent,
|
2003-02-23 01:21:20 +03:00
|
|
|
newContext);
|
1999-10-02 08:25:29 +04:00
|
|
|
}
|
2002-11-17 18:37:56 +03:00
|
|
|
else if (pseudoTag == nsCSSAnonBoxes::mozNonElement) {
|
2003-02-23 01:21:20 +03:00
|
|
|
undisplayedContext = aPresContext->ResolveStyleContextForNonElement(newContext);
|
2002-03-27 05:38:13 +03:00
|
|
|
}
|
1999-10-02 08:25:29 +04:00
|
|
|
else { // pseudo element
|
2002-05-16 17:30:57 +04:00
|
|
|
NS_NOTREACHED("no pseudo elements in undisplayed map");
|
1999-10-02 08:25:29 +04:00
|
|
|
NS_ASSERTION(pseudoTag, "pseudo element without tag");
|
2003-02-22 03:32:13 +03:00
|
|
|
undisplayedContext = aPresContext->ResolvePseudoStyleContextFor(localContent,
|
|
|
|
pseudoTag,
|
2003-02-23 01:21:20 +03:00
|
|
|
newContext);
|
1999-10-02 08:25:29 +04:00
|
|
|
}
|
|
|
|
if (undisplayedContext) {
|
2003-05-15 07:42:21 +04:00
|
|
|
const nsStyleDisplay* display = undisplayedContext->GetStyleDisplay();
|
1999-10-02 08:25:29 +04:00
|
|
|
if (display->mDisplay != NS_STYLE_DISPLAY_NONE) {
|
2003-01-21 03:47:14 +03:00
|
|
|
aChangeList.AppendChange(nsnull,
|
|
|
|
undisplayed->mContent
|
|
|
|
? NS_STATIC_CAST(nsIContent*,
|
|
|
|
undisplayed->mContent)
|
|
|
|
: localContent,
|
1999-12-02 12:19:16 +03:00
|
|
|
NS_STYLE_HINT_FRAMECHANGE);
|
2002-05-01 04:36:50 +04:00
|
|
|
// The node should be removed from the undisplayed map when
|
|
|
|
// we reframe it.
|
2002-03-27 05:38:13 +03:00
|
|
|
} else {
|
|
|
|
// update the undisplayed node with the new context
|
|
|
|
undisplayed->mStyle = undisplayedContext;
|
1999-10-02 08:25:29 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-09-21 11:53:14 +04:00
|
|
|
aResultChange = aMinChange;
|
|
|
|
|
2004-01-15 06:32:06 +03:00
|
|
|
if (!(aMinChange & nsChangeHint_ReconstructFrame)) {
|
2003-04-23 04:43:03 +04:00
|
|
|
// Make sure not to do this for pseudo-frames -- those can't have :before
|
|
|
|
// or :after content.
|
|
|
|
if (!pseudoTag && localContent &&
|
|
|
|
localContent->IsContentOfType(nsIContent::eELEMENT)) {
|
2003-01-05 08:05:17 +03:00
|
|
|
// Check for a new :before pseudo and an existing :before
|
|
|
|
// frame, but only if the frame is the first-in-flow.
|
|
|
|
nsIFrame* prevInFlow = nsnull;
|
|
|
|
aFrame->GetPrevInFlow(&prevInFlow);
|
|
|
|
if (!prevInFlow) {
|
|
|
|
// Checking for a :before frame is cheaper than getting the
|
|
|
|
// :before style context.
|
2003-04-22 03:06:40 +04:00
|
|
|
if (!nsLayoutUtils::GetBeforeFrame(aFrame, aPresContext) &&
|
|
|
|
nsLayoutUtils::HasPseudoStyle(localContent, newContext,
|
|
|
|
nsCSSPseudoElements::before,
|
|
|
|
aPresContext)) {
|
|
|
|
// Have to create the new :before frame
|
|
|
|
NS_UpdateHint(aMinChange, nsChangeHint_ReconstructFrame);
|
|
|
|
aChangeList.AppendChange(aFrame, content,
|
|
|
|
nsChangeHint_ReconstructFrame);
|
2003-01-05 08:05:17 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-01-15 06:32:06 +03:00
|
|
|
if (!(aMinChange & nsChangeHint_ReconstructFrame)) {
|
2003-04-23 04:43:03 +04:00
|
|
|
// Make sure not to do this for pseudo-frames -- those can't have :before
|
|
|
|
// or :after content.
|
|
|
|
if (!pseudoTag && localContent &&
|
|
|
|
localContent->IsContentOfType(nsIContent::eELEMENT)) {
|
2003-04-22 03:06:40 +04:00
|
|
|
// Check for new :after content, but only if the frame is the
|
|
|
|
// first-in-flow.
|
2003-01-05 08:05:17 +03:00
|
|
|
nsIFrame* nextInFlow = nsnull;
|
|
|
|
aFrame->GetNextInFlow(&nextInFlow);
|
|
|
|
|
|
|
|
if (!nextInFlow) {
|
2003-04-22 03:06:40 +04:00
|
|
|
// Getting the :after frame is more expensive than getting the pseudo
|
|
|
|
// context, so get the pseudo context first.
|
|
|
|
if (nsLayoutUtils::HasPseudoStyle(localContent, newContext,
|
|
|
|
nsCSSPseudoElements::after,
|
|
|
|
aPresContext) &&
|
|
|
|
!nsLayoutUtils::GetAfterFrame(aFrame, aPresContext)) {
|
|
|
|
// have to create the new :after frame
|
|
|
|
NS_UpdateHint(aMinChange, nsChangeHint_ReconstructFrame);
|
|
|
|
aChangeList.AppendChange(aFrame, content,
|
|
|
|
nsChangeHint_ReconstructFrame);
|
2003-01-05 08:05:17 +03:00
|
|
|
}
|
2003-04-22 03:06:40 +04:00
|
|
|
}
|
2003-01-05 08:05:17 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-01-15 06:32:06 +03:00
|
|
|
if (!(aMinChange & nsChangeHint_ReconstructFrame)) {
|
2003-01-05 08:05:17 +03:00
|
|
|
|
2001-12-18 01:51:39 +03:00
|
|
|
// There is no need to waste time crawling into a frame's children on a frame change.
|
|
|
|
// The act of reconstructing frames will force new style contexts to be resolved on all
|
|
|
|
// of this frame's descendants anyway, so we want to avoid wasting time processing
|
|
|
|
// style contexts that we're just going to throw away anyway. - dwh
|
|
|
|
|
|
|
|
// now do children
|
|
|
|
PRInt32 listIndex = 0;
|
|
|
|
nsIAtom* childList = nsnull;
|
2002-08-24 18:41:28 +04:00
|
|
|
nsChangeHint childChange;
|
2001-12-18 01:51:39 +03:00
|
|
|
|
|
|
|
do {
|
2004-01-09 17:20:53 +03:00
|
|
|
nsIFrame* child = aFrame->GetFirstChild(childList);
|
|
|
|
while (child) {
|
2003-06-29 07:43:05 +04:00
|
|
|
if (!(child->GetStateBits() & NS_FRAME_OUT_OF_FLOW)) {
|
2001-12-18 01:51:39 +03:00
|
|
|
// only do frames that are in flow
|
2003-10-31 23:19:18 +03:00
|
|
|
if (nsLayoutAtoms::placeholderFrame == child->GetType()) { // placeholder
|
2002-03-27 05:38:13 +03:00
|
|
|
// get out of flow frame and recur there
|
|
|
|
nsIFrame* outOfFlowFrame =
|
|
|
|
NS_STATIC_CAST(nsPlaceholderFrame*,child)->GetOutOfFlowFrame();
|
2001-12-18 01:51:39 +03:00
|
|
|
NS_ASSERTION(outOfFlowFrame, "no out-of-flow frame");
|
2002-03-27 05:38:13 +03:00
|
|
|
NS_ASSERTION(outOfFlowFrame != resolvedChild,
|
|
|
|
"out-of-flow frame not a true descendant");
|
2001-12-18 01:51:39 +03:00
|
|
|
|
2002-03-27 05:38:13 +03:00
|
|
|
// |nsFrame::GetParentStyleContextFrame| checks being out
|
|
|
|
// of flow so that this works correctly.
|
|
|
|
ReResolveStyleContext(aPresContext, outOfFlowFrame, content,
|
|
|
|
aAttrNameSpaceID, aAttribute,
|
|
|
|
aChangeList, aMinChange, childChange);
|
2000-09-13 02:47:09 +04:00
|
|
|
|
2002-03-27 05:38:13 +03:00
|
|
|
// reresolve placeholder's context under the same parent
|
|
|
|
// as the out-of-flow frame
|
|
|
|
ReResolveStyleContext(aPresContext, child, content,
|
2001-12-18 01:51:39 +03:00
|
|
|
kNameSpaceID_Unknown, nsnull,
|
2000-09-13 02:47:09 +04:00
|
|
|
aChangeList, aMinChange, childChange);
|
2001-12-18 01:51:39 +03:00
|
|
|
}
|
|
|
|
else { // regular child frame
|
2002-03-27 05:38:13 +03:00
|
|
|
if (child != resolvedChild) {
|
|
|
|
ReResolveStyleContext(aPresContext, child, content,
|
2001-12-18 01:51:39 +03:00
|
|
|
aAttrNameSpaceID, aAttribute,
|
|
|
|
aChangeList, aMinChange, childChange);
|
|
|
|
} else {
|
|
|
|
NOISY_TRACE_FRAME("child frame already resolved as descendent, skipping",aFrame);
|
|
|
|
}
|
2000-09-13 02:47:09 +04:00
|
|
|
}
|
|
|
|
}
|
2003-06-29 07:43:05 +04:00
|
|
|
child = child->GetNextSibling();
|
2000-09-13 02:47:09 +04:00
|
|
|
}
|
|
|
|
|
2004-01-09 17:20:53 +03:00
|
|
|
childList = aFrame->GetAdditionalChildListName(listIndex++);
|
2001-12-18 01:51:39 +03:00
|
|
|
} while (childList);
|
|
|
|
// XXX need to do overflow frames???
|
|
|
|
}
|
2000-09-13 02:47:09 +04:00
|
|
|
|
2003-02-22 03:32:13 +03:00
|
|
|
newContext->Release();
|
2000-09-13 02:47:09 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-09-21 11:53:14 +04:00
|
|
|
NS_IMETHODIMP
|
2003-06-20 03:52:58 +04:00
|
|
|
FrameManager::ComputeStyleChangeFor(nsIFrame* aFrame,
|
1999-10-16 03:14:44 +04:00
|
|
|
PRInt32 aAttrNameSpaceID,
|
|
|
|
nsIAtom* aAttribute,
|
1999-09-21 11:53:14 +04:00
|
|
|
nsStyleChangeList& aChangeList,
|
2002-08-24 18:41:28 +04:00
|
|
|
nsChangeHint aMinChange,
|
|
|
|
nsChangeHint& aTopLevelChange)
|
1999-09-21 11:53:14 +04:00
|
|
|
{
|
2001-03-06 04:46:03 +03:00
|
|
|
NS_ENSURE_TRUE(mPresShell, NS_ERROR_NOT_AVAILABLE);
|
2003-04-04 01:51:06 +04:00
|
|
|
aTopLevelChange = aMinChange;
|
1999-10-16 03:14:44 +04:00
|
|
|
nsIFrame* frame = aFrame;
|
2002-09-13 00:33:11 +04:00
|
|
|
nsIFrame* frame2 = aFrame;
|
1999-09-21 11:53:14 +04:00
|
|
|
|
2002-03-16 18:26:56 +03:00
|
|
|
#ifdef DEBUG
|
|
|
|
{
|
|
|
|
nsIFrame* prevInFlow;
|
|
|
|
frame->GetPrevInFlow(&prevInFlow);
|
|
|
|
NS_ASSERTION(!prevInFlow, "must start with the first in flow");
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2002-09-13 00:33:11 +04:00
|
|
|
// We want to start with this frame and walk all its next-in-flows,
|
|
|
|
// as well as all its special siblings and their next-in-flows,
|
|
|
|
// reresolving style on all the frames we encounter in this walk.
|
|
|
|
|
1999-10-16 03:14:44 +04:00
|
|
|
do {
|
2002-09-13 00:33:11 +04:00
|
|
|
// Outer loop over special siblings
|
|
|
|
do {
|
|
|
|
// Inner loop over next-in-flows of the current frame
|
|
|
|
nsChangeHint frameChange;
|
2003-06-20 03:52:58 +04:00
|
|
|
ReResolveStyleContext(GetPresContext(), frame, nsnull,
|
2002-09-13 00:33:11 +04:00
|
|
|
aAttrNameSpaceID, aAttribute,
|
2003-04-04 01:51:06 +04:00
|
|
|
aChangeList, aTopLevelChange, frameChange);
|
2002-09-13 00:33:11 +04:00
|
|
|
NS_UpdateHint(aTopLevelChange, frameChange);
|
1999-09-21 11:53:14 +04:00
|
|
|
|
2004-01-15 06:32:06 +03:00
|
|
|
if (aTopLevelChange & nsChangeHint_ReconstructFrame) {
|
2002-09-13 00:33:11 +04:00
|
|
|
// If it's going to cause a framechange, then don't bother
|
|
|
|
// with the continuations or special siblings since they'll be
|
|
|
|
// clobbered by the frame reconstruct anyway.
|
2001-05-23 10:39:34 +04:00
|
|
|
#ifdef NS_DEBUG
|
2002-09-13 00:33:11 +04:00
|
|
|
nsIFrame* prevInFlow;
|
|
|
|
frame->GetPrevInFlow(&prevInFlow);
|
|
|
|
NS_ASSERTION(!prevInFlow, "continuing frame had more severe impact than first-in-flow");
|
2001-05-23 10:39:34 +04:00
|
|
|
#endif
|
2002-09-13 00:33:11 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
2001-05-23 10:39:34 +04:00
|
|
|
|
2002-09-13 00:33:11 +04:00
|
|
|
frame->GetNextInFlow(&frame);
|
|
|
|
} while (frame);
|
|
|
|
|
|
|
|
// Might we have special siblings?
|
2003-06-29 07:43:05 +04:00
|
|
|
if (!(frame2->GetStateBits() & NS_FRAME_IS_SPECIAL)) {
|
2002-09-13 00:33:11 +04:00
|
|
|
// nothing more to do here
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
GetFrameProperty(frame2, nsLayoutAtoms::IBSplitSpecialSibling, 0, (void**)&frame2);
|
|
|
|
frame = frame2;
|
|
|
|
} while (frame2);
|
1999-09-21 11:53:14 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2000-09-13 02:47:09 +04:00
|
|
|
|
2000-05-16 06:43:33 +04:00
|
|
|
NS_IMETHODIMP
|
2003-06-20 03:52:58 +04:00
|
|
|
FrameManager::HasAttributeDependentStyle(nsIContent *aContent,
|
2003-02-22 19:10:53 +03:00
|
|
|
nsIAtom *aAttribute,
|
|
|
|
PRInt32 aModType,
|
2004-01-14 04:36:35 +03:00
|
|
|
nsReStyleHint *aResult)
|
2000-05-16 06:43:33 +04:00
|
|
|
{
|
2001-03-06 04:46:03 +03:00
|
|
|
NS_ENSURE_TRUE(mPresShell, NS_ERROR_NOT_AVAILABLE);
|
2000-05-26 03:02:31 +04:00
|
|
|
|
2004-01-14 04:36:35 +03:00
|
|
|
*aResult = mStyleSet->HasAttributeDependentStyle(GetPresContext(),
|
|
|
|
aContent, aAttribute,
|
|
|
|
aModType);
|
|
|
|
|
2002-08-22 04:01:30 +04:00
|
|
|
if (aAttribute == nsHTMLAtoms::style) {
|
|
|
|
// Perhaps should check that it's XUL, SVG, (or HTML) namespace, but
|
2003-02-22 19:10:53 +03:00
|
|
|
// it doesn't really matter. Or we could even let
|
|
|
|
// HTMLCSSStyleSheetImpl::HasAttributeDependentStyle handle it.
|
2004-01-14 04:36:35 +03:00
|
|
|
*aResult = nsReStyleHint(*aResult | eReStyle_Self);
|
2002-08-22 04:01:30 +04:00
|
|
|
}
|
|
|
|
|
2004-01-08 01:30:53 +03:00
|
|
|
return NS_OK;
|
2000-05-16 06:43:33 +04:00
|
|
|
}
|
1999-09-04 03:35:41 +04:00
|
|
|
|
2000-06-15 04:35:46 +04:00
|
|
|
// Capture state for a given frame.
|
|
|
|
// Accept a content id here, in some cases we may not have content (scroll position)
|
|
|
|
NS_IMETHODIMP
|
2003-06-20 03:52:58 +04:00
|
|
|
FrameManager::CaptureFrameStateFor(nsIFrame* aFrame,
|
2001-05-30 15:26:21 +04:00
|
|
|
nsILayoutHistoryState* aState,
|
|
|
|
nsIStatefulFrame::SpecialStateID aID)
|
1999-08-31 18:35:50 +04:00
|
|
|
{
|
2001-05-30 15:26:21 +04:00
|
|
|
NS_ENSURE_TRUE(mPresShell && aFrame && aState, NS_ERROR_FAILURE);
|
1999-08-31 18:35:50 +04:00
|
|
|
|
2001-05-30 15:26:21 +04:00
|
|
|
// Only capture state for stateful frames
|
1999-10-23 05:43:49 +04:00
|
|
|
nsIStatefulFrame* statefulFrame = nsnull;
|
2000-02-03 01:24:56 +03:00
|
|
|
aFrame->QueryInterface(NS_GET_IID(nsIStatefulFrame), (void**) &statefulFrame);
|
2001-05-30 15:26:21 +04:00
|
|
|
if (!statefulFrame) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2000-06-15 04:35:46 +04:00
|
|
|
|
2001-05-30 15:26:21 +04:00
|
|
|
// Capture the state, exit early if we get null (nothing to save)
|
|
|
|
nsCOMPtr<nsIPresState> frameState;
|
|
|
|
nsresult rv = NS_OK;
|
2003-06-20 03:52:58 +04:00
|
|
|
rv = statefulFrame->SaveState(GetPresContext(), getter_AddRefs(frameState));
|
2001-05-30 15:26:21 +04:00
|
|
|
if (!frameState) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2000-06-15 04:35:46 +04:00
|
|
|
|
2001-05-30 15:26:21 +04:00
|
|
|
// Generate the hash key to store the state under
|
|
|
|
// Exit early if we get empty key
|
|
|
|
nsCAutoString stateKey;
|
2003-06-29 07:43:05 +04:00
|
|
|
rv = nsContentUtils::GenerateStateKey(aFrame->GetContent(), aID, stateKey);
|
2001-05-30 15:26:21 +04:00
|
|
|
if(NS_FAILED(rv) || stateKey.IsEmpty()) {
|
|
|
|
return rv;
|
1999-08-31 18:35:50 +04:00
|
|
|
}
|
|
|
|
|
2001-05-30 15:26:21 +04:00
|
|
|
// Store the state
|
|
|
|
return aState->AddState(stateKey, frameState);
|
1999-10-23 05:43:49 +04:00
|
|
|
}
|
1999-08-31 18:35:50 +04:00
|
|
|
|
1999-10-23 05:43:49 +04:00
|
|
|
NS_IMETHODIMP
|
2003-06-20 03:52:58 +04:00
|
|
|
FrameManager::CaptureFrameState(nsIFrame* aFrame,
|
2001-05-30 15:26:21 +04:00
|
|
|
nsILayoutHistoryState* aState)
|
1999-10-23 05:43:49 +04:00
|
|
|
{
|
|
|
|
nsresult rv = NS_OK;
|
2001-03-06 04:46:03 +03:00
|
|
|
NS_ENSURE_TRUE(mPresShell, NS_ERROR_NOT_AVAILABLE);
|
1999-10-23 05:43:49 +04:00
|
|
|
NS_PRECONDITION(nsnull != aFrame && nsnull != aState, "null parameters passed in");
|
1999-08-31 18:35:50 +04:00
|
|
|
|
2003-06-20 03:52:58 +04:00
|
|
|
rv = CaptureFrameStateFor(aFrame, aState);
|
1999-10-23 05:43:49 +04:00
|
|
|
|
|
|
|
// Now capture state recursively for the frame hierarchy rooted at aFrame
|
|
|
|
nsIAtom* childListName = nsnull;
|
|
|
|
PRInt32 childListIndex = 0;
|
|
|
|
do {
|
2004-01-09 17:20:53 +03:00
|
|
|
nsIFrame* childFrame = aFrame->GetFirstChild(childListName);
|
1999-10-23 05:43:49 +04:00
|
|
|
while (childFrame) {
|
2003-06-20 03:52:58 +04:00
|
|
|
rv = CaptureFrameState(childFrame, aState);
|
1999-10-23 05:43:49 +04:00
|
|
|
// Get the next sibling child frame
|
2003-06-29 07:43:05 +04:00
|
|
|
childFrame = childFrame->GetNextSibling();
|
1999-10-23 05:43:49 +04:00
|
|
|
}
|
2004-01-09 17:20:53 +03:00
|
|
|
childListName = aFrame->GetAdditionalChildListName(childListIndex++);
|
1999-10-23 05:43:49 +04:00
|
|
|
} while (childListName);
|
1999-08-31 18:35:50 +04:00
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2000-06-15 04:35:46 +04:00
|
|
|
// Restore state for a given frame.
|
|
|
|
// Accept a content id here, in some cases we may not have content (scroll position)
|
|
|
|
NS_IMETHODIMP
|
2003-06-20 03:52:58 +04:00
|
|
|
FrameManager::RestoreFrameStateFor(nsIFrame* aFrame,
|
|
|
|
nsILayoutHistoryState* aState,
|
|
|
|
nsIStatefulFrame::SpecialStateID aID)
|
1999-08-31 18:35:50 +04:00
|
|
|
{
|
2001-05-30 15:26:21 +04:00
|
|
|
NS_ENSURE_TRUE(mPresShell && aFrame && aState, NS_ERROR_FAILURE);
|
1999-08-31 18:35:50 +04:00
|
|
|
|
2001-05-30 15:26:21 +04:00
|
|
|
// Only capture state for stateful frames
|
1999-10-23 05:43:49 +04:00
|
|
|
nsIStatefulFrame* statefulFrame = nsnull;
|
2000-02-03 01:24:56 +03:00
|
|
|
aFrame->QueryInterface(NS_GET_IID(nsIStatefulFrame), (void**) &statefulFrame);
|
2001-05-30 15:26:21 +04:00
|
|
|
if (!statefulFrame) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2000-06-15 04:35:46 +04:00
|
|
|
|
2001-05-30 15:26:21 +04:00
|
|
|
// Generate the hash key the state was stored under
|
|
|
|
// Exit early if we get empty key
|
2003-06-29 07:43:05 +04:00
|
|
|
nsIContent* content = aFrame->GetContent();
|
2001-09-29 21:50:15 +04:00
|
|
|
// If we don't have content, we can't generate a hash
|
|
|
|
// key and there's probably no state information for us.
|
|
|
|
if (!content) {
|
2003-06-29 07:43:05 +04:00
|
|
|
return NS_OK;
|
2001-09-29 21:50:15 +04:00
|
|
|
}
|
2000-06-15 04:35:46 +04:00
|
|
|
|
2001-05-30 15:26:21 +04:00
|
|
|
nsCAutoString stateKey;
|
2003-06-29 07:43:05 +04:00
|
|
|
nsresult rv = nsContentUtils::GenerateStateKey(content, aID, stateKey);
|
2001-11-02 10:40:01 +03:00
|
|
|
if (NS_FAILED(rv) || stateKey.IsEmpty()) {
|
2001-05-30 15:26:21 +04:00
|
|
|
return rv;
|
|
|
|
}
|
2000-06-15 04:35:46 +04:00
|
|
|
|
2001-05-30 15:26:21 +04:00
|
|
|
// Get the state from the hash
|
|
|
|
nsCOMPtr<nsIPresState> frameState;
|
|
|
|
rv = aState->GetState(stateKey, getter_AddRefs(frameState));
|
|
|
|
if (!frameState) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2000-06-15 04:35:46 +04:00
|
|
|
|
2001-05-30 15:26:21 +04:00
|
|
|
// Restore it
|
2003-06-20 03:52:58 +04:00
|
|
|
rv = statefulFrame->RestoreState(GetPresContext(), frameState);
|
2001-05-30 15:26:21 +04:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
1999-08-31 18:35:50 +04:00
|
|
|
|
2001-05-30 15:26:21 +04:00
|
|
|
// If we restore ok, remove the state from the state table
|
|
|
|
return aState->RemoveState(stateKey);
|
1999-10-23 05:43:49 +04:00
|
|
|
}
|
1999-08-31 18:35:50 +04:00
|
|
|
|
1999-10-23 05:43:49 +04:00
|
|
|
NS_IMETHODIMP
|
2003-06-20 03:52:58 +04:00
|
|
|
FrameManager::RestoreFrameState(nsIFrame* aFrame, nsILayoutHistoryState* aState)
|
1999-10-23 05:43:49 +04:00
|
|
|
{
|
|
|
|
nsresult rv = NS_OK;
|
2001-03-06 04:46:03 +03:00
|
|
|
NS_ENSURE_TRUE(mPresShell, NS_ERROR_NOT_AVAILABLE);
|
1999-10-23 05:43:49 +04:00
|
|
|
NS_PRECONDITION(nsnull != aFrame && nsnull != aState, "null parameters passed in");
|
|
|
|
|
2003-06-20 03:52:58 +04:00
|
|
|
rv = RestoreFrameStateFor(aFrame, aState);
|
1999-10-23 05:43:49 +04:00
|
|
|
|
|
|
|
// Now restore state recursively for the frame hierarchy rooted at aFrame
|
|
|
|
nsIAtom* childListName = nsnull;
|
|
|
|
PRInt32 childListIndex = 0;
|
|
|
|
do {
|
2004-01-09 17:20:53 +03:00
|
|
|
nsIFrame* childFrame = aFrame->GetFirstChild(childListName);
|
2001-05-30 15:26:21 +04:00
|
|
|
while (childFrame) {
|
2003-06-20 03:52:58 +04:00
|
|
|
rv = RestoreFrameState(childFrame, aState);
|
1999-10-23 05:43:49 +04:00
|
|
|
// Get the next sibling child frame
|
2003-06-29 07:43:05 +04:00
|
|
|
childFrame = childFrame->GetNextSibling();
|
1999-10-23 05:43:49 +04:00
|
|
|
}
|
2004-01-09 17:20:53 +03:00
|
|
|
childListName = aFrame->GetAdditionalChildListName(childListIndex++);
|
1999-10-23 05:43:49 +04:00
|
|
|
} while (childListName);
|
1999-08-31 18:35:50 +04:00
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
1999-08-06 00:17:44 +04:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
|
|
|
|
static PLHashNumber
|
|
|
|
HashKey(void* key)
|
|
|
|
{
|
2001-08-14 11:59:59 +04:00
|
|
|
return NS_PTR_TO_INT32(key);
|
1999-08-06 00:17:44 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
static PRIntn
|
|
|
|
CompareKeys(void* key1, void* key2)
|
|
|
|
{
|
|
|
|
return key1 == key2;
|
|
|
|
}
|
|
|
|
|
1999-10-16 04:55:48 +04:00
|
|
|
void
|
1999-10-19 18:41:55 +04:00
|
|
|
FrameManager::DestroyPropertyList(nsIPresContext* aPresContext)
|
1999-10-16 04:55:48 +04:00
|
|
|
{
|
|
|
|
if (mPropertyList) {
|
|
|
|
while (mPropertyList) {
|
|
|
|
PropertyList* tmp = mPropertyList;
|
|
|
|
|
|
|
|
mPropertyList = mPropertyList->mNext;
|
2001-12-06 08:45:07 +03:00
|
|
|
tmp->Destroy(aPresContext);
|
1999-10-19 08:52:33 +04:00
|
|
|
delete tmp;
|
1999-10-16 04:55:48 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
FrameManager::PropertyList*
|
|
|
|
FrameManager::GetPropertyListFor(nsIAtom* aPropertyName) const
|
|
|
|
{
|
|
|
|
PropertyList* result;
|
|
|
|
|
|
|
|
for (result = mPropertyList; result; result = result->mNext) {
|
|
|
|
if (result->mName.get() == aPropertyName) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
1999-10-19 18:41:55 +04:00
|
|
|
FrameManager::RemoveAllPropertiesFor(nsIPresContext* aPresContext,
|
|
|
|
nsIFrame* aFrame)
|
1999-10-16 04:55:48 +04:00
|
|
|
{
|
|
|
|
for (PropertyList* prop = mPropertyList; prop; prop = prop->mNext) {
|
1999-10-19 18:41:55 +04:00
|
|
|
prop->RemovePropertyForFrame(aPresContext, aFrame);
|
1999-10-16 04:55:48 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
FrameManager::GetFrameProperty(nsIFrame* aFrame,
|
|
|
|
nsIAtom* aPropertyName,
|
1999-10-19 08:52:33 +04:00
|
|
|
PRUint32 aOptions,
|
1999-10-16 04:55:48 +04:00
|
|
|
void** aPropertyValue)
|
|
|
|
{
|
2001-03-06 04:46:03 +03:00
|
|
|
NS_ENSURE_TRUE(mPresShell, NS_ERROR_NOT_AVAILABLE);
|
2001-12-06 08:45:07 +03:00
|
|
|
NS_PRECONDITION(aPropertyName && aFrame, "unexpected null param");
|
1999-10-16 04:55:48 +04:00
|
|
|
|
2001-12-06 08:45:07 +03:00
|
|
|
PropertyList* propertyList = GetPropertyListFor(aPropertyName);
|
1999-10-16 04:55:48 +04:00
|
|
|
if (propertyList) {
|
2001-12-06 08:45:07 +03:00
|
|
|
PropertyListMapEntry *entry = NS_STATIC_CAST(PropertyListMapEntry*,
|
|
|
|
PL_DHashTableOperate(&propertyList->mFrameValueMap, aFrame,
|
|
|
|
PL_DHASH_LOOKUP));
|
|
|
|
if (PL_DHASH_ENTRY_IS_BUSY(entry)) {
|
|
|
|
*aPropertyValue = entry->value;
|
|
|
|
if (aOptions & NS_IFRAME_MGR_REMOVE_PROP) {
|
|
|
|
// don't call propertyList->mDtorFunc. That's the caller's job now.
|
|
|
|
PL_DHashTableRawRemove(&propertyList->mFrameValueMap, entry);
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
1999-10-16 04:55:48 +04:00
|
|
|
}
|
|
|
|
|
2001-12-06 08:45:07 +03:00
|
|
|
*aPropertyValue = 0;
|
|
|
|
return NS_IFRAME_MGR_PROP_NOT_THERE;
|
1999-10-16 04:55:48 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2002-12-04 03:58:52 +03:00
|
|
|
FrameManager::SetFrameProperty(nsIFrame* aFrame,
|
|
|
|
nsIAtom* aPropertyName,
|
|
|
|
void* aPropertyValue,
|
|
|
|
NSFramePropertyDtorFunc aPropDtorFunc)
|
1999-10-16 04:55:48 +04:00
|
|
|
{
|
2001-03-06 04:46:03 +03:00
|
|
|
NS_ENSURE_TRUE(mPresShell, NS_ERROR_NOT_AVAILABLE);
|
2001-12-06 08:45:07 +03:00
|
|
|
NS_PRECONDITION(aPropertyName && aFrame, "unexpected null param");
|
|
|
|
|
1999-10-16 04:55:48 +04:00
|
|
|
PropertyList* propertyList = GetPropertyListFor(aPropertyName);
|
|
|
|
|
|
|
|
if (propertyList) {
|
|
|
|
// Make sure the dtor function matches
|
|
|
|
if (aPropDtorFunc != propertyList->mDtorFunc) {
|
|
|
|
return NS_ERROR_INVALID_ARG;
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
2001-12-06 08:45:07 +03:00
|
|
|
propertyList = new PropertyList(aPropertyName, aPropDtorFunc);
|
|
|
|
if (!propertyList)
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
if (!propertyList->mFrameValueMap.ops) {
|
|
|
|
delete propertyList;
|
1999-10-16 04:55:48 +04:00
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
}
|
|
|
|
|
|
|
|
propertyList->mNext = mPropertyList;
|
|
|
|
mPropertyList = propertyList;
|
|
|
|
}
|
|
|
|
|
1999-10-19 08:52:33 +04:00
|
|
|
// The current property value (if there is one) is replaced and the current
|
|
|
|
// value is destroyed
|
2001-12-06 08:45:07 +03:00
|
|
|
nsresult result = NS_OK;
|
|
|
|
PropertyListMapEntry *entry = NS_STATIC_CAST(PropertyListMapEntry*,
|
|
|
|
PL_DHashTableOperate(&propertyList->mFrameValueMap, aFrame, PL_DHASH_ADD));
|
2003-06-20 03:44:01 +04:00
|
|
|
if (!entry)
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
2001-12-06 08:45:07 +03:00
|
|
|
// A NULL entry->key is the sign that the entry has just been allocated
|
|
|
|
// for us. If it's non-NULL then we have an existing entry.
|
|
|
|
if (entry->key && propertyList->mDtorFunc) {
|
|
|
|
nsCOMPtr<nsIPresContext> presContext;
|
|
|
|
mPresShell->GetPresContext(getter_AddRefs(presContext));
|
|
|
|
propertyList->mDtorFunc(presContext, aFrame, aPropertyName, entry->value);
|
|
|
|
result = NS_IFRAME_MGR_PROP_OVERWRITTEN;
|
1999-10-19 08:52:33 +04:00
|
|
|
}
|
2001-12-06 08:45:07 +03:00
|
|
|
entry->key = aFrame;
|
|
|
|
entry->value = aPropertyValue;
|
1999-10-19 08:52:33 +04:00
|
|
|
|
1999-10-21 09:11:43 +04:00
|
|
|
return result;
|
1999-10-16 04:55:48 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
FrameManager::RemoveFrameProperty(nsIFrame* aFrame,
|
|
|
|
nsIAtom* aPropertyName)
|
|
|
|
{
|
2001-03-06 04:46:03 +03:00
|
|
|
NS_ENSURE_TRUE(mPresShell, NS_ERROR_NOT_AVAILABLE);
|
2001-12-06 08:45:07 +03:00
|
|
|
NS_PRECONDITION(aPropertyName && aFrame, "unexpected null param");
|
1999-10-16 04:55:48 +04:00
|
|
|
|
2001-12-06 08:45:07 +03:00
|
|
|
PropertyList* propertyList = GetPropertyListFor(aPropertyName);
|
1999-10-16 04:55:48 +04:00
|
|
|
if (propertyList) {
|
1999-10-19 18:41:55 +04:00
|
|
|
nsCOMPtr<nsIPresContext> presContext;
|
|
|
|
mPresShell->GetPresContext(getter_AddRefs(presContext));
|
|
|
|
|
2001-12-06 08:45:07 +03:00
|
|
|
if (propertyList->RemovePropertyForFrame(presContext, aFrame))
|
|
|
|
return NS_OK;
|
1999-10-16 04:55:48 +04:00
|
|
|
}
|
|
|
|
|
2001-12-06 08:45:07 +03:00
|
|
|
return NS_IFRAME_MGR_PROP_NOT_THERE;
|
1999-10-16 04:55:48 +04:00
|
|
|
}
|
|
|
|
|
1999-10-09 00:41:19 +04:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
|
2001-01-28 02:06:33 +03:00
|
|
|
MOZ_DECL_CTOR_COUNTER(UndisplayedMap)
|
1999-10-09 00:41:19 +04:00
|
|
|
|
1999-10-02 08:25:29 +04:00
|
|
|
UndisplayedMap::UndisplayedMap(PRUint32 aNumBuckets)
|
|
|
|
{
|
1999-10-09 00:41:19 +04:00
|
|
|
MOZ_COUNT_CTOR(UndisplayedMap);
|
1999-10-02 08:25:29 +04:00
|
|
|
mTable = PL_NewHashTable(aNumBuckets, (PLHashFunction)HashKey,
|
|
|
|
(PLHashComparator)CompareKeys,
|
|
|
|
(PLHashComparator)nsnull,
|
|
|
|
nsnull, nsnull);
|
|
|
|
mLastLookup = nsnull;
|
|
|
|
}
|
|
|
|
|
|
|
|
UndisplayedMap::~UndisplayedMap(void)
|
|
|
|
{
|
1999-10-09 00:41:19 +04:00
|
|
|
MOZ_COUNT_DTOR(UndisplayedMap);
|
1999-10-02 08:25:29 +04:00
|
|
|
Clear();
|
|
|
|
PL_HashTableDestroy(mTable);
|
|
|
|
}
|
|
|
|
|
|
|
|
PLHashEntry**
|
|
|
|
UndisplayedMap::GetEntryFor(nsIContent* aParentContent)
|
|
|
|
{
|
|
|
|
if (mLastLookup && (aParentContent == (*mLastLookup)->key)) {
|
|
|
|
return mLastLookup;
|
|
|
|
}
|
2001-08-14 11:59:59 +04:00
|
|
|
PLHashNumber hashCode = NS_PTR_TO_INT32(aParentContent);
|
1999-10-02 08:25:29 +04:00
|
|
|
PLHashEntry** entry = PL_HashTableRawLookup(mTable, hashCode, aParentContent);
|
|
|
|
if (*entry) {
|
|
|
|
mLastLookup = entry;
|
|
|
|
}
|
|
|
|
return entry;
|
|
|
|
}
|
|
|
|
|
|
|
|
UndisplayedNode*
|
|
|
|
UndisplayedMap::GetFirstNode(nsIContent* aParentContent)
|
|
|
|
{
|
|
|
|
PLHashEntry** entry = GetEntryFor(aParentContent);
|
|
|
|
if (*entry) {
|
|
|
|
return (UndisplayedNode*)((*entry)->value);
|
|
|
|
}
|
|
|
|
return nsnull;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
UndisplayedMap::AppendNodeFor(UndisplayedNode* aNode, nsIContent* aParentContent)
|
|
|
|
{
|
|
|
|
PLHashEntry** entry = GetEntryFor(aParentContent);
|
|
|
|
if (*entry) {
|
|
|
|
UndisplayedNode* node = (UndisplayedNode*)((*entry)->value);
|
|
|
|
while (node->mNext) {
|
2002-05-16 17:30:57 +04:00
|
|
|
if (node->mContent == aNode->mContent) {
|
|
|
|
// We actually need to check this in optimized builds because
|
|
|
|
// there are some callers that do this. See bug 118014, bug
|
|
|
|
// 136704, etc.
|
|
|
|
NS_NOTREACHED("node in map twice");
|
|
|
|
delete aNode;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
1999-10-02 08:25:29 +04:00
|
|
|
node = node->mNext;
|
|
|
|
}
|
|
|
|
node->mNext = aNode;
|
|
|
|
}
|
|
|
|
else {
|
2001-08-14 11:59:59 +04:00
|
|
|
PLHashNumber hashCode = NS_PTR_TO_INT32(aParentContent);
|
1999-10-02 08:25:29 +04:00
|
|
|
PL_HashTableRawAdd(mTable, entry, hashCode, aParentContent, aNode);
|
|
|
|
mLastLookup = nsnull; // hashtable may have shifted bucket out from under us
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
UndisplayedMap::AddNodeFor(nsIContent* aParentContent, nsIContent* aChild,
|
2003-02-22 03:32:13 +03:00
|
|
|
nsStyleContext* aStyle)
|
1999-10-02 08:25:29 +04:00
|
|
|
{
|
|
|
|
UndisplayedNode* node = new UndisplayedNode(aChild, aStyle);
|
|
|
|
if (! node) {
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
}
|
|
|
|
return AppendNodeFor(node, aParentContent);
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
UndisplayedMap::RemoveNodeFor(nsIContent* aParentContent, UndisplayedNode* aNode)
|
|
|
|
{
|
|
|
|
PLHashEntry** entry = GetEntryFor(aParentContent);
|
|
|
|
NS_ASSERTION(*entry, "content not in map");
|
|
|
|
if (*entry) {
|
|
|
|
if ((UndisplayedNode*)((*entry)->value) == aNode) { // first node
|
|
|
|
if (aNode->mNext) {
|
|
|
|
(*entry)->value = aNode->mNext;
|
|
|
|
aNode->mNext = nsnull;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
PL_HashTableRawRemove(mTable, entry, *entry);
|
|
|
|
mLastLookup = nsnull; // hashtable may have shifted bucket out from under us
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
UndisplayedNode* node = (UndisplayedNode*)((*entry)->value);
|
|
|
|
while (node->mNext) {
|
|
|
|
if (node->mNext == aNode) {
|
|
|
|
node->mNext = aNode->mNext;
|
|
|
|
aNode->mNext = nsnull;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
node = node->mNext;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
delete aNode;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
UndisplayedMap::RemoveNodesFor(nsIContent* aParentContent)
|
|
|
|
{
|
|
|
|
PLHashEntry** entry = GetEntryFor(aParentContent);
|
|
|
|
NS_ASSERTION(entry, "content not in map");
|
|
|
|
if (*entry) {
|
|
|
|
UndisplayedNode* node = (UndisplayedNode*)((*entry)->value);
|
2002-04-03 01:14:43 +04:00
|
|
|
NS_ASSERTION(node, "null node for non-null entry in UndisplayedMap");
|
1999-10-02 08:25:29 +04:00
|
|
|
delete node;
|
|
|
|
PL_HashTableRawRemove(mTable, entry, *entry);
|
2002-04-03 01:14:43 +04:00
|
|
|
mLastLookup = nsnull; // hashtable may have shifted bucket out from under us
|
1999-10-02 08:25:29 +04:00
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2000-05-03 03:07:11 +04:00
|
|
|
static PRIntn PR_CALLBACK
|
1999-10-02 08:25:29 +04:00
|
|
|
RemoveUndisplayedEntry(PLHashEntry* he, PRIntn i, void* arg)
|
|
|
|
{
|
|
|
|
UndisplayedNode* node = (UndisplayedNode*)(he->value);
|
|
|
|
delete node;
|
|
|
|
// Remove and free this entry and continue enumerating
|
|
|
|
return HT_ENUMERATE_REMOVE | HT_ENUMERATE_NEXT;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
UndisplayedMap::Clear(void)
|
|
|
|
{
|
|
|
|
mLastLookup = nsnull;
|
|
|
|
PL_HashTableEnumerateEntries(mTable, RemoveUndisplayedEntry, 0);
|
|
|
|
}
|
1999-10-16 04:55:48 +04:00
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
|
2002-12-04 03:58:52 +03:00
|
|
|
FrameManager::PropertyList::PropertyList(nsIAtom* aName,
|
|
|
|
NSFramePropertyDtorFunc aDtorFunc)
|
2001-12-06 08:45:07 +03:00
|
|
|
: mName(aName), mDtorFunc(aDtorFunc), mNext(nsnull)
|
1999-10-16 04:55:48 +04:00
|
|
|
{
|
2001-12-06 08:45:07 +03:00
|
|
|
PL_DHashTableInit(&mFrameValueMap, PL_DHashGetStubOps(), this,
|
|
|
|
sizeof(PropertyListMapEntry), 16);
|
1999-10-16 04:55:48 +04:00
|
|
|
}
|
|
|
|
|
1999-10-19 18:41:55 +04:00
|
|
|
FrameManager::PropertyList::~PropertyList()
|
|
|
|
{
|
2001-12-06 08:45:07 +03:00
|
|
|
PL_DHashTableFinish(&mFrameValueMap);
|
1999-10-19 18:41:55 +04:00
|
|
|
}
|
|
|
|
|
2001-12-06 08:45:07 +03:00
|
|
|
PR_STATIC_CALLBACK(PLDHashOperator)
|
|
|
|
DestroyPropertyEnumerator(PLDHashTable *table, PLDHashEntryHdr *hdr,
|
|
|
|
PRUint32 number, void *arg)
|
|
|
|
{
|
|
|
|
FrameManager::PropertyList *propList =
|
|
|
|
NS_STATIC_CAST(FrameManager::PropertyList*, table->data);
|
|
|
|
nsIPresContext *presContext = NS_STATIC_CAST(nsIPresContext*, arg);
|
|
|
|
PropertyListMapEntry* entry = NS_STATIC_CAST(PropertyListMapEntry*, hdr);
|
1999-10-16 04:55:48 +04:00
|
|
|
|
2001-12-06 08:45:07 +03:00
|
|
|
propList->mDtorFunc(presContext, entry->key, propList->mName, entry->value);
|
|
|
|
return PL_DHASH_NEXT;
|
|
|
|
}
|
1999-10-16 04:55:48 +04:00
|
|
|
|
1999-10-19 18:41:55 +04:00
|
|
|
void
|
2001-12-06 08:45:07 +03:00
|
|
|
FrameManager::PropertyList::Destroy(nsIPresContext* aPresContext)
|
1999-10-16 04:55:48 +04:00
|
|
|
{
|
2001-12-06 08:45:07 +03:00
|
|
|
// Enumerate any remaining frame/value pairs and destroy the value object
|
|
|
|
if (mDtorFunc)
|
|
|
|
PL_DHashTableEnumerate(&mFrameValueMap, DestroyPropertyEnumerator,
|
|
|
|
aPresContext);
|
1999-10-16 04:55:48 +04:00
|
|
|
}
|
|
|
|
|
1999-10-21 09:11:43 +04:00
|
|
|
PRBool
|
1999-10-19 18:41:55 +04:00
|
|
|
FrameManager::PropertyList::RemovePropertyForFrame(nsIPresContext* aPresContext,
|
|
|
|
nsIFrame* aFrame)
|
1999-10-16 04:55:48 +04:00
|
|
|
{
|
2001-12-06 08:45:07 +03:00
|
|
|
PropertyListMapEntry *entry = NS_STATIC_CAST(PropertyListMapEntry*,
|
|
|
|
PL_DHashTableOperate(&mFrameValueMap, aFrame, PL_DHASH_LOOKUP));
|
|
|
|
if (!PL_DHASH_ENTRY_IS_BUSY(entry))
|
|
|
|
return PR_FALSE;
|
1999-10-21 09:11:43 +04:00
|
|
|
|
2001-12-06 08:45:07 +03:00
|
|
|
if (mDtorFunc)
|
|
|
|
mDtorFunc(aPresContext, aFrame, mName, entry->value);
|
1999-10-16 04:55:48 +04:00
|
|
|
|
2001-12-06 08:45:07 +03:00
|
|
|
PL_DHashTableRawRemove(&mFrameValueMap, entry);
|
1999-10-21 09:11:43 +04:00
|
|
|
|
2001-12-06 08:45:07 +03:00
|
|
|
return PR_TRUE;
|
1999-10-16 04:55:48 +04:00
|
|
|
}
|