mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-28 11:28:38 +00:00
Initial check-in
This commit is contained in:
parent
c1d3f6c6c8
commit
886f6583d3
444
layout/base/nsFrameManager.cpp
Normal file
444
layout/base/nsFrameManager.cpp
Normal file
@ -0,0 +1,444 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
#include "nsIFrameManager.h"
|
||||
#include "nsIFrame.h"
|
||||
#include "nsIPresContext.h"
|
||||
#include "nsIPresShell.h"
|
||||
#include "nsIStyleSet.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "plhash.h"
|
||||
#include "nsDST.h"
|
||||
#include "nsPlaceholderFrame.h"
|
||||
#ifdef NS_DEBUG
|
||||
#include "nsLayoutAtoms.h"
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
static PLHashNumber
|
||||
HashKey(void* key)
|
||||
{
|
||||
return (PLHashNumber)key;
|
||||
}
|
||||
|
||||
static PRIntn
|
||||
CompareKeys(void* key1, void* key2)
|
||||
{
|
||||
return key1 == key2;
|
||||
}
|
||||
|
||||
// Thin veneer around an NSPR hash table. Provides a map from a key that's
|
||||
// a pointer to a value that's also a pointer.
|
||||
class FrameHashTable {
|
||||
public:
|
||||
FrameHashTable(PRUint32 aNumBuckets = 16);
|
||||
~FrameHashTable();
|
||||
|
||||
// Gets the value associated with the specified key
|
||||
void* Get(void* aKey);
|
||||
|
||||
// Creates an association between the key and value. Returns the previous
|
||||
// value associated with the key, or NULL if there was none
|
||||
void* Put(void* aKey, void* aValue);
|
||||
|
||||
// Removes association for the key, and returns its associated value
|
||||
void* Remove(void* aKey);
|
||||
|
||||
// Removes all entries from the hash table
|
||||
void Clear();
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
void Dump(FILE* fp);
|
||||
#endif
|
||||
|
||||
protected:
|
||||
PLHashTable* mTable;
|
||||
};
|
||||
|
||||
FrameHashTable::FrameHashTable(PRUint32 aNumBuckets)
|
||||
{
|
||||
mTable = PL_NewHashTable(aNumBuckets, (PLHashFunction)HashKey,
|
||||
(PLHashComparator)CompareKeys,
|
||||
(PLHashComparator)nsnull,
|
||||
nsnull, nsnull);
|
||||
}
|
||||
|
||||
FrameHashTable::~FrameHashTable()
|
||||
{
|
||||
PL_HashTableDestroy(mTable);
|
||||
}
|
||||
|
||||
void*
|
||||
FrameHashTable::Get(void* aKey)
|
||||
{
|
||||
PRInt32 hashCode = (PRInt32) aKey;
|
||||
PLHashEntry** hep = PL_HashTableRawLookup(mTable, hashCode, aKey);
|
||||
PLHashEntry* he = *hep;
|
||||
if (nsnull != he) {
|
||||
return he->value;
|
||||
}
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
void*
|
||||
FrameHashTable::Put(void* aKey, void* aData)
|
||||
{
|
||||
PRInt32 hashCode = (PRInt32) aKey;
|
||||
PLHashEntry** hep = PL_HashTableRawLookup(mTable, hashCode, aKey);
|
||||
PLHashEntry* he = *hep;
|
||||
if (nsnull != he) {
|
||||
void* oldValue = he->value;
|
||||
he->value = aData;
|
||||
return oldValue;
|
||||
}
|
||||
PL_HashTableRawAdd(mTable, hep, hashCode, aKey, aData);
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
void*
|
||||
FrameHashTable::Remove(void* aKey)
|
||||
{
|
||||
PRInt32 hashCode = (PRInt32) aKey;
|
||||
PLHashEntry** hep = PL_HashTableRawLookup(mTable, hashCode, aKey);
|
||||
PLHashEntry* he = *hep;
|
||||
void* oldValue = nsnull;
|
||||
if (nsnull != he) {
|
||||
oldValue = he->value;
|
||||
PL_HashTableRawRemove(mTable, hep, he);
|
||||
}
|
||||
return oldValue;
|
||||
}
|
||||
|
||||
static PRIntn
|
||||
RemoveEntry(PLHashEntry* he, PRIntn i, void* arg)
|
||||
{
|
||||
// Remove and free this entry and continue enumerating
|
||||
return HT_ENUMERATE_REMOVE | HT_ENUMERATE_NEXT;
|
||||
}
|
||||
|
||||
void
|
||||
FrameHashTable::Clear()
|
||||
{
|
||||
PL_HashTableEnumerateEntries(mTable, RemoveEntry, 0);
|
||||
}
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
static PRIntn
|
||||
EnumEntries(PLHashEntry* he, PRIntn i, void* arg)
|
||||
{
|
||||
// Continue enumerating
|
||||
return HT_ENUMERATE_NEXT;
|
||||
}
|
||||
|
||||
void
|
||||
FrameHashTable::Dump(FILE* fp)
|
||||
{
|
||||
PL_HashTableDump(mTable, EnumEntries, fp);
|
||||
}
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
class FrameManager : public nsIFrameManager
|
||||
{
|
||||
public:
|
||||
FrameManager();
|
||||
virtual ~FrameManager();
|
||||
|
||||
NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW
|
||||
|
||||
// nsISupports
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsIFrameManager
|
||||
NS_IMETHOD Init(nsIPresShell* aPresShell);
|
||||
|
||||
// Primary frame functions
|
||||
NS_IMETHOD GetPrimaryFrameFor(nsIContent* aContent,
|
||||
nsIFrame** aPrimaryFrame) const;
|
||||
NS_IMETHOD SetPrimaryFrameFor(nsIContent* aContent,
|
||||
nsIFrame* aPrimaryFrame);
|
||||
NS_IMETHOD ClearPrimaryFrameMap();
|
||||
|
||||
// Placeholder frame functions
|
||||
NS_IMETHOD GetPlaceholderFrameFor(nsIFrame* aFrame,
|
||||
nsIFrame** aPlaceholderFrame) const;
|
||||
NS_IMETHOD SetPlaceholderFrameFor(nsIFrame* aFrame,
|
||||
nsIFrame* aPlaceholderFrame);
|
||||
NS_IMETHOD ClearPlaceholderFrameMap();
|
||||
|
||||
// Functions for manipulating the frame model
|
||||
NS_IMETHOD AppendFrames(nsIPresContext& aPresContext,
|
||||
nsIPresShell& aPresShell,
|
||||
nsIFrame* aParentFrame,
|
||||
nsIAtom* aListName,
|
||||
nsIFrame* aFrameList);
|
||||
NS_IMETHOD InsertFrames(nsIPresContext& aPresContext,
|
||||
nsIPresShell& aPresShell,
|
||||
nsIFrame* aParentFrame,
|
||||
nsIAtom* aListName,
|
||||
nsIFrame* aPrevFrame,
|
||||
nsIFrame* aFrameList);
|
||||
NS_IMETHOD RemoveFrame(nsIPresContext& aPresContext,
|
||||
nsIPresShell& aPresShell,
|
||||
nsIFrame* aParentFrame,
|
||||
nsIAtom* aListName,
|
||||
nsIFrame* aOldFrame);
|
||||
NS_IMETHOD ReplaceFrame(nsIPresContext& aPresContext,
|
||||
nsIPresShell& aPresShell,
|
||||
nsIFrame* aParentFrame,
|
||||
nsIAtom* aListName,
|
||||
nsIFrame* aOldFrame,
|
||||
nsIFrame* aNewFrame);
|
||||
|
||||
private:
|
||||
nsIPresShell* mPresShell; // weak link
|
||||
nsDST* mPrimaryFrameMap;
|
||||
FrameHashTable* mPlaceholderMap;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
NS_LAYOUT nsresult
|
||||
NS_NewFrameManager(nsIFrameManager** aInstancePtrResult)
|
||||
{
|
||||
NS_PRECONDITION(nsnull != aInstancePtrResult, "null ptr");
|
||||
if (nsnull == aInstancePtrResult) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
FrameManager* it = new FrameManager;
|
||||
if (nsnull == it) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
return it->QueryInterface(nsIFrameManager::GetIID(), (void **)aInstancePtrResult);
|
||||
}
|
||||
|
||||
FrameManager::FrameManager()
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMPL_ADDREF(FrameManager)
|
||||
NS_IMPL_RELEASE(FrameManager)
|
||||
|
||||
FrameManager::~FrameManager()
|
||||
{
|
||||
delete mPrimaryFrameMap;
|
||||
delete mPlaceholderMap;
|
||||
}
|
||||
|
||||
nsresult
|
||||
FrameManager::QueryInterface(const nsIID& aIID, void** aInstancePtr)
|
||||
{
|
||||
if (aIID.Equals(GetIID())) {
|
||||
*aInstancePtr = (void*)(nsIFrameManager*)this;
|
||||
NS_ADDREF_THIS();
|
||||
return NS_OK;
|
||||
}
|
||||
return NS_NOINTERFACE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
FrameManager::Init(nsIPresShell* aPresShell)
|
||||
{
|
||||
mPresShell = aPresShell;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Primary frame functions
|
||||
NS_IMETHODIMP
|
||||
FrameManager::GetPrimaryFrameFor(nsIContent* aContent,
|
||||
nsIFrame** aResult) const
|
||||
{
|
||||
NS_PRECONDITION(nsnull != aResult, "null ptr");
|
||||
NS_PRECONDITION(nsnull != aContent, "no content object");
|
||||
if (nsnull == aResult) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
if (nsnull == mPrimaryFrameMap) {
|
||||
*aResult = nsnull;
|
||||
} else {
|
||||
*aResult = (nsIFrame*)mPrimaryFrameMap->Search(aContent);
|
||||
if (!*aResult) {
|
||||
nsCOMPtr<nsIStyleSet> styleSet;
|
||||
nsCOMPtr<nsIPresContext> presContext;
|
||||
|
||||
// Give the frame construction code the opportunity to return the
|
||||
// frame that maps the content object
|
||||
mPresShell->GetStyleSet(getter_AddRefs(styleSet));
|
||||
mPresShell->GetPresContext(getter_AddRefs(presContext));
|
||||
styleSet->FindPrimaryFrameFor(presContext, aContent, aResult);
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
FrameManager::SetPrimaryFrameFor(nsIContent* aContent,
|
||||
nsIFrame* aPrimaryFrame)
|
||||
{
|
||||
NS_PRECONDITION(aContent, "no content object");
|
||||
|
||||
// If aPrimaryFrame is NULL, then remove the mapping
|
||||
if (!aPrimaryFrame) {
|
||||
if (mPrimaryFrameMap) {
|
||||
mPrimaryFrameMap->Remove(aContent);
|
||||
}
|
||||
} else {
|
||||
// Create a new DST if necessary
|
||||
if (!mPrimaryFrameMap) {
|
||||
mPrimaryFrameMap = new nsDST;
|
||||
if (!mPrimaryFrameMap) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
// Add a mapping to the hash table
|
||||
nsIFrame* oldPrimaryFrame;
|
||||
|
||||
oldPrimaryFrame = (nsIFrame*)mPrimaryFrameMap->Insert(aContent, (void*)aPrimaryFrame);
|
||||
#ifdef NS_DEBUG
|
||||
if (oldPrimaryFrame && (oldPrimaryFrame != aPrimaryFrame)) {
|
||||
NS_WARNING("overwriting current primary frame");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
FrameManager::ClearPrimaryFrameMap()
|
||||
{
|
||||
if (mPrimaryFrameMap) {
|
||||
mPrimaryFrameMap->Clear();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Placeholder frame functions
|
||||
NS_IMETHODIMP
|
||||
FrameManager::GetPlaceholderFrameFor(nsIFrame* aFrame,
|
||||
nsIFrame** aResult) const
|
||||
{
|
||||
NS_PRECONDITION(nsnull != aResult, "null ptr");
|
||||
NS_PRECONDITION(nsnull != aFrame, "no frame");
|
||||
if ((nsnull == aResult) || (nsnull == aFrame)) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
if (nsnull == mPlaceholderMap) {
|
||||
*aResult = nsnull;
|
||||
} else {
|
||||
*aResult = (nsIFrame*)mPlaceholderMap->Get(aFrame);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
FrameManager::SetPlaceholderFrameFor(nsIFrame* aFrame,
|
||||
nsIFrame* aPlaceholderFrame)
|
||||
{
|
||||
NS_PRECONDITION(aFrame, "no frame");
|
||||
#ifdef NS_DEBUG
|
||||
// Verify that the placeholder frame is of the correct type
|
||||
if (aPlaceholderFrame) {
|
||||
nsIAtom* frameType;
|
||||
|
||||
aPlaceholderFrame->GetFrameType(&frameType);
|
||||
NS_PRECONDITION(nsLayoutAtoms::placeholderFrame == frameType, "unexpected frame type");
|
||||
NS_IF_RELEASE(frameType);
|
||||
}
|
||||
#endif
|
||||
|
||||
// If aPlaceholderFrame is NULL, then remove the mapping
|
||||
if (!aPlaceholderFrame) {
|
||||
if (mPlaceholderMap) {
|
||||
mPlaceholderMap->Remove(aFrame);
|
||||
}
|
||||
} else {
|
||||
// Create a new hash table if necessary
|
||||
if (!mPlaceholderMap) {
|
||||
mPlaceholderMap = new FrameHashTable;
|
||||
if (!mPlaceholderMap) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
// Add a mapping to the hash table
|
||||
mPlaceholderMap->Put(aFrame, (void*)aPlaceholderFrame);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
FrameManager::ClearPlaceholderFrameMap()
|
||||
{
|
||||
if (mPlaceholderMap) {
|
||||
mPlaceholderMap->Clear();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
FrameManager::AppendFrames(nsIPresContext& aPresContext,
|
||||
nsIPresShell& aPresShell,
|
||||
nsIFrame* aParentFrame,
|
||||
nsIAtom* aListName,
|
||||
nsIFrame* aFrameList)
|
||||
{
|
||||
return aParentFrame->AppendFrames(aPresContext, aPresShell, aListName,
|
||||
aFrameList);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
FrameManager::InsertFrames(nsIPresContext& aPresContext,
|
||||
nsIPresShell& aPresShell,
|
||||
nsIFrame* aParentFrame,
|
||||
nsIAtom* aListName,
|
||||
nsIFrame* aPrevFrame,
|
||||
nsIFrame* aFrameList)
|
||||
{
|
||||
return aParentFrame->InsertFrames(aPresContext, aPresShell, aListName,
|
||||
aPrevFrame, aFrameList);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
FrameManager::RemoveFrame(nsIPresContext& aPresContext,
|
||||
nsIPresShell& aPresShell,
|
||||
nsIFrame* aParentFrame,
|
||||
nsIAtom* aListName,
|
||||
nsIFrame* aOldFrame)
|
||||
{
|
||||
return aParentFrame->RemoveFrame(aPresContext, aPresShell, aListName,
|
||||
aOldFrame);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
FrameManager::ReplaceFrame(nsIPresContext& aPresContext,
|
||||
nsIPresShell& aPresShell,
|
||||
nsIFrame* aParentFrame,
|
||||
nsIAtom* aListName,
|
||||
nsIFrame* aOldFrame,
|
||||
nsIFrame* aNewFrame)
|
||||
{
|
||||
return aParentFrame->ReplaceFrame(aPresContext, aPresShell, aListName,
|
||||
aOldFrame, aNewFrame);
|
||||
}
|
||||
|
95
layout/base/public/nsIFrameManager.h
Normal file
95
layout/base/public/nsIFrameManager.h
Normal file
@ -0,0 +1,95 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
#ifndef nsIFrameManager_h___
|
||||
#define nsIFrameManager_h___
|
||||
|
||||
#include "nslayout.h"
|
||||
#include "nsISupports.h"
|
||||
|
||||
class nsIAtom;
|
||||
class nsIContent;
|
||||
class nsIFrame;
|
||||
class nsIPresContext;
|
||||
class nsIPresShell;
|
||||
|
||||
#define NS_IFRAMEMANAGER_IID \
|
||||
{ 0xa6cf9107, 0x15b3, 0x11d2, \
|
||||
{0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32} }
|
||||
|
||||
/**
|
||||
* Frame manager interface. The frame manager serves two purposes:
|
||||
* <li>provides a serice for mapping from content to frame and from out-of-flow
|
||||
* frame to placeholder frame
|
||||
* <li>handles structural modifications to the frame model. If the frame model
|
||||
* lock can be acquired, then the changes are processed immediately; otherwise,
|
||||
* they're queued and processed later
|
||||
*/
|
||||
class nsIFrameManager : public nsISupports {
|
||||
public:
|
||||
static const nsIID& GetIID() {static nsIID iid = NS_IFRAMEMANAGER_IID; return iid;}
|
||||
|
||||
// Initialization
|
||||
NS_IMETHOD Init(nsIPresShell* aPresShell) = 0;
|
||||
|
||||
// Primary frame functions
|
||||
NS_IMETHOD GetPrimaryFrameFor(nsIContent* aContent,
|
||||
nsIFrame** aPrimaryFrame) const = 0;
|
||||
NS_IMETHOD SetPrimaryFrameFor(nsIContent* aContent,
|
||||
nsIFrame* aPrimaryFrame) = 0;
|
||||
NS_IMETHOD ClearPrimaryFrameMap() = 0;
|
||||
|
||||
// Placeholder frame functions
|
||||
NS_IMETHOD GetPlaceholderFrameFor(nsIFrame* aFrame,
|
||||
nsIFrame** aPlaceholderFrame) const = 0;
|
||||
NS_IMETHOD SetPlaceholderFrameFor(nsIFrame* aFrame,
|
||||
nsIFrame* aPlaceholderFrame) = 0;
|
||||
NS_IMETHOD ClearPlaceholderFrameMap() = 0;
|
||||
|
||||
// Functions for manipulating the frame model
|
||||
NS_IMETHOD AppendFrames(nsIPresContext& aPresContext,
|
||||
nsIPresShell& aPresShell,
|
||||
nsIFrame* aParentFrame,
|
||||
nsIAtom* aListName,
|
||||
nsIFrame* aFrameList) = 0;
|
||||
NS_IMETHOD InsertFrames(nsIPresContext& aPresContext,
|
||||
nsIPresShell& aPresShell,
|
||||
nsIFrame* aParentFrame,
|
||||
nsIAtom* aListName,
|
||||
nsIFrame* aPrevFrame,
|
||||
nsIFrame* aFrameList) = 0;
|
||||
NS_IMETHOD RemoveFrame(nsIPresContext& aPresContext,
|
||||
nsIPresShell& aPresShell,
|
||||
nsIFrame* aParentFrame,
|
||||
nsIAtom* aListName,
|
||||
nsIFrame* aOldFrame) = 0;
|
||||
NS_IMETHOD ReplaceFrame(nsIPresContext& aPresContext,
|
||||
nsIPresShell& aPresShell,
|
||||
nsIFrame* aParentFrame,
|
||||
nsIAtom* aListName,
|
||||
nsIFrame* aOldFrame,
|
||||
nsIFrame* aNewFrame) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a frame manager. Upon success, call Init() before attempting to
|
||||
* use it.
|
||||
*/
|
||||
extern NS_LAYOUT nsresult
|
||||
NS_NewFrameManager(nsIFrameManager** aInstancePtrResult);
|
||||
|
||||
#endif /* nsIFrameManager_h___ */
|
444
layout/html/base/src/nsFrameManager.cpp
Normal file
444
layout/html/base/src/nsFrameManager.cpp
Normal file
@ -0,0 +1,444 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
#include "nsIFrameManager.h"
|
||||
#include "nsIFrame.h"
|
||||
#include "nsIPresContext.h"
|
||||
#include "nsIPresShell.h"
|
||||
#include "nsIStyleSet.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "plhash.h"
|
||||
#include "nsDST.h"
|
||||
#include "nsPlaceholderFrame.h"
|
||||
#ifdef NS_DEBUG
|
||||
#include "nsLayoutAtoms.h"
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
static PLHashNumber
|
||||
HashKey(void* key)
|
||||
{
|
||||
return (PLHashNumber)key;
|
||||
}
|
||||
|
||||
static PRIntn
|
||||
CompareKeys(void* key1, void* key2)
|
||||
{
|
||||
return key1 == key2;
|
||||
}
|
||||
|
||||
// Thin veneer around an NSPR hash table. Provides a map from a key that's
|
||||
// a pointer to a value that's also a pointer.
|
||||
class FrameHashTable {
|
||||
public:
|
||||
FrameHashTable(PRUint32 aNumBuckets = 16);
|
||||
~FrameHashTable();
|
||||
|
||||
// Gets the value associated with the specified key
|
||||
void* Get(void* aKey);
|
||||
|
||||
// Creates an association between the key and value. Returns the previous
|
||||
// value associated with the key, or NULL if there was none
|
||||
void* Put(void* aKey, void* aValue);
|
||||
|
||||
// Removes association for the key, and returns its associated value
|
||||
void* Remove(void* aKey);
|
||||
|
||||
// Removes all entries from the hash table
|
||||
void Clear();
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
void Dump(FILE* fp);
|
||||
#endif
|
||||
|
||||
protected:
|
||||
PLHashTable* mTable;
|
||||
};
|
||||
|
||||
FrameHashTable::FrameHashTable(PRUint32 aNumBuckets)
|
||||
{
|
||||
mTable = PL_NewHashTable(aNumBuckets, (PLHashFunction)HashKey,
|
||||
(PLHashComparator)CompareKeys,
|
||||
(PLHashComparator)nsnull,
|
||||
nsnull, nsnull);
|
||||
}
|
||||
|
||||
FrameHashTable::~FrameHashTable()
|
||||
{
|
||||
PL_HashTableDestroy(mTable);
|
||||
}
|
||||
|
||||
void*
|
||||
FrameHashTable::Get(void* aKey)
|
||||
{
|
||||
PRInt32 hashCode = (PRInt32) aKey;
|
||||
PLHashEntry** hep = PL_HashTableRawLookup(mTable, hashCode, aKey);
|
||||
PLHashEntry* he = *hep;
|
||||
if (nsnull != he) {
|
||||
return he->value;
|
||||
}
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
void*
|
||||
FrameHashTable::Put(void* aKey, void* aData)
|
||||
{
|
||||
PRInt32 hashCode = (PRInt32) aKey;
|
||||
PLHashEntry** hep = PL_HashTableRawLookup(mTable, hashCode, aKey);
|
||||
PLHashEntry* he = *hep;
|
||||
if (nsnull != he) {
|
||||
void* oldValue = he->value;
|
||||
he->value = aData;
|
||||
return oldValue;
|
||||
}
|
||||
PL_HashTableRawAdd(mTable, hep, hashCode, aKey, aData);
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
void*
|
||||
FrameHashTable::Remove(void* aKey)
|
||||
{
|
||||
PRInt32 hashCode = (PRInt32) aKey;
|
||||
PLHashEntry** hep = PL_HashTableRawLookup(mTable, hashCode, aKey);
|
||||
PLHashEntry* he = *hep;
|
||||
void* oldValue = nsnull;
|
||||
if (nsnull != he) {
|
||||
oldValue = he->value;
|
||||
PL_HashTableRawRemove(mTable, hep, he);
|
||||
}
|
||||
return oldValue;
|
||||
}
|
||||
|
||||
static PRIntn
|
||||
RemoveEntry(PLHashEntry* he, PRIntn i, void* arg)
|
||||
{
|
||||
// Remove and free this entry and continue enumerating
|
||||
return HT_ENUMERATE_REMOVE | HT_ENUMERATE_NEXT;
|
||||
}
|
||||
|
||||
void
|
||||
FrameHashTable::Clear()
|
||||
{
|
||||
PL_HashTableEnumerateEntries(mTable, RemoveEntry, 0);
|
||||
}
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
static PRIntn
|
||||
EnumEntries(PLHashEntry* he, PRIntn i, void* arg)
|
||||
{
|
||||
// Continue enumerating
|
||||
return HT_ENUMERATE_NEXT;
|
||||
}
|
||||
|
||||
void
|
||||
FrameHashTable::Dump(FILE* fp)
|
||||
{
|
||||
PL_HashTableDump(mTable, EnumEntries, fp);
|
||||
}
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
class FrameManager : public nsIFrameManager
|
||||
{
|
||||
public:
|
||||
FrameManager();
|
||||
virtual ~FrameManager();
|
||||
|
||||
NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW
|
||||
|
||||
// nsISupports
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsIFrameManager
|
||||
NS_IMETHOD Init(nsIPresShell* aPresShell);
|
||||
|
||||
// Primary frame functions
|
||||
NS_IMETHOD GetPrimaryFrameFor(nsIContent* aContent,
|
||||
nsIFrame** aPrimaryFrame) const;
|
||||
NS_IMETHOD SetPrimaryFrameFor(nsIContent* aContent,
|
||||
nsIFrame* aPrimaryFrame);
|
||||
NS_IMETHOD ClearPrimaryFrameMap();
|
||||
|
||||
// Placeholder frame functions
|
||||
NS_IMETHOD GetPlaceholderFrameFor(nsIFrame* aFrame,
|
||||
nsIFrame** aPlaceholderFrame) const;
|
||||
NS_IMETHOD SetPlaceholderFrameFor(nsIFrame* aFrame,
|
||||
nsIFrame* aPlaceholderFrame);
|
||||
NS_IMETHOD ClearPlaceholderFrameMap();
|
||||
|
||||
// Functions for manipulating the frame model
|
||||
NS_IMETHOD AppendFrames(nsIPresContext& aPresContext,
|
||||
nsIPresShell& aPresShell,
|
||||
nsIFrame* aParentFrame,
|
||||
nsIAtom* aListName,
|
||||
nsIFrame* aFrameList);
|
||||
NS_IMETHOD InsertFrames(nsIPresContext& aPresContext,
|
||||
nsIPresShell& aPresShell,
|
||||
nsIFrame* aParentFrame,
|
||||
nsIAtom* aListName,
|
||||
nsIFrame* aPrevFrame,
|
||||
nsIFrame* aFrameList);
|
||||
NS_IMETHOD RemoveFrame(nsIPresContext& aPresContext,
|
||||
nsIPresShell& aPresShell,
|
||||
nsIFrame* aParentFrame,
|
||||
nsIAtom* aListName,
|
||||
nsIFrame* aOldFrame);
|
||||
NS_IMETHOD ReplaceFrame(nsIPresContext& aPresContext,
|
||||
nsIPresShell& aPresShell,
|
||||
nsIFrame* aParentFrame,
|
||||
nsIAtom* aListName,
|
||||
nsIFrame* aOldFrame,
|
||||
nsIFrame* aNewFrame);
|
||||
|
||||
private:
|
||||
nsIPresShell* mPresShell; // weak link
|
||||
nsDST* mPrimaryFrameMap;
|
||||
FrameHashTable* mPlaceholderMap;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
NS_LAYOUT nsresult
|
||||
NS_NewFrameManager(nsIFrameManager** aInstancePtrResult)
|
||||
{
|
||||
NS_PRECONDITION(nsnull != aInstancePtrResult, "null ptr");
|
||||
if (nsnull == aInstancePtrResult) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
FrameManager* it = new FrameManager;
|
||||
if (nsnull == it) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
return it->QueryInterface(nsIFrameManager::GetIID(), (void **)aInstancePtrResult);
|
||||
}
|
||||
|
||||
FrameManager::FrameManager()
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMPL_ADDREF(FrameManager)
|
||||
NS_IMPL_RELEASE(FrameManager)
|
||||
|
||||
FrameManager::~FrameManager()
|
||||
{
|
||||
delete mPrimaryFrameMap;
|
||||
delete mPlaceholderMap;
|
||||
}
|
||||
|
||||
nsresult
|
||||
FrameManager::QueryInterface(const nsIID& aIID, void** aInstancePtr)
|
||||
{
|
||||
if (aIID.Equals(GetIID())) {
|
||||
*aInstancePtr = (void*)(nsIFrameManager*)this;
|
||||
NS_ADDREF_THIS();
|
||||
return NS_OK;
|
||||
}
|
||||
return NS_NOINTERFACE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
FrameManager::Init(nsIPresShell* aPresShell)
|
||||
{
|
||||
mPresShell = aPresShell;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Primary frame functions
|
||||
NS_IMETHODIMP
|
||||
FrameManager::GetPrimaryFrameFor(nsIContent* aContent,
|
||||
nsIFrame** aResult) const
|
||||
{
|
||||
NS_PRECONDITION(nsnull != aResult, "null ptr");
|
||||
NS_PRECONDITION(nsnull != aContent, "no content object");
|
||||
if (nsnull == aResult) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
if (nsnull == mPrimaryFrameMap) {
|
||||
*aResult = nsnull;
|
||||
} else {
|
||||
*aResult = (nsIFrame*)mPrimaryFrameMap->Search(aContent);
|
||||
if (!*aResult) {
|
||||
nsCOMPtr<nsIStyleSet> styleSet;
|
||||
nsCOMPtr<nsIPresContext> presContext;
|
||||
|
||||
// Give the frame construction code the opportunity to return the
|
||||
// frame that maps the content object
|
||||
mPresShell->GetStyleSet(getter_AddRefs(styleSet));
|
||||
mPresShell->GetPresContext(getter_AddRefs(presContext));
|
||||
styleSet->FindPrimaryFrameFor(presContext, aContent, aResult);
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
FrameManager::SetPrimaryFrameFor(nsIContent* aContent,
|
||||
nsIFrame* aPrimaryFrame)
|
||||
{
|
||||
NS_PRECONDITION(aContent, "no content object");
|
||||
|
||||
// If aPrimaryFrame is NULL, then remove the mapping
|
||||
if (!aPrimaryFrame) {
|
||||
if (mPrimaryFrameMap) {
|
||||
mPrimaryFrameMap->Remove(aContent);
|
||||
}
|
||||
} else {
|
||||
// Create a new DST if necessary
|
||||
if (!mPrimaryFrameMap) {
|
||||
mPrimaryFrameMap = new nsDST;
|
||||
if (!mPrimaryFrameMap) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
// Add a mapping to the hash table
|
||||
nsIFrame* oldPrimaryFrame;
|
||||
|
||||
oldPrimaryFrame = (nsIFrame*)mPrimaryFrameMap->Insert(aContent, (void*)aPrimaryFrame);
|
||||
#ifdef NS_DEBUG
|
||||
if (oldPrimaryFrame && (oldPrimaryFrame != aPrimaryFrame)) {
|
||||
NS_WARNING("overwriting current primary frame");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
FrameManager::ClearPrimaryFrameMap()
|
||||
{
|
||||
if (mPrimaryFrameMap) {
|
||||
mPrimaryFrameMap->Clear();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Placeholder frame functions
|
||||
NS_IMETHODIMP
|
||||
FrameManager::GetPlaceholderFrameFor(nsIFrame* aFrame,
|
||||
nsIFrame** aResult) const
|
||||
{
|
||||
NS_PRECONDITION(nsnull != aResult, "null ptr");
|
||||
NS_PRECONDITION(nsnull != aFrame, "no frame");
|
||||
if ((nsnull == aResult) || (nsnull == aFrame)) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
if (nsnull == mPlaceholderMap) {
|
||||
*aResult = nsnull;
|
||||
} else {
|
||||
*aResult = (nsIFrame*)mPlaceholderMap->Get(aFrame);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
FrameManager::SetPlaceholderFrameFor(nsIFrame* aFrame,
|
||||
nsIFrame* aPlaceholderFrame)
|
||||
{
|
||||
NS_PRECONDITION(aFrame, "no frame");
|
||||
#ifdef NS_DEBUG
|
||||
// Verify that the placeholder frame is of the correct type
|
||||
if (aPlaceholderFrame) {
|
||||
nsIAtom* frameType;
|
||||
|
||||
aPlaceholderFrame->GetFrameType(&frameType);
|
||||
NS_PRECONDITION(nsLayoutAtoms::placeholderFrame == frameType, "unexpected frame type");
|
||||
NS_IF_RELEASE(frameType);
|
||||
}
|
||||
#endif
|
||||
|
||||
// If aPlaceholderFrame is NULL, then remove the mapping
|
||||
if (!aPlaceholderFrame) {
|
||||
if (mPlaceholderMap) {
|
||||
mPlaceholderMap->Remove(aFrame);
|
||||
}
|
||||
} else {
|
||||
// Create a new hash table if necessary
|
||||
if (!mPlaceholderMap) {
|
||||
mPlaceholderMap = new FrameHashTable;
|
||||
if (!mPlaceholderMap) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
// Add a mapping to the hash table
|
||||
mPlaceholderMap->Put(aFrame, (void*)aPlaceholderFrame);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
FrameManager::ClearPlaceholderFrameMap()
|
||||
{
|
||||
if (mPlaceholderMap) {
|
||||
mPlaceholderMap->Clear();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
FrameManager::AppendFrames(nsIPresContext& aPresContext,
|
||||
nsIPresShell& aPresShell,
|
||||
nsIFrame* aParentFrame,
|
||||
nsIAtom* aListName,
|
||||
nsIFrame* aFrameList)
|
||||
{
|
||||
return aParentFrame->AppendFrames(aPresContext, aPresShell, aListName,
|
||||
aFrameList);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
FrameManager::InsertFrames(nsIPresContext& aPresContext,
|
||||
nsIPresShell& aPresShell,
|
||||
nsIFrame* aParentFrame,
|
||||
nsIAtom* aListName,
|
||||
nsIFrame* aPrevFrame,
|
||||
nsIFrame* aFrameList)
|
||||
{
|
||||
return aParentFrame->InsertFrames(aPresContext, aPresShell, aListName,
|
||||
aPrevFrame, aFrameList);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
FrameManager::RemoveFrame(nsIPresContext& aPresContext,
|
||||
nsIPresShell& aPresShell,
|
||||
nsIFrame* aParentFrame,
|
||||
nsIAtom* aListName,
|
||||
nsIFrame* aOldFrame)
|
||||
{
|
||||
return aParentFrame->RemoveFrame(aPresContext, aPresShell, aListName,
|
||||
aOldFrame);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
FrameManager::ReplaceFrame(nsIPresContext& aPresContext,
|
||||
nsIPresShell& aPresShell,
|
||||
nsIFrame* aParentFrame,
|
||||
nsIAtom* aListName,
|
||||
nsIFrame* aOldFrame,
|
||||
nsIFrame* aNewFrame)
|
||||
{
|
||||
return aParentFrame->ReplaceFrame(aPresContext, aPresShell, aListName,
|
||||
aOldFrame, aNewFrame);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user