зеркало из https://github.com/mozilla/pjs.git
fixes bugs 46782,50161,48643,49266,49265,46395;
This commit is contained in:
Родитель
6013c0413a
Коммит
1edcca94d8
|
@ -122,14 +122,14 @@ nsresult TypeInState::SetProp(nsIAtom *aProp, const nsString &aAttr, const nsStr
|
|||
}
|
||||
|
||||
// if it's already set we are done
|
||||
if (IsPropSet(aProp,aAttr,aValue)) return NS_OK;
|
||||
if (IsPropSet(aProp,aAttr,nsnull)) return NS_OK;
|
||||
|
||||
// make a new propitem
|
||||
PropItem *item = new PropItem(aProp,aAttr,aValue);
|
||||
if (!item) return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
// remove it from the list of cleared properties, if we have a match
|
||||
RemovePropFromClearedList(aProp,aAttr,aValue);
|
||||
RemovePropFromClearedList(aProp,aAttr);
|
||||
|
||||
// add it to the list of set properties
|
||||
mSetArray.AppendElement((void*)item);
|
||||
|
@ -141,30 +141,25 @@ nsresult TypeInState::SetProp(nsIAtom *aProp, const nsString &aAttr, const nsStr
|
|||
nsresult TypeInState::ClearAllProps()
|
||||
{
|
||||
// null prop means "all" props
|
||||
return ClearProp(nsnull,nsAutoString(),nsAutoString());
|
||||
return ClearProp(nsnull,nsAutoString());
|
||||
}
|
||||
|
||||
nsresult TypeInState::ClearProp(nsIAtom *aProp)
|
||||
{
|
||||
return ClearProp(aProp,nsAutoString(),nsAutoString());
|
||||
return ClearProp(aProp,nsAutoString());
|
||||
}
|
||||
|
||||
nsresult TypeInState::ClearProp(nsIAtom *aProp, const nsString &aAttr)
|
||||
{
|
||||
return ClearProp(aProp,aAttr,nsAutoString());
|
||||
}
|
||||
|
||||
nsresult TypeInState::ClearProp(nsIAtom *aProp, const nsString &aAttr, const nsString &aValue)
|
||||
{
|
||||
// if it's already cleared we are done
|
||||
if (IsPropCleared(aProp,aAttr,aValue)) return NS_OK;
|
||||
if (IsPropCleared(aProp,aAttr)) return NS_OK;
|
||||
|
||||
// make a new propitem
|
||||
PropItem *item = new PropItem(aProp,aAttr,aValue);
|
||||
PropItem *item = new PropItem(aProp,aAttr,nsAutoString());
|
||||
if (!item) return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
// remove it from the list of set properties, if we have a match
|
||||
RemovePropFromSetList(aProp,aAttr,aValue);
|
||||
RemovePropFromSetList(aProp,aAttr);
|
||||
|
||||
// add it to the list of cleared properties
|
||||
mClearedArray.AppendElement((void*)item);
|
||||
|
@ -222,7 +217,7 @@ nsresult TypeInState::TakeRelativeFontSize(PRInt32 *outRelSize)
|
|||
|
||||
nsresult TypeInState::GetTypingState(PRBool &isSet, PRBool &theSetting, nsIAtom *aProp)
|
||||
{
|
||||
return GetTypingState(isSet, theSetting, aProp, nsAutoString(), nsAutoString());
|
||||
return GetTypingState(isSet, theSetting, aProp, nsAutoString(), nsnull);
|
||||
}
|
||||
|
||||
nsresult TypeInState::GetTypingState(PRBool &isSet,
|
||||
|
@ -230,7 +225,7 @@ nsresult TypeInState::GetTypingState(PRBool &isSet,
|
|||
nsIAtom *aProp,
|
||||
const nsString &aAttr)
|
||||
{
|
||||
return GetTypingState(isSet, theSetting, aProp, aAttr, nsAutoString());
|
||||
return GetTypingState(isSet, theSetting, aProp, aAttr, nsnull);
|
||||
}
|
||||
|
||||
|
||||
|
@ -238,14 +233,14 @@ nsresult TypeInState::GetTypingState(PRBool &isSet,
|
|||
PRBool &theSetting,
|
||||
nsIAtom *aProp,
|
||||
const nsString &aAttr,
|
||||
const nsString &aValue)
|
||||
nsString *aValue)
|
||||
{
|
||||
if (IsPropSet(aProp, aAttr, aValue))
|
||||
{
|
||||
isSet = PR_TRUE;
|
||||
theSetting = PR_TRUE;
|
||||
}
|
||||
else if (IsPropCleared(aProp, aAttr, aValue))
|
||||
else if (IsPropCleared(aProp, aAttr))
|
||||
{
|
||||
isSet = PR_TRUE;
|
||||
theSetting = PR_FALSE;
|
||||
|
@ -264,8 +259,7 @@ nsresult TypeInState::GetTypingState(PRBool &isSet,
|
|||
*******************************************************************/
|
||||
|
||||
nsresult TypeInState::RemovePropFromSetList(nsIAtom *aProp,
|
||||
const nsString &aAttr,
|
||||
const nsString &aValue)
|
||||
const nsString &aAttr)
|
||||
{
|
||||
PRInt32 index;
|
||||
PropItem *item;
|
||||
|
@ -282,7 +276,7 @@ nsresult TypeInState::RemovePropFromSetList(nsIAtom *aProp,
|
|||
if (item) delete item;
|
||||
}
|
||||
}
|
||||
else if (FindPropInList(aProp, aAttr, aValue, mSetArray, index))
|
||||
else if (FindPropInList(aProp, aAttr, nsnull, mSetArray, index))
|
||||
{
|
||||
item = (PropItem*)mSetArray.ElementAt(index);
|
||||
mSetArray.RemoveElementAt(index);
|
||||
|
@ -293,11 +287,10 @@ nsresult TypeInState::RemovePropFromSetList(nsIAtom *aProp,
|
|||
|
||||
|
||||
nsresult TypeInState::RemovePropFromClearedList(nsIAtom *aProp,
|
||||
const nsString &aAttr,
|
||||
const nsString &aValue)
|
||||
const nsString &aAttr)
|
||||
{
|
||||
PRInt32 index;
|
||||
if (FindPropInList(aProp, aAttr, aValue, mClearedArray, index))
|
||||
if (FindPropInList(aProp, aAttr, nsnull, mClearedArray, index))
|
||||
{
|
||||
PropItem *item = (PropItem*)mClearedArray.ElementAt(index);
|
||||
mClearedArray.RemoveElementAt(index);
|
||||
|
@ -309,16 +302,16 @@ nsresult TypeInState::RemovePropFromClearedList(nsIAtom *aProp,
|
|||
|
||||
PRBool TypeInState::IsPropSet(nsIAtom *aProp,
|
||||
const nsString &aAttr,
|
||||
const nsString &aValue)
|
||||
nsString* outValue)
|
||||
{
|
||||
PRInt32 i;
|
||||
return IsPropSet(aProp, aAttr, aValue, i);
|
||||
return IsPropSet(aProp, aAttr, outValue, i);
|
||||
}
|
||||
|
||||
|
||||
PRBool TypeInState::IsPropSet(nsIAtom *aProp,
|
||||
const nsString &aAttr,
|
||||
const nsString &aValue,
|
||||
nsString *outValue,
|
||||
PRInt32 &outIndex)
|
||||
{
|
||||
// linear search. list should be short.
|
||||
|
@ -329,6 +322,7 @@ PRBool TypeInState::IsPropSet(nsIAtom *aProp,
|
|||
if ( (item->tag == aProp) &&
|
||||
(item->attr == aAttr) )
|
||||
{
|
||||
if (outValue) *outValue = item->value;
|
||||
outIndex = i;
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
@ -338,22 +332,20 @@ PRBool TypeInState::IsPropSet(nsIAtom *aProp,
|
|||
|
||||
|
||||
PRBool TypeInState::IsPropCleared(nsIAtom *aProp,
|
||||
const nsString &aAttr,
|
||||
const nsString &aValue)
|
||||
const nsString &aAttr)
|
||||
{
|
||||
PRInt32 i;
|
||||
return IsPropCleared(aProp, aAttr, aValue, i);
|
||||
return IsPropCleared(aProp, aAttr, i);
|
||||
}
|
||||
|
||||
|
||||
PRBool TypeInState::IsPropCleared(nsIAtom *aProp,
|
||||
const nsString &aAttr,
|
||||
const nsString &aValue,
|
||||
PRInt32 &outIndex)
|
||||
{
|
||||
if (FindPropInList(aProp, aAttr, aValue, mClearedArray, outIndex))
|
||||
if (FindPropInList(aProp, aAttr, nsnull, mClearedArray, outIndex))
|
||||
return PR_TRUE;
|
||||
if (FindPropInList(0, nsAutoString(), nsAutoString(), mClearedArray, outIndex))
|
||||
if (FindPropInList(0, nsAutoString(), nsnull, mClearedArray, outIndex))
|
||||
{
|
||||
// special case for all props cleared
|
||||
outIndex = -1;
|
||||
|
@ -364,7 +356,7 @@ PRBool TypeInState::IsPropCleared(nsIAtom *aProp,
|
|||
|
||||
PRBool TypeInState::FindPropInList(nsIAtom *aProp,
|
||||
const nsString &aAttr,
|
||||
const nsString &aValue,
|
||||
nsString *outValue,
|
||||
nsVoidArray &aList,
|
||||
PRInt32 &outIndex)
|
||||
{
|
||||
|
@ -376,6 +368,7 @@ PRBool TypeInState::FindPropInList(nsIAtom *aProp,
|
|||
if ( (item->tag == aProp) &&
|
||||
(item->attr == aAttr) )
|
||||
{
|
||||
if (outValue) *outValue = item->value;
|
||||
outIndex = i;
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
|
|
@ -57,7 +57,6 @@ public:
|
|||
nsresult ClearAllProps();
|
||||
nsresult ClearProp(nsIAtom *aProp);
|
||||
nsresult ClearProp(nsIAtom *aProp, const nsString &aAttr);
|
||||
nsresult ClearProp(nsIAtom *aProp, const nsString &aAttr, const nsString &aValue);
|
||||
|
||||
//**************************************************************************
|
||||
// TakeClearProperty: hands back next poroperty item on the clear list.
|
||||
|
@ -78,17 +77,17 @@ public:
|
|||
nsresult GetTypingState(PRBool &isSet, PRBool &theSetting, nsIAtom *aProp,
|
||||
const nsString &aAttr);
|
||||
nsresult GetTypingState(PRBool &isSet, PRBool &theSetting, nsIAtom *aProp,
|
||||
const nsString &aAttr, const nsString &aValue);
|
||||
const nsString &aAttr, nsString* outValue);
|
||||
|
||||
protected:
|
||||
|
||||
nsresult RemovePropFromSetList(nsIAtom *aProp, const nsString &aAttr, const nsString &aValue);
|
||||
nsresult RemovePropFromClearedList(nsIAtom *aProp, const nsString &aAttr, const nsString &aValue);
|
||||
PRBool IsPropSet(nsIAtom *aProp, const nsString &aAttr, const nsString &aValue);
|
||||
PRBool IsPropSet(nsIAtom *aProp, const nsString &aAttr, const nsString &aValue, PRInt32 &outIndex);
|
||||
PRBool IsPropCleared(nsIAtom *aProp, const nsString &aAttr, const nsString &aValue);
|
||||
PRBool IsPropCleared(nsIAtom *aProp, const nsString &aAttr, const nsString &aValue, PRInt32 &outIndex);
|
||||
PRBool FindPropInList(nsIAtom *aProp, const nsString &aAttr, const nsString &aValue, nsVoidArray &aList, PRInt32 &outIndex);
|
||||
nsresult RemovePropFromSetList(nsIAtom *aProp, const nsString &aAttr);
|
||||
nsresult RemovePropFromClearedList(nsIAtom *aProp, const nsString &aAttr);
|
||||
PRBool IsPropSet(nsIAtom *aProp, const nsString &aAttr, nsString* outValue);
|
||||
PRBool IsPropSet(nsIAtom *aProp, const nsString &aAttr, nsString* outValue, PRInt32 &outIndex);
|
||||
PRBool IsPropCleared(nsIAtom *aProp, const nsString &aAttr);
|
||||
PRBool IsPropCleared(nsIAtom *aProp, const nsString &aAttr, PRInt32 &outIndex);
|
||||
PRBool FindPropInList(nsIAtom *aProp, const nsString &aAttr, nsString *outValue, nsVoidArray &aList, PRInt32 &outIndex);
|
||||
|
||||
nsVoidArray mSetArray;
|
||||
nsVoidArray mClearedArray;
|
||||
|
|
|
@ -152,17 +152,11 @@ PRInt32 nsEditor::gInstanceCount = 0;
|
|||
* { {startnode, startoffset} , {endnode, endoffset} } tuples. Cant store
|
||||
* ranges since dom gravity will possibly change the ranges.
|
||||
*/
|
||||
nsSelectionState::nsSelectionState() : mArray(), mLock(PR_FALSE) {}
|
||||
nsSelectionState::nsSelectionState() : mArray(){}
|
||||
|
||||
nsSelectionState::~nsSelectionState()
|
||||
{
|
||||
// free any items in the array
|
||||
SelRangeStore *item;
|
||||
while ((item = (SelRangeStore*)mArray.ElementAt(0)))
|
||||
{
|
||||
delete item;
|
||||
mArray.RemoveElementAt(0);
|
||||
}
|
||||
MakeEmpty();
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -171,7 +165,7 @@ nsSelectionState::SaveSelection(nsIDOMSelection *aSel)
|
|||
if (!aSel) return NS_ERROR_NULL_POINTER;
|
||||
nsresult res = NS_OK;
|
||||
PRInt32 i,rangeCount, arrayCount = mArray.Count();
|
||||
SelRangeStore *item;
|
||||
nsRangeStore *item;
|
||||
aSel->GetRangeCount(&rangeCount);
|
||||
|
||||
// if we need more items in the array, new them
|
||||
|
@ -180,7 +174,7 @@ nsSelectionState::SaveSelection(nsIDOMSelection *aSel)
|
|||
PRInt32 count = rangeCount-arrayCount;
|
||||
for (i=0; i<count; i++)
|
||||
{
|
||||
item = new SelRangeStore;
|
||||
item = new nsRangeStore;
|
||||
mArray.AppendElement(item);
|
||||
}
|
||||
}
|
||||
|
@ -188,7 +182,7 @@ nsSelectionState::SaveSelection(nsIDOMSelection *aSel)
|
|||
// else if we have too many, delete them
|
||||
else if (rangeCount>arrayCount)
|
||||
{
|
||||
while ((item = (SelRangeStore*)mArray.ElementAt(rangeCount)))
|
||||
while ((item = (nsRangeStore*)mArray.ElementAt(rangeCount)))
|
||||
{
|
||||
delete item;
|
||||
mArray.RemoveElementAt(rangeCount);
|
||||
|
@ -198,7 +192,7 @@ nsSelectionState::SaveSelection(nsIDOMSelection *aSel)
|
|||
// now store the selection ranges
|
||||
for (i=0; i<rangeCount; i++)
|
||||
{
|
||||
item = (SelRangeStore*)mArray.ElementAt(i);
|
||||
item = (nsRangeStore*)mArray.ElementAt(i);
|
||||
if (!item) return NS_ERROR_UNEXPECTED;
|
||||
nsCOMPtr<nsIDOMRange> range;
|
||||
res = aSel->GetRangeAt(i, getter_AddRefs(range));
|
||||
|
@ -214,7 +208,7 @@ nsSelectionState::RestoreSelection(nsIDOMSelection *aSel)
|
|||
if (!aSel) return NS_ERROR_NULL_POINTER;
|
||||
nsresult res = NS_OK;
|
||||
PRInt32 i, arrayCount = mArray.Count();
|
||||
SelRangeStore *item;
|
||||
nsRangeStore *item;
|
||||
|
||||
// clear out selection
|
||||
aSel->ClearSelection();
|
||||
|
@ -222,7 +216,7 @@ nsSelectionState::RestoreSelection(nsIDOMSelection *aSel)
|
|||
// set the selection ranges anew
|
||||
for (i=0; i<arrayCount; i++)
|
||||
{
|
||||
item = (SelRangeStore*)mArray.ElementAt(i);
|
||||
item = (nsRangeStore*)mArray.ElementAt(i);
|
||||
if (!item) return NS_ERROR_UNEXPECTED;
|
||||
nsCOMPtr<nsIDOMRange> range;
|
||||
item->GetRange(&range);
|
||||
|
@ -239,8 +233,8 @@ PRBool
|
|||
nsSelectionState::IsCollapsed()
|
||||
{
|
||||
if (1 != mArray.Count()) return PR_FALSE;
|
||||
SelRangeStore *item;
|
||||
item = (SelRangeStore*)mArray.ElementAt(0);
|
||||
nsRangeStore *item;
|
||||
item = (nsRangeStore*)mArray.ElementAt(0);
|
||||
if (!item) return PR_FALSE;
|
||||
nsCOMPtr<nsIDOMRange> range;
|
||||
item->GetRange(&range);
|
||||
|
@ -258,12 +252,12 @@ nsSelectionState::IsEqual(nsSelectionState *aSelState)
|
|||
if (myCount != itsCount) return PR_FALSE;
|
||||
if (myCount < 1) return PR_FALSE;
|
||||
|
||||
SelRangeStore *myItem, *itsItem;
|
||||
nsRangeStore *myItem, *itsItem;
|
||||
|
||||
for (i=0; i<myCount; i++)
|
||||
{
|
||||
myItem = (SelRangeStore*)mArray.ElementAt(0);
|
||||
itsItem = (SelRangeStore*)(aSelState->mArray.ElementAt(0));
|
||||
myItem = (nsRangeStore*)mArray.ElementAt(0);
|
||||
itsItem = (nsRangeStore*)(aSelState->mArray.ElementAt(0));
|
||||
if (!myItem || !itsItem) return PR_FALSE;
|
||||
|
||||
nsCOMPtr<nsIDOMRange> myRange, itsRange;
|
||||
|
@ -281,22 +275,137 @@ nsSelectionState::IsEqual(nsSelectionState *aSelState)
|
|||
return PR_TRUE;
|
||||
}
|
||||
|
||||
// notification routines used to update the saved selection state in response to
|
||||
// document editing.
|
||||
void
|
||||
nsSelectionState::MakeEmpty()
|
||||
{
|
||||
// free any items in the array
|
||||
nsRangeStore *item;
|
||||
while ((item = (nsRangeStore*)mArray.ElementAt(0)))
|
||||
{
|
||||
delete item;
|
||||
mArray.RemoveElementAt(0);
|
||||
}
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsSelectionState::IsEmpty()
|
||||
{
|
||||
return (mArray.Count() == 0);
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
* nsRangeUpdater: class for updating nsIDOMRanges in response to editor actions.
|
||||
*/
|
||||
|
||||
nsRangeUpdater::nsRangeUpdater() : mArray(), mLock(PR_FALSE) {}
|
||||
|
||||
nsRangeUpdater::~nsRangeUpdater()
|
||||
{
|
||||
// free any items in the array
|
||||
nsRangeStore *item;
|
||||
while ((item = (nsRangeStore*)mArray.ElementAt(0)))
|
||||
{
|
||||
delete item;
|
||||
mArray.RemoveElementAt(0);
|
||||
}
|
||||
}
|
||||
|
||||
void*
|
||||
nsRangeUpdater::RegisterRange(nsIDOMRange *aRange)
|
||||
{
|
||||
nsRangeStore *item = new nsRangeStore;
|
||||
if (!item) return nsnull;
|
||||
item->StoreRange(aRange);
|
||||
mArray.AppendElement(item);
|
||||
return item;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMRange>
|
||||
nsRangeUpdater::ReclaimRange(void *aCookie)
|
||||
{
|
||||
nsRangeStore *item = NS_STATIC_CAST(nsRangeStore*,aCookie);
|
||||
if (!item) return nsnull;
|
||||
nsCOMPtr<nsIDOMRange> outRange;
|
||||
item->GetRange(&outRange);
|
||||
mArray.RemoveElement(aCookie);
|
||||
delete item;
|
||||
return outRange;
|
||||
}
|
||||
|
||||
void
|
||||
nsRangeUpdater::DropRange(void *aCookie)
|
||||
{
|
||||
nsRangeStore *item = NS_STATIC_CAST(nsRangeStore*,aCookie);
|
||||
if (!item) return;
|
||||
mArray.RemoveElement(aCookie);
|
||||
delete item;
|
||||
}
|
||||
|
||||
void
|
||||
nsRangeUpdater::RegisterRangeItem(nsRangeStore *aRangeItem)
|
||||
{
|
||||
if (!aRangeItem) return;
|
||||
mArray.AppendElement(aRangeItem);
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
nsRangeUpdater::DropRangeItem(nsRangeStore *aRangeItem)
|
||||
{
|
||||
if (!aRangeItem) return;
|
||||
mArray.RemoveElement(aRangeItem);
|
||||
return;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsRangeUpdater::RegisterSelectionState(nsSelectionState &aSelState)
|
||||
{
|
||||
PRInt32 i, theCount = aSelState.mArray.Count();
|
||||
if (theCount < 1) return NS_ERROR_FAILURE;
|
||||
|
||||
nsRangeStore *item;
|
||||
|
||||
for (i=0; i<theCount; i++)
|
||||
{
|
||||
item = (nsRangeStore*)aSelState.mArray.ElementAt(i);
|
||||
RegisterRangeItem(item);
|
||||
}
|
||||
|
||||
return NS_OK;;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsRangeUpdater::DropSelectionState(nsSelectionState &aSelState)
|
||||
{
|
||||
PRInt32 i, theCount = aSelState.mArray.Count();
|
||||
if (theCount < 1) return NS_ERROR_FAILURE;
|
||||
|
||||
nsRangeStore *item;
|
||||
|
||||
for (i=0; i<theCount; i++)
|
||||
{
|
||||
item = (nsRangeStore*)aSelState.mArray.ElementAt(i);
|
||||
DropRangeItem(item);
|
||||
}
|
||||
|
||||
return NS_OK;;
|
||||
}
|
||||
|
||||
// gravity methods:
|
||||
|
||||
nsresult
|
||||
nsSelectionState::SelAdjCreateNode(nsIDOMNode *aParent, PRInt32 aPosition)
|
||||
nsRangeUpdater::SelAdjCreateNode(nsIDOMNode *aParent, PRInt32 aPosition)
|
||||
{
|
||||
if (mLock) return NS_OK; // lock set by Will/DidReplaceParent, etc...
|
||||
if (!aParent) return NS_ERROR_NULL_POINTER;
|
||||
PRInt32 i, count = mArray.Count();
|
||||
if (!count) return NS_OK;
|
||||
|
||||
SelRangeStore *item;
|
||||
nsRangeStore *item;
|
||||
|
||||
for (i=0; i<count; i++)
|
||||
{
|
||||
item = (SelRangeStore*)mArray.ElementAt(i);
|
||||
item = (nsRangeStore*)mArray.ElementAt(i);
|
||||
if (!item) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
if ((item->startNode.get() == aParent) && (item->startOffset > aPosition))
|
||||
|
@ -308,25 +417,25 @@ nsSelectionState::SelAdjCreateNode(nsIDOMNode *aParent, PRInt32 aPosition)
|
|||
}
|
||||
|
||||
nsresult
|
||||
nsSelectionState::SelAdjInsertNode(nsIDOMNode *aParent, PRInt32 aPosition)
|
||||
nsRangeUpdater::SelAdjInsertNode(nsIDOMNode *aParent, PRInt32 aPosition)
|
||||
{
|
||||
return SelAdjCreateNode(aParent, aPosition);
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsSelectionState::SelAdjDeleteNode(nsIDOMNode *aNode, nsIDOMNode *aParent, PRInt32 aOffset)
|
||||
nsRangeUpdater::SelAdjDeleteNode(nsIDOMNode *aNode, nsIDOMNode *aParent, PRInt32 aOffset)
|
||||
{
|
||||
if (mLock) return NS_OK; // lock set by Will/DidReplaceParent, etc...
|
||||
if (!aNode) return NS_ERROR_NULL_POINTER;
|
||||
PRInt32 i, count = mArray.Count();
|
||||
if (!count) return NS_OK;
|
||||
|
||||
SelRangeStore *item;
|
||||
nsRangeStore *item;
|
||||
|
||||
for (i=0; i<count; i++)
|
||||
{
|
||||
item = (SelRangeStore*)mArray.ElementAt(i);
|
||||
item = (nsRangeStore*)mArray.ElementAt(i);
|
||||
if (!item) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
if ((item->startNode.get() == aParent) && (item->startOffset > aOffset))
|
||||
|
@ -341,7 +450,7 @@ nsSelectionState::SelAdjDeleteNode(nsIDOMNode *aNode, nsIDOMNode *aParent, PRInt
|
|||
|
||||
|
||||
nsresult
|
||||
nsSelectionState::SelAdjSplitNode(nsIDOMNode *aOldRightNode, PRInt32 aOffset, nsIDOMNode *aNewLeftNode)
|
||||
nsRangeUpdater::SelAdjSplitNode(nsIDOMNode *aOldRightNode, PRInt32 aOffset, nsIDOMNode *aNewLeftNode)
|
||||
{
|
||||
if (mLock) return NS_OK; // lock set by Will/DidReplaceParent, etc...
|
||||
if (!aOldRightNode || !aNewLeftNode) return NS_ERROR_NULL_POINTER;
|
||||
|
@ -358,11 +467,11 @@ nsSelectionState::SelAdjSplitNode(nsIDOMNode *aOldRightNode, PRInt32 aOffset, ns
|
|||
if (NS_FAILED(result)) return result;
|
||||
|
||||
// next step is to check for range enpoints inside aOldRightNode
|
||||
SelRangeStore *item;
|
||||
nsRangeStore *item;
|
||||
|
||||
for (i=0; i<count; i++)
|
||||
{
|
||||
item = (SelRangeStore*)mArray.ElementAt(i);
|
||||
item = (nsRangeStore*)mArray.ElementAt(i);
|
||||
if (!item) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
if (item->startNode.get() == aOldRightNode)
|
||||
|
@ -393,7 +502,7 @@ nsSelectionState::SelAdjSplitNode(nsIDOMNode *aOldRightNode, PRInt32 aOffset, ns
|
|||
|
||||
|
||||
nsresult
|
||||
nsSelectionState::SelAdjJoinNodes(nsIDOMNode *aLeftNode,
|
||||
nsRangeUpdater::SelAdjJoinNodes(nsIDOMNode *aLeftNode,
|
||||
nsIDOMNode *aRightNode,
|
||||
nsIDOMNode *aParent,
|
||||
PRInt32 aOffset,
|
||||
|
@ -404,11 +513,11 @@ nsSelectionState::SelAdjJoinNodes(nsIDOMNode *aLeftNode,
|
|||
PRInt32 i, count = mArray.Count();
|
||||
if (!count) return NS_OK;
|
||||
|
||||
SelRangeStore *item;
|
||||
nsRangeStore *item;
|
||||
|
||||
for (i=0; i<count; i++)
|
||||
{
|
||||
item = (SelRangeStore*)mArray.ElementAt(i);
|
||||
item = (nsRangeStore*)mArray.ElementAt(i);
|
||||
if (!item) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
// adjust endpoints in aParent
|
||||
|
@ -450,7 +559,7 @@ nsSelectionState::SelAdjJoinNodes(nsIDOMNode *aLeftNode,
|
|||
|
||||
|
||||
nsresult
|
||||
nsSelectionState::SelAdjInsertText(nsIDOMCharacterData *aTextNode, PRInt32 aOffset, const nsString &aString)
|
||||
nsRangeUpdater::SelAdjInsertText(nsIDOMCharacterData *aTextNode, PRInt32 aOffset, const nsString &aString)
|
||||
{
|
||||
if (mLock) return NS_OK; // lock set by Will/DidReplaceParent, etc...
|
||||
return NS_OK;
|
||||
|
@ -458,7 +567,7 @@ nsSelectionState::SelAdjInsertText(nsIDOMCharacterData *aTextNode, PRInt32 aOffs
|
|||
|
||||
|
||||
nsresult
|
||||
nsSelectionState::SelAdjDeleteText(nsIDOMCharacterData *aTextNode, PRInt32 aOffset, PRInt32 aLength)
|
||||
nsRangeUpdater::SelAdjDeleteText(nsIDOMCharacterData *aTextNode, PRInt32 aOffset, PRInt32 aLength)
|
||||
{
|
||||
if (mLock) return NS_OK; // lock set by Will/DidReplaceParent, etc...
|
||||
return NS_OK;
|
||||
|
@ -466,7 +575,7 @@ nsSelectionState::SelAdjDeleteText(nsIDOMCharacterData *aTextNode, PRInt32 aOffs
|
|||
|
||||
|
||||
nsresult
|
||||
nsSelectionState::WillReplaceContainer()
|
||||
nsRangeUpdater::WillReplaceContainer()
|
||||
{
|
||||
if (mLock) return NS_ERROR_UNEXPECTED;
|
||||
mLock = PR_TRUE;
|
||||
|
@ -475,7 +584,7 @@ nsSelectionState::WillReplaceContainer()
|
|||
|
||||
|
||||
nsresult
|
||||
nsSelectionState::DidReplaceContainer(nsIDOMNode *aOriginalNode, nsIDOMNode *aNewNode)
|
||||
nsRangeUpdater::DidReplaceContainer(nsIDOMNode *aOriginalNode, nsIDOMNode *aNewNode)
|
||||
{
|
||||
if (!mLock) return NS_ERROR_UNEXPECTED;
|
||||
mLock = PR_FALSE;
|
||||
|
@ -484,11 +593,11 @@ nsSelectionState::DidReplaceContainer(nsIDOMNode *aOriginalNode, nsIDOMNode *aNe
|
|||
PRInt32 i, count = mArray.Count();
|
||||
if (!count) return NS_OK;
|
||||
|
||||
SelRangeStore *item;
|
||||
nsRangeStore *item;
|
||||
|
||||
for (i=0; i<count; i++)
|
||||
{
|
||||
item = (SelRangeStore*)mArray.ElementAt(i);
|
||||
item = (nsRangeStore*)mArray.ElementAt(i);
|
||||
if (!item) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
if (item->startNode.get() == aOriginalNode)
|
||||
|
@ -501,7 +610,7 @@ nsSelectionState::DidReplaceContainer(nsIDOMNode *aOriginalNode, nsIDOMNode *aNe
|
|||
|
||||
|
||||
nsresult
|
||||
nsSelectionState::WillRemoveContainer()
|
||||
nsRangeUpdater::WillRemoveContainer()
|
||||
{
|
||||
if (mLock) return NS_ERROR_UNEXPECTED;
|
||||
mLock = PR_TRUE;
|
||||
|
@ -510,7 +619,7 @@ nsSelectionState::WillRemoveContainer()
|
|||
|
||||
|
||||
nsresult
|
||||
nsSelectionState::DidRemoveContainer(nsIDOMNode *aNode, nsIDOMNode *aParent, PRInt32 aOffset, PRUint32 aNodeOrigLen)
|
||||
nsRangeUpdater::DidRemoveContainer(nsIDOMNode *aNode, nsIDOMNode *aParent, PRInt32 aOffset, PRUint32 aNodeOrigLen)
|
||||
{
|
||||
if (!mLock) return NS_ERROR_UNEXPECTED;
|
||||
mLock = PR_FALSE;
|
||||
|
@ -519,11 +628,11 @@ nsSelectionState::DidRemoveContainer(nsIDOMNode *aNode, nsIDOMNode *aParent, PRI
|
|||
PRInt32 i, count = mArray.Count();
|
||||
if (!count) return NS_OK;
|
||||
|
||||
SelRangeStore *item;
|
||||
nsRangeStore *item;
|
||||
|
||||
for (i=0; i<count; i++)
|
||||
{
|
||||
item = (SelRangeStore*)mArray.ElementAt(i);
|
||||
item = (nsRangeStore*)mArray.ElementAt(i);
|
||||
if (!item) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
if (item->startNode.get() == aNode)
|
||||
|
@ -546,7 +655,7 @@ nsSelectionState::DidRemoveContainer(nsIDOMNode *aNode, nsIDOMNode *aParent, PRI
|
|||
|
||||
|
||||
nsresult
|
||||
nsSelectionState::WillInsertContainer()
|
||||
nsRangeUpdater::WillInsertContainer()
|
||||
{
|
||||
if (mLock) return NS_ERROR_UNEXPECTED;
|
||||
mLock = PR_TRUE;
|
||||
|
@ -555,7 +664,7 @@ nsSelectionState::WillInsertContainer()
|
|||
|
||||
|
||||
nsresult
|
||||
nsSelectionState::DidInsertContainer()
|
||||
nsRangeUpdater::DidInsertContainer()
|
||||
{
|
||||
if (!mLock) return NS_ERROR_UNEXPECTED;
|
||||
mLock = PR_FALSE;
|
||||
|
@ -564,7 +673,7 @@ nsSelectionState::DidInsertContainer()
|
|||
|
||||
|
||||
nsresult
|
||||
nsSelectionState::WillMoveNode()
|
||||
nsRangeUpdater::WillMoveNode()
|
||||
{
|
||||
if (mLock) return NS_ERROR_UNEXPECTED;
|
||||
mLock = PR_TRUE;
|
||||
|
@ -573,7 +682,7 @@ nsSelectionState::WillMoveNode()
|
|||
|
||||
|
||||
nsresult
|
||||
nsSelectionState::DidMoveNode(nsIDOMNode *aOldParent, PRInt32 aOldOffset, nsIDOMNode *aNewParent, PRInt32 aNewOffset)
|
||||
nsRangeUpdater::DidMoveNode(nsIDOMNode *aOldParent, PRInt32 aOldOffset, nsIDOMNode *aNewParent, PRInt32 aNewOffset)
|
||||
{
|
||||
if (!mLock) return NS_ERROR_UNEXPECTED;
|
||||
mLock = PR_FALSE;
|
||||
|
@ -582,11 +691,11 @@ nsSelectionState::DidMoveNode(nsIDOMNode *aOldParent, PRInt32 aOldOffset, nsIDOM
|
|||
PRInt32 i, count = mArray.Count();
|
||||
if (!count) return NS_OK;
|
||||
|
||||
SelRangeStore *item;
|
||||
nsRangeStore *item;
|
||||
|
||||
for (i=0; i<count; i++)
|
||||
{
|
||||
item = (SelRangeStore*)mArray.ElementAt(i);
|
||||
item = (nsRangeStore*)mArray.ElementAt(i);
|
||||
if (!item) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
// like a delete in aOldParent
|
||||
|
@ -607,10 +716,21 @@ nsSelectionState::DidMoveNode(nsIDOMNode *aOldParent, PRInt32 aOldOffset, nsIDOM
|
|||
|
||||
|
||||
/***************************************************************************
|
||||
* helper class for nsSelectionState. SelRangeStore stores range endpoints.
|
||||
* helper class for nsSelectionState. nsRangeStore stores range endpoints.
|
||||
*/
|
||||
|
||||
nsresult SelRangeStore::StoreRange(nsIDOMRange *aRange)
|
||||
// DEBUG: PRInt32 nsRangeStore::n = 0;
|
||||
|
||||
nsRangeStore::nsRangeStore()
|
||||
{
|
||||
// DEBUG: n++; printf("range store alloc count=%d\n", n);
|
||||
}
|
||||
nsRangeStore::~nsRangeStore()
|
||||
{
|
||||
// DEBUG: n--; printf("range store alloc count=%d\n", n);
|
||||
}
|
||||
|
||||
nsresult nsRangeStore::StoreRange(nsIDOMRange *aRange)
|
||||
{
|
||||
if (!aRange) return NS_ERROR_NULL_POINTER;
|
||||
aRange->GetStartContainer(getter_AddRefs(startNode));
|
||||
|
@ -620,7 +740,7 @@ nsresult SelRangeStore::StoreRange(nsIDOMRange *aRange)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult SelRangeStore::GetRange(nsCOMPtr<nsIDOMRange> *outRange)
|
||||
nsresult nsRangeStore::GetRange(nsCOMPtr<nsIDOMRange> *outRange)
|
||||
{
|
||||
if (!outRange) return NS_ERROR_NULL_POINTER;
|
||||
nsresult res = nsComponentManager::CreateInstance(kCRangeCID,
|
||||
|
@ -644,22 +764,22 @@ nsresult SelRangeStore::GetRange(nsCOMPtr<nsIDOMRange> *outRange)
|
|||
class nsAutoReplaceContainerSelNotify
|
||||
{
|
||||
private:
|
||||
nsSelectionState *mSel;
|
||||
nsRangeUpdater &mRU;
|
||||
nsIDOMNode *mOriginalNode;
|
||||
nsIDOMNode *mNewNode;
|
||||
|
||||
public:
|
||||
nsAutoReplaceContainerSelNotify(nsSelectionState *aSelState, nsIDOMNode *aOriginalNode, nsIDOMNode *aNewNode) :
|
||||
mSel(aSelState)
|
||||
nsAutoReplaceContainerSelNotify(nsRangeUpdater &aRangeUpdater, nsIDOMNode *aOriginalNode, nsIDOMNode *aNewNode) :
|
||||
mRU(aRangeUpdater)
|
||||
,mOriginalNode(aOriginalNode)
|
||||
,mNewNode(aNewNode)
|
||||
{
|
||||
if (mSel) mSel->WillReplaceContainer();
|
||||
mRU.WillReplaceContainer();
|
||||
}
|
||||
|
||||
~nsAutoReplaceContainerSelNotify()
|
||||
{
|
||||
if (mSel) mSel->DidReplaceContainer(mOriginalNode, mNewNode);
|
||||
mRU.DidReplaceContainer(mOriginalNode, mNewNode);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -672,30 +792,30 @@ class nsAutoReplaceContainerSelNotify
|
|||
class nsAutoRemoveContainerSelNotify
|
||||
{
|
||||
private:
|
||||
nsSelectionState *mSel;
|
||||
nsRangeUpdater &mRU;
|
||||
nsIDOMNode *mNode;
|
||||
nsIDOMNode *mParent;
|
||||
PRInt32 mOffset;
|
||||
PRUint32 mNodeOrigLen;
|
||||
|
||||
public:
|
||||
nsAutoRemoveContainerSelNotify(nsSelectionState *aSelState,
|
||||
nsAutoRemoveContainerSelNotify(nsRangeUpdater &aRangeUpdater,
|
||||
nsIDOMNode *aNode,
|
||||
nsIDOMNode *aParent,
|
||||
PRInt32 aOffset,
|
||||
PRUint32 aNodeOrigLen) :
|
||||
mSel(aSelState)
|
||||
mRU(aRangeUpdater)
|
||||
,mNode(aNode)
|
||||
,mParent(aParent)
|
||||
,mOffset(aOffset)
|
||||
,mNodeOrigLen(aNodeOrigLen)
|
||||
{
|
||||
if (mSel) mSel->WillRemoveContainer();
|
||||
mRU.WillRemoveContainer();
|
||||
}
|
||||
|
||||
~nsAutoRemoveContainerSelNotify()
|
||||
{
|
||||
if (mSel) mSel->DidRemoveContainer(mNode, mParent, mOffset, mNodeOrigLen);
|
||||
mRU.DidRemoveContainer(mNode, mParent, mOffset, mNodeOrigLen);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -707,18 +827,18 @@ class nsAutoRemoveContainerSelNotify
|
|||
class nsAutoInsertContainerSelNotify
|
||||
{
|
||||
private:
|
||||
nsSelectionState *mSel;
|
||||
nsRangeUpdater &mRU;
|
||||
|
||||
public:
|
||||
nsAutoInsertContainerSelNotify(nsSelectionState *aSelState) :
|
||||
mSel(aSelState)
|
||||
nsAutoInsertContainerSelNotify(nsRangeUpdater &aRangeUpdater) :
|
||||
mRU(aRangeUpdater)
|
||||
{
|
||||
if (mSel) mSel->WillInsertContainer();
|
||||
mRU.WillInsertContainer();
|
||||
}
|
||||
|
||||
~nsAutoInsertContainerSelNotify()
|
||||
{
|
||||
if (mSel) mSel->DidInsertContainer();
|
||||
mRU.DidInsertContainer();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -731,30 +851,30 @@ class nsAutoInsertContainerSelNotify
|
|||
class nsAutoMoveNodeSelNotify
|
||||
{
|
||||
private:
|
||||
nsSelectionState *mSel;
|
||||
nsRangeUpdater &mRU;
|
||||
nsIDOMNode *mOldParent;
|
||||
nsIDOMNode *mNewParent;
|
||||
PRInt32 mOldOffset;
|
||||
PRInt32 mNewOffset;
|
||||
|
||||
public:
|
||||
nsAutoMoveNodeSelNotify(nsSelectionState *aSelState,
|
||||
nsAutoMoveNodeSelNotify(nsRangeUpdater &aRangeUpdater,
|
||||
nsIDOMNode *aOldParent,
|
||||
PRInt32 aOldOffset,
|
||||
nsIDOMNode *aNewParent,
|
||||
PRInt32 aNewOffset) :
|
||||
mSel(aSelState)
|
||||
mRU(aRangeUpdater)
|
||||
,mOldParent(aOldParent)
|
||||
,mNewParent(aNewParent)
|
||||
,mOldOffset(aOldOffset)
|
||||
,mNewOffset(aNewOffset)
|
||||
{
|
||||
if (mSel) mSel->WillMoveNode();
|
||||
mRU.WillMoveNode();
|
||||
}
|
||||
|
||||
~nsAutoMoveNodeSelNotify()
|
||||
{
|
||||
if (mSel) mSel->DidMoveNode(mOldParent, mOldOffset, mNewParent, mNewOffset);
|
||||
mRU.DidMoveNode(mOldParent, mOldOffset, mNewParent, mNewOffset);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -774,7 +894,8 @@ nsEditor::nsEditor()
|
|||
, mPlaceHolderName(nsnull)
|
||||
, mPlaceHolderBatch(0)
|
||||
, mSelState(nsnull)
|
||||
, mSavedSel(nsnull)
|
||||
, mSavedSel()
|
||||
, mRangeUpdater()
|
||||
, mShouldTxnSetSelection(PR_TRUE)
|
||||
, mBodyElement(nsnull)
|
||||
, mInIMEMode(PR_FALSE)
|
||||
|
@ -1595,7 +1716,7 @@ NS_IMETHODIMP nsEditor::CreateNode(const nsString& aTag,
|
|||
// The transaction system (if any) has taken ownwership of txn
|
||||
NS_IF_RELEASE(txn);
|
||||
|
||||
if (mSavedSel) mSavedSel->SelAdjCreateNode(aParent, aPosition);
|
||||
mRangeUpdater.SelAdjCreateNode(aParent, aPosition);
|
||||
|
||||
if (mActionListeners)
|
||||
{
|
||||
|
@ -1637,7 +1758,7 @@ NS_IMETHODIMP nsEditor::InsertNode(nsIDOMNode * aNode,
|
|||
// The transaction system (if any) has taken ownwership of txn
|
||||
NS_IF_RELEASE(txn);
|
||||
|
||||
if (mSavedSel) mSavedSel->SelAdjInsertNode(aParent, aPosition);
|
||||
mRangeUpdater.SelAdjInsertNode(aParent, aPosition);
|
||||
|
||||
if (mActionListeners)
|
||||
{
|
||||
|
@ -1686,7 +1807,7 @@ nsEditor::SplitNode(nsIDOMNode * aNode,
|
|||
// The transaction system (if any) has taken ownwership of txn
|
||||
NS_IF_RELEASE(txn);
|
||||
|
||||
if (mSavedSel) mSavedSel->SelAdjSplitNode(aNode, aOffset, *aNewLeftNode);
|
||||
mRangeUpdater.SelAdjSplitNode(aNode, aOffset, *aNewLeftNode);
|
||||
|
||||
if (mActionListeners)
|
||||
{
|
||||
|
@ -1743,7 +1864,7 @@ nsEditor::JoinNodes(nsIDOMNode * aLeftNode,
|
|||
// The transaction system (if any) has taken ownwership of txn
|
||||
NS_IF_RELEASE(txn);
|
||||
|
||||
if (mSavedSel) mSavedSel->SelAdjJoinNodes(aLeftNode, aRightNode, aParent, offset, (PRInt32)oldLeftNodeLen);
|
||||
mRangeUpdater.SelAdjJoinNodes(aLeftNode, aRightNode, aParent, offset, (PRInt32)oldLeftNodeLen);
|
||||
|
||||
if (mActionListeners)
|
||||
{
|
||||
|
@ -1789,7 +1910,7 @@ NS_IMETHODIMP nsEditor::DeleteNode(nsIDOMNode * aElement)
|
|||
// The transaction system (if any) has taken ownwership of txn
|
||||
NS_IF_RELEASE(txn);
|
||||
|
||||
if (mSavedSel) mSavedSel->SelAdjDeleteNode(aElement, parent, offset);
|
||||
mRangeUpdater.SelAdjDeleteNode(aElement, parent, offset);
|
||||
|
||||
if (mActionListeners)
|
||||
{
|
||||
|
@ -1856,8 +1977,8 @@ nsEditor::ReplaceContainer(nsIDOMNode *inNode,
|
|||
|
||||
// notify our internal selection state listener
|
||||
// (Note: A nsAutoSelectionReset object must be created
|
||||
// before calling this to initialize mSavedSel)
|
||||
nsAutoReplaceContainerSelNotify selStateNotify(mSavedSel, inNode, *outNode);
|
||||
// before calling this to initialize mRangeUpdater)
|
||||
nsAutoReplaceContainerSelNotify selStateNotify(mRangeUpdater, inNode, *outNode);
|
||||
|
||||
nsCOMPtr<nsIDOMNode> child;
|
||||
PRBool bHasMoreChildren;
|
||||
|
@ -1908,7 +2029,7 @@ nsEditor::RemoveContainer(nsIDOMNode *inNode)
|
|||
nodeList->GetLength(&nodeOrigLen);
|
||||
|
||||
// notify our internal selection state listener
|
||||
nsAutoRemoveContainerSelNotify selNotify(mSavedSel, inNode, parent, offset, nodeOrigLen);
|
||||
nsAutoRemoveContainerSelNotify selNotify(mRangeUpdater, inNode, parent, offset, nodeOrigLen);
|
||||
|
||||
nsCOMPtr<nsIDOMNode> child;
|
||||
while (bHasMoreChildren)
|
||||
|
@ -1970,7 +2091,7 @@ nsEditor::InsertContainerAbove( nsIDOMNode *inNode,
|
|||
}
|
||||
|
||||
// notify our internal selection state listener
|
||||
nsAutoInsertContainerSelNotify selNotify(mSavedSel);
|
||||
nsAutoInsertContainerSelNotify selNotify(mRangeUpdater);
|
||||
|
||||
// put inNode in new parent, outNode
|
||||
res = DeleteNode(inNode);
|
||||
|
@ -2009,7 +2130,7 @@ nsEditor::MoveNode(nsIDOMNode *aNode, nsIDOMNode *aParent, PRInt32 aOffset)
|
|||
if ((aParent == oldParent.get()) && (oldOffset == aOffset)) return NS_OK;
|
||||
|
||||
// notify our internal selection state listener
|
||||
nsAutoMoveNodeSelNotify selNotify(mSavedSel, oldParent, oldOffset, aParent, aOffset);
|
||||
nsAutoMoveNodeSelNotify selNotify(mRangeUpdater, oldParent, oldOffset, aParent, aOffset);
|
||||
|
||||
// need to adjust aOffset if we are moving aNode further along in it's current parent
|
||||
if ((aParent == oldParent.get()) && (oldOffset < aOffset))
|
||||
|
@ -2250,6 +2371,44 @@ nsEditor::DebugUnitTests(PRInt32 *outNumTests, PRInt32 *outNumTestsFailed)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
#ifdef XP_MAC
|
||||
#pragma mark -
|
||||
#pragma mark support for selection preservation
|
||||
#pragma mark -
|
||||
#endif
|
||||
|
||||
PRBool
|
||||
nsEditor::ArePreservingSelection()
|
||||
{
|
||||
if (mSavedSel.IsEmpty()) return PR_FALSE;
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsEditor::PreserveSelectionAcrossActions(nsIDOMSelection *aSel)
|
||||
{
|
||||
mSavedSel.SaveSelection(aSel);
|
||||
mRangeUpdater.RegisterSelectionState(mSavedSel);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsEditor::RestorePreservedSelection(nsIDOMSelection *aSel)
|
||||
{
|
||||
if (mSavedSel.IsEmpty()) return NS_ERROR_FAILURE;
|
||||
mSavedSel.RestoreSelection(aSel);
|
||||
StopPreservingSelection();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsEditor::StopPreservingSelection()
|
||||
{
|
||||
mRangeUpdater.DropSelectionState(mSavedSel);
|
||||
mSavedSel.MakeEmpty();
|
||||
}
|
||||
|
||||
|
||||
#ifdef XP_MAC
|
||||
#pragma mark -
|
||||
#pragma mark nsIEditorIMESupport
|
||||
|
@ -4985,6 +5144,7 @@ nsEditor::SplitNodeDeep(nsIDOMNode *aNode,
|
|||
nsIDOMNode *aSplitPointParent,
|
||||
PRInt32 aSplitPointOffset,
|
||||
PRInt32 *outOffset,
|
||||
PRBool aNoEmptyContainers,
|
||||
nsCOMPtr<nsIDOMNode> *outLeftNode,
|
||||
nsCOMPtr<nsIDOMNode> *outRightNode)
|
||||
{
|
||||
|
@ -5006,12 +5166,12 @@ nsEditor::SplitNodeDeep(nsIDOMNode *aNode,
|
|||
// this nsEditor routine.
|
||||
|
||||
nsCOMPtr<nsIDOMCharacterData> nodeAsText = do_QueryInterface(nodeToSplit);
|
||||
PRUint32 textLen=0;
|
||||
if (nodeAsText)
|
||||
nodeAsText->GetLength(&textLen);
|
||||
PRUint32 len;
|
||||
PRBool bDoSplit = PR_FALSE;
|
||||
res = GetLengthOfDOMNode(nodeToSplit, len);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
if (!nodeAsText || (offset && (offset != (PRInt32)textLen)))
|
||||
if (!(aNoEmptyContainers || nodeAsText) || (offset && (offset != (PRInt32)len)))
|
||||
{
|
||||
bDoSplit = PR_TRUE;
|
||||
res = SplitNode(nodeToSplit, offset, getter_AddRefs(tempNode));
|
||||
|
|
|
@ -80,8 +80,10 @@ class nsISelectionController;
|
|||
*/
|
||||
|
||||
// first a helper struct for saving/setting ranges
|
||||
struct SelRangeStore
|
||||
struct nsRangeStore
|
||||
{
|
||||
nsRangeStore();
|
||||
~nsRangeStore();
|
||||
nsresult StoreRange(nsIDOMRange *aRange);
|
||||
nsresult GetRange(nsCOMPtr<nsIDOMRange> *outRange);
|
||||
|
||||
|
@ -89,6 +91,7 @@ struct SelRangeStore
|
|||
PRInt32 startOffset;
|
||||
nsCOMPtr<nsIDOMNode> endNode;
|
||||
PRInt32 endOffset;
|
||||
// DEBUG: static PRInt32 n;
|
||||
};
|
||||
|
||||
class nsSelectionState
|
||||
|
@ -104,6 +107,26 @@ class nsSelectionState
|
|||
PRBool IsEqual(nsSelectionState *aSelState);
|
||||
void MakeEmpty();
|
||||
PRBool IsEmpty();
|
||||
protected:
|
||||
nsVoidArray mArray;
|
||||
|
||||
friend class nsRangeUpdater;
|
||||
};
|
||||
|
||||
class nsRangeUpdater
|
||||
{
|
||||
public:
|
||||
|
||||
nsRangeUpdater();
|
||||
~nsRangeUpdater();
|
||||
|
||||
void* RegisterRange(nsIDOMRange *aRange);
|
||||
nsCOMPtr<nsIDOMRange> ReclaimRange(void *aCookie);
|
||||
void DropRange(void *aCookie);
|
||||
void RegisterRangeItem(nsRangeStore *aRangeItem);
|
||||
void DropRangeItem(nsRangeStore *aRangeItem);
|
||||
nsresult RegisterSelectionState(nsSelectionState &aSelState);
|
||||
nsresult DropSelectionState(nsSelectionState &aSelState);
|
||||
|
||||
// editor selection gravity routines. Note that we can't always depend on
|
||||
// DOM Range gravity to do what we want to the "real" selection. For instance,
|
||||
|
@ -131,7 +154,7 @@ class nsSelectionState
|
|||
nsresult DidInsertContainer();
|
||||
nsresult WillMoveNode();
|
||||
nsresult DidMoveNode(nsIDOMNode *aOldParent, PRInt32 aOldOffset, nsIDOMNode *aNewParent, PRInt32 aNewOffset);
|
||||
|
||||
protected:
|
||||
nsVoidArray mArray;
|
||||
PRBool mLock;
|
||||
};
|
||||
|
@ -483,6 +506,14 @@ public:
|
|||
* with a call to EndOperation */
|
||||
NS_IMETHOD EndOperation();
|
||||
|
||||
/** routines for managing the preservation of selection across
|
||||
* various editor actions */
|
||||
PRBool ArePreservingSelection();
|
||||
nsresult PreserveSelectionAcrossActions(nsIDOMSelection *aSel);
|
||||
nsresult RestorePreservedSelection(nsIDOMSelection *aSel);
|
||||
void StopPreservingSelection();
|
||||
|
||||
|
||||
/** return the string that represents text nodes in the content tree */
|
||||
static nsresult GetTextNodeTag(nsString& aOutString);
|
||||
|
||||
|
@ -725,6 +756,7 @@ public:
|
|||
nsIDOMNode *aSplitPointParent,
|
||||
PRInt32 aSplitPointOffset,
|
||||
PRInt32 *outOffset,
|
||||
PRBool aNoEmptyContainers = PR_FALSE,
|
||||
nsCOMPtr<nsIDOMNode> *outLeftNode = 0,
|
||||
nsCOMPtr<nsIDOMNode> *outRightNode = 0);
|
||||
nsresult JoinNodeDeep(nsIDOMNode *aLeftNode, nsIDOMNode *aRightNode, nsCOMPtr<nsIDOMNode> *aOutJoinNode, PRInt32 *outOffset);
|
||||
|
@ -748,15 +780,16 @@ protected:
|
|||
nsCOMPtr<nsITransactionManager> mTxnMgr;
|
||||
nsCOMPtr<nsIEditProperty> mEditProperty;
|
||||
nsCOMPtr<nsICSSStyleSheet> mLastStyleSheet; // is owning this dangerous?
|
||||
nsWeakPtr mPlaceHolderTxn; // weak reference to placeholder for begin/end batch purposes
|
||||
nsIAtom *mPlaceHolderName; // name of placeholder transaction
|
||||
PRInt32 mPlaceHolderBatch; // nesting count for batching
|
||||
nsSelectionState *mSelState; // saved selection state for placeholder txn batching
|
||||
nsSelectionState *mSavedSel; // cached selection for nsAutoSelectionReset
|
||||
PRBool mShouldTxnSetSelection; // turn off for conservative selection adjustment by txns
|
||||
nsWeakPtr mPlaceHolderTxn; // weak reference to placeholder for begin/end batch purposes
|
||||
nsIAtom *mPlaceHolderName; // name of placeholder transaction
|
||||
PRInt32 mPlaceHolderBatch; // nesting count for batching
|
||||
nsSelectionState *mSelState; // saved selection state for placeholder txn batching
|
||||
nsSelectionState mSavedSel; // cached selection for nsAutoSelectionReset
|
||||
nsRangeUpdater mRangeUpdater; // utility class object for maintaining preserved ranges
|
||||
PRBool mShouldTxnSetSelection; // turn off for conservative selection adjustment by txns
|
||||
nsCOMPtr<nsIDOMElement> mBodyElement; // cached body node
|
||||
PRInt32 mAction; // the current editor action
|
||||
EDirection mDirection; // the current direction of editor action
|
||||
PRInt32 mAction; // the current editor action
|
||||
EDirection mDirection; // the current direction of editor action
|
||||
|
||||
// data necessary to build IME transactions
|
||||
PRBool mInIMEMode; // are we inside an IME composition?
|
||||
|
|
|
@ -23,6 +23,9 @@
|
|||
|
||||
#include "nsEditorUtils.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsIDOMRange.h"
|
||||
#include "nsIContent.h"
|
||||
#include "nsLayoutCID.h"
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
|
@ -34,24 +37,162 @@ mSel(nsnull)
|
|||
,mEd(nsnull)
|
||||
{
|
||||
if (!aSel || !aEd) return; // not much we can do, bail.
|
||||
if (aEd->mSavedSel) return; // we already have initted mSavedSel, so this must be nested call.
|
||||
if (aEd->ArePreservingSelection()) return; // we already have initted mSavedSel, so this must be nested call.
|
||||
mSel = do_QueryInterface(aSel);
|
||||
mEd = aEd;
|
||||
if (mSel)
|
||||
{
|
||||
mEd->mSavedSel = new nsSelectionState();
|
||||
mEd->mSavedSel->SaveSelection(mSel);
|
||||
mEd->PreserveSelectionAcrossActions(mSel);
|
||||
}
|
||||
}
|
||||
|
||||
nsAutoSelectionReset::~nsAutoSelectionReset()
|
||||
{
|
||||
if (mSel && mEd->mSavedSel) // mSel will be null if this was nested call
|
||||
if (mSel && mEd->ArePreservingSelection()) // mSel will be null if this was nested call
|
||||
{
|
||||
mEd->mSavedSel->RestoreSelection(mSel);
|
||||
delete mEd->mSavedSel;
|
||||
mEd->mSavedSel = nsnull;
|
||||
mEd->RestorePreservedSelection(mSel);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsAutoSelectionReset::Abort()
|
||||
{
|
||||
mEd->StopPreservingSelection();
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* some helper classes for iterating the dom tree
|
||||
*****************************************************************************/
|
||||
|
||||
static NS_DEFINE_IID(kSubtreeIteratorCID, NS_SUBTREEITERATOR_CID);
|
||||
static NS_DEFINE_IID(kContentIteratorCID, NS_CONTENTITERATOR_CID);
|
||||
|
||||
nsDOMIterator::nsDOMIterator() :
|
||||
mIter(nsnull)
|
||||
{
|
||||
}
|
||||
|
||||
nsDOMIterator::~nsDOMIterator()
|
||||
{
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMIterator::Init(nsIDOMRange* aRange)
|
||||
{
|
||||
nsresult res = nsComponentManager::CreateInstance(kContentIteratorCID,
|
||||
nsnull,
|
||||
NS_GET_IID(nsIContentIterator),
|
||||
getter_AddRefs(mIter));
|
||||
if (NS_FAILED(res)) return res;
|
||||
return mIter->Init(aRange);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMIterator::Init(nsIDOMNode* aNode)
|
||||
{
|
||||
nsresult res = nsComponentManager::CreateInstance(kContentIteratorCID,
|
||||
nsnull,
|
||||
NS_GET_IID(nsIContentIterator),
|
||||
getter_AddRefs(mIter));
|
||||
if (NS_FAILED(res)) return res;
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(aNode);
|
||||
return mIter->Init(content);
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMIterator::ForEach(nsDomIterFunctor& functor) const
|
||||
{
|
||||
nsCOMPtr<nsIContent> content;
|
||||
nsCOMPtr<nsIDOMNode> node;
|
||||
nsCOMPtr<nsISupports> isupports;
|
||||
nsresult res;
|
||||
|
||||
// iterate through dom
|
||||
while (NS_ENUMERATOR_FALSE == mIter->IsDone())
|
||||
{
|
||||
res = mIter->CurrentNode(getter_AddRefs(content));
|
||||
if (NS_FAILED(res)) return;
|
||||
node = do_QueryInterface(content);
|
||||
if (!node) return;
|
||||
functor(node);
|
||||
res = mIter->Next();
|
||||
if (NS_FAILED(res)) return;
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMIterator::MakeList(nsBoolDomIterFunctor& functor,
|
||||
nsCOMPtr<nsISupportsArray> *outArrayOfNodes) const
|
||||
{
|
||||
nsCOMPtr<nsIContent> content;
|
||||
nsCOMPtr<nsIDOMNode> node;
|
||||
nsCOMPtr<nsISupports> isupports;
|
||||
nsresult res;
|
||||
|
||||
// make a array
|
||||
res = NS_NewISupportsArray(getter_AddRefs(*outArrayOfNodes));
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
return AppendList(functor, *outArrayOfNodes);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMIterator::AppendList(nsBoolDomIterFunctor& functor,
|
||||
nsCOMPtr<nsISupportsArray> arrayOfNodes) const
|
||||
{
|
||||
if (!arrayOfNodes) return NS_ERROR_NULL_POINTER;
|
||||
nsCOMPtr<nsIContent> content;
|
||||
nsCOMPtr<nsIDOMNode> node;
|
||||
nsCOMPtr<nsISupports> isupports;
|
||||
nsresult res;
|
||||
|
||||
// iterate through dom and build list
|
||||
while (NS_ENUMERATOR_FALSE == mIter->IsDone())
|
||||
{
|
||||
res = mIter->CurrentNode(getter_AddRefs(content));
|
||||
if (NS_FAILED(res)) return res;
|
||||
node = do_QueryInterface(content);
|
||||
if (!node) return NS_ERROR_NULL_POINTER;
|
||||
if (functor(node))
|
||||
{
|
||||
isupports = do_QueryInterface(node);
|
||||
arrayOfNodes->AppendElement(isupports);
|
||||
}
|
||||
res = mIter->Next();
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsDOMSubtreeIterator::nsDOMSubtreeIterator()
|
||||
{
|
||||
}
|
||||
|
||||
nsDOMSubtreeIterator::~nsDOMSubtreeIterator()
|
||||
{
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMSubtreeIterator::Init(nsIDOMRange* aRange)
|
||||
{
|
||||
nsresult res = nsComponentManager::CreateInstance(kSubtreeIteratorCID,
|
||||
nsnull,
|
||||
NS_GET_IID(nsIContentIterator),
|
||||
getter_AddRefs(mIter));
|
||||
if (NS_FAILED(res)) return res;
|
||||
return mIter->Init(aRange);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMSubtreeIterator::Init(nsIDOMNode* aNode)
|
||||
{
|
||||
nsresult res = nsComponentManager::CreateInstance(kSubtreeIteratorCID,
|
||||
nsnull,
|
||||
NS_GET_IID(nsIContentIterator),
|
||||
getter_AddRefs(mIter));
|
||||
if (NS_FAILED(res)) return res;
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(aNode);
|
||||
return mIter->Init(content);
|
||||
}
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include "nsIAtom.h"
|
||||
#include "nsVoidArray.h"
|
||||
#include "nsEditor.h"
|
||||
#include "nsIContentIterator.h"
|
||||
|
||||
/***************************************************************************
|
||||
* stack based helper class for batching a collection of txns inside a
|
||||
|
@ -77,6 +78,9 @@ class nsAutoSelectionReset
|
|||
|
||||
/** destructor restores mSel to its former state */
|
||||
~nsAutoSelectionReset();
|
||||
|
||||
/** Abort: cancel selection saver */
|
||||
void Abort();
|
||||
};
|
||||
|
||||
/***************************************************************************
|
||||
|
@ -139,5 +143,47 @@ class nsAutoTxnsConserveSelection
|
|||
PRBool mOldState;
|
||||
};
|
||||
|
||||
/******************************************************************************
|
||||
* some helper classes for iterating the dom tree
|
||||
*****************************************************************************/
|
||||
|
||||
class nsDomIterFunctor
|
||||
{
|
||||
public:
|
||||
virtual void* operator()(nsIDOMNode* aNode)=0;
|
||||
};
|
||||
|
||||
class nsBoolDomIterFunctor
|
||||
{
|
||||
public:
|
||||
virtual PRBool operator()(nsIDOMNode* aNode)=0;
|
||||
};
|
||||
|
||||
class nsDOMIterator
|
||||
{
|
||||
public:
|
||||
nsDOMIterator();
|
||||
virtual ~nsDOMIterator();
|
||||
|
||||
nsresult Init(nsIDOMRange* aRange);
|
||||
nsresult Init(nsIDOMNode* aNode);
|
||||
void ForEach(nsDomIterFunctor& functor) const;
|
||||
nsresult MakeList(nsBoolDomIterFunctor& functor,
|
||||
nsCOMPtr<nsISupportsArray> *outArrayOfNodes) const;
|
||||
nsresult AppendList(nsBoolDomIterFunctor& functor,
|
||||
nsCOMPtr<nsISupportsArray> arrayOfNodes) const;
|
||||
protected:
|
||||
nsCOMPtr<nsIContentIterator> mIter;
|
||||
};
|
||||
|
||||
class nsDOMSubtreeIterator : public nsDOMIterator
|
||||
{
|
||||
public:
|
||||
nsDOMSubtreeIterator();
|
||||
virtual ~nsDOMSubtreeIterator();
|
||||
|
||||
nsresult Init(nsIDOMRange* aRange);
|
||||
nsresult Init(nsIDOMNode* aNode);
|
||||
};
|
||||
|
||||
#endif // nsEditorUtils_h__
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -109,8 +109,8 @@ protected:
|
|||
nsresult WillMakeBasicBlock(nsIDOMSelection *aSelection, const nsString *aBlockType, PRBool *aCancel, PRBool *aHandled);
|
||||
nsresult DidMakeBasicBlock(nsIDOMSelection *aSelection, nsRulesInfo *aInfo, nsresult aResult);
|
||||
|
||||
nsresult AlignTableElement(nsIDOMNode *aNode, const nsString *alignType);
|
||||
nsresult AlignTableCellContents(nsIDOMNode *aNode, const nsString *alignType);
|
||||
nsresult AlignInnerBlocks(nsIDOMNode *aNode, const nsString *alignType);
|
||||
nsresult AlignBlockContents(nsIDOMNode *aNode, const nsString *alignType);
|
||||
nsresult GetInnerContent(nsIDOMNode *aNode, nsISupportsArray *outArrayOfNodes, PRBool aList = PR_TRUE, PRBool aTble = PR_TRUE);
|
||||
|
||||
nsresult InsertTab(nsIDOMSelection *aSelection, nsString *outString);
|
||||
|
@ -146,12 +146,13 @@ protected:
|
|||
nsresult GetListActionNodes(nsCOMPtr<nsISupportsArray> *outArrayOfNodes, PRBool aDontTouchContent=PR_FALSE);
|
||||
nsresult GetDefinitionListItemTypes(nsIDOMNode *aNode, PRBool &aDT, PRBool &aDD);
|
||||
nsresult GetParagraphFormatNodes(nsCOMPtr<nsISupportsArray> *outArrayOfNodes, PRBool aDontTouchContent=PR_FALSE);
|
||||
nsresult BustUpInlinesAtRangeEndpoints(nsRangeStore &inRange);
|
||||
nsresult BustUpInlinesAtBRs(nsIDOMNode *inNode,
|
||||
nsCOMPtr<nsISupportsArray> *outArrayOfNodes);
|
||||
nsCOMPtr<nsIDOMNode> GetHighestInlineParent(nsIDOMNode* aNode);
|
||||
nsresult MakeTransitionList(nsISupportsArray *inArrayOfNodes,
|
||||
nsVoidArray *inTransitionArray);
|
||||
|
||||
nsresult ShouldMakeEmptyBlock(nsIDOMSelection *aSelection, const nsString *blockTag, PRBool *outMakeEmpty);
|
||||
nsresult ApplyBlockStyle(nsISupportsArray *arrayOfNodes, const nsString *aBlockTag);
|
||||
nsresult MakeBlockquote(nsISupportsArray *arrayOfNodes);
|
||||
nsresult SplitAsNeeded(const nsString *aTag, nsCOMPtr<nsIDOMNode> *inOutParent, PRInt32 *inOutOffset);
|
||||
|
|
|
@ -42,6 +42,7 @@ nsHTMLEditUtils::IsBody(nsIDOMNode *node)
|
|||
{
|
||||
nsAutoString tag;
|
||||
nsEditor::GetTagString(node,tag);
|
||||
tag.ToLowerCase();
|
||||
if (tag.EqualsWithConversion("body"))
|
||||
{
|
||||
return PR_TRUE;
|
||||
|
@ -573,4 +574,11 @@ nsHTMLEditUtils::IsDescendantOf(nsIDOMNode *aNode, nsIDOMNode *aParent)
|
|||
}
|
||||
|
||||
|
||||
|
||||
PRBool
|
||||
nsHTMLEditUtils::IsLeafNode(nsIDOMNode *aNode)
|
||||
{
|
||||
if (!aNode) return PR_FALSE;
|
||||
PRBool hasChildren = PR_FALSE;
|
||||
aNode->HasChildNodes(&hasChildren);
|
||||
return !hasChildren;
|
||||
}
|
|
@ -63,6 +63,9 @@ public:
|
|||
static PRBool IsMozDiv(nsIDOMNode *aNode);
|
||||
static PRBool IsMailCite(nsIDOMNode *aNode);
|
||||
static PRBool IsDescendantOf(nsIDOMNode *aNode, nsIDOMNode *aParent);
|
||||
|
||||
static PRBool IsLeafNode(nsIDOMNode *aNode);
|
||||
|
||||
};
|
||||
|
||||
#endif /* nsHTMLEditUtils_h__ */
|
||||
|
|
|
@ -1777,6 +1777,16 @@ NS_IMETHODIMP nsHTMLEditor::GetInlinePropertyWithAttrValue(nsIAtom *aProperty,
|
|||
if (collapsedNode != mCachedNode) CacheInlineStyles(collapsedNode);
|
||||
// cache now current, use it! But override it with typeInState results if any...
|
||||
PRBool isSet, theSetting;
|
||||
if (aAttribute)
|
||||
mTypeInState->GetTypingState(isSet, theSetting, aProperty, *aAttribute, outValue);
|
||||
else
|
||||
mTypeInState->GetTypingState(isSet, theSetting, aProperty);
|
||||
if (isSet)
|
||||
{
|
||||
aFirst = aAny = aAll = theSetting;
|
||||
return NS_OK;
|
||||
}
|
||||
/*
|
||||
if (aProperty == mBoldAtom.get())
|
||||
{
|
||||
mTypeInState->GetTypingState(isSet, theSetting, aProperty);
|
||||
|
@ -1815,7 +1825,7 @@ NS_IMETHODIMP nsHTMLEditor::GetInlinePropertyWithAttrValue(nsIAtom *aProperty,
|
|||
aFirst = aAny = aAll = mCachedUnderlineStyle;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
} */
|
||||
}
|
||||
|
||||
// either non-collapsed selection or no cached value: do it the hard way
|
||||
|
@ -7102,7 +7112,7 @@ nsHTMLEditor::GetPriorHTMLNode(nsIDOMNode *inParent, PRInt32 inOffset, nsCOMPtr<
|
|||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// GetNextHTMLNode: returns the previous editable leaf node, if there is
|
||||
// GetNextHTMLNode: returns the next editable leaf node, if there is
|
||||
// one within the <body>
|
||||
//
|
||||
nsresult
|
||||
|
@ -7239,6 +7249,75 @@ nsHTMLEditor::GetLastEditableChild( nsIDOMNode *aNode, nsCOMPtr<nsIDOMNode> *aOu
|
|||
return res;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLEditor::GetFirstEditableLeaf( nsIDOMNode *aNode, nsCOMPtr<nsIDOMNode> *aOutFirstLeaf)
|
||||
{
|
||||
// check parms
|
||||
if (!aOutFirstLeaf || !aNode) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
// init out parms
|
||||
*aOutFirstLeaf = nsnull;
|
||||
|
||||
// find leftmost leaf
|
||||
nsCOMPtr<nsIDOMNode> child;
|
||||
nsresult res = GetLeftmostChild(aNode, getter_AddRefs(child));
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
while (child && (!IsEditable(child) || !nsHTMLEditUtils::IsLeafNode(child)))
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> tmp;
|
||||
res = GetNextHTMLNode(child, &tmp);
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!tmp) return NS_ERROR_FAILURE;
|
||||
|
||||
// only accept nodes that are descendants of aNode
|
||||
if (nsHTMLEditUtils::IsDescendantOf(tmp, aNode))
|
||||
child = tmp;
|
||||
else
|
||||
{
|
||||
child = nsnull; // this will abort the loop
|
||||
}
|
||||
}
|
||||
|
||||
*aOutFirstLeaf = child;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsHTMLEditor::GetLastEditableLeaf( nsIDOMNode *aNode, nsCOMPtr<nsIDOMNode> *aOutLastLeaf)
|
||||
{
|
||||
// check parms
|
||||
if (!aOutLastLeaf || !aNode) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
// init out parms
|
||||
*aOutLastLeaf = nsnull;
|
||||
|
||||
// find leftmost leaf
|
||||
nsCOMPtr<nsIDOMNode> child;
|
||||
nsresult res = GetRightmostChild(aNode, getter_AddRefs(child));
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
while (child && (!IsEditable(child) || !nsHTMLEditUtils::IsLeafNode(child)))
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> tmp;
|
||||
res = GetPriorHTMLNode(child, &tmp);
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!tmp) return NS_ERROR_FAILURE;
|
||||
|
||||
// only accept nodes that are descendants of aNode
|
||||
if (nsHTMLEditUtils::IsDescendantOf(tmp, aNode))
|
||||
child = tmp;
|
||||
else
|
||||
{
|
||||
child = nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
*aOutLastLeaf = child;
|
||||
return res;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// IsEmptyNode: figure out if aNode is an empty node.
|
||||
// A block can have children and still be considered empty,
|
||||
|
|
|
@ -332,6 +332,11 @@ public:
|
|||
// aSelection is optional -- if null, we get current seletion
|
||||
nsresult CollapseSelectionToDeepestNonTableFirstChild(nsIDOMSelection *aSelection, nsIDOMNode *aNode);
|
||||
|
||||
nsresult IsEmptyNode(nsIDOMNode *aNode, PRBool *outIsEmptyBlock,
|
||||
PRBool aMozBRDoesntCount = PR_FALSE,
|
||||
PRBool aListOrCellNotEmpty = PR_FALSE,
|
||||
PRBool aSafeToAskFrames = PR_FALSE);
|
||||
|
||||
protected:
|
||||
|
||||
NS_IMETHOD InitRules();
|
||||
|
@ -563,10 +568,8 @@ protected:
|
|||
nsresult IsLastEditableChild( nsIDOMNode *aNode, PRBool *aOutIsLast);
|
||||
nsresult GetFirstEditableChild( nsIDOMNode *aNode, nsCOMPtr<nsIDOMNode> *aOutFirstChild);
|
||||
nsresult GetLastEditableChild( nsIDOMNode *aNode, nsCOMPtr<nsIDOMNode> *aOutLastChild);
|
||||
nsresult IsEmptyNode(nsIDOMNode *aNode, PRBool *outIsEmptyBlock,
|
||||
PRBool aMozBRDoesntCount = PR_FALSE,
|
||||
PRBool aListOrCellNotEmpty = PR_FALSE,
|
||||
PRBool aSafeToAskFrames = PR_FALSE);
|
||||
nsresult GetFirstEditableLeaf( nsIDOMNode *aNode, nsCOMPtr<nsIDOMNode> *aOutFirstLeaf);
|
||||
nsresult GetLastEditableLeaf( nsIDOMNode *aNode, nsCOMPtr<nsIDOMNode> *aOutLastLeaf);
|
||||
|
||||
nsresult GetDOMEventReceiver(nsIDOMEventReceiver **aEventReceiver);
|
||||
|
||||
|
|
|
@ -477,7 +477,7 @@ nsTextEditRules::WillInsertBreak(nsIDOMSelection *aSelection, PRBool *aCancel, P
|
|||
printf("It's a moz quote -- splitting\n");
|
||||
nsCOMPtr<nsIDOMNode> outLeftNode;
|
||||
nsCOMPtr<nsIDOMNode> outRightNode;
|
||||
res = mEditor->SplitNodeDeep(preNode, selNode, selOffset, &newOffset, &outLeftNode, &outRightNode);
|
||||
res = mEditor->SplitNodeDeep(preNode, selNode, selOffset, &newOffset, PR_TRUE, &outLeftNode, &outRightNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
PRBool bIsEmptyNode;
|
||||
|
||||
|
|
|
@ -152,17 +152,11 @@ PRInt32 nsEditor::gInstanceCount = 0;
|
|||
* { {startnode, startoffset} , {endnode, endoffset} } tuples. Cant store
|
||||
* ranges since dom gravity will possibly change the ranges.
|
||||
*/
|
||||
nsSelectionState::nsSelectionState() : mArray(), mLock(PR_FALSE) {}
|
||||
nsSelectionState::nsSelectionState() : mArray(){}
|
||||
|
||||
nsSelectionState::~nsSelectionState()
|
||||
{
|
||||
// free any items in the array
|
||||
SelRangeStore *item;
|
||||
while ((item = (SelRangeStore*)mArray.ElementAt(0)))
|
||||
{
|
||||
delete item;
|
||||
mArray.RemoveElementAt(0);
|
||||
}
|
||||
MakeEmpty();
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -171,7 +165,7 @@ nsSelectionState::SaveSelection(nsIDOMSelection *aSel)
|
|||
if (!aSel) return NS_ERROR_NULL_POINTER;
|
||||
nsresult res = NS_OK;
|
||||
PRInt32 i,rangeCount, arrayCount = mArray.Count();
|
||||
SelRangeStore *item;
|
||||
nsRangeStore *item;
|
||||
aSel->GetRangeCount(&rangeCount);
|
||||
|
||||
// if we need more items in the array, new them
|
||||
|
@ -180,7 +174,7 @@ nsSelectionState::SaveSelection(nsIDOMSelection *aSel)
|
|||
PRInt32 count = rangeCount-arrayCount;
|
||||
for (i=0; i<count; i++)
|
||||
{
|
||||
item = new SelRangeStore;
|
||||
item = new nsRangeStore;
|
||||
mArray.AppendElement(item);
|
||||
}
|
||||
}
|
||||
|
@ -188,7 +182,7 @@ nsSelectionState::SaveSelection(nsIDOMSelection *aSel)
|
|||
// else if we have too many, delete them
|
||||
else if (rangeCount>arrayCount)
|
||||
{
|
||||
while ((item = (SelRangeStore*)mArray.ElementAt(rangeCount)))
|
||||
while ((item = (nsRangeStore*)mArray.ElementAt(rangeCount)))
|
||||
{
|
||||
delete item;
|
||||
mArray.RemoveElementAt(rangeCount);
|
||||
|
@ -198,7 +192,7 @@ nsSelectionState::SaveSelection(nsIDOMSelection *aSel)
|
|||
// now store the selection ranges
|
||||
for (i=0; i<rangeCount; i++)
|
||||
{
|
||||
item = (SelRangeStore*)mArray.ElementAt(i);
|
||||
item = (nsRangeStore*)mArray.ElementAt(i);
|
||||
if (!item) return NS_ERROR_UNEXPECTED;
|
||||
nsCOMPtr<nsIDOMRange> range;
|
||||
res = aSel->GetRangeAt(i, getter_AddRefs(range));
|
||||
|
@ -214,7 +208,7 @@ nsSelectionState::RestoreSelection(nsIDOMSelection *aSel)
|
|||
if (!aSel) return NS_ERROR_NULL_POINTER;
|
||||
nsresult res = NS_OK;
|
||||
PRInt32 i, arrayCount = mArray.Count();
|
||||
SelRangeStore *item;
|
||||
nsRangeStore *item;
|
||||
|
||||
// clear out selection
|
||||
aSel->ClearSelection();
|
||||
|
@ -222,7 +216,7 @@ nsSelectionState::RestoreSelection(nsIDOMSelection *aSel)
|
|||
// set the selection ranges anew
|
||||
for (i=0; i<arrayCount; i++)
|
||||
{
|
||||
item = (SelRangeStore*)mArray.ElementAt(i);
|
||||
item = (nsRangeStore*)mArray.ElementAt(i);
|
||||
if (!item) return NS_ERROR_UNEXPECTED;
|
||||
nsCOMPtr<nsIDOMRange> range;
|
||||
item->GetRange(&range);
|
||||
|
@ -239,8 +233,8 @@ PRBool
|
|||
nsSelectionState::IsCollapsed()
|
||||
{
|
||||
if (1 != mArray.Count()) return PR_FALSE;
|
||||
SelRangeStore *item;
|
||||
item = (SelRangeStore*)mArray.ElementAt(0);
|
||||
nsRangeStore *item;
|
||||
item = (nsRangeStore*)mArray.ElementAt(0);
|
||||
if (!item) return PR_FALSE;
|
||||
nsCOMPtr<nsIDOMRange> range;
|
||||
item->GetRange(&range);
|
||||
|
@ -258,12 +252,12 @@ nsSelectionState::IsEqual(nsSelectionState *aSelState)
|
|||
if (myCount != itsCount) return PR_FALSE;
|
||||
if (myCount < 1) return PR_FALSE;
|
||||
|
||||
SelRangeStore *myItem, *itsItem;
|
||||
nsRangeStore *myItem, *itsItem;
|
||||
|
||||
for (i=0; i<myCount; i++)
|
||||
{
|
||||
myItem = (SelRangeStore*)mArray.ElementAt(0);
|
||||
itsItem = (SelRangeStore*)(aSelState->mArray.ElementAt(0));
|
||||
myItem = (nsRangeStore*)mArray.ElementAt(0);
|
||||
itsItem = (nsRangeStore*)(aSelState->mArray.ElementAt(0));
|
||||
if (!myItem || !itsItem) return PR_FALSE;
|
||||
|
||||
nsCOMPtr<nsIDOMRange> myRange, itsRange;
|
||||
|
@ -281,22 +275,137 @@ nsSelectionState::IsEqual(nsSelectionState *aSelState)
|
|||
return PR_TRUE;
|
||||
}
|
||||
|
||||
// notification routines used to update the saved selection state in response to
|
||||
// document editing.
|
||||
void
|
||||
nsSelectionState::MakeEmpty()
|
||||
{
|
||||
// free any items in the array
|
||||
nsRangeStore *item;
|
||||
while ((item = (nsRangeStore*)mArray.ElementAt(0)))
|
||||
{
|
||||
delete item;
|
||||
mArray.RemoveElementAt(0);
|
||||
}
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsSelectionState::IsEmpty()
|
||||
{
|
||||
return (mArray.Count() == 0);
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
* nsRangeUpdater: class for updating nsIDOMRanges in response to editor actions.
|
||||
*/
|
||||
|
||||
nsRangeUpdater::nsRangeUpdater() : mArray(), mLock(PR_FALSE) {}
|
||||
|
||||
nsRangeUpdater::~nsRangeUpdater()
|
||||
{
|
||||
// free any items in the array
|
||||
nsRangeStore *item;
|
||||
while ((item = (nsRangeStore*)mArray.ElementAt(0)))
|
||||
{
|
||||
delete item;
|
||||
mArray.RemoveElementAt(0);
|
||||
}
|
||||
}
|
||||
|
||||
void*
|
||||
nsRangeUpdater::RegisterRange(nsIDOMRange *aRange)
|
||||
{
|
||||
nsRangeStore *item = new nsRangeStore;
|
||||
if (!item) return nsnull;
|
||||
item->StoreRange(aRange);
|
||||
mArray.AppendElement(item);
|
||||
return item;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMRange>
|
||||
nsRangeUpdater::ReclaimRange(void *aCookie)
|
||||
{
|
||||
nsRangeStore *item = NS_STATIC_CAST(nsRangeStore*,aCookie);
|
||||
if (!item) return nsnull;
|
||||
nsCOMPtr<nsIDOMRange> outRange;
|
||||
item->GetRange(&outRange);
|
||||
mArray.RemoveElement(aCookie);
|
||||
delete item;
|
||||
return outRange;
|
||||
}
|
||||
|
||||
void
|
||||
nsRangeUpdater::DropRange(void *aCookie)
|
||||
{
|
||||
nsRangeStore *item = NS_STATIC_CAST(nsRangeStore*,aCookie);
|
||||
if (!item) return;
|
||||
mArray.RemoveElement(aCookie);
|
||||
delete item;
|
||||
}
|
||||
|
||||
void
|
||||
nsRangeUpdater::RegisterRangeItem(nsRangeStore *aRangeItem)
|
||||
{
|
||||
if (!aRangeItem) return;
|
||||
mArray.AppendElement(aRangeItem);
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
nsRangeUpdater::DropRangeItem(nsRangeStore *aRangeItem)
|
||||
{
|
||||
if (!aRangeItem) return;
|
||||
mArray.RemoveElement(aRangeItem);
|
||||
return;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsRangeUpdater::RegisterSelectionState(nsSelectionState &aSelState)
|
||||
{
|
||||
PRInt32 i, theCount = aSelState.mArray.Count();
|
||||
if (theCount < 1) return NS_ERROR_FAILURE;
|
||||
|
||||
nsRangeStore *item;
|
||||
|
||||
for (i=0; i<theCount; i++)
|
||||
{
|
||||
item = (nsRangeStore*)aSelState.mArray.ElementAt(i);
|
||||
RegisterRangeItem(item);
|
||||
}
|
||||
|
||||
return NS_OK;;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsRangeUpdater::DropSelectionState(nsSelectionState &aSelState)
|
||||
{
|
||||
PRInt32 i, theCount = aSelState.mArray.Count();
|
||||
if (theCount < 1) return NS_ERROR_FAILURE;
|
||||
|
||||
nsRangeStore *item;
|
||||
|
||||
for (i=0; i<theCount; i++)
|
||||
{
|
||||
item = (nsRangeStore*)aSelState.mArray.ElementAt(i);
|
||||
DropRangeItem(item);
|
||||
}
|
||||
|
||||
return NS_OK;;
|
||||
}
|
||||
|
||||
// gravity methods:
|
||||
|
||||
nsresult
|
||||
nsSelectionState::SelAdjCreateNode(nsIDOMNode *aParent, PRInt32 aPosition)
|
||||
nsRangeUpdater::SelAdjCreateNode(nsIDOMNode *aParent, PRInt32 aPosition)
|
||||
{
|
||||
if (mLock) return NS_OK; // lock set by Will/DidReplaceParent, etc...
|
||||
if (!aParent) return NS_ERROR_NULL_POINTER;
|
||||
PRInt32 i, count = mArray.Count();
|
||||
if (!count) return NS_OK;
|
||||
|
||||
SelRangeStore *item;
|
||||
nsRangeStore *item;
|
||||
|
||||
for (i=0; i<count; i++)
|
||||
{
|
||||
item = (SelRangeStore*)mArray.ElementAt(i);
|
||||
item = (nsRangeStore*)mArray.ElementAt(i);
|
||||
if (!item) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
if ((item->startNode.get() == aParent) && (item->startOffset > aPosition))
|
||||
|
@ -308,25 +417,25 @@ nsSelectionState::SelAdjCreateNode(nsIDOMNode *aParent, PRInt32 aPosition)
|
|||
}
|
||||
|
||||
nsresult
|
||||
nsSelectionState::SelAdjInsertNode(nsIDOMNode *aParent, PRInt32 aPosition)
|
||||
nsRangeUpdater::SelAdjInsertNode(nsIDOMNode *aParent, PRInt32 aPosition)
|
||||
{
|
||||
return SelAdjCreateNode(aParent, aPosition);
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsSelectionState::SelAdjDeleteNode(nsIDOMNode *aNode, nsIDOMNode *aParent, PRInt32 aOffset)
|
||||
nsRangeUpdater::SelAdjDeleteNode(nsIDOMNode *aNode, nsIDOMNode *aParent, PRInt32 aOffset)
|
||||
{
|
||||
if (mLock) return NS_OK; // lock set by Will/DidReplaceParent, etc...
|
||||
if (!aNode) return NS_ERROR_NULL_POINTER;
|
||||
PRInt32 i, count = mArray.Count();
|
||||
if (!count) return NS_OK;
|
||||
|
||||
SelRangeStore *item;
|
||||
nsRangeStore *item;
|
||||
|
||||
for (i=0; i<count; i++)
|
||||
{
|
||||
item = (SelRangeStore*)mArray.ElementAt(i);
|
||||
item = (nsRangeStore*)mArray.ElementAt(i);
|
||||
if (!item) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
if ((item->startNode.get() == aParent) && (item->startOffset > aOffset))
|
||||
|
@ -341,7 +450,7 @@ nsSelectionState::SelAdjDeleteNode(nsIDOMNode *aNode, nsIDOMNode *aParent, PRInt
|
|||
|
||||
|
||||
nsresult
|
||||
nsSelectionState::SelAdjSplitNode(nsIDOMNode *aOldRightNode, PRInt32 aOffset, nsIDOMNode *aNewLeftNode)
|
||||
nsRangeUpdater::SelAdjSplitNode(nsIDOMNode *aOldRightNode, PRInt32 aOffset, nsIDOMNode *aNewLeftNode)
|
||||
{
|
||||
if (mLock) return NS_OK; // lock set by Will/DidReplaceParent, etc...
|
||||
if (!aOldRightNode || !aNewLeftNode) return NS_ERROR_NULL_POINTER;
|
||||
|
@ -358,11 +467,11 @@ nsSelectionState::SelAdjSplitNode(nsIDOMNode *aOldRightNode, PRInt32 aOffset, ns
|
|||
if (NS_FAILED(result)) return result;
|
||||
|
||||
// next step is to check for range enpoints inside aOldRightNode
|
||||
SelRangeStore *item;
|
||||
nsRangeStore *item;
|
||||
|
||||
for (i=0; i<count; i++)
|
||||
{
|
||||
item = (SelRangeStore*)mArray.ElementAt(i);
|
||||
item = (nsRangeStore*)mArray.ElementAt(i);
|
||||
if (!item) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
if (item->startNode.get() == aOldRightNode)
|
||||
|
@ -393,7 +502,7 @@ nsSelectionState::SelAdjSplitNode(nsIDOMNode *aOldRightNode, PRInt32 aOffset, ns
|
|||
|
||||
|
||||
nsresult
|
||||
nsSelectionState::SelAdjJoinNodes(nsIDOMNode *aLeftNode,
|
||||
nsRangeUpdater::SelAdjJoinNodes(nsIDOMNode *aLeftNode,
|
||||
nsIDOMNode *aRightNode,
|
||||
nsIDOMNode *aParent,
|
||||
PRInt32 aOffset,
|
||||
|
@ -404,11 +513,11 @@ nsSelectionState::SelAdjJoinNodes(nsIDOMNode *aLeftNode,
|
|||
PRInt32 i, count = mArray.Count();
|
||||
if (!count) return NS_OK;
|
||||
|
||||
SelRangeStore *item;
|
||||
nsRangeStore *item;
|
||||
|
||||
for (i=0; i<count; i++)
|
||||
{
|
||||
item = (SelRangeStore*)mArray.ElementAt(i);
|
||||
item = (nsRangeStore*)mArray.ElementAt(i);
|
||||
if (!item) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
// adjust endpoints in aParent
|
||||
|
@ -450,7 +559,7 @@ nsSelectionState::SelAdjJoinNodes(nsIDOMNode *aLeftNode,
|
|||
|
||||
|
||||
nsresult
|
||||
nsSelectionState::SelAdjInsertText(nsIDOMCharacterData *aTextNode, PRInt32 aOffset, const nsString &aString)
|
||||
nsRangeUpdater::SelAdjInsertText(nsIDOMCharacterData *aTextNode, PRInt32 aOffset, const nsString &aString)
|
||||
{
|
||||
if (mLock) return NS_OK; // lock set by Will/DidReplaceParent, etc...
|
||||
return NS_OK;
|
||||
|
@ -458,7 +567,7 @@ nsSelectionState::SelAdjInsertText(nsIDOMCharacterData *aTextNode, PRInt32 aOffs
|
|||
|
||||
|
||||
nsresult
|
||||
nsSelectionState::SelAdjDeleteText(nsIDOMCharacterData *aTextNode, PRInt32 aOffset, PRInt32 aLength)
|
||||
nsRangeUpdater::SelAdjDeleteText(nsIDOMCharacterData *aTextNode, PRInt32 aOffset, PRInt32 aLength)
|
||||
{
|
||||
if (mLock) return NS_OK; // lock set by Will/DidReplaceParent, etc...
|
||||
return NS_OK;
|
||||
|
@ -466,7 +575,7 @@ nsSelectionState::SelAdjDeleteText(nsIDOMCharacterData *aTextNode, PRInt32 aOffs
|
|||
|
||||
|
||||
nsresult
|
||||
nsSelectionState::WillReplaceContainer()
|
||||
nsRangeUpdater::WillReplaceContainer()
|
||||
{
|
||||
if (mLock) return NS_ERROR_UNEXPECTED;
|
||||
mLock = PR_TRUE;
|
||||
|
@ -475,7 +584,7 @@ nsSelectionState::WillReplaceContainer()
|
|||
|
||||
|
||||
nsresult
|
||||
nsSelectionState::DidReplaceContainer(nsIDOMNode *aOriginalNode, nsIDOMNode *aNewNode)
|
||||
nsRangeUpdater::DidReplaceContainer(nsIDOMNode *aOriginalNode, nsIDOMNode *aNewNode)
|
||||
{
|
||||
if (!mLock) return NS_ERROR_UNEXPECTED;
|
||||
mLock = PR_FALSE;
|
||||
|
@ -484,11 +593,11 @@ nsSelectionState::DidReplaceContainer(nsIDOMNode *aOriginalNode, nsIDOMNode *aNe
|
|||
PRInt32 i, count = mArray.Count();
|
||||
if (!count) return NS_OK;
|
||||
|
||||
SelRangeStore *item;
|
||||
nsRangeStore *item;
|
||||
|
||||
for (i=0; i<count; i++)
|
||||
{
|
||||
item = (SelRangeStore*)mArray.ElementAt(i);
|
||||
item = (nsRangeStore*)mArray.ElementAt(i);
|
||||
if (!item) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
if (item->startNode.get() == aOriginalNode)
|
||||
|
@ -501,7 +610,7 @@ nsSelectionState::DidReplaceContainer(nsIDOMNode *aOriginalNode, nsIDOMNode *aNe
|
|||
|
||||
|
||||
nsresult
|
||||
nsSelectionState::WillRemoveContainer()
|
||||
nsRangeUpdater::WillRemoveContainer()
|
||||
{
|
||||
if (mLock) return NS_ERROR_UNEXPECTED;
|
||||
mLock = PR_TRUE;
|
||||
|
@ -510,7 +619,7 @@ nsSelectionState::WillRemoveContainer()
|
|||
|
||||
|
||||
nsresult
|
||||
nsSelectionState::DidRemoveContainer(nsIDOMNode *aNode, nsIDOMNode *aParent, PRInt32 aOffset, PRUint32 aNodeOrigLen)
|
||||
nsRangeUpdater::DidRemoveContainer(nsIDOMNode *aNode, nsIDOMNode *aParent, PRInt32 aOffset, PRUint32 aNodeOrigLen)
|
||||
{
|
||||
if (!mLock) return NS_ERROR_UNEXPECTED;
|
||||
mLock = PR_FALSE;
|
||||
|
@ -519,11 +628,11 @@ nsSelectionState::DidRemoveContainer(nsIDOMNode *aNode, nsIDOMNode *aParent, PRI
|
|||
PRInt32 i, count = mArray.Count();
|
||||
if (!count) return NS_OK;
|
||||
|
||||
SelRangeStore *item;
|
||||
nsRangeStore *item;
|
||||
|
||||
for (i=0; i<count; i++)
|
||||
{
|
||||
item = (SelRangeStore*)mArray.ElementAt(i);
|
||||
item = (nsRangeStore*)mArray.ElementAt(i);
|
||||
if (!item) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
if (item->startNode.get() == aNode)
|
||||
|
@ -546,7 +655,7 @@ nsSelectionState::DidRemoveContainer(nsIDOMNode *aNode, nsIDOMNode *aParent, PRI
|
|||
|
||||
|
||||
nsresult
|
||||
nsSelectionState::WillInsertContainer()
|
||||
nsRangeUpdater::WillInsertContainer()
|
||||
{
|
||||
if (mLock) return NS_ERROR_UNEXPECTED;
|
||||
mLock = PR_TRUE;
|
||||
|
@ -555,7 +664,7 @@ nsSelectionState::WillInsertContainer()
|
|||
|
||||
|
||||
nsresult
|
||||
nsSelectionState::DidInsertContainer()
|
||||
nsRangeUpdater::DidInsertContainer()
|
||||
{
|
||||
if (!mLock) return NS_ERROR_UNEXPECTED;
|
||||
mLock = PR_FALSE;
|
||||
|
@ -564,7 +673,7 @@ nsSelectionState::DidInsertContainer()
|
|||
|
||||
|
||||
nsresult
|
||||
nsSelectionState::WillMoveNode()
|
||||
nsRangeUpdater::WillMoveNode()
|
||||
{
|
||||
if (mLock) return NS_ERROR_UNEXPECTED;
|
||||
mLock = PR_TRUE;
|
||||
|
@ -573,7 +682,7 @@ nsSelectionState::WillMoveNode()
|
|||
|
||||
|
||||
nsresult
|
||||
nsSelectionState::DidMoveNode(nsIDOMNode *aOldParent, PRInt32 aOldOffset, nsIDOMNode *aNewParent, PRInt32 aNewOffset)
|
||||
nsRangeUpdater::DidMoveNode(nsIDOMNode *aOldParent, PRInt32 aOldOffset, nsIDOMNode *aNewParent, PRInt32 aNewOffset)
|
||||
{
|
||||
if (!mLock) return NS_ERROR_UNEXPECTED;
|
||||
mLock = PR_FALSE;
|
||||
|
@ -582,11 +691,11 @@ nsSelectionState::DidMoveNode(nsIDOMNode *aOldParent, PRInt32 aOldOffset, nsIDOM
|
|||
PRInt32 i, count = mArray.Count();
|
||||
if (!count) return NS_OK;
|
||||
|
||||
SelRangeStore *item;
|
||||
nsRangeStore *item;
|
||||
|
||||
for (i=0; i<count; i++)
|
||||
{
|
||||
item = (SelRangeStore*)mArray.ElementAt(i);
|
||||
item = (nsRangeStore*)mArray.ElementAt(i);
|
||||
if (!item) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
// like a delete in aOldParent
|
||||
|
@ -607,10 +716,21 @@ nsSelectionState::DidMoveNode(nsIDOMNode *aOldParent, PRInt32 aOldOffset, nsIDOM
|
|||
|
||||
|
||||
/***************************************************************************
|
||||
* helper class for nsSelectionState. SelRangeStore stores range endpoints.
|
||||
* helper class for nsSelectionState. nsRangeStore stores range endpoints.
|
||||
*/
|
||||
|
||||
nsresult SelRangeStore::StoreRange(nsIDOMRange *aRange)
|
||||
// DEBUG: PRInt32 nsRangeStore::n = 0;
|
||||
|
||||
nsRangeStore::nsRangeStore()
|
||||
{
|
||||
// DEBUG: n++; printf("range store alloc count=%d\n", n);
|
||||
}
|
||||
nsRangeStore::~nsRangeStore()
|
||||
{
|
||||
// DEBUG: n--; printf("range store alloc count=%d\n", n);
|
||||
}
|
||||
|
||||
nsresult nsRangeStore::StoreRange(nsIDOMRange *aRange)
|
||||
{
|
||||
if (!aRange) return NS_ERROR_NULL_POINTER;
|
||||
aRange->GetStartContainer(getter_AddRefs(startNode));
|
||||
|
@ -620,7 +740,7 @@ nsresult SelRangeStore::StoreRange(nsIDOMRange *aRange)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult SelRangeStore::GetRange(nsCOMPtr<nsIDOMRange> *outRange)
|
||||
nsresult nsRangeStore::GetRange(nsCOMPtr<nsIDOMRange> *outRange)
|
||||
{
|
||||
if (!outRange) return NS_ERROR_NULL_POINTER;
|
||||
nsresult res = nsComponentManager::CreateInstance(kCRangeCID,
|
||||
|
@ -644,22 +764,22 @@ nsresult SelRangeStore::GetRange(nsCOMPtr<nsIDOMRange> *outRange)
|
|||
class nsAutoReplaceContainerSelNotify
|
||||
{
|
||||
private:
|
||||
nsSelectionState *mSel;
|
||||
nsRangeUpdater &mRU;
|
||||
nsIDOMNode *mOriginalNode;
|
||||
nsIDOMNode *mNewNode;
|
||||
|
||||
public:
|
||||
nsAutoReplaceContainerSelNotify(nsSelectionState *aSelState, nsIDOMNode *aOriginalNode, nsIDOMNode *aNewNode) :
|
||||
mSel(aSelState)
|
||||
nsAutoReplaceContainerSelNotify(nsRangeUpdater &aRangeUpdater, nsIDOMNode *aOriginalNode, nsIDOMNode *aNewNode) :
|
||||
mRU(aRangeUpdater)
|
||||
,mOriginalNode(aOriginalNode)
|
||||
,mNewNode(aNewNode)
|
||||
{
|
||||
if (mSel) mSel->WillReplaceContainer();
|
||||
mRU.WillReplaceContainer();
|
||||
}
|
||||
|
||||
~nsAutoReplaceContainerSelNotify()
|
||||
{
|
||||
if (mSel) mSel->DidReplaceContainer(mOriginalNode, mNewNode);
|
||||
mRU.DidReplaceContainer(mOriginalNode, mNewNode);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -672,30 +792,30 @@ class nsAutoReplaceContainerSelNotify
|
|||
class nsAutoRemoveContainerSelNotify
|
||||
{
|
||||
private:
|
||||
nsSelectionState *mSel;
|
||||
nsRangeUpdater &mRU;
|
||||
nsIDOMNode *mNode;
|
||||
nsIDOMNode *mParent;
|
||||
PRInt32 mOffset;
|
||||
PRUint32 mNodeOrigLen;
|
||||
|
||||
public:
|
||||
nsAutoRemoveContainerSelNotify(nsSelectionState *aSelState,
|
||||
nsAutoRemoveContainerSelNotify(nsRangeUpdater &aRangeUpdater,
|
||||
nsIDOMNode *aNode,
|
||||
nsIDOMNode *aParent,
|
||||
PRInt32 aOffset,
|
||||
PRUint32 aNodeOrigLen) :
|
||||
mSel(aSelState)
|
||||
mRU(aRangeUpdater)
|
||||
,mNode(aNode)
|
||||
,mParent(aParent)
|
||||
,mOffset(aOffset)
|
||||
,mNodeOrigLen(aNodeOrigLen)
|
||||
{
|
||||
if (mSel) mSel->WillRemoveContainer();
|
||||
mRU.WillRemoveContainer();
|
||||
}
|
||||
|
||||
~nsAutoRemoveContainerSelNotify()
|
||||
{
|
||||
if (mSel) mSel->DidRemoveContainer(mNode, mParent, mOffset, mNodeOrigLen);
|
||||
mRU.DidRemoveContainer(mNode, mParent, mOffset, mNodeOrigLen);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -707,18 +827,18 @@ class nsAutoRemoveContainerSelNotify
|
|||
class nsAutoInsertContainerSelNotify
|
||||
{
|
||||
private:
|
||||
nsSelectionState *mSel;
|
||||
nsRangeUpdater &mRU;
|
||||
|
||||
public:
|
||||
nsAutoInsertContainerSelNotify(nsSelectionState *aSelState) :
|
||||
mSel(aSelState)
|
||||
nsAutoInsertContainerSelNotify(nsRangeUpdater &aRangeUpdater) :
|
||||
mRU(aRangeUpdater)
|
||||
{
|
||||
if (mSel) mSel->WillInsertContainer();
|
||||
mRU.WillInsertContainer();
|
||||
}
|
||||
|
||||
~nsAutoInsertContainerSelNotify()
|
||||
{
|
||||
if (mSel) mSel->DidInsertContainer();
|
||||
mRU.DidInsertContainer();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -731,30 +851,30 @@ class nsAutoInsertContainerSelNotify
|
|||
class nsAutoMoveNodeSelNotify
|
||||
{
|
||||
private:
|
||||
nsSelectionState *mSel;
|
||||
nsRangeUpdater &mRU;
|
||||
nsIDOMNode *mOldParent;
|
||||
nsIDOMNode *mNewParent;
|
||||
PRInt32 mOldOffset;
|
||||
PRInt32 mNewOffset;
|
||||
|
||||
public:
|
||||
nsAutoMoveNodeSelNotify(nsSelectionState *aSelState,
|
||||
nsAutoMoveNodeSelNotify(nsRangeUpdater &aRangeUpdater,
|
||||
nsIDOMNode *aOldParent,
|
||||
PRInt32 aOldOffset,
|
||||
nsIDOMNode *aNewParent,
|
||||
PRInt32 aNewOffset) :
|
||||
mSel(aSelState)
|
||||
mRU(aRangeUpdater)
|
||||
,mOldParent(aOldParent)
|
||||
,mNewParent(aNewParent)
|
||||
,mOldOffset(aOldOffset)
|
||||
,mNewOffset(aNewOffset)
|
||||
{
|
||||
if (mSel) mSel->WillMoveNode();
|
||||
mRU.WillMoveNode();
|
||||
}
|
||||
|
||||
~nsAutoMoveNodeSelNotify()
|
||||
{
|
||||
if (mSel) mSel->DidMoveNode(mOldParent, mOldOffset, mNewParent, mNewOffset);
|
||||
mRU.DidMoveNode(mOldParent, mOldOffset, mNewParent, mNewOffset);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -774,7 +894,8 @@ nsEditor::nsEditor()
|
|||
, mPlaceHolderName(nsnull)
|
||||
, mPlaceHolderBatch(0)
|
||||
, mSelState(nsnull)
|
||||
, mSavedSel(nsnull)
|
||||
, mSavedSel()
|
||||
, mRangeUpdater()
|
||||
, mShouldTxnSetSelection(PR_TRUE)
|
||||
, mBodyElement(nsnull)
|
||||
, mInIMEMode(PR_FALSE)
|
||||
|
@ -1595,7 +1716,7 @@ NS_IMETHODIMP nsEditor::CreateNode(const nsString& aTag,
|
|||
// The transaction system (if any) has taken ownwership of txn
|
||||
NS_IF_RELEASE(txn);
|
||||
|
||||
if (mSavedSel) mSavedSel->SelAdjCreateNode(aParent, aPosition);
|
||||
mRangeUpdater.SelAdjCreateNode(aParent, aPosition);
|
||||
|
||||
if (mActionListeners)
|
||||
{
|
||||
|
@ -1637,7 +1758,7 @@ NS_IMETHODIMP nsEditor::InsertNode(nsIDOMNode * aNode,
|
|||
// The transaction system (if any) has taken ownwership of txn
|
||||
NS_IF_RELEASE(txn);
|
||||
|
||||
if (mSavedSel) mSavedSel->SelAdjInsertNode(aParent, aPosition);
|
||||
mRangeUpdater.SelAdjInsertNode(aParent, aPosition);
|
||||
|
||||
if (mActionListeners)
|
||||
{
|
||||
|
@ -1686,7 +1807,7 @@ nsEditor::SplitNode(nsIDOMNode * aNode,
|
|||
// The transaction system (if any) has taken ownwership of txn
|
||||
NS_IF_RELEASE(txn);
|
||||
|
||||
if (mSavedSel) mSavedSel->SelAdjSplitNode(aNode, aOffset, *aNewLeftNode);
|
||||
mRangeUpdater.SelAdjSplitNode(aNode, aOffset, *aNewLeftNode);
|
||||
|
||||
if (mActionListeners)
|
||||
{
|
||||
|
@ -1743,7 +1864,7 @@ nsEditor::JoinNodes(nsIDOMNode * aLeftNode,
|
|||
// The transaction system (if any) has taken ownwership of txn
|
||||
NS_IF_RELEASE(txn);
|
||||
|
||||
if (mSavedSel) mSavedSel->SelAdjJoinNodes(aLeftNode, aRightNode, aParent, offset, (PRInt32)oldLeftNodeLen);
|
||||
mRangeUpdater.SelAdjJoinNodes(aLeftNode, aRightNode, aParent, offset, (PRInt32)oldLeftNodeLen);
|
||||
|
||||
if (mActionListeners)
|
||||
{
|
||||
|
@ -1789,7 +1910,7 @@ NS_IMETHODIMP nsEditor::DeleteNode(nsIDOMNode * aElement)
|
|||
// The transaction system (if any) has taken ownwership of txn
|
||||
NS_IF_RELEASE(txn);
|
||||
|
||||
if (mSavedSel) mSavedSel->SelAdjDeleteNode(aElement, parent, offset);
|
||||
mRangeUpdater.SelAdjDeleteNode(aElement, parent, offset);
|
||||
|
||||
if (mActionListeners)
|
||||
{
|
||||
|
@ -1856,8 +1977,8 @@ nsEditor::ReplaceContainer(nsIDOMNode *inNode,
|
|||
|
||||
// notify our internal selection state listener
|
||||
// (Note: A nsAutoSelectionReset object must be created
|
||||
// before calling this to initialize mSavedSel)
|
||||
nsAutoReplaceContainerSelNotify selStateNotify(mSavedSel, inNode, *outNode);
|
||||
// before calling this to initialize mRangeUpdater)
|
||||
nsAutoReplaceContainerSelNotify selStateNotify(mRangeUpdater, inNode, *outNode);
|
||||
|
||||
nsCOMPtr<nsIDOMNode> child;
|
||||
PRBool bHasMoreChildren;
|
||||
|
@ -1908,7 +2029,7 @@ nsEditor::RemoveContainer(nsIDOMNode *inNode)
|
|||
nodeList->GetLength(&nodeOrigLen);
|
||||
|
||||
// notify our internal selection state listener
|
||||
nsAutoRemoveContainerSelNotify selNotify(mSavedSel, inNode, parent, offset, nodeOrigLen);
|
||||
nsAutoRemoveContainerSelNotify selNotify(mRangeUpdater, inNode, parent, offset, nodeOrigLen);
|
||||
|
||||
nsCOMPtr<nsIDOMNode> child;
|
||||
while (bHasMoreChildren)
|
||||
|
@ -1970,7 +2091,7 @@ nsEditor::InsertContainerAbove( nsIDOMNode *inNode,
|
|||
}
|
||||
|
||||
// notify our internal selection state listener
|
||||
nsAutoInsertContainerSelNotify selNotify(mSavedSel);
|
||||
nsAutoInsertContainerSelNotify selNotify(mRangeUpdater);
|
||||
|
||||
// put inNode in new parent, outNode
|
||||
res = DeleteNode(inNode);
|
||||
|
@ -2009,7 +2130,7 @@ nsEditor::MoveNode(nsIDOMNode *aNode, nsIDOMNode *aParent, PRInt32 aOffset)
|
|||
if ((aParent == oldParent.get()) && (oldOffset == aOffset)) return NS_OK;
|
||||
|
||||
// notify our internal selection state listener
|
||||
nsAutoMoveNodeSelNotify selNotify(mSavedSel, oldParent, oldOffset, aParent, aOffset);
|
||||
nsAutoMoveNodeSelNotify selNotify(mRangeUpdater, oldParent, oldOffset, aParent, aOffset);
|
||||
|
||||
// need to adjust aOffset if we are moving aNode further along in it's current parent
|
||||
if ((aParent == oldParent.get()) && (oldOffset < aOffset))
|
||||
|
@ -2250,6 +2371,44 @@ nsEditor::DebugUnitTests(PRInt32 *outNumTests, PRInt32 *outNumTestsFailed)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
#ifdef XP_MAC
|
||||
#pragma mark -
|
||||
#pragma mark support for selection preservation
|
||||
#pragma mark -
|
||||
#endif
|
||||
|
||||
PRBool
|
||||
nsEditor::ArePreservingSelection()
|
||||
{
|
||||
if (mSavedSel.IsEmpty()) return PR_FALSE;
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsEditor::PreserveSelectionAcrossActions(nsIDOMSelection *aSel)
|
||||
{
|
||||
mSavedSel.SaveSelection(aSel);
|
||||
mRangeUpdater.RegisterSelectionState(mSavedSel);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsEditor::RestorePreservedSelection(nsIDOMSelection *aSel)
|
||||
{
|
||||
if (mSavedSel.IsEmpty()) return NS_ERROR_FAILURE;
|
||||
mSavedSel.RestoreSelection(aSel);
|
||||
StopPreservingSelection();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsEditor::StopPreservingSelection()
|
||||
{
|
||||
mRangeUpdater.DropSelectionState(mSavedSel);
|
||||
mSavedSel.MakeEmpty();
|
||||
}
|
||||
|
||||
|
||||
#ifdef XP_MAC
|
||||
#pragma mark -
|
||||
#pragma mark nsIEditorIMESupport
|
||||
|
@ -4985,6 +5144,7 @@ nsEditor::SplitNodeDeep(nsIDOMNode *aNode,
|
|||
nsIDOMNode *aSplitPointParent,
|
||||
PRInt32 aSplitPointOffset,
|
||||
PRInt32 *outOffset,
|
||||
PRBool aNoEmptyContainers,
|
||||
nsCOMPtr<nsIDOMNode> *outLeftNode,
|
||||
nsCOMPtr<nsIDOMNode> *outRightNode)
|
||||
{
|
||||
|
@ -5006,12 +5166,12 @@ nsEditor::SplitNodeDeep(nsIDOMNode *aNode,
|
|||
// this nsEditor routine.
|
||||
|
||||
nsCOMPtr<nsIDOMCharacterData> nodeAsText = do_QueryInterface(nodeToSplit);
|
||||
PRUint32 textLen=0;
|
||||
if (nodeAsText)
|
||||
nodeAsText->GetLength(&textLen);
|
||||
PRUint32 len;
|
||||
PRBool bDoSplit = PR_FALSE;
|
||||
res = GetLengthOfDOMNode(nodeToSplit, len);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
if (!nodeAsText || (offset && (offset != (PRInt32)textLen)))
|
||||
if (!(aNoEmptyContainers || nodeAsText) || (offset && (offset != (PRInt32)len)))
|
||||
{
|
||||
bDoSplit = PR_TRUE;
|
||||
res = SplitNode(nodeToSplit, offset, getter_AddRefs(tempNode));
|
||||
|
|
|
@ -80,8 +80,10 @@ class nsISelectionController;
|
|||
*/
|
||||
|
||||
// first a helper struct for saving/setting ranges
|
||||
struct SelRangeStore
|
||||
struct nsRangeStore
|
||||
{
|
||||
nsRangeStore();
|
||||
~nsRangeStore();
|
||||
nsresult StoreRange(nsIDOMRange *aRange);
|
||||
nsresult GetRange(nsCOMPtr<nsIDOMRange> *outRange);
|
||||
|
||||
|
@ -89,6 +91,7 @@ struct SelRangeStore
|
|||
PRInt32 startOffset;
|
||||
nsCOMPtr<nsIDOMNode> endNode;
|
||||
PRInt32 endOffset;
|
||||
// DEBUG: static PRInt32 n;
|
||||
};
|
||||
|
||||
class nsSelectionState
|
||||
|
@ -104,6 +107,26 @@ class nsSelectionState
|
|||
PRBool IsEqual(nsSelectionState *aSelState);
|
||||
void MakeEmpty();
|
||||
PRBool IsEmpty();
|
||||
protected:
|
||||
nsVoidArray mArray;
|
||||
|
||||
friend class nsRangeUpdater;
|
||||
};
|
||||
|
||||
class nsRangeUpdater
|
||||
{
|
||||
public:
|
||||
|
||||
nsRangeUpdater();
|
||||
~nsRangeUpdater();
|
||||
|
||||
void* RegisterRange(nsIDOMRange *aRange);
|
||||
nsCOMPtr<nsIDOMRange> ReclaimRange(void *aCookie);
|
||||
void DropRange(void *aCookie);
|
||||
void RegisterRangeItem(nsRangeStore *aRangeItem);
|
||||
void DropRangeItem(nsRangeStore *aRangeItem);
|
||||
nsresult RegisterSelectionState(nsSelectionState &aSelState);
|
||||
nsresult DropSelectionState(nsSelectionState &aSelState);
|
||||
|
||||
// editor selection gravity routines. Note that we can't always depend on
|
||||
// DOM Range gravity to do what we want to the "real" selection. For instance,
|
||||
|
@ -131,7 +154,7 @@ class nsSelectionState
|
|||
nsresult DidInsertContainer();
|
||||
nsresult WillMoveNode();
|
||||
nsresult DidMoveNode(nsIDOMNode *aOldParent, PRInt32 aOldOffset, nsIDOMNode *aNewParent, PRInt32 aNewOffset);
|
||||
|
||||
protected:
|
||||
nsVoidArray mArray;
|
||||
PRBool mLock;
|
||||
};
|
||||
|
@ -483,6 +506,14 @@ public:
|
|||
* with a call to EndOperation */
|
||||
NS_IMETHOD EndOperation();
|
||||
|
||||
/** routines for managing the preservation of selection across
|
||||
* various editor actions */
|
||||
PRBool ArePreservingSelection();
|
||||
nsresult PreserveSelectionAcrossActions(nsIDOMSelection *aSel);
|
||||
nsresult RestorePreservedSelection(nsIDOMSelection *aSel);
|
||||
void StopPreservingSelection();
|
||||
|
||||
|
||||
/** return the string that represents text nodes in the content tree */
|
||||
static nsresult GetTextNodeTag(nsString& aOutString);
|
||||
|
||||
|
@ -725,6 +756,7 @@ public:
|
|||
nsIDOMNode *aSplitPointParent,
|
||||
PRInt32 aSplitPointOffset,
|
||||
PRInt32 *outOffset,
|
||||
PRBool aNoEmptyContainers = PR_FALSE,
|
||||
nsCOMPtr<nsIDOMNode> *outLeftNode = 0,
|
||||
nsCOMPtr<nsIDOMNode> *outRightNode = 0);
|
||||
nsresult JoinNodeDeep(nsIDOMNode *aLeftNode, nsIDOMNode *aRightNode, nsCOMPtr<nsIDOMNode> *aOutJoinNode, PRInt32 *outOffset);
|
||||
|
@ -748,15 +780,16 @@ protected:
|
|||
nsCOMPtr<nsITransactionManager> mTxnMgr;
|
||||
nsCOMPtr<nsIEditProperty> mEditProperty;
|
||||
nsCOMPtr<nsICSSStyleSheet> mLastStyleSheet; // is owning this dangerous?
|
||||
nsWeakPtr mPlaceHolderTxn; // weak reference to placeholder for begin/end batch purposes
|
||||
nsIAtom *mPlaceHolderName; // name of placeholder transaction
|
||||
PRInt32 mPlaceHolderBatch; // nesting count for batching
|
||||
nsSelectionState *mSelState; // saved selection state for placeholder txn batching
|
||||
nsSelectionState *mSavedSel; // cached selection for nsAutoSelectionReset
|
||||
PRBool mShouldTxnSetSelection; // turn off for conservative selection adjustment by txns
|
||||
nsWeakPtr mPlaceHolderTxn; // weak reference to placeholder for begin/end batch purposes
|
||||
nsIAtom *mPlaceHolderName; // name of placeholder transaction
|
||||
PRInt32 mPlaceHolderBatch; // nesting count for batching
|
||||
nsSelectionState *mSelState; // saved selection state for placeholder txn batching
|
||||
nsSelectionState mSavedSel; // cached selection for nsAutoSelectionReset
|
||||
nsRangeUpdater mRangeUpdater; // utility class object for maintaining preserved ranges
|
||||
PRBool mShouldTxnSetSelection; // turn off for conservative selection adjustment by txns
|
||||
nsCOMPtr<nsIDOMElement> mBodyElement; // cached body node
|
||||
PRInt32 mAction; // the current editor action
|
||||
EDirection mDirection; // the current direction of editor action
|
||||
PRInt32 mAction; // the current editor action
|
||||
EDirection mDirection; // the current direction of editor action
|
||||
|
||||
// data necessary to build IME transactions
|
||||
PRBool mInIMEMode; // are we inside an IME composition?
|
||||
|
|
|
@ -23,6 +23,9 @@
|
|||
|
||||
#include "nsEditorUtils.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsIDOMRange.h"
|
||||
#include "nsIContent.h"
|
||||
#include "nsLayoutCID.h"
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
|
@ -34,24 +37,162 @@ mSel(nsnull)
|
|||
,mEd(nsnull)
|
||||
{
|
||||
if (!aSel || !aEd) return; // not much we can do, bail.
|
||||
if (aEd->mSavedSel) return; // we already have initted mSavedSel, so this must be nested call.
|
||||
if (aEd->ArePreservingSelection()) return; // we already have initted mSavedSel, so this must be nested call.
|
||||
mSel = do_QueryInterface(aSel);
|
||||
mEd = aEd;
|
||||
if (mSel)
|
||||
{
|
||||
mEd->mSavedSel = new nsSelectionState();
|
||||
mEd->mSavedSel->SaveSelection(mSel);
|
||||
mEd->PreserveSelectionAcrossActions(mSel);
|
||||
}
|
||||
}
|
||||
|
||||
nsAutoSelectionReset::~nsAutoSelectionReset()
|
||||
{
|
||||
if (mSel && mEd->mSavedSel) // mSel will be null if this was nested call
|
||||
if (mSel && mEd->ArePreservingSelection()) // mSel will be null if this was nested call
|
||||
{
|
||||
mEd->mSavedSel->RestoreSelection(mSel);
|
||||
delete mEd->mSavedSel;
|
||||
mEd->mSavedSel = nsnull;
|
||||
mEd->RestorePreservedSelection(mSel);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsAutoSelectionReset::Abort()
|
||||
{
|
||||
mEd->StopPreservingSelection();
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* some helper classes for iterating the dom tree
|
||||
*****************************************************************************/
|
||||
|
||||
static NS_DEFINE_IID(kSubtreeIteratorCID, NS_SUBTREEITERATOR_CID);
|
||||
static NS_DEFINE_IID(kContentIteratorCID, NS_CONTENTITERATOR_CID);
|
||||
|
||||
nsDOMIterator::nsDOMIterator() :
|
||||
mIter(nsnull)
|
||||
{
|
||||
}
|
||||
|
||||
nsDOMIterator::~nsDOMIterator()
|
||||
{
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMIterator::Init(nsIDOMRange* aRange)
|
||||
{
|
||||
nsresult res = nsComponentManager::CreateInstance(kContentIteratorCID,
|
||||
nsnull,
|
||||
NS_GET_IID(nsIContentIterator),
|
||||
getter_AddRefs(mIter));
|
||||
if (NS_FAILED(res)) return res;
|
||||
return mIter->Init(aRange);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMIterator::Init(nsIDOMNode* aNode)
|
||||
{
|
||||
nsresult res = nsComponentManager::CreateInstance(kContentIteratorCID,
|
||||
nsnull,
|
||||
NS_GET_IID(nsIContentIterator),
|
||||
getter_AddRefs(mIter));
|
||||
if (NS_FAILED(res)) return res;
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(aNode);
|
||||
return mIter->Init(content);
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMIterator::ForEach(nsDomIterFunctor& functor) const
|
||||
{
|
||||
nsCOMPtr<nsIContent> content;
|
||||
nsCOMPtr<nsIDOMNode> node;
|
||||
nsCOMPtr<nsISupports> isupports;
|
||||
nsresult res;
|
||||
|
||||
// iterate through dom
|
||||
while (NS_ENUMERATOR_FALSE == mIter->IsDone())
|
||||
{
|
||||
res = mIter->CurrentNode(getter_AddRefs(content));
|
||||
if (NS_FAILED(res)) return;
|
||||
node = do_QueryInterface(content);
|
||||
if (!node) return;
|
||||
functor(node);
|
||||
res = mIter->Next();
|
||||
if (NS_FAILED(res)) return;
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMIterator::MakeList(nsBoolDomIterFunctor& functor,
|
||||
nsCOMPtr<nsISupportsArray> *outArrayOfNodes) const
|
||||
{
|
||||
nsCOMPtr<nsIContent> content;
|
||||
nsCOMPtr<nsIDOMNode> node;
|
||||
nsCOMPtr<nsISupports> isupports;
|
||||
nsresult res;
|
||||
|
||||
// make a array
|
||||
res = NS_NewISupportsArray(getter_AddRefs(*outArrayOfNodes));
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
return AppendList(functor, *outArrayOfNodes);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMIterator::AppendList(nsBoolDomIterFunctor& functor,
|
||||
nsCOMPtr<nsISupportsArray> arrayOfNodes) const
|
||||
{
|
||||
if (!arrayOfNodes) return NS_ERROR_NULL_POINTER;
|
||||
nsCOMPtr<nsIContent> content;
|
||||
nsCOMPtr<nsIDOMNode> node;
|
||||
nsCOMPtr<nsISupports> isupports;
|
||||
nsresult res;
|
||||
|
||||
// iterate through dom and build list
|
||||
while (NS_ENUMERATOR_FALSE == mIter->IsDone())
|
||||
{
|
||||
res = mIter->CurrentNode(getter_AddRefs(content));
|
||||
if (NS_FAILED(res)) return res;
|
||||
node = do_QueryInterface(content);
|
||||
if (!node) return NS_ERROR_NULL_POINTER;
|
||||
if (functor(node))
|
||||
{
|
||||
isupports = do_QueryInterface(node);
|
||||
arrayOfNodes->AppendElement(isupports);
|
||||
}
|
||||
res = mIter->Next();
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsDOMSubtreeIterator::nsDOMSubtreeIterator()
|
||||
{
|
||||
}
|
||||
|
||||
nsDOMSubtreeIterator::~nsDOMSubtreeIterator()
|
||||
{
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMSubtreeIterator::Init(nsIDOMRange* aRange)
|
||||
{
|
||||
nsresult res = nsComponentManager::CreateInstance(kSubtreeIteratorCID,
|
||||
nsnull,
|
||||
NS_GET_IID(nsIContentIterator),
|
||||
getter_AddRefs(mIter));
|
||||
if (NS_FAILED(res)) return res;
|
||||
return mIter->Init(aRange);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMSubtreeIterator::Init(nsIDOMNode* aNode)
|
||||
{
|
||||
nsresult res = nsComponentManager::CreateInstance(kSubtreeIteratorCID,
|
||||
nsnull,
|
||||
NS_GET_IID(nsIContentIterator),
|
||||
getter_AddRefs(mIter));
|
||||
if (NS_FAILED(res)) return res;
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(aNode);
|
||||
return mIter->Init(content);
|
||||
}
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include "nsIAtom.h"
|
||||
#include "nsVoidArray.h"
|
||||
#include "nsEditor.h"
|
||||
#include "nsIContentIterator.h"
|
||||
|
||||
/***************************************************************************
|
||||
* stack based helper class for batching a collection of txns inside a
|
||||
|
@ -77,6 +78,9 @@ class nsAutoSelectionReset
|
|||
|
||||
/** destructor restores mSel to its former state */
|
||||
~nsAutoSelectionReset();
|
||||
|
||||
/** Abort: cancel selection saver */
|
||||
void Abort();
|
||||
};
|
||||
|
||||
/***************************************************************************
|
||||
|
@ -139,5 +143,47 @@ class nsAutoTxnsConserveSelection
|
|||
PRBool mOldState;
|
||||
};
|
||||
|
||||
/******************************************************************************
|
||||
* some helper classes for iterating the dom tree
|
||||
*****************************************************************************/
|
||||
|
||||
class nsDomIterFunctor
|
||||
{
|
||||
public:
|
||||
virtual void* operator()(nsIDOMNode* aNode)=0;
|
||||
};
|
||||
|
||||
class nsBoolDomIterFunctor
|
||||
{
|
||||
public:
|
||||
virtual PRBool operator()(nsIDOMNode* aNode)=0;
|
||||
};
|
||||
|
||||
class nsDOMIterator
|
||||
{
|
||||
public:
|
||||
nsDOMIterator();
|
||||
virtual ~nsDOMIterator();
|
||||
|
||||
nsresult Init(nsIDOMRange* aRange);
|
||||
nsresult Init(nsIDOMNode* aNode);
|
||||
void ForEach(nsDomIterFunctor& functor) const;
|
||||
nsresult MakeList(nsBoolDomIterFunctor& functor,
|
||||
nsCOMPtr<nsISupportsArray> *outArrayOfNodes) const;
|
||||
nsresult AppendList(nsBoolDomIterFunctor& functor,
|
||||
nsCOMPtr<nsISupportsArray> arrayOfNodes) const;
|
||||
protected:
|
||||
nsCOMPtr<nsIContentIterator> mIter;
|
||||
};
|
||||
|
||||
class nsDOMSubtreeIterator : public nsDOMIterator
|
||||
{
|
||||
public:
|
||||
nsDOMSubtreeIterator();
|
||||
virtual ~nsDOMSubtreeIterator();
|
||||
|
||||
nsresult Init(nsIDOMRange* aRange);
|
||||
nsresult Init(nsIDOMNode* aNode);
|
||||
};
|
||||
|
||||
#endif // nsEditorUtils_h__
|
||||
|
|
|
@ -122,14 +122,14 @@ nsresult TypeInState::SetProp(nsIAtom *aProp, const nsString &aAttr, const nsStr
|
|||
}
|
||||
|
||||
// if it's already set we are done
|
||||
if (IsPropSet(aProp,aAttr,aValue)) return NS_OK;
|
||||
if (IsPropSet(aProp,aAttr,nsnull)) return NS_OK;
|
||||
|
||||
// make a new propitem
|
||||
PropItem *item = new PropItem(aProp,aAttr,aValue);
|
||||
if (!item) return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
// remove it from the list of cleared properties, if we have a match
|
||||
RemovePropFromClearedList(aProp,aAttr,aValue);
|
||||
RemovePropFromClearedList(aProp,aAttr);
|
||||
|
||||
// add it to the list of set properties
|
||||
mSetArray.AppendElement((void*)item);
|
||||
|
@ -141,30 +141,25 @@ nsresult TypeInState::SetProp(nsIAtom *aProp, const nsString &aAttr, const nsStr
|
|||
nsresult TypeInState::ClearAllProps()
|
||||
{
|
||||
// null prop means "all" props
|
||||
return ClearProp(nsnull,nsAutoString(),nsAutoString());
|
||||
return ClearProp(nsnull,nsAutoString());
|
||||
}
|
||||
|
||||
nsresult TypeInState::ClearProp(nsIAtom *aProp)
|
||||
{
|
||||
return ClearProp(aProp,nsAutoString(),nsAutoString());
|
||||
return ClearProp(aProp,nsAutoString());
|
||||
}
|
||||
|
||||
nsresult TypeInState::ClearProp(nsIAtom *aProp, const nsString &aAttr)
|
||||
{
|
||||
return ClearProp(aProp,aAttr,nsAutoString());
|
||||
}
|
||||
|
||||
nsresult TypeInState::ClearProp(nsIAtom *aProp, const nsString &aAttr, const nsString &aValue)
|
||||
{
|
||||
// if it's already cleared we are done
|
||||
if (IsPropCleared(aProp,aAttr,aValue)) return NS_OK;
|
||||
if (IsPropCleared(aProp,aAttr)) return NS_OK;
|
||||
|
||||
// make a new propitem
|
||||
PropItem *item = new PropItem(aProp,aAttr,aValue);
|
||||
PropItem *item = new PropItem(aProp,aAttr,nsAutoString());
|
||||
if (!item) return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
// remove it from the list of set properties, if we have a match
|
||||
RemovePropFromSetList(aProp,aAttr,aValue);
|
||||
RemovePropFromSetList(aProp,aAttr);
|
||||
|
||||
// add it to the list of cleared properties
|
||||
mClearedArray.AppendElement((void*)item);
|
||||
|
@ -222,7 +217,7 @@ nsresult TypeInState::TakeRelativeFontSize(PRInt32 *outRelSize)
|
|||
|
||||
nsresult TypeInState::GetTypingState(PRBool &isSet, PRBool &theSetting, nsIAtom *aProp)
|
||||
{
|
||||
return GetTypingState(isSet, theSetting, aProp, nsAutoString(), nsAutoString());
|
||||
return GetTypingState(isSet, theSetting, aProp, nsAutoString(), nsnull);
|
||||
}
|
||||
|
||||
nsresult TypeInState::GetTypingState(PRBool &isSet,
|
||||
|
@ -230,7 +225,7 @@ nsresult TypeInState::GetTypingState(PRBool &isSet,
|
|||
nsIAtom *aProp,
|
||||
const nsString &aAttr)
|
||||
{
|
||||
return GetTypingState(isSet, theSetting, aProp, aAttr, nsAutoString());
|
||||
return GetTypingState(isSet, theSetting, aProp, aAttr, nsnull);
|
||||
}
|
||||
|
||||
|
||||
|
@ -238,14 +233,14 @@ nsresult TypeInState::GetTypingState(PRBool &isSet,
|
|||
PRBool &theSetting,
|
||||
nsIAtom *aProp,
|
||||
const nsString &aAttr,
|
||||
const nsString &aValue)
|
||||
nsString *aValue)
|
||||
{
|
||||
if (IsPropSet(aProp, aAttr, aValue))
|
||||
{
|
||||
isSet = PR_TRUE;
|
||||
theSetting = PR_TRUE;
|
||||
}
|
||||
else if (IsPropCleared(aProp, aAttr, aValue))
|
||||
else if (IsPropCleared(aProp, aAttr))
|
||||
{
|
||||
isSet = PR_TRUE;
|
||||
theSetting = PR_FALSE;
|
||||
|
@ -264,8 +259,7 @@ nsresult TypeInState::GetTypingState(PRBool &isSet,
|
|||
*******************************************************************/
|
||||
|
||||
nsresult TypeInState::RemovePropFromSetList(nsIAtom *aProp,
|
||||
const nsString &aAttr,
|
||||
const nsString &aValue)
|
||||
const nsString &aAttr)
|
||||
{
|
||||
PRInt32 index;
|
||||
PropItem *item;
|
||||
|
@ -282,7 +276,7 @@ nsresult TypeInState::RemovePropFromSetList(nsIAtom *aProp,
|
|||
if (item) delete item;
|
||||
}
|
||||
}
|
||||
else if (FindPropInList(aProp, aAttr, aValue, mSetArray, index))
|
||||
else if (FindPropInList(aProp, aAttr, nsnull, mSetArray, index))
|
||||
{
|
||||
item = (PropItem*)mSetArray.ElementAt(index);
|
||||
mSetArray.RemoveElementAt(index);
|
||||
|
@ -293,11 +287,10 @@ nsresult TypeInState::RemovePropFromSetList(nsIAtom *aProp,
|
|||
|
||||
|
||||
nsresult TypeInState::RemovePropFromClearedList(nsIAtom *aProp,
|
||||
const nsString &aAttr,
|
||||
const nsString &aValue)
|
||||
const nsString &aAttr)
|
||||
{
|
||||
PRInt32 index;
|
||||
if (FindPropInList(aProp, aAttr, aValue, mClearedArray, index))
|
||||
if (FindPropInList(aProp, aAttr, nsnull, mClearedArray, index))
|
||||
{
|
||||
PropItem *item = (PropItem*)mClearedArray.ElementAt(index);
|
||||
mClearedArray.RemoveElementAt(index);
|
||||
|
@ -309,16 +302,16 @@ nsresult TypeInState::RemovePropFromClearedList(nsIAtom *aProp,
|
|||
|
||||
PRBool TypeInState::IsPropSet(nsIAtom *aProp,
|
||||
const nsString &aAttr,
|
||||
const nsString &aValue)
|
||||
nsString* outValue)
|
||||
{
|
||||
PRInt32 i;
|
||||
return IsPropSet(aProp, aAttr, aValue, i);
|
||||
return IsPropSet(aProp, aAttr, outValue, i);
|
||||
}
|
||||
|
||||
|
||||
PRBool TypeInState::IsPropSet(nsIAtom *aProp,
|
||||
const nsString &aAttr,
|
||||
const nsString &aValue,
|
||||
nsString *outValue,
|
||||
PRInt32 &outIndex)
|
||||
{
|
||||
// linear search. list should be short.
|
||||
|
@ -329,6 +322,7 @@ PRBool TypeInState::IsPropSet(nsIAtom *aProp,
|
|||
if ( (item->tag == aProp) &&
|
||||
(item->attr == aAttr) )
|
||||
{
|
||||
if (outValue) *outValue = item->value;
|
||||
outIndex = i;
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
@ -338,22 +332,20 @@ PRBool TypeInState::IsPropSet(nsIAtom *aProp,
|
|||
|
||||
|
||||
PRBool TypeInState::IsPropCleared(nsIAtom *aProp,
|
||||
const nsString &aAttr,
|
||||
const nsString &aValue)
|
||||
const nsString &aAttr)
|
||||
{
|
||||
PRInt32 i;
|
||||
return IsPropCleared(aProp, aAttr, aValue, i);
|
||||
return IsPropCleared(aProp, aAttr, i);
|
||||
}
|
||||
|
||||
|
||||
PRBool TypeInState::IsPropCleared(nsIAtom *aProp,
|
||||
const nsString &aAttr,
|
||||
const nsString &aValue,
|
||||
PRInt32 &outIndex)
|
||||
{
|
||||
if (FindPropInList(aProp, aAttr, aValue, mClearedArray, outIndex))
|
||||
if (FindPropInList(aProp, aAttr, nsnull, mClearedArray, outIndex))
|
||||
return PR_TRUE;
|
||||
if (FindPropInList(0, nsAutoString(), nsAutoString(), mClearedArray, outIndex))
|
||||
if (FindPropInList(0, nsAutoString(), nsnull, mClearedArray, outIndex))
|
||||
{
|
||||
// special case for all props cleared
|
||||
outIndex = -1;
|
||||
|
@ -364,7 +356,7 @@ PRBool TypeInState::IsPropCleared(nsIAtom *aProp,
|
|||
|
||||
PRBool TypeInState::FindPropInList(nsIAtom *aProp,
|
||||
const nsString &aAttr,
|
||||
const nsString &aValue,
|
||||
nsString *outValue,
|
||||
nsVoidArray &aList,
|
||||
PRInt32 &outIndex)
|
||||
{
|
||||
|
@ -376,6 +368,7 @@ PRBool TypeInState::FindPropInList(nsIAtom *aProp,
|
|||
if ( (item->tag == aProp) &&
|
||||
(item->attr == aAttr) )
|
||||
{
|
||||
if (outValue) *outValue = item->value;
|
||||
outIndex = i;
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
|
|
@ -57,7 +57,6 @@ public:
|
|||
nsresult ClearAllProps();
|
||||
nsresult ClearProp(nsIAtom *aProp);
|
||||
nsresult ClearProp(nsIAtom *aProp, const nsString &aAttr);
|
||||
nsresult ClearProp(nsIAtom *aProp, const nsString &aAttr, const nsString &aValue);
|
||||
|
||||
//**************************************************************************
|
||||
// TakeClearProperty: hands back next poroperty item on the clear list.
|
||||
|
@ -78,17 +77,17 @@ public:
|
|||
nsresult GetTypingState(PRBool &isSet, PRBool &theSetting, nsIAtom *aProp,
|
||||
const nsString &aAttr);
|
||||
nsresult GetTypingState(PRBool &isSet, PRBool &theSetting, nsIAtom *aProp,
|
||||
const nsString &aAttr, const nsString &aValue);
|
||||
const nsString &aAttr, nsString* outValue);
|
||||
|
||||
protected:
|
||||
|
||||
nsresult RemovePropFromSetList(nsIAtom *aProp, const nsString &aAttr, const nsString &aValue);
|
||||
nsresult RemovePropFromClearedList(nsIAtom *aProp, const nsString &aAttr, const nsString &aValue);
|
||||
PRBool IsPropSet(nsIAtom *aProp, const nsString &aAttr, const nsString &aValue);
|
||||
PRBool IsPropSet(nsIAtom *aProp, const nsString &aAttr, const nsString &aValue, PRInt32 &outIndex);
|
||||
PRBool IsPropCleared(nsIAtom *aProp, const nsString &aAttr, const nsString &aValue);
|
||||
PRBool IsPropCleared(nsIAtom *aProp, const nsString &aAttr, const nsString &aValue, PRInt32 &outIndex);
|
||||
PRBool FindPropInList(nsIAtom *aProp, const nsString &aAttr, const nsString &aValue, nsVoidArray &aList, PRInt32 &outIndex);
|
||||
nsresult RemovePropFromSetList(nsIAtom *aProp, const nsString &aAttr);
|
||||
nsresult RemovePropFromClearedList(nsIAtom *aProp, const nsString &aAttr);
|
||||
PRBool IsPropSet(nsIAtom *aProp, const nsString &aAttr, nsString* outValue);
|
||||
PRBool IsPropSet(nsIAtom *aProp, const nsString &aAttr, nsString* outValue, PRInt32 &outIndex);
|
||||
PRBool IsPropCleared(nsIAtom *aProp, const nsString &aAttr);
|
||||
PRBool IsPropCleared(nsIAtom *aProp, const nsString &aAttr, PRInt32 &outIndex);
|
||||
PRBool FindPropInList(nsIAtom *aProp, const nsString &aAttr, nsString *outValue, nsVoidArray &aList, PRInt32 &outIndex);
|
||||
|
||||
nsVoidArray mSetArray;
|
||||
nsVoidArray mClearedArray;
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -109,8 +109,8 @@ protected:
|
|||
nsresult WillMakeBasicBlock(nsIDOMSelection *aSelection, const nsString *aBlockType, PRBool *aCancel, PRBool *aHandled);
|
||||
nsresult DidMakeBasicBlock(nsIDOMSelection *aSelection, nsRulesInfo *aInfo, nsresult aResult);
|
||||
|
||||
nsresult AlignTableElement(nsIDOMNode *aNode, const nsString *alignType);
|
||||
nsresult AlignTableCellContents(nsIDOMNode *aNode, const nsString *alignType);
|
||||
nsresult AlignInnerBlocks(nsIDOMNode *aNode, const nsString *alignType);
|
||||
nsresult AlignBlockContents(nsIDOMNode *aNode, const nsString *alignType);
|
||||
nsresult GetInnerContent(nsIDOMNode *aNode, nsISupportsArray *outArrayOfNodes, PRBool aList = PR_TRUE, PRBool aTble = PR_TRUE);
|
||||
|
||||
nsresult InsertTab(nsIDOMSelection *aSelection, nsString *outString);
|
||||
|
@ -146,12 +146,13 @@ protected:
|
|||
nsresult GetListActionNodes(nsCOMPtr<nsISupportsArray> *outArrayOfNodes, PRBool aDontTouchContent=PR_FALSE);
|
||||
nsresult GetDefinitionListItemTypes(nsIDOMNode *aNode, PRBool &aDT, PRBool &aDD);
|
||||
nsresult GetParagraphFormatNodes(nsCOMPtr<nsISupportsArray> *outArrayOfNodes, PRBool aDontTouchContent=PR_FALSE);
|
||||
nsresult BustUpInlinesAtRangeEndpoints(nsRangeStore &inRange);
|
||||
nsresult BustUpInlinesAtBRs(nsIDOMNode *inNode,
|
||||
nsCOMPtr<nsISupportsArray> *outArrayOfNodes);
|
||||
nsCOMPtr<nsIDOMNode> GetHighestInlineParent(nsIDOMNode* aNode);
|
||||
nsresult MakeTransitionList(nsISupportsArray *inArrayOfNodes,
|
||||
nsVoidArray *inTransitionArray);
|
||||
|
||||
nsresult ShouldMakeEmptyBlock(nsIDOMSelection *aSelection, const nsString *blockTag, PRBool *outMakeEmpty);
|
||||
nsresult ApplyBlockStyle(nsISupportsArray *arrayOfNodes, const nsString *aBlockTag);
|
||||
nsresult MakeBlockquote(nsISupportsArray *arrayOfNodes);
|
||||
nsresult SplitAsNeeded(const nsString *aTag, nsCOMPtr<nsIDOMNode> *inOutParent, PRInt32 *inOutOffset);
|
||||
|
|
|
@ -42,6 +42,7 @@ nsHTMLEditUtils::IsBody(nsIDOMNode *node)
|
|||
{
|
||||
nsAutoString tag;
|
||||
nsEditor::GetTagString(node,tag);
|
||||
tag.ToLowerCase();
|
||||
if (tag.EqualsWithConversion("body"))
|
||||
{
|
||||
return PR_TRUE;
|
||||
|
@ -573,4 +574,11 @@ nsHTMLEditUtils::IsDescendantOf(nsIDOMNode *aNode, nsIDOMNode *aParent)
|
|||
}
|
||||
|
||||
|
||||
|
||||
PRBool
|
||||
nsHTMLEditUtils::IsLeafNode(nsIDOMNode *aNode)
|
||||
{
|
||||
if (!aNode) return PR_FALSE;
|
||||
PRBool hasChildren = PR_FALSE;
|
||||
aNode->HasChildNodes(&hasChildren);
|
||||
return !hasChildren;
|
||||
}
|
|
@ -63,6 +63,9 @@ public:
|
|||
static PRBool IsMozDiv(nsIDOMNode *aNode);
|
||||
static PRBool IsMailCite(nsIDOMNode *aNode);
|
||||
static PRBool IsDescendantOf(nsIDOMNode *aNode, nsIDOMNode *aParent);
|
||||
|
||||
static PRBool IsLeafNode(nsIDOMNode *aNode);
|
||||
|
||||
};
|
||||
|
||||
#endif /* nsHTMLEditUtils_h__ */
|
||||
|
|
|
@ -1777,6 +1777,16 @@ NS_IMETHODIMP nsHTMLEditor::GetInlinePropertyWithAttrValue(nsIAtom *aProperty,
|
|||
if (collapsedNode != mCachedNode) CacheInlineStyles(collapsedNode);
|
||||
// cache now current, use it! But override it with typeInState results if any...
|
||||
PRBool isSet, theSetting;
|
||||
if (aAttribute)
|
||||
mTypeInState->GetTypingState(isSet, theSetting, aProperty, *aAttribute, outValue);
|
||||
else
|
||||
mTypeInState->GetTypingState(isSet, theSetting, aProperty);
|
||||
if (isSet)
|
||||
{
|
||||
aFirst = aAny = aAll = theSetting;
|
||||
return NS_OK;
|
||||
}
|
||||
/*
|
||||
if (aProperty == mBoldAtom.get())
|
||||
{
|
||||
mTypeInState->GetTypingState(isSet, theSetting, aProperty);
|
||||
|
@ -1815,7 +1825,7 @@ NS_IMETHODIMP nsHTMLEditor::GetInlinePropertyWithAttrValue(nsIAtom *aProperty,
|
|||
aFirst = aAny = aAll = mCachedUnderlineStyle;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
} */
|
||||
}
|
||||
|
||||
// either non-collapsed selection or no cached value: do it the hard way
|
||||
|
@ -7102,7 +7112,7 @@ nsHTMLEditor::GetPriorHTMLNode(nsIDOMNode *inParent, PRInt32 inOffset, nsCOMPtr<
|
|||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// GetNextHTMLNode: returns the previous editable leaf node, if there is
|
||||
// GetNextHTMLNode: returns the next editable leaf node, if there is
|
||||
// one within the <body>
|
||||
//
|
||||
nsresult
|
||||
|
@ -7239,6 +7249,75 @@ nsHTMLEditor::GetLastEditableChild( nsIDOMNode *aNode, nsCOMPtr<nsIDOMNode> *aOu
|
|||
return res;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLEditor::GetFirstEditableLeaf( nsIDOMNode *aNode, nsCOMPtr<nsIDOMNode> *aOutFirstLeaf)
|
||||
{
|
||||
// check parms
|
||||
if (!aOutFirstLeaf || !aNode) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
// init out parms
|
||||
*aOutFirstLeaf = nsnull;
|
||||
|
||||
// find leftmost leaf
|
||||
nsCOMPtr<nsIDOMNode> child;
|
||||
nsresult res = GetLeftmostChild(aNode, getter_AddRefs(child));
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
while (child && (!IsEditable(child) || !nsHTMLEditUtils::IsLeafNode(child)))
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> tmp;
|
||||
res = GetNextHTMLNode(child, &tmp);
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!tmp) return NS_ERROR_FAILURE;
|
||||
|
||||
// only accept nodes that are descendants of aNode
|
||||
if (nsHTMLEditUtils::IsDescendantOf(tmp, aNode))
|
||||
child = tmp;
|
||||
else
|
||||
{
|
||||
child = nsnull; // this will abort the loop
|
||||
}
|
||||
}
|
||||
|
||||
*aOutFirstLeaf = child;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsHTMLEditor::GetLastEditableLeaf( nsIDOMNode *aNode, nsCOMPtr<nsIDOMNode> *aOutLastLeaf)
|
||||
{
|
||||
// check parms
|
||||
if (!aOutLastLeaf || !aNode) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
// init out parms
|
||||
*aOutLastLeaf = nsnull;
|
||||
|
||||
// find leftmost leaf
|
||||
nsCOMPtr<nsIDOMNode> child;
|
||||
nsresult res = GetRightmostChild(aNode, getter_AddRefs(child));
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
while (child && (!IsEditable(child) || !nsHTMLEditUtils::IsLeafNode(child)))
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> tmp;
|
||||
res = GetPriorHTMLNode(child, &tmp);
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!tmp) return NS_ERROR_FAILURE;
|
||||
|
||||
// only accept nodes that are descendants of aNode
|
||||
if (nsHTMLEditUtils::IsDescendantOf(tmp, aNode))
|
||||
child = tmp;
|
||||
else
|
||||
{
|
||||
child = nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
*aOutLastLeaf = child;
|
||||
return res;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// IsEmptyNode: figure out if aNode is an empty node.
|
||||
// A block can have children and still be considered empty,
|
||||
|
|
|
@ -332,6 +332,11 @@ public:
|
|||
// aSelection is optional -- if null, we get current seletion
|
||||
nsresult CollapseSelectionToDeepestNonTableFirstChild(nsIDOMSelection *aSelection, nsIDOMNode *aNode);
|
||||
|
||||
nsresult IsEmptyNode(nsIDOMNode *aNode, PRBool *outIsEmptyBlock,
|
||||
PRBool aMozBRDoesntCount = PR_FALSE,
|
||||
PRBool aListOrCellNotEmpty = PR_FALSE,
|
||||
PRBool aSafeToAskFrames = PR_FALSE);
|
||||
|
||||
protected:
|
||||
|
||||
NS_IMETHOD InitRules();
|
||||
|
@ -563,10 +568,8 @@ protected:
|
|||
nsresult IsLastEditableChild( nsIDOMNode *aNode, PRBool *aOutIsLast);
|
||||
nsresult GetFirstEditableChild( nsIDOMNode *aNode, nsCOMPtr<nsIDOMNode> *aOutFirstChild);
|
||||
nsresult GetLastEditableChild( nsIDOMNode *aNode, nsCOMPtr<nsIDOMNode> *aOutLastChild);
|
||||
nsresult IsEmptyNode(nsIDOMNode *aNode, PRBool *outIsEmptyBlock,
|
||||
PRBool aMozBRDoesntCount = PR_FALSE,
|
||||
PRBool aListOrCellNotEmpty = PR_FALSE,
|
||||
PRBool aSafeToAskFrames = PR_FALSE);
|
||||
nsresult GetFirstEditableLeaf( nsIDOMNode *aNode, nsCOMPtr<nsIDOMNode> *aOutFirstLeaf);
|
||||
nsresult GetLastEditableLeaf( nsIDOMNode *aNode, nsCOMPtr<nsIDOMNode> *aOutLastLeaf);
|
||||
|
||||
nsresult GetDOMEventReceiver(nsIDOMEventReceiver **aEventReceiver);
|
||||
|
||||
|
|
|
@ -477,7 +477,7 @@ nsTextEditRules::WillInsertBreak(nsIDOMSelection *aSelection, PRBool *aCancel, P
|
|||
printf("It's a moz quote -- splitting\n");
|
||||
nsCOMPtr<nsIDOMNode> outLeftNode;
|
||||
nsCOMPtr<nsIDOMNode> outRightNode;
|
||||
res = mEditor->SplitNodeDeep(preNode, selNode, selOffset, &newOffset, &outLeftNode, &outRightNode);
|
||||
res = mEditor->SplitNodeDeep(preNode, selNode, selOffset, &newOffset, PR_TRUE, &outLeftNode, &outRightNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
PRBool bIsEmptyNode;
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче