diff --git a/content/base/public/nsIContentIterator.h b/content/base/public/nsIContentIterator.h index dbac9541f4fc..65394d1e358e 100644 --- a/content/base/public/nsIContentIterator.h +++ b/content/base/public/nsIContentIterator.h @@ -25,6 +25,8 @@ #include "nsISupports.h" + +class nsIFocusTracker; class nsIContent; class nsIDOMRange; @@ -32,6 +34,11 @@ class nsIDOMRange; {0xa6cf90e4, 0x15b3, 0x11d2, \ {0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32} } +// {B4BC9F63-D9BA-11d3-9938-00108301233C} +#define NS_IGENERATEDCONTENTITERTOR_IID \ +{ 0xb4bc9f63, 0xd9ba, 0x11d3, \ +{ 0x99, 0x38, 0x0, 0x10, 0x83, 0x1, 0x23, 0x3c } } + class nsIContentIterator : public nsISupports { public: @@ -86,6 +93,16 @@ public: }; +class nsIGeneratedContentIterator : public nsISupports { +public: + + static const nsIID& GetIID() { static nsIID iid = NS_IGENERATEDCONTENTITERTOR_IID; return iid; } + + /* Initializes an iterator for the subtree rooted by the node aRoot + */ + NS_IMETHOD Init(nsIFocusTracker *aTracker, nsIDOMRange* aRange, PRBool aSelectBefore, PRBool aSelectAfter)=0; +}; + #endif // __nsIContentIterator_h___ diff --git a/content/base/src/nsContentIterator.cpp b/content/base/src/nsContentIterator.cpp index 9457bfed4543..d907010b0ec5 100644 --- a/content/base/src/nsContentIterator.cpp +++ b/content/base/src/nsContentIterator.cpp @@ -33,10 +33,15 @@ #include "nsIContent.h" #include "nsIDOMText.h" #include "nsISupportsArray.h" - +#include "nsIFocusTracker.h" #include "nsCOMPtr.h" +#include "nsIPresContext.h" +#include "nsIComponentManager.h" +#include "nsLayoutCID.h" static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); +static NS_DEFINE_IID(kCContentIteratorCID, NS_CONTENTITERATOR_CID); +static NS_DEFINE_IID(kCSubtreeIteratorCID, NS_SUBTREEITERATOR_CID); // couple of utility static functs @@ -159,6 +164,65 @@ private: }; nsresult NS_NewContentIterator(nsIContentIterator** aInstancePtrResult); +nsresult NS_NewGeneratedContentIterator(nsIGeneratedContentIterator** aInstancePtrResult); + +class nsGeneratedContentIterator : public nsContentIterator, nsIGeneratedContentIterator +{ +public: + NS_DECL_ISUPPORTS + nsGeneratedContentIterator(); + virtual ~nsGeneratedContentIterator(); + + // nsIGeneratedContentIterator interface methods ------------------------------ + + NS_IMETHOD Init(nsIFocusTracker *aTracker, nsIDOMRange* aRange, PRBool aSelectBefore, PRBool aSelectAfter); + NS_IMETHOD First(); + + NS_IMETHOD Last(); + + NS_IMETHOD Next(); + + NS_IMETHOD Prev(); + + NS_IMETHOD CurrentNode(nsIContent **aNode); + +protected: + PRBool mSelectBefore;//set at init time + PRBool mSelectAfter; + nsCOMPtr mGenIter;//reset for every before and after + nsIFocusTracker *mTracker;//weak reference + + nsresult FillGenIter(PRInt8 aSide); + PRInt8 mCurSideOfContent; //-1= before, 0 = current, 1=next +}; + + +nsGeneratedContentIterator::nsGeneratedContentIterator() +:mSelectBefore(0),mSelectAfter(0), mCurSideOfContent(-1) +{ +} + +nsGeneratedContentIterator::~nsGeneratedContentIterator() +{ +} + + +NS_IMPL_ADDREF_INHERITED(nsGeneratedContentIterator, nsContentIterator) +NS_IMPL_RELEASE_INHERITED(nsGeneratedContentIterator, nsContentIterator) + +NS_IMETHODIMP +nsGeneratedContentIterator::QueryInterface(REFNSIID aIID, void** aInstancePtr) +{ + if (nsnull == aInstancePtr) { + return NS_ERROR_NULL_POINTER; + } + if (aIID.Equals(nsIGeneratedContentIterator::GetIID())) { + *aInstancePtr = NS_STATIC_CAST(nsIGeneratedContentIterator *,this); + NS_ADDREF_THIS(); + return NS_OK; + } + return nsContentIterator::QueryInterface(aIID,aInstancePtr); +} /****************************************************** @@ -173,6 +237,14 @@ nsresult NS_NewContentIterator(nsIContentIterator** aInstancePtrResult) return NS_ERROR_OUT_OF_MEMORY; } +nsresult NS_NewGeneratedContentIterator(nsIContentIterator** aInstancePtrResult) +{ + nsGeneratedContentIterator * iter = new nsGeneratedContentIterator(); + if (iter) + return iter->QueryInterface(NS_GET_IID(nsIContentIterator), (void**) aInstancePtrResult); + return NS_ERROR_OUT_OF_MEMORY; +} + /****************************************************** * XPCOM cruft @@ -1086,4 +1158,478 @@ nsresult nsContentSubtreeIterator::GetTopAncestorInRange( return NS_ERROR_FAILURE; } +/****************************************************** + * nsGeneratedSubtreeIterator + ******************************************************/ + +nsresult NS_NewGeneratedSubtreeIterator(nsIGeneratedContentIterator** aInstancePtrResult); + +class nsGeneratedSubTreeIterator : public nsContentSubtreeIterator, nsIGeneratedContentIterator +{ +public: + NS_DECL_ISUPPORTS + nsGeneratedSubTreeIterator(); + virtual ~nsGeneratedSubTreeIterator(); + + // nsIGeneratedContentIterator interface methods ------------------------------ + + NS_IMETHOD Init(nsIFocusTracker *aTracker, nsIContent* aRange, PRBool aSelectBefore, PRBool aSelectAfter); + NS_IMETHOD First(); + + NS_IMETHOD Last(); + + NS_IMETHOD Next(); + + NS_IMETHOD Prev(); + + NS_IMETHOD CurrentNode(nsIContent **aNode); + +protected: + PRBool mSelectBefore;//set at init time + PRBool mSelectAfter; + nsCOMPtr mGenIter;//reset for every before and after + nsIFocusTracker *mTracker;//weak reference + + nsresult FillGenIter(PRInt8 aSide); + PRInt8 mCurSideOfContent; //-1= before, 0 = current, 1=next +}; + + +nsGeneratedSubTreeIterator::nsGeneratedSubTreeIterator() +:mSelectBefore(0),mSelectAfter(0), mCurSideOfContent(-1) +{ +} + +nsGeneratedSubTreeIterator::~nsGeneratedSubTreeIterator() +{ +} + + +NS_IMPL_ADDREF_INHERITED(nsGeneratedSubTreeIterator, nsContentIterator) +NS_IMPL_RELEASE_INHERITED(nsGeneratedSubTreeIterator, nsContentIterator) + +NS_IMETHODIMP +nsGeneratedSubTreeIterator::QueryInterface(REFNSIID aIID, void** aInstancePtr) +{ + if (nsnull == aInstancePtr) { + return NS_ERROR_NULL_POINTER; + } + if (aIID.Equals(nsIGeneratedContentIterator::GetIID())) { + *aInstancePtr = NS_STATIC_CAST(nsIGeneratedContentIterator *,this); + NS_ADDREF_THIS(); + return NS_OK; + } + return nsContentSubtreeIterator::QueryInterface(aIID,aInstancePtr); +} + + +/****************************************************** + * nsGeneratedSubTreeIterator + ******************************************************/ + +nsresult nsGeneratedSubTreeIterator::Init(nsIFocusTracker *aTracker, nsIContent* aContent, PRBool aSelectBefore, PRBool aSelectAfter) +{ + mTracker = aTracker; + mSelectBefore = aSelectBefore; + mSelectAfter = aSelectAfter; + return nsContentSubtreeIterator::Init(aContent); +} + + +nsresult nsGeneratedSubTreeIterator::First() +{ + nsContentSubtreeIterator::First(); + if (!mFirst) + return NS_ERROR_FAILURE; + + mIsDone = PR_FALSE; + mGenIter = 0; + if (mSelectBefore) + { + mCurSideOfContent = -1;//get generated from in FRONT of this node + FillGenIter(mCurSideOfContent); + } + if (!mGenIter) + mCurSideOfContent = 0; + return NS_OK; +} + +nsresult nsGeneratedSubTreeIterator::Next() +{ + if (mIsDone) + return NS_OK; + if (!mCurNode) + return NS_OK; + + nsresult result = NS_OK; + + if (mGenIter) + { + result = mGenIter->Next(); + if (NS_FAILED(result) || (NS_SUCCEEDED(mGenIter->IsDone()) )) + { + mGenIter = 0; + } + else + return result; + } + + if (mCurNode == mLast && !mGenIter) + { + mIsDone = PR_TRUE; + return NS_OK; + } + + mCurSideOfContent ++; + if (mCurSideOfContent > 0)//current node currently + { + FillGenIter(mCurSideOfContent); + } + if (!mGenIter) //nothing after current node + { + mCurSideOfContent = -1; + result = nsContentSubtreeIterator::NextNode(&mCurNode); + FillGenIter(mCurSideOfContent); + if (!mGenIter)//nothing before new node. + mCurSideOfContent = 0;//advance to actual node + } + return result; +} + +nsresult nsGeneratedSubTreeIterator::Prev() +{ + if (mIsDone) + return NS_OK; + if (!mCurNode) + return NS_OK; + + nsresult result = NS_OK; + + if (mGenIter) + { + result = mGenIter->Prev(); + if (NS_FAILED(result) || (NS_SUCCEEDED(mGenIter->IsDone()) )) + { + mGenIter = 0; + } + else + return result; + } + + if (mCurNode == mFirst && !mGenIter) + { + mIsDone = PR_TRUE; + return NS_OK; + } + + mCurSideOfContent --; + if (mCurSideOfContent < 0)//current node currently + { + FillGenIter(mCurSideOfContent); + } + if (!mGenIter) //nothing after current node + { + mCurSideOfContent = 1; + result = nsContentSubtreeIterator::PrevNode(&mCurNode); + FillGenIter(mCurSideOfContent); + if (!mGenIter)//nothing before new node. + mCurSideOfContent = 0;//advance to actual node + } + return result; +} + + +nsresult nsGeneratedSubTreeIterator::Last() +{ + if (!mLast) + return NS_ERROR_FAILURE; + nsContentSubtreeIterator::Last(); + mGenIter = 0; + mIsDone = PR_FALSE; + if (mSelectAfter) + { + mCurSideOfContent = 1; + FillGenIter(mCurSideOfContent); + } + if (!mGenIter) + mCurSideOfContent = 0; + + return NS_OK; +} + +nsresult +nsGeneratedSubTreeIterator::FillGenIter(PRInt8 aSide) +{ + if (!mCurNode || !mTracker) + return NS_ERROR_NULL_POINTER; + nsresult result; + if (aSide == 0) + return NS_OK; + nsFrameState frameState; + nsIFrame *genFrame; + result = mTracker->GetPrimaryFrameFor(mCurNode, &genFrame); + if (NS_FAILED(result)) + return result; + if (!genFrame) + return NS_ERROR_FAILURE; + nsCOMPtr context; + result = mTracker->GetPresContext(getter_AddRefs(context)); + if (NS_FAILED(result) || !context) + return result?result:NS_ERROR_FAILURE; + result = genFrame->FirstChild(context,nsnull,&genFrame); + if (NS_FAILED(result) || !genFrame) + return NS_OK;//fine nothing to do here + if (aSide < 0) + { + //we SHOULD now have a generated content frame if one exists. we need to check the flag for gen content + result = genFrame->GetFrameState(&frameState); + + if (NS_FAILED(result)) + return result; + + } + else if (aSide > 0) + { + nsIFrame *nextFrame = genFrame; + while(nextFrame) + { + result = nextFrame->GetNextSibling(&nextFrame); + if (NS_SUCCEEDED(result) && nextFrame) + genFrame = nextFrame; + else + nextFrame = nsnull; + } + } + if (frameState & NS_FRAME_GENERATED_CONTENT) { + nsCOMPtr content; + result = genFrame->GetContent(getter_AddRefs(content)); + if (NS_FAILED(result) || !content) + return result ? result:NS_ERROR_FAILURE; + result = nsComponentManager::CreateInstance(kCSubtreeIteratorCID, nsnull, + NS_GET_IID(nsIContentIterator), + getter_AddRefs(mGenIter)); + if (NS_FAILED(result) || !mGenIter) + return result ? result:NS_ERROR_FAILURE; + mGenIter->Init(content); + if (aSide > 0) + mGenIter->Last(); + } + + return NS_OK; +} + +nsresult nsGeneratedSubTreeIterator::CurrentNode(nsIContent **aNode) +{ + if (!mCurNode) + return NS_ERROR_FAILURE; + if (mIsDone) + return NS_ERROR_FAILURE; + if (mGenIter) + return mGenIter->CurrentNode(aNode); + return mCurNode->QueryInterface(nsIContent::GetIID(), (void**) aNode); +} + + +/****************************************************** + * nsGeneratedContentIterator + ******************************************************/ + +nsresult nsGeneratedContentIterator::Init(nsIFocusTracker *aTracker, nsIDOMRange* aRange, PRBool aSelectBefore, PRBool aSelectAfter) +{ + mTracker = aTracker; + mSelectBefore = aSelectBefore; + mSelectAfter = aSelectAfter; + return nsContentIterator::Init(aRange); +} + + +nsresult nsGeneratedContentIterator::First() +{ + nsContentIterator::First(); + if (!mFirst) + return NS_ERROR_FAILURE; + mIsDone = PR_FALSE; + mGenIter = 0; + if (mSelectBefore) + { + mCurSideOfContent = -1;//get generated from in FRONT of this node + FillGenIter(mCurSideOfContent); + } + if (!mGenIter) + mCurSideOfContent = 0; + return NS_OK; +} + +nsresult nsGeneratedContentIterator::Next() +{ + if (mIsDone) + return NS_OK; + if (!mCurNode) + return NS_OK; + + nsresult result = NS_OK; + + if (mGenIter) + { + result = mGenIter->Next(); + if (NS_FAILED(result) || (NS_SUCCEEDED(mGenIter->IsDone()) )) + { + mGenIter = 0; + } + else + return result; + } + + if (mCurNode == mLast && !mGenIter) + { + mIsDone = PR_TRUE; + return NS_OK; + } + + mCurSideOfContent ++; + if (mCurSideOfContent > 0)//current node currently + { + FillGenIter(mCurSideOfContent); + } + if (!mGenIter) //nothing after current node + { + mCurSideOfContent = -1; + result = nsContentIterator::NextNode(&mCurNode); + FillGenIter(mCurSideOfContent); + if (!mGenIter)//nothing before new node. + mCurSideOfContent = 0;//advance to actual node + } + return result; +} + +nsresult nsGeneratedContentIterator::Prev() +{ + if (mIsDone) + return NS_OK; + if (!mCurNode) + return NS_OK; + + nsresult result = NS_OK; + + if (mGenIter) + { + result = mGenIter->Prev(); + if (NS_FAILED(result) || (NS_SUCCEEDED(mGenIter->IsDone()) )) + { + mGenIter = 0; + } + else + return result; + } + + if (mCurNode == mFirst && !mGenIter) + { + mIsDone = PR_TRUE; + return NS_OK; + } + + mCurSideOfContent --; + if (mCurSideOfContent < 0)//current node currently + { + FillGenIter(mCurSideOfContent); + } + if (!mGenIter) //nothing after current node + { + mCurSideOfContent = 1; + result = nsContentIterator::PrevNode(&mCurNode); + FillGenIter(mCurSideOfContent); + if (!mGenIter)//nothing before new node. + mCurSideOfContent = 0;//advance to actual node + } + return result; +} + + +nsresult nsGeneratedContentIterator::Last() +{ + nsContentIterator::Last(); + if (!mLast) + return NS_ERROR_FAILURE; + mGenIter = 0; + mIsDone = PR_FALSE; + mCurNode = mLast; + mCurSideOfContent = 1; + FillGenIter(mCurSideOfContent); + if (!mGenIter) + mCurSideOfContent = 0; + + return NS_OK; +} + +nsresult +nsGeneratedContentIterator::FillGenIter(PRInt8 aSide) +{ + if (!mCurNode || !mTracker) + return NS_ERROR_NULL_POINTER; + nsresult result; + if (aSide == 0) + return NS_OK; + nsFrameState frameState; + nsIFrame *genFrame; + result = mTracker->GetPrimaryFrameFor(mCurNode, &genFrame); + if (NS_FAILED(result)) + return result; + if (!genFrame) + return NS_ERROR_FAILURE; + nsCOMPtr context; + result = mTracker->GetPresContext(getter_AddRefs(context)); + if (NS_FAILED(result) || !context) + return result?result:NS_ERROR_FAILURE; + result = genFrame->FirstChild(context,nsnull,&genFrame); + if (NS_FAILED(result) || !genFrame) + return NS_OK;//fine nothing to do here + if (aSide < 0) + { + //we SHOULD now have a generated content frame if one exists. we need to check the flag for gen content + result = genFrame->GetFrameState(&frameState); + + if (NS_FAILED(result)) + return result; + + } + else if (aSide > 0) + { + nsIFrame *nextFrame = genFrame; + while(nextFrame) + { + result = nextFrame->GetNextSibling(&nextFrame); + if (NS_SUCCEEDED(result) && nextFrame) + genFrame = nextFrame; + else + nextFrame = nsnull; + } + } + if (frameState & NS_FRAME_GENERATED_CONTENT) { + nsCOMPtr content; + result = genFrame->GetContent(getter_AddRefs(content)); + if (NS_FAILED(result) || !content) + return result ? result:NS_ERROR_FAILURE; + result = nsComponentManager::CreateInstance(kCSubtreeIteratorCID, nsnull, + NS_GET_IID(nsIContentIterator), + getter_AddRefs(mGenIter)); + if (NS_FAILED(result) || !mGenIter) + return result ? result:NS_ERROR_FAILURE; + mGenIter->Init(content); + if (aSide > 0) + mGenIter->Last(); + } + + return NS_OK; +} + +nsresult nsGeneratedContentIterator::CurrentNode(nsIContent **aNode) +{ + if (!mCurNode) + return NS_ERROR_FAILURE; + if (mIsDone) + return NS_ERROR_FAILURE; + if (mGenIter) + return mGenIter->CurrentNode(aNode); + return mCurNode->QueryInterface(nsIContent::GetIID(), (void**) aNode); +} diff --git a/content/base/src/nsDocumentViewer.cpp b/content/base/src/nsDocumentViewer.cpp index 9bd62c14e91b..20653de7454a 100644 --- a/content/base/src/nsDocumentViewer.cpp +++ b/content/base/src/nsDocumentViewer.cpp @@ -1609,3 +1609,10 @@ NS_IMETHODIMP DocumentViewerImpl::NotifySelectionChanged(void) // to the right nsIDOMXULCommandDispatcher yet. return NS_OK; } + +NS_IMETHODIMP DocumentViewerImpl::TableCellNotification(nsIDOMNode* aNode, PRInt32 aOffset) +{ + //stub + return NS_OK; +} + diff --git a/content/base/src/nsRange.cpp b/content/base/src/nsRange.cpp index ee7c440f12c5..f2ca70d58b22 100644 --- a/content/base/src/nsRange.cpp +++ b/content/base/src/nsRange.cpp @@ -58,6 +58,7 @@ nsVoidArray* nsRange::mStartAncestorOffsets = nsnull; nsVoidArray* nsRange::mEndAncestorOffsets = nsnull; nsresult NS_NewContentIterator(nsIContentIterator** aInstancePtrResult); +nsresult NS_NewGeneratedContentIterator(nsIContentIterator** aInstancePtrResult); /****************************************************** @@ -1974,6 +1975,44 @@ nsRange::IsValidFragment(const nsString& aFragment, PRBool* aReturn) return result; } +NS_IMETHODIMP +nsRange::GetHasGeneratedBefore(PRBool *aBool) +{ + NS_ENSURE_ARG_POINTER(aBool); + *aBool = mBeforeGenContent; + return NS_OK; +} + +NS_IMETHODIMP +nsRange::GetHasGeneratedAfter(PRBool *aBool) +{ + NS_ENSURE_ARG_POINTER(aBool); + *aBool = mAfterGenContent; + return NS_OK; +} + +NS_IMETHODIMP +nsRange::SetHasGeneratedBefore(PRBool aBool) +{ + mBeforeGenContent = aBool; + return NS_OK; +} + +NS_IMETHODIMP +nsRange::SetHasGeneratedAfter(PRBool aBool) +{ + mAfterGenContent = aBool; + return NS_OK; +} + +NS_IMETHODIMP +nsRange::SetBeforeAndAfter(PRBool aBefore, PRBool aAfter) +{ + mBeforeGenContent = aBefore; + mBeforeGenContent = aAfter; + return NS_OK; +} + // BEGIN nsIScriptObjectOwner interface implementations NS_IMETHODIMP nsRange::GetScriptObject(nsIScriptContext *aContext, void** aScriptObject) diff --git a/content/base/src/nsRange.h b/content/base/src/nsRange.h index 58571a810658..05d1701d5175 100644 --- a/content/base/src/nsRange.h +++ b/content/base/src/nsRange.h @@ -94,12 +94,18 @@ public: NS_IMETHOD CreateContextualFragment(const nsString& aFragment, nsIDOMDocumentFragment** aReturn); NS_IMETHOD IsValidFragment(const nsString& aFragment, PRBool* aReturn); + NS_IMETHOD GetHasGeneratedBefore(PRBool *aBool); + NS_IMETHOD GetHasGeneratedAfter(PRBool *aBool); + NS_IMETHOD SetHasGeneratedBefore(PRBool aBool); + NS_IMETHOD SetHasGeneratedAfter(PRBool aBool); + NS_IMETHOD SetBeforeAndAfter(PRBool aBefore, PRBool aAfter); /*BEGIN nsIScriptObjectOwner interface implementations*/ NS_IMETHOD GetScriptObject(nsIScriptContext *aContext, void** aScriptObject); NS_IMETHOD SetScriptObject(void *aScriptObject); /*END nsIScriptObjectOwner interface implementations*/ + // nsRange interface extensions static NS_METHOD OwnerGone(nsIContent* aParentNode); @@ -169,6 +175,8 @@ public: protected: void* mScriptObject; + PRBool mBeforeGenContent; + PRBool mAfterGenContent; }; diff --git a/content/html/content/src/nsIHTMLTableCellElement.h b/content/html/content/src/nsIHTMLTableCellElement.h index 7483a24ff011..7abef081260d 100644 --- a/content/html/content/src/nsIHTMLTableCellElement.h +++ b/content/html/content/src/nsIHTMLTableCellElement.h @@ -35,6 +35,7 @@ class nsIHTMLTableCellElement : public nsISupports { public: + static const nsIID& GetIID() { static nsIID iid = NS_IHTMLTABLECELLELEMENT_IID; return iid; } /** @return the starting column for this cell. Always >= 1 */ NS_IMETHOD GetColIndex (PRInt32* aColIndex) = 0; diff --git a/dom/public/idl/range/SelectionListener.idl b/dom/public/idl/range/SelectionListener.idl index 18763f97f2ed..c8162f4ee4e0 100644 --- a/dom/public/idl/range/SelectionListener.idl +++ b/dom/public/idl/range/SelectionListener.idl @@ -3,5 +3,10 @@ { 0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32} } */ void notifySelectionChanged(); + /* tableCellNotification is a call back for when a cell is trying to be + selected. No selection action will take place. only this notification. + currently CTRL-LEFTMOUSEBUTTON in a table cell is the event that will + trigger this call.*/ + void tableCellNotification(in Node parent, in long offset); }; diff --git a/dom/public/nsDOMPropEnums.h b/dom/public/nsDOMPropEnums.h index 6eaea496f300..ce8882884511 100644 --- a/dom/public/nsDOMPropEnums.h +++ b/dom/public/nsDOMPropEnums.h @@ -782,6 +782,7 @@ enum nsDOMProp { NS_DOM_PROP_SELECTION_STARTBATCHCHANGES, NS_DOM_PROP_SELECTION_TOSTRING, NS_DOM_PROP_SELECTIONLISTENER_NOTIFYSELECTIONCHANGED, + NS_DOM_PROP_SELECTIONLISTENER_TABLECELLNOTIFICATION, NS_DOM_PROP_STYLESHEET_DISABLED, NS_DOM_PROP_STYLESHEET_READONLY, NS_DOM_PROP_STYLESHEET_TYPE, diff --git a/dom/public/range/nsIDOMSelectionListener.h b/dom/public/range/nsIDOMSelectionListener.h index 007c257acabe..9ae4b592acfc 100644 --- a/dom/public/range/nsIDOMSelectionListener.h +++ b/dom/public/range/nsIDOMSelectionListener.h @@ -28,6 +28,7 @@ #include "nsString.h" #include "nsIScriptContext.h" +class nsIDOMNode; #define NS_IDOMSELECTIONLISTENER_IID \ { 0xa6cf90e2, 0x15b3, 0x11d2, \ @@ -38,16 +39,20 @@ public: static const nsIID& GetIID() { static nsIID iid = NS_IDOMSELECTIONLISTENER_IID; return iid; } NS_IMETHOD NotifySelectionChanged()=0; + + NS_IMETHOD TableCellNotification(nsIDOMNode* aParent, PRInt32 aOffset)=0; }; #define NS_DECL_IDOMSELECTIONLISTENER \ NS_IMETHOD NotifySelectionChanged(); \ + NS_IMETHOD TableCellNotification(nsIDOMNode* aParent, PRInt32 aOffset); \ #define NS_FORWARD_IDOMSELECTIONLISTENER(_to) \ NS_IMETHOD NotifySelectionChanged() { return _to NotifySelectionChanged(); } \ + NS_IMETHOD TableCellNotification(nsIDOMNode* aParent, PRInt32 aOffset) { return _to TableCellNotification(aParent, aOffset); } \ extern "C" NS_DOM nsresult NS_InitSelectionListenerClass(nsIScriptContext *aContext, void **aPrototype); diff --git a/dom/src/range/nsJSSelectionListener.cpp b/dom/src/range/nsJSSelectionListener.cpp index 3a93fd7c3b7f..2e9623663e9c 100644 --- a/dom/src/range/nsJSSelectionListener.cpp +++ b/dom/src/range/nsJSSelectionListener.cpp @@ -34,12 +34,14 @@ #include "nsCOMPtr.h" #include "nsDOMPropEnums.h" #include "nsString.h" +#include "nsIDOMNode.h" #include "nsIDOMSelectionListener.h" static NS_DEFINE_IID(kIScriptObjectOwnerIID, NS_ISCRIPTOBJECTOWNER_IID); static NS_DEFINE_IID(kIJSScriptObjectIID, NS_IJSSCRIPTOBJECT_IID); static NS_DEFINE_IID(kIScriptGlobalObjectIID, NS_ISCRIPTGLOBALOBJECT_IID); +static NS_DEFINE_IID(kINodeIID, NS_IDOMNODE_IID); static NS_DEFINE_IID(kISelectionListenerIID, NS_IDOMSELECTIONLISTENER_IID); @@ -184,6 +186,64 @@ SelectionListenerNotifySelectionChanged(JSContext *cx, JSObject *obj, uintN argc } +// +// Native method TableCellNotification +// +PR_STATIC_CALLBACK(JSBool) +SelectionListenerTableCellNotification(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) +{ + nsIDOMSelectionListener *nativeThis = (nsIDOMSelectionListener*)nsJSUtils::nsGetNativeThis(cx, obj); + nsresult result = NS_OK; + nsCOMPtr b0; + PRInt32 b1; + // If there's no private data, this must be the prototype, so ignore + if (nsnull == nativeThis) { + return JS_TRUE; + } + + { + + *rval = JSVAL_NULL; + + { + nsresult rv; + NS_WITH_SERVICE(nsIScriptSecurityManager, secMan, + NS_SCRIPTSECURITYMANAGER_PROGID, &rv); + if (NS_SUCCEEDED(rv)) { + rv = secMan->CheckScriptAccess(cx, obj, NS_DOM_PROP_SELECTIONLISTENER_TABLECELLNOTIFICATION, PR_FALSE); + } + if (NS_FAILED(rv)) { + return nsJSUtils::nsReportError(cx, obj, rv); + } + } + + if (argc < 2) { + return nsJSUtils::nsReportError(cx, obj, NS_ERROR_DOM_TOO_FEW_PARAMETERS_ERR); + } + + if (JS_FALSE == nsJSUtils::nsConvertJSValToObject((nsISupports **)(void**)getter_AddRefs(b0), + kINodeIID, + "Node", + cx, + argv[0])) { + return nsJSUtils::nsReportError(cx, obj, NS_ERROR_DOM_NOT_OBJECT_ERR); + } + if (!JS_ValueToInt32(cx, argv[1], (int32 *)&b1)) { + return nsJSUtils::nsReportError(cx, obj, NS_ERROR_DOM_NOT_NUMBER_ERR); + } + + result = nativeThis->TableCellNotification(b0, b1); + if (NS_FAILED(result)) { + return nsJSUtils::nsReportError(cx, obj, result); + } + + *rval = JSVAL_VOID; + } + + return JS_TRUE; +} + + /***********************************************************************/ // // class for SelectionListener @@ -219,6 +279,7 @@ static JSPropertySpec SelectionListenerProperties[] = static JSFunctionSpec SelectionListenerMethods[] = { {"notifySelectionChanged", SelectionListenerNotifySelectionChanged, 0}, + {"tableCellNotification", SelectionListenerTableCellNotification, 2}, {0} }; diff --git a/editor/base/TypeInState.cpp b/editor/base/TypeInState.cpp index 6d4897073149..e6518bed252d 100644 --- a/editor/base/TypeInState.cpp +++ b/editor/base/TypeInState.cpp @@ -57,3 +57,8 @@ NS_IMETHODIMP TypeInState::NotifySelectionChanged() return NS_OK; }; +NS_IMETHODIMP TypeInState::TableCellNotification(nsIDOMNode* aNode, PRInt32 aOffset) +{ + //stub + return NS_OK; +} diff --git a/editor/base/TypeInState.h b/editor/base/TypeInState.h index efa8dc2df1c8..30bf98d2731b 100644 --- a/editor/base/TypeInState.h +++ b/editor/base/TypeInState.h @@ -38,6 +38,7 @@ public: virtual ~TypeInState(); NS_IMETHOD NotifySelectionChanged(); + NS_IMETHOD TableCellNotification(nsIDOMNode* aNode, PRInt32 aOffset); void GetEnumForName(nsIAtom *aPropName, PRUint32 &aEnum); void GetPropertyIsString(PRUint32 aProp, PRUint32 &aIsString); diff --git a/editor/base/nsInterfaceState.cpp b/editor/base/nsInterfaceState.cpp index 054cc7614bcb..6059612b9ef5 100644 --- a/editor/base/nsInterfaceState.cpp +++ b/editor/base/nsInterfaceState.cpp @@ -115,6 +115,13 @@ nsInterfaceState::NotifyDocumentCreated() return NS_OK; } +NS_IMETHODIMP +nsInterfaceState::TableCellNotification(nsIDOMNode* aNode, PRInt32 aOffset) +{ + //stub + return NS_OK; +} + NS_IMETHODIMP nsInterfaceState::NotifyDocumentWillBeDestroyed() { diff --git a/editor/base/nsInterfaceState.h b/editor/base/nsInterfaceState.h index 409f29b0b0c2..dfd27b85055e 100644 --- a/editor/base/nsInterfaceState.h +++ b/editor/base/nsInterfaceState.h @@ -53,7 +53,8 @@ public: // nsIDOMSelectionListener interface NS_IMETHOD NotifySelectionChanged(); - + NS_IMETHOD TableCellNotification(nsIDOMNode* aNode, PRInt32 aOffset); + NS_DECL_NSIDOCUMENTSTATELISTENER protected: diff --git a/editor/composer/src/nsInterfaceState.cpp b/editor/composer/src/nsInterfaceState.cpp index 054cc7614bcb..6059612b9ef5 100644 --- a/editor/composer/src/nsInterfaceState.cpp +++ b/editor/composer/src/nsInterfaceState.cpp @@ -115,6 +115,13 @@ nsInterfaceState::NotifyDocumentCreated() return NS_OK; } +NS_IMETHODIMP +nsInterfaceState::TableCellNotification(nsIDOMNode* aNode, PRInt32 aOffset) +{ + //stub + return NS_OK; +} + NS_IMETHODIMP nsInterfaceState::NotifyDocumentWillBeDestroyed() { diff --git a/editor/composer/src/nsInterfaceState.h b/editor/composer/src/nsInterfaceState.h index 409f29b0b0c2..dfd27b85055e 100644 --- a/editor/composer/src/nsInterfaceState.h +++ b/editor/composer/src/nsInterfaceState.h @@ -53,7 +53,8 @@ public: // nsIDOMSelectionListener interface NS_IMETHOD NotifySelectionChanged(); - + NS_IMETHOD TableCellNotification(nsIDOMNode* aNode, PRInt32 aOffset); + NS_DECL_NSIDOCUMENTSTATELISTENER protected: diff --git a/editor/libeditor/html/TypeInState.cpp b/editor/libeditor/html/TypeInState.cpp index 6d4897073149..e6518bed252d 100644 --- a/editor/libeditor/html/TypeInState.cpp +++ b/editor/libeditor/html/TypeInState.cpp @@ -57,3 +57,8 @@ NS_IMETHODIMP TypeInState::NotifySelectionChanged() return NS_OK; }; +NS_IMETHODIMP TypeInState::TableCellNotification(nsIDOMNode* aNode, PRInt32 aOffset) +{ + //stub + return NS_OK; +} diff --git a/editor/libeditor/html/TypeInState.h b/editor/libeditor/html/TypeInState.h index efa8dc2df1c8..30bf98d2731b 100644 --- a/editor/libeditor/html/TypeInState.h +++ b/editor/libeditor/html/TypeInState.h @@ -38,6 +38,7 @@ public: virtual ~TypeInState(); NS_IMETHOD NotifySelectionChanged(); + NS_IMETHOD TableCellNotification(nsIDOMNode* aNode, PRInt32 aOffset); void GetEnumForName(nsIAtom *aPropName, PRUint32 &aEnum); void GetPropertyIsString(PRUint32 aProp, PRUint32 &aIsString); diff --git a/layout/base/nsCSSFrameConstructor.cpp b/layout/base/nsCSSFrameConstructor.cpp index a4f2a4101621..5ada15aa6cd2 100644 --- a/layout/base/nsCSSFrameConstructor.cpp +++ b/layout/base/nsCSSFrameConstructor.cpp @@ -858,13 +858,27 @@ nsCSSFrameConstructor::CreateGeneratedContentFrame(nsIPresShell* aPresShe // the 'display' property nsIFrame* containerFrame; nsFrameItems childFrames; - + + nsCOMPtrcontainerElement; + nsCOMPtr containerContent; + nsCOMPtr document; + + aContent->GetDocument(*getter_AddRefs(document)); + + nsCOMPtr domdoc(do_QueryInterface(document)); + nsresult result; + result = domdoc->CreateElement("SPAN",getter_AddRefs(containerElement));//is the literal the correct way? + if (NS_SUCCEEDED(result) && containerElement) + { + containerContent = do_QueryInterface(containerElement); + } + if (NS_STYLE_DISPLAY_BLOCK == displayValue) { NS_NewBlockFrame(aPresShell, &containerFrame); } else { NS_NewInlineFrame(aPresShell, &containerFrame); } - InitAndRestoreFrame(aPresContext, aState, aContent, + InitAndRestoreFrame(aPresContext, aState, containerContent?containerContent:aContent, aFrame, pseudoStyleContext, nsnull, containerFrame); // Mark the frame as being associated with generated content @@ -882,8 +896,6 @@ nsCSSFrameConstructor::CreateGeneratedContentFrame(nsIPresShell* aPresShe // Now create content objects (and child frames) for each value of the // 'content' property - nsCOMPtr document; - aContent->GetDocument(*getter_AddRefs(document)); for (PRUint32 contentIndex = 0; contentIndex < contentCount; contentIndex++) { nsIFrame* frame; diff --git a/layout/base/nsCaret.cpp b/layout/base/nsCaret.cpp index 99cf5fe4f9ac..678869203c8a 100644 --- a/layout/base/nsCaret.cpp +++ b/layout/base/nsCaret.cpp @@ -320,6 +320,12 @@ NS_IMETHODIMP nsCaret::NotifySelectionChanged() return NS_OK; } +NS_IMETHODIMP nsCaret::TableCellNotification(nsIDOMNode* aNode, PRInt32 aOffset) +{ + //stub + return NS_OK; +} + #ifdef XP_MAC #pragma mark - #endif diff --git a/layout/base/nsCaret.h b/layout/base/nsCaret.h index 56dc183ba89c..d136b8a54b6f 100644 --- a/layout/base/nsCaret.h +++ b/layout/base/nsCaret.h @@ -58,6 +58,7 @@ class nsCaret : public nsICaret, //nsIDOMSelectionListener interface NS_IMETHOD NotifySelectionChanged(); + NS_IMETHOD TableCellNotification(nsIDOMNode* aNode, PRInt32 aOffset); static void CaretBlinkCallback(nsITimer *aTimer, void *aClosure); diff --git a/layout/base/nsDocumentViewer.cpp b/layout/base/nsDocumentViewer.cpp index 9bd62c14e91b..20653de7454a 100644 --- a/layout/base/nsDocumentViewer.cpp +++ b/layout/base/nsDocumentViewer.cpp @@ -1609,3 +1609,10 @@ NS_IMETHODIMP DocumentViewerImpl::NotifySelectionChanged(void) // to the right nsIDOMXULCommandDispatcher yet. return NS_OK; } + +NS_IMETHODIMP DocumentViewerImpl::TableCellNotification(nsIDOMNode* aNode, PRInt32 aOffset) +{ + //stub + return NS_OK; +} + diff --git a/layout/base/nsIFrameSelection.h b/layout/base/nsIFrameSelection.h index 3e343452677f..09470748ee77 100644 --- a/layout/base/nsIFrameSelection.h +++ b/layout/base/nsIFrameSelection.h @@ -142,9 +142,10 @@ public: * cannot coexist with aContinueSelection * @param aHint will tell the selection which direction geometrically to actually show the caret on. * 1 = end of this line 0 = beggining of this line + * @param aIsCell will tell us if this range describes a Cell. */ NS_IMETHOD HandleClick(nsIContent *aNewFocus, PRUint32 aContentOffset, PRUint32 aContentEndOffset , - PRBool aContinueSelection, PRBool aMultipleSelection, PRBool aHint) = 0; + PRBool aContinueSelection, PRBool aMultipleSelection, PRBool aHint, PRBool aIsCell) = 0; /** HandleDrag extends the selection to contain the frame closest to aPoint. * @param aPresContext is the context to use when figuring out what frame contains the point. diff --git a/layout/base/public/nsIContentIterator.h b/layout/base/public/nsIContentIterator.h index dbac9541f4fc..65394d1e358e 100644 --- a/layout/base/public/nsIContentIterator.h +++ b/layout/base/public/nsIContentIterator.h @@ -25,6 +25,8 @@ #include "nsISupports.h" + +class nsIFocusTracker; class nsIContent; class nsIDOMRange; @@ -32,6 +34,11 @@ class nsIDOMRange; {0xa6cf90e4, 0x15b3, 0x11d2, \ {0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32} } +// {B4BC9F63-D9BA-11d3-9938-00108301233C} +#define NS_IGENERATEDCONTENTITERTOR_IID \ +{ 0xb4bc9f63, 0xd9ba, 0x11d3, \ +{ 0x99, 0x38, 0x0, 0x10, 0x83, 0x1, 0x23, 0x3c } } + class nsIContentIterator : public nsISupports { public: @@ -86,6 +93,16 @@ public: }; +class nsIGeneratedContentIterator : public nsISupports { +public: + + static const nsIID& GetIID() { static nsIID iid = NS_IGENERATEDCONTENTITERTOR_IID; return iid; } + + /* Initializes an iterator for the subtree rooted by the node aRoot + */ + NS_IMETHOD Init(nsIFocusTracker *aTracker, nsIDOMRange* aRange, PRBool aSelectBefore, PRBool aSelectAfter)=0; +}; + #endif // __nsIContentIterator_h___ diff --git a/layout/base/public/nsIFrameSelection.h b/layout/base/public/nsIFrameSelection.h index 3e343452677f..09470748ee77 100644 --- a/layout/base/public/nsIFrameSelection.h +++ b/layout/base/public/nsIFrameSelection.h @@ -142,9 +142,10 @@ public: * cannot coexist with aContinueSelection * @param aHint will tell the selection which direction geometrically to actually show the caret on. * 1 = end of this line 0 = beggining of this line + * @param aIsCell will tell us if this range describes a Cell. */ NS_IMETHOD HandleClick(nsIContent *aNewFocus, PRUint32 aContentOffset, PRUint32 aContentEndOffset , - PRBool aContinueSelection, PRBool aMultipleSelection, PRBool aHint) = 0; + PRBool aContinueSelection, PRBool aMultipleSelection, PRBool aHint, PRBool aIsCell) = 0; /** HandleDrag extends the selection to contain the frame closest to aPoint. * @param aPresContext is the context to use when figuring out what frame contains the point. diff --git a/layout/base/src/nsCaret.cpp b/layout/base/src/nsCaret.cpp index 99cf5fe4f9ac..678869203c8a 100644 --- a/layout/base/src/nsCaret.cpp +++ b/layout/base/src/nsCaret.cpp @@ -320,6 +320,12 @@ NS_IMETHODIMP nsCaret::NotifySelectionChanged() return NS_OK; } +NS_IMETHODIMP nsCaret::TableCellNotification(nsIDOMNode* aNode, PRInt32 aOffset) +{ + //stub + return NS_OK; +} + #ifdef XP_MAC #pragma mark - #endif diff --git a/layout/base/src/nsCaret.h b/layout/base/src/nsCaret.h index 56dc183ba89c..d136b8a54b6f 100644 --- a/layout/base/src/nsCaret.h +++ b/layout/base/src/nsCaret.h @@ -58,6 +58,7 @@ class nsCaret : public nsICaret, //nsIDOMSelectionListener interface NS_IMETHOD NotifySelectionChanged(); + NS_IMETHOD TableCellNotification(nsIDOMNode* aNode, PRInt32 aOffset); static void CaretBlinkCallback(nsITimer *aTimer, void *aClosure); diff --git a/layout/base/src/nsContentIterator.cpp b/layout/base/src/nsContentIterator.cpp index 9457bfed4543..d907010b0ec5 100644 --- a/layout/base/src/nsContentIterator.cpp +++ b/layout/base/src/nsContentIterator.cpp @@ -33,10 +33,15 @@ #include "nsIContent.h" #include "nsIDOMText.h" #include "nsISupportsArray.h" - +#include "nsIFocusTracker.h" #include "nsCOMPtr.h" +#include "nsIPresContext.h" +#include "nsIComponentManager.h" +#include "nsLayoutCID.h" static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); +static NS_DEFINE_IID(kCContentIteratorCID, NS_CONTENTITERATOR_CID); +static NS_DEFINE_IID(kCSubtreeIteratorCID, NS_SUBTREEITERATOR_CID); // couple of utility static functs @@ -159,6 +164,65 @@ private: }; nsresult NS_NewContentIterator(nsIContentIterator** aInstancePtrResult); +nsresult NS_NewGeneratedContentIterator(nsIGeneratedContentIterator** aInstancePtrResult); + +class nsGeneratedContentIterator : public nsContentIterator, nsIGeneratedContentIterator +{ +public: + NS_DECL_ISUPPORTS + nsGeneratedContentIterator(); + virtual ~nsGeneratedContentIterator(); + + // nsIGeneratedContentIterator interface methods ------------------------------ + + NS_IMETHOD Init(nsIFocusTracker *aTracker, nsIDOMRange* aRange, PRBool aSelectBefore, PRBool aSelectAfter); + NS_IMETHOD First(); + + NS_IMETHOD Last(); + + NS_IMETHOD Next(); + + NS_IMETHOD Prev(); + + NS_IMETHOD CurrentNode(nsIContent **aNode); + +protected: + PRBool mSelectBefore;//set at init time + PRBool mSelectAfter; + nsCOMPtr mGenIter;//reset for every before and after + nsIFocusTracker *mTracker;//weak reference + + nsresult FillGenIter(PRInt8 aSide); + PRInt8 mCurSideOfContent; //-1= before, 0 = current, 1=next +}; + + +nsGeneratedContentIterator::nsGeneratedContentIterator() +:mSelectBefore(0),mSelectAfter(0), mCurSideOfContent(-1) +{ +} + +nsGeneratedContentIterator::~nsGeneratedContentIterator() +{ +} + + +NS_IMPL_ADDREF_INHERITED(nsGeneratedContentIterator, nsContentIterator) +NS_IMPL_RELEASE_INHERITED(nsGeneratedContentIterator, nsContentIterator) + +NS_IMETHODIMP +nsGeneratedContentIterator::QueryInterface(REFNSIID aIID, void** aInstancePtr) +{ + if (nsnull == aInstancePtr) { + return NS_ERROR_NULL_POINTER; + } + if (aIID.Equals(nsIGeneratedContentIterator::GetIID())) { + *aInstancePtr = NS_STATIC_CAST(nsIGeneratedContentIterator *,this); + NS_ADDREF_THIS(); + return NS_OK; + } + return nsContentIterator::QueryInterface(aIID,aInstancePtr); +} /****************************************************** @@ -173,6 +237,14 @@ nsresult NS_NewContentIterator(nsIContentIterator** aInstancePtrResult) return NS_ERROR_OUT_OF_MEMORY; } +nsresult NS_NewGeneratedContentIterator(nsIContentIterator** aInstancePtrResult) +{ + nsGeneratedContentIterator * iter = new nsGeneratedContentIterator(); + if (iter) + return iter->QueryInterface(NS_GET_IID(nsIContentIterator), (void**) aInstancePtrResult); + return NS_ERROR_OUT_OF_MEMORY; +} + /****************************************************** * XPCOM cruft @@ -1086,4 +1158,478 @@ nsresult nsContentSubtreeIterator::GetTopAncestorInRange( return NS_ERROR_FAILURE; } +/****************************************************** + * nsGeneratedSubtreeIterator + ******************************************************/ + +nsresult NS_NewGeneratedSubtreeIterator(nsIGeneratedContentIterator** aInstancePtrResult); + +class nsGeneratedSubTreeIterator : public nsContentSubtreeIterator, nsIGeneratedContentIterator +{ +public: + NS_DECL_ISUPPORTS + nsGeneratedSubTreeIterator(); + virtual ~nsGeneratedSubTreeIterator(); + + // nsIGeneratedContentIterator interface methods ------------------------------ + + NS_IMETHOD Init(nsIFocusTracker *aTracker, nsIContent* aRange, PRBool aSelectBefore, PRBool aSelectAfter); + NS_IMETHOD First(); + + NS_IMETHOD Last(); + + NS_IMETHOD Next(); + + NS_IMETHOD Prev(); + + NS_IMETHOD CurrentNode(nsIContent **aNode); + +protected: + PRBool mSelectBefore;//set at init time + PRBool mSelectAfter; + nsCOMPtr mGenIter;//reset for every before and after + nsIFocusTracker *mTracker;//weak reference + + nsresult FillGenIter(PRInt8 aSide); + PRInt8 mCurSideOfContent; //-1= before, 0 = current, 1=next +}; + + +nsGeneratedSubTreeIterator::nsGeneratedSubTreeIterator() +:mSelectBefore(0),mSelectAfter(0), mCurSideOfContent(-1) +{ +} + +nsGeneratedSubTreeIterator::~nsGeneratedSubTreeIterator() +{ +} + + +NS_IMPL_ADDREF_INHERITED(nsGeneratedSubTreeIterator, nsContentIterator) +NS_IMPL_RELEASE_INHERITED(nsGeneratedSubTreeIterator, nsContentIterator) + +NS_IMETHODIMP +nsGeneratedSubTreeIterator::QueryInterface(REFNSIID aIID, void** aInstancePtr) +{ + if (nsnull == aInstancePtr) { + return NS_ERROR_NULL_POINTER; + } + if (aIID.Equals(nsIGeneratedContentIterator::GetIID())) { + *aInstancePtr = NS_STATIC_CAST(nsIGeneratedContentIterator *,this); + NS_ADDREF_THIS(); + return NS_OK; + } + return nsContentSubtreeIterator::QueryInterface(aIID,aInstancePtr); +} + + +/****************************************************** + * nsGeneratedSubTreeIterator + ******************************************************/ + +nsresult nsGeneratedSubTreeIterator::Init(nsIFocusTracker *aTracker, nsIContent* aContent, PRBool aSelectBefore, PRBool aSelectAfter) +{ + mTracker = aTracker; + mSelectBefore = aSelectBefore; + mSelectAfter = aSelectAfter; + return nsContentSubtreeIterator::Init(aContent); +} + + +nsresult nsGeneratedSubTreeIterator::First() +{ + nsContentSubtreeIterator::First(); + if (!mFirst) + return NS_ERROR_FAILURE; + + mIsDone = PR_FALSE; + mGenIter = 0; + if (mSelectBefore) + { + mCurSideOfContent = -1;//get generated from in FRONT of this node + FillGenIter(mCurSideOfContent); + } + if (!mGenIter) + mCurSideOfContent = 0; + return NS_OK; +} + +nsresult nsGeneratedSubTreeIterator::Next() +{ + if (mIsDone) + return NS_OK; + if (!mCurNode) + return NS_OK; + + nsresult result = NS_OK; + + if (mGenIter) + { + result = mGenIter->Next(); + if (NS_FAILED(result) || (NS_SUCCEEDED(mGenIter->IsDone()) )) + { + mGenIter = 0; + } + else + return result; + } + + if (mCurNode == mLast && !mGenIter) + { + mIsDone = PR_TRUE; + return NS_OK; + } + + mCurSideOfContent ++; + if (mCurSideOfContent > 0)//current node currently + { + FillGenIter(mCurSideOfContent); + } + if (!mGenIter) //nothing after current node + { + mCurSideOfContent = -1; + result = nsContentSubtreeIterator::NextNode(&mCurNode); + FillGenIter(mCurSideOfContent); + if (!mGenIter)//nothing before new node. + mCurSideOfContent = 0;//advance to actual node + } + return result; +} + +nsresult nsGeneratedSubTreeIterator::Prev() +{ + if (mIsDone) + return NS_OK; + if (!mCurNode) + return NS_OK; + + nsresult result = NS_OK; + + if (mGenIter) + { + result = mGenIter->Prev(); + if (NS_FAILED(result) || (NS_SUCCEEDED(mGenIter->IsDone()) )) + { + mGenIter = 0; + } + else + return result; + } + + if (mCurNode == mFirst && !mGenIter) + { + mIsDone = PR_TRUE; + return NS_OK; + } + + mCurSideOfContent --; + if (mCurSideOfContent < 0)//current node currently + { + FillGenIter(mCurSideOfContent); + } + if (!mGenIter) //nothing after current node + { + mCurSideOfContent = 1; + result = nsContentSubtreeIterator::PrevNode(&mCurNode); + FillGenIter(mCurSideOfContent); + if (!mGenIter)//nothing before new node. + mCurSideOfContent = 0;//advance to actual node + } + return result; +} + + +nsresult nsGeneratedSubTreeIterator::Last() +{ + if (!mLast) + return NS_ERROR_FAILURE; + nsContentSubtreeIterator::Last(); + mGenIter = 0; + mIsDone = PR_FALSE; + if (mSelectAfter) + { + mCurSideOfContent = 1; + FillGenIter(mCurSideOfContent); + } + if (!mGenIter) + mCurSideOfContent = 0; + + return NS_OK; +} + +nsresult +nsGeneratedSubTreeIterator::FillGenIter(PRInt8 aSide) +{ + if (!mCurNode || !mTracker) + return NS_ERROR_NULL_POINTER; + nsresult result; + if (aSide == 0) + return NS_OK; + nsFrameState frameState; + nsIFrame *genFrame; + result = mTracker->GetPrimaryFrameFor(mCurNode, &genFrame); + if (NS_FAILED(result)) + return result; + if (!genFrame) + return NS_ERROR_FAILURE; + nsCOMPtr context; + result = mTracker->GetPresContext(getter_AddRefs(context)); + if (NS_FAILED(result) || !context) + return result?result:NS_ERROR_FAILURE; + result = genFrame->FirstChild(context,nsnull,&genFrame); + if (NS_FAILED(result) || !genFrame) + return NS_OK;//fine nothing to do here + if (aSide < 0) + { + //we SHOULD now have a generated content frame if one exists. we need to check the flag for gen content + result = genFrame->GetFrameState(&frameState); + + if (NS_FAILED(result)) + return result; + + } + else if (aSide > 0) + { + nsIFrame *nextFrame = genFrame; + while(nextFrame) + { + result = nextFrame->GetNextSibling(&nextFrame); + if (NS_SUCCEEDED(result) && nextFrame) + genFrame = nextFrame; + else + nextFrame = nsnull; + } + } + if (frameState & NS_FRAME_GENERATED_CONTENT) { + nsCOMPtr content; + result = genFrame->GetContent(getter_AddRefs(content)); + if (NS_FAILED(result) || !content) + return result ? result:NS_ERROR_FAILURE; + result = nsComponentManager::CreateInstance(kCSubtreeIteratorCID, nsnull, + NS_GET_IID(nsIContentIterator), + getter_AddRefs(mGenIter)); + if (NS_FAILED(result) || !mGenIter) + return result ? result:NS_ERROR_FAILURE; + mGenIter->Init(content); + if (aSide > 0) + mGenIter->Last(); + } + + return NS_OK; +} + +nsresult nsGeneratedSubTreeIterator::CurrentNode(nsIContent **aNode) +{ + if (!mCurNode) + return NS_ERROR_FAILURE; + if (mIsDone) + return NS_ERROR_FAILURE; + if (mGenIter) + return mGenIter->CurrentNode(aNode); + return mCurNode->QueryInterface(nsIContent::GetIID(), (void**) aNode); +} + + +/****************************************************** + * nsGeneratedContentIterator + ******************************************************/ + +nsresult nsGeneratedContentIterator::Init(nsIFocusTracker *aTracker, nsIDOMRange* aRange, PRBool aSelectBefore, PRBool aSelectAfter) +{ + mTracker = aTracker; + mSelectBefore = aSelectBefore; + mSelectAfter = aSelectAfter; + return nsContentIterator::Init(aRange); +} + + +nsresult nsGeneratedContentIterator::First() +{ + nsContentIterator::First(); + if (!mFirst) + return NS_ERROR_FAILURE; + mIsDone = PR_FALSE; + mGenIter = 0; + if (mSelectBefore) + { + mCurSideOfContent = -1;//get generated from in FRONT of this node + FillGenIter(mCurSideOfContent); + } + if (!mGenIter) + mCurSideOfContent = 0; + return NS_OK; +} + +nsresult nsGeneratedContentIterator::Next() +{ + if (mIsDone) + return NS_OK; + if (!mCurNode) + return NS_OK; + + nsresult result = NS_OK; + + if (mGenIter) + { + result = mGenIter->Next(); + if (NS_FAILED(result) || (NS_SUCCEEDED(mGenIter->IsDone()) )) + { + mGenIter = 0; + } + else + return result; + } + + if (mCurNode == mLast && !mGenIter) + { + mIsDone = PR_TRUE; + return NS_OK; + } + + mCurSideOfContent ++; + if (mCurSideOfContent > 0)//current node currently + { + FillGenIter(mCurSideOfContent); + } + if (!mGenIter) //nothing after current node + { + mCurSideOfContent = -1; + result = nsContentIterator::NextNode(&mCurNode); + FillGenIter(mCurSideOfContent); + if (!mGenIter)//nothing before new node. + mCurSideOfContent = 0;//advance to actual node + } + return result; +} + +nsresult nsGeneratedContentIterator::Prev() +{ + if (mIsDone) + return NS_OK; + if (!mCurNode) + return NS_OK; + + nsresult result = NS_OK; + + if (mGenIter) + { + result = mGenIter->Prev(); + if (NS_FAILED(result) || (NS_SUCCEEDED(mGenIter->IsDone()) )) + { + mGenIter = 0; + } + else + return result; + } + + if (mCurNode == mFirst && !mGenIter) + { + mIsDone = PR_TRUE; + return NS_OK; + } + + mCurSideOfContent --; + if (mCurSideOfContent < 0)//current node currently + { + FillGenIter(mCurSideOfContent); + } + if (!mGenIter) //nothing after current node + { + mCurSideOfContent = 1; + result = nsContentIterator::PrevNode(&mCurNode); + FillGenIter(mCurSideOfContent); + if (!mGenIter)//nothing before new node. + mCurSideOfContent = 0;//advance to actual node + } + return result; +} + + +nsresult nsGeneratedContentIterator::Last() +{ + nsContentIterator::Last(); + if (!mLast) + return NS_ERROR_FAILURE; + mGenIter = 0; + mIsDone = PR_FALSE; + mCurNode = mLast; + mCurSideOfContent = 1; + FillGenIter(mCurSideOfContent); + if (!mGenIter) + mCurSideOfContent = 0; + + return NS_OK; +} + +nsresult +nsGeneratedContentIterator::FillGenIter(PRInt8 aSide) +{ + if (!mCurNode || !mTracker) + return NS_ERROR_NULL_POINTER; + nsresult result; + if (aSide == 0) + return NS_OK; + nsFrameState frameState; + nsIFrame *genFrame; + result = mTracker->GetPrimaryFrameFor(mCurNode, &genFrame); + if (NS_FAILED(result)) + return result; + if (!genFrame) + return NS_ERROR_FAILURE; + nsCOMPtr context; + result = mTracker->GetPresContext(getter_AddRefs(context)); + if (NS_FAILED(result) || !context) + return result?result:NS_ERROR_FAILURE; + result = genFrame->FirstChild(context,nsnull,&genFrame); + if (NS_FAILED(result) || !genFrame) + return NS_OK;//fine nothing to do here + if (aSide < 0) + { + //we SHOULD now have a generated content frame if one exists. we need to check the flag for gen content + result = genFrame->GetFrameState(&frameState); + + if (NS_FAILED(result)) + return result; + + } + else if (aSide > 0) + { + nsIFrame *nextFrame = genFrame; + while(nextFrame) + { + result = nextFrame->GetNextSibling(&nextFrame); + if (NS_SUCCEEDED(result) && nextFrame) + genFrame = nextFrame; + else + nextFrame = nsnull; + } + } + if (frameState & NS_FRAME_GENERATED_CONTENT) { + nsCOMPtr content; + result = genFrame->GetContent(getter_AddRefs(content)); + if (NS_FAILED(result) || !content) + return result ? result:NS_ERROR_FAILURE; + result = nsComponentManager::CreateInstance(kCSubtreeIteratorCID, nsnull, + NS_GET_IID(nsIContentIterator), + getter_AddRefs(mGenIter)); + if (NS_FAILED(result) || !mGenIter) + return result ? result:NS_ERROR_FAILURE; + mGenIter->Init(content); + if (aSide > 0) + mGenIter->Last(); + } + + return NS_OK; +} + +nsresult nsGeneratedContentIterator::CurrentNode(nsIContent **aNode) +{ + if (!mCurNode) + return NS_ERROR_FAILURE; + if (mIsDone) + return NS_ERROR_FAILURE; + if (mGenIter) + return mGenIter->CurrentNode(aNode); + return mCurNode->QueryInterface(nsIContent::GetIID(), (void**) aNode); +} diff --git a/layout/base/src/nsDocumentViewer.cpp b/layout/base/src/nsDocumentViewer.cpp index 9bd62c14e91b..20653de7454a 100644 --- a/layout/base/src/nsDocumentViewer.cpp +++ b/layout/base/src/nsDocumentViewer.cpp @@ -1609,3 +1609,10 @@ NS_IMETHODIMP DocumentViewerImpl::NotifySelectionChanged(void) // to the right nsIDOMXULCommandDispatcher yet. return NS_OK; } + +NS_IMETHODIMP DocumentViewerImpl::TableCellNotification(nsIDOMNode* aNode, PRInt32 aOffset) +{ + //stub + return NS_OK; +} + diff --git a/layout/base/src/nsRange.cpp b/layout/base/src/nsRange.cpp index ee7c440f12c5..f2ca70d58b22 100644 --- a/layout/base/src/nsRange.cpp +++ b/layout/base/src/nsRange.cpp @@ -58,6 +58,7 @@ nsVoidArray* nsRange::mStartAncestorOffsets = nsnull; nsVoidArray* nsRange::mEndAncestorOffsets = nsnull; nsresult NS_NewContentIterator(nsIContentIterator** aInstancePtrResult); +nsresult NS_NewGeneratedContentIterator(nsIContentIterator** aInstancePtrResult); /****************************************************** @@ -1974,6 +1975,44 @@ nsRange::IsValidFragment(const nsString& aFragment, PRBool* aReturn) return result; } +NS_IMETHODIMP +nsRange::GetHasGeneratedBefore(PRBool *aBool) +{ + NS_ENSURE_ARG_POINTER(aBool); + *aBool = mBeforeGenContent; + return NS_OK; +} + +NS_IMETHODIMP +nsRange::GetHasGeneratedAfter(PRBool *aBool) +{ + NS_ENSURE_ARG_POINTER(aBool); + *aBool = mAfterGenContent; + return NS_OK; +} + +NS_IMETHODIMP +nsRange::SetHasGeneratedBefore(PRBool aBool) +{ + mBeforeGenContent = aBool; + return NS_OK; +} + +NS_IMETHODIMP +nsRange::SetHasGeneratedAfter(PRBool aBool) +{ + mAfterGenContent = aBool; + return NS_OK; +} + +NS_IMETHODIMP +nsRange::SetBeforeAndAfter(PRBool aBefore, PRBool aAfter) +{ + mBeforeGenContent = aBefore; + mBeforeGenContent = aAfter; + return NS_OK; +} + // BEGIN nsIScriptObjectOwner interface implementations NS_IMETHODIMP nsRange::GetScriptObject(nsIScriptContext *aContext, void** aScriptObject) diff --git a/layout/base/src/nsRange.h b/layout/base/src/nsRange.h index 58571a810658..05d1701d5175 100644 --- a/layout/base/src/nsRange.h +++ b/layout/base/src/nsRange.h @@ -94,12 +94,18 @@ public: NS_IMETHOD CreateContextualFragment(const nsString& aFragment, nsIDOMDocumentFragment** aReturn); NS_IMETHOD IsValidFragment(const nsString& aFragment, PRBool* aReturn); + NS_IMETHOD GetHasGeneratedBefore(PRBool *aBool); + NS_IMETHOD GetHasGeneratedAfter(PRBool *aBool); + NS_IMETHOD SetHasGeneratedBefore(PRBool aBool); + NS_IMETHOD SetHasGeneratedAfter(PRBool aBool); + NS_IMETHOD SetBeforeAndAfter(PRBool aBefore, PRBool aAfter); /*BEGIN nsIScriptObjectOwner interface implementations*/ NS_IMETHOD GetScriptObject(nsIScriptContext *aContext, void** aScriptObject); NS_IMETHOD SetScriptObject(void *aScriptObject); /*END nsIScriptObjectOwner interface implementations*/ + // nsRange interface extensions static NS_METHOD OwnerGone(nsIContent* aParentNode); @@ -169,6 +175,8 @@ public: protected: void* mScriptObject; + PRBool mBeforeGenContent; + PRBool mAfterGenContent; }; diff --git a/layout/base/src/nsRangeList.cpp b/layout/base/src/nsRangeList.cpp index 351de2e97f12..6a1d8609e85d 100644 --- a/layout/base/src/nsRangeList.cpp +++ b/layout/base/src/nsRangeList.cpp @@ -216,7 +216,7 @@ public: NS_IMETHOD HandleTextEvent(nsGUIEvent *aGUIEvent); NS_IMETHOD HandleKeyEvent(nsIPresContext* aPresContext, nsGUIEvent *aGuiEvent); NS_IMETHOD HandleClick(nsIContent *aNewFocus, PRUint32 aContentOffset, PRUint32 aContentEndOffset, - PRBool aContinueSelection, PRBool aMultipleSelection,PRBool aHint); + PRBool aContinueSelection, PRBool aMultipleSelection,PRBool aHint, PRBool aIsCell); NS_IMETHOD HandleDrag(nsIPresContext *aPresContext, nsIFrame *aFrame, nsPoint& aPoint); NS_IMETHOD StartAutoScrollTimer(nsIPresContext *aPresContext, nsIFrame *aFrame, nsPoint& aPoint, PRUint32 aDelay); NS_IMETHOD StopAutoScrollTimer(); @@ -274,6 +274,8 @@ private: void SetDirty(PRBool aDirty=PR_TRUE){if (mBatching) mChangesDuringBatching = aDirty;} nsresult NotifySelectionListeners(); // add parameters to say collapsed etc? + nsresult NotifySelectionListeners(nsIDOMNode *aNode, PRUint32 aCellOffset); + nsDOMSelection *mDomSelections[NUM_SELECTIONTYPES]; @@ -1348,10 +1350,15 @@ nsDOMSelection::ToString(nsString& aReturn) NS_IMETHODIMP nsRangeList::HandleClick(nsIContent *aNewFocus, PRUint32 aContentOffset, PRUint32 aContentEndOffset, PRBool aContinueSelection, - PRBool aMultipleSelection, PRBool aHint) + PRBool aMultipleSelection, PRBool aHint, PRBool aIsCell) { InvalidateDesiredX(); mHint = HINT(aHint); + if (aIsCell) + { + nsCOMPtr domNode = do_QueryInterface(aNewFocus); + return NotifySelectionListeners(domNode, aContentOffset); + } return TakeFocus(aNewFocus, aContentOffset, aContentEndOffset, aContinueSelection, aMultipleSelection); } @@ -1390,7 +1397,7 @@ nsRangeList::HandleDrag(nsIPresContext *aPresContext, nsIFrame *aFrame, nsPoint& startPos, contentOffsetEnd,beginOfContent); if (NS_SUCCEEDED(result)) - result = HandleClick(newContent, startPos, contentOffsetEnd , PR_TRUE, PR_FALSE,beginOfContent); + result = HandleClick(newContent, startPos, contentOffsetEnd , PR_TRUE, PR_FALSE,beginOfContent, PR_FALSE); return result; } @@ -1793,6 +1800,26 @@ nsRangeList::NotifySelectionListeners() return NS_OK; } + +nsresult +nsRangeList::NotifySelectionListeners(nsIDOMNode *aNode, PRUint32 aCellOffset) +{ + if (!mSelectionListeners) + return NS_ERROR_FAILURE; + + PRUint32 cnt; + nsresult rv = mSelectionListeners->Count(&cnt); + if (NS_FAILED(rv)) return rv; + for (PRUint32 i = 0; i < cnt;i++) + { + nsCOMPtr isupports(dont_AddRef(mSelectionListeners->ElementAt(i))); + nsCOMPtr thisListener = do_QueryInterface(isupports); + if (thisListener) + thisListener->TableCellNotification(aNode,aCellOffset); + } + return NS_OK; +} + //END nsIFrameSelection methods #ifdef XP_MAC diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp index dda1e3fb000f..bc83e1d6a391 100644 --- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -58,6 +58,7 @@ #include "nsCOMPtr.h" #include "nsStyleChangeList.h" #include "nsIDOMRange.h" +#include "nsITableCellLayout.h"//selection neccesity #define NORMAL_DRAG_HANDLING 1 // remove this to simulate a start-drag event. @@ -865,13 +866,40 @@ nsFrame::HandlePress(nsIPresContext* aPresContext, nsCOMPtr frameselection; if (NS_SUCCEEDED(shell->GetFrameSelection(getter_AddRefs(frameselection))) && frameselection){ frameselection->SetMouseDownState(PR_TRUE);//not important if it fails here - PRBool doMultipleSelection; + PRBool doCellSelection; #ifdef XP_MAC - doMultipleSelection = me->isMeta; + doCellSelection = me->isMeta; #else - doMultipleSelection = me->isControl; + doCellSelection = me->isControl; #endif - frameselection->HandleClick(newContent, startPos , contentOffsetEnd , me->isShift, doMultipleSelection, beginContent); + nsIFrame *cellFrame; + + if (doCellSelection) + { + nsresult result = GrabContainingCell(&cellFrame); + if (NS_SUCCEEDED(result) && cellFrame) + { + nsIContent* cellContent; + result = cellFrame->GetContent(&cellContent); + if (NS_SUCCEEDED(result) && cellContent) + { + nsIContent* parentContent; + result = cellContent->GetParent(parentContent); + if (parentContent){ + PRInt32 newIndex; + result = parentContent->IndexOf(cellContent, newIndex); + if (NS_SUCCEEDED(result) && newIndex >= 0) + { + frameselection->HandleClick(parentContent,newIndex, newIndex+1,me->isShift,PR_FALSE, beginContent, PR_TRUE); + } + NS_IF_RELEASE(parentContent); + } + NS_IF_RELEASE(cellContent); + } + } + } + else + frameselection->HandleClick(newContent, startPos , contentOffsetEnd , me->isShift, PR_FALSE, beginContent, PR_FALSE); } //no release } @@ -2710,6 +2738,24 @@ nsFrame::GetFirstLeaf(nsIPresContext* aPresContext, nsIFrame **aFrame) } } +NS_IMETHODIMP +nsFrame::GrabContainingCell(nsIFrame **aCellFrame) +{ + *aCellFrame = this; + nsresult result = NS_OK; + while (*aCellFrame && NS_SUCCEEDED(result)) + { + nsITableCellLayout *cellelement; + + result = (*aCellFrame)->QueryInterface(nsITableCellLayout::GetIID(), (void **)&cellelement); + if (NS_SUCCEEDED(result) && cellelement) + return NS_OK; + else + result = (*aCellFrame)->GetParent(aCellFrame); + } + return result?result:NS_ERROR_FAILURE; +} + nsresult nsFrame::CreateAndPostReflowCommand(nsIPresShell* aPresShell, nsIFrame* aTargetFrame, nsIReflowCommand::ReflowType aReflowType, diff --git a/layout/generic/nsFrame.h b/layout/generic/nsFrame.h index 336af7c07a0b..8efd96dea17a 100644 --- a/layout/generic/nsFrame.h +++ b/layout/generic/nsFrame.h @@ -401,7 +401,8 @@ protected: //given a frame five me the first/last leaf available static void GetLastLeaf(nsIPresContext* aPresContext, nsIFrame **aFrame); static void GetFirstLeaf(nsIPresContext* aPresContext, nsIFrame **aFrame); - + //grab this as the closest cell or go up the chain till nothing or a cell + NS_IMETHOD GrabContainingCell(nsIFrame **aCellFrame); static void XMLQuote(nsString& aString); virtual PRBool ParentDisablesSelection() const; diff --git a/layout/html/base/src/nsFrame.cpp b/layout/html/base/src/nsFrame.cpp index dda1e3fb000f..bc83e1d6a391 100644 --- a/layout/html/base/src/nsFrame.cpp +++ b/layout/html/base/src/nsFrame.cpp @@ -58,6 +58,7 @@ #include "nsCOMPtr.h" #include "nsStyleChangeList.h" #include "nsIDOMRange.h" +#include "nsITableCellLayout.h"//selection neccesity #define NORMAL_DRAG_HANDLING 1 // remove this to simulate a start-drag event. @@ -865,13 +866,40 @@ nsFrame::HandlePress(nsIPresContext* aPresContext, nsCOMPtr frameselection; if (NS_SUCCEEDED(shell->GetFrameSelection(getter_AddRefs(frameselection))) && frameselection){ frameselection->SetMouseDownState(PR_TRUE);//not important if it fails here - PRBool doMultipleSelection; + PRBool doCellSelection; #ifdef XP_MAC - doMultipleSelection = me->isMeta; + doCellSelection = me->isMeta; #else - doMultipleSelection = me->isControl; + doCellSelection = me->isControl; #endif - frameselection->HandleClick(newContent, startPos , contentOffsetEnd , me->isShift, doMultipleSelection, beginContent); + nsIFrame *cellFrame; + + if (doCellSelection) + { + nsresult result = GrabContainingCell(&cellFrame); + if (NS_SUCCEEDED(result) && cellFrame) + { + nsIContent* cellContent; + result = cellFrame->GetContent(&cellContent); + if (NS_SUCCEEDED(result) && cellContent) + { + nsIContent* parentContent; + result = cellContent->GetParent(parentContent); + if (parentContent){ + PRInt32 newIndex; + result = parentContent->IndexOf(cellContent, newIndex); + if (NS_SUCCEEDED(result) && newIndex >= 0) + { + frameselection->HandleClick(parentContent,newIndex, newIndex+1,me->isShift,PR_FALSE, beginContent, PR_TRUE); + } + NS_IF_RELEASE(parentContent); + } + NS_IF_RELEASE(cellContent); + } + } + } + else + frameselection->HandleClick(newContent, startPos , contentOffsetEnd , me->isShift, PR_FALSE, beginContent, PR_FALSE); } //no release } @@ -2710,6 +2738,24 @@ nsFrame::GetFirstLeaf(nsIPresContext* aPresContext, nsIFrame **aFrame) } } +NS_IMETHODIMP +nsFrame::GrabContainingCell(nsIFrame **aCellFrame) +{ + *aCellFrame = this; + nsresult result = NS_OK; + while (*aCellFrame && NS_SUCCEEDED(result)) + { + nsITableCellLayout *cellelement; + + result = (*aCellFrame)->QueryInterface(nsITableCellLayout::GetIID(), (void **)&cellelement); + if (NS_SUCCEEDED(result) && cellelement) + return NS_OK; + else + result = (*aCellFrame)->GetParent(aCellFrame); + } + return result?result:NS_ERROR_FAILURE; +} + nsresult nsFrame::CreateAndPostReflowCommand(nsIPresShell* aPresShell, nsIFrame* aTargetFrame, nsIReflowCommand::ReflowType aReflowType, diff --git a/layout/html/base/src/nsFrame.h b/layout/html/base/src/nsFrame.h index 336af7c07a0b..8efd96dea17a 100644 --- a/layout/html/base/src/nsFrame.h +++ b/layout/html/base/src/nsFrame.h @@ -401,7 +401,8 @@ protected: //given a frame five me the first/last leaf available static void GetLastLeaf(nsIPresContext* aPresContext, nsIFrame **aFrame); static void GetFirstLeaf(nsIPresContext* aPresContext, nsIFrame **aFrame); - + //grab this as the closest cell or go up the chain till nothing or a cell + NS_IMETHOD GrabContainingCell(nsIFrame **aCellFrame); static void XMLQuote(nsString& aString); virtual PRBool ParentDisablesSelection() const; diff --git a/layout/html/content/src/nsIHTMLTableCellElement.h b/layout/html/content/src/nsIHTMLTableCellElement.h index 7483a24ff011..7abef081260d 100644 --- a/layout/html/content/src/nsIHTMLTableCellElement.h +++ b/layout/html/content/src/nsIHTMLTableCellElement.h @@ -35,6 +35,7 @@ class nsIHTMLTableCellElement : public nsISupports { public: + static const nsIID& GetIID() { static nsIID iid = NS_IHTMLTABLECELLELEMENT_IID; return iid; } /** @return the starting column for this cell. Always >= 1 */ NS_IMETHOD GetColIndex (PRInt32* aColIndex) = 0; diff --git a/layout/html/forms/src/nsGfxTextControlFrame.cpp b/layout/html/forms/src/nsGfxTextControlFrame.cpp index 1caa005a7744..39e5c561c512 100644 --- a/layout/html/forms/src/nsGfxTextControlFrame.cpp +++ b/layout/html/forms/src/nsGfxTextControlFrame.cpp @@ -4094,6 +4094,13 @@ nsEnderEventListener::NotifySelectionChanged() return NS_OK; } +NS_IMETHODIMP +nsEnderEventListener::TableCellNotification(nsIDOMNode* aNode, PRInt32 aOffset) +{ + //stub + return NS_OK; +} + /******************************************************************************* diff --git a/layout/html/forms/src/nsGfxTextControlFrame.h b/layout/html/forms/src/nsGfxTextControlFrame.h index ed7063c5eae2..c933e32db822 100644 --- a/layout/html/forms/src/nsGfxTextControlFrame.h +++ b/layout/html/forms/src/nsGfxTextControlFrame.h @@ -271,6 +271,7 @@ public: * @see nsIDOMSelectionListener */ NS_IMETHOD NotifySelectionChanged(); + NS_IMETHOD TableCellNotification(nsIDOMNode* aNode, PRInt32 aOffset); /*END interfaces from nsIDOMSelectionListener*/ friend nsresult NS_NewEnderEventListener(nsIEnderEventListener ** aInstancePtrResult); diff --git a/layout/html/style/src/nsCSSFrameConstructor.cpp b/layout/html/style/src/nsCSSFrameConstructor.cpp index a4f2a4101621..5ada15aa6cd2 100644 --- a/layout/html/style/src/nsCSSFrameConstructor.cpp +++ b/layout/html/style/src/nsCSSFrameConstructor.cpp @@ -858,13 +858,27 @@ nsCSSFrameConstructor::CreateGeneratedContentFrame(nsIPresShell* aPresShe // the 'display' property nsIFrame* containerFrame; nsFrameItems childFrames; - + + nsCOMPtrcontainerElement; + nsCOMPtr containerContent; + nsCOMPtr document; + + aContent->GetDocument(*getter_AddRefs(document)); + + nsCOMPtr domdoc(do_QueryInterface(document)); + nsresult result; + result = domdoc->CreateElement("SPAN",getter_AddRefs(containerElement));//is the literal the correct way? + if (NS_SUCCEEDED(result) && containerElement) + { + containerContent = do_QueryInterface(containerElement); + } + if (NS_STYLE_DISPLAY_BLOCK == displayValue) { NS_NewBlockFrame(aPresShell, &containerFrame); } else { NS_NewInlineFrame(aPresShell, &containerFrame); } - InitAndRestoreFrame(aPresContext, aState, aContent, + InitAndRestoreFrame(aPresContext, aState, containerContent?containerContent:aContent, aFrame, pseudoStyleContext, nsnull, containerFrame); // Mark the frame as being associated with generated content @@ -882,8 +896,6 @@ nsCSSFrameConstructor::CreateGeneratedContentFrame(nsIPresShell* aPresShe // Now create content objects (and child frames) for each value of the // 'content' property - nsCOMPtr document; - aContent->GetDocument(*getter_AddRefs(document)); for (PRUint32 contentIndex = 0; contentIndex < contentCount; contentIndex++) { nsIFrame* frame;