зеркало из https://github.com/mozilla/gecko-dev.git
added WillUndo, DidUndo, WillRedo, DidRedo and some supporting code so
the text edit rule object can maintain it's own state more efficiently and correctly.
This commit is contained in:
Родитель
c149d1f5b8
Коммит
6ce58013c8
|
@ -1083,8 +1083,6 @@ NS_IMETHODIMP nsEditor::DoInitialInsert(const nsString & aStringToInsert)
|
|||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
BeginTransaction();
|
||||
|
||||
nsCOMPtr<nsIDOMNodeList>nodeList;
|
||||
nsAutoString bodyTag = "body";
|
||||
nsresult result = mDoc->GetElementsByTagName(bodyTag, getter_AddRefs(nodeList));
|
||||
|
@ -1128,7 +1126,6 @@ NS_IMETHODIMP nsEditor::DoInitialInsert(const nsString & aStringToInsert)
|
|||
}
|
||||
}
|
||||
}
|
||||
EndTransaction();
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -124,6 +124,10 @@ nsTextEditRules::WillInsert(nsIDOMSelection *aSelection, PRBool *aCancel)
|
|||
mEditor->DeleteNode(mBogusNode);
|
||||
mBogusNode = do_QueryInterface(nsnull);
|
||||
// there is no longer any legit selection, so clear it.
|
||||
// BEGIN HACK -- ClearSelection does not remove the anchor! Subsequent code depends on
|
||||
// ClearSelection making it so IsCollapsed returns TRUE
|
||||
aSelection->Collapse(mBogusNode, 0);
|
||||
// END HACK
|
||||
aSelection->ClearSelection();
|
||||
}
|
||||
|
||||
|
@ -188,7 +192,7 @@ nsTextEditRules::DidInsertBreak(nsIDOMSelection *aSelection, nsresult aResult)
|
|||
NS_ASSERTION(PR_TRUE==isCollapsed, "selection not collapsed after insert break.");
|
||||
// if the insert break resulted in consecutive BR tags,
|
||||
// collapse the two BR tags into a single P
|
||||
if (NS_SUCCEEDED(aResult)) // note we're checking aResult, the param that tells us if the insert break happened or not
|
||||
if (NS_SUCCEEDED(result))
|
||||
{
|
||||
nsCOMPtr<nsIEnumerator> enumerator;
|
||||
enumerator = do_QueryInterface(aSelection,&result);
|
||||
|
@ -384,6 +388,103 @@ nsTextEditRules::DidDeleteSelection(nsIDOMSelection *aSelection, nsresult aResul
|
|||
return result;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTextEditRules::WillUndo(nsIDOMSelection *aSelection, PRBool *aCancel)
|
||||
{
|
||||
if (!aSelection || !aCancel) { return NS_ERROR_NULL_POINTER; }
|
||||
// initialize out param
|
||||
*aCancel = PR_FALSE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* the idea here is to see if the magic empty node has suddenly reappeared as the result of the undo.
|
||||
* if it has, set our state so we remember it.
|
||||
* There is a tradeoff between doing here and at redo, or doing it everywhere else that might care.
|
||||
* Since undo and redo are relatively rare, it makes sense to take the (small) performance hit here.
|
||||
*/
|
||||
NS_IMETHODIMP
|
||||
nsTextEditRules:: DidUndo(nsIDOMSelection *aSelection, nsresult aResult)
|
||||
{
|
||||
nsresult result = aResult; // if aResult is an error, we return it.
|
||||
if (!aSelection) { return NS_ERROR_NULL_POINTER; }
|
||||
if (NS_SUCCEEDED(result))
|
||||
{
|
||||
if (mBogusNode) {
|
||||
mBogusNode = do_QueryInterface(nsnull);
|
||||
}
|
||||
else
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode>node;
|
||||
PRInt32 offset;
|
||||
nsresult result = aSelection->GetAnchorNodeAndOffset(getter_AddRefs(node), &offset);
|
||||
while ((NS_SUCCEEDED(result)) && node)
|
||||
{
|
||||
nsCOMPtr<nsIDOMElement>element;
|
||||
element = do_QueryInterface(node);
|
||||
if (element)
|
||||
{
|
||||
nsAutoString att(kMOZEditorBogusNodeAttr);
|
||||
nsAutoString val;
|
||||
nsresult result = element->GetAttribute(att, val);
|
||||
if (val.Equals(kMOZEditorBogusNodeValue)) {
|
||||
mBogusNode = do_QueryInterface(element);
|
||||
}
|
||||
}
|
||||
nsCOMPtr<nsIDOMNode> temp;
|
||||
result = node->GetParentNode(getter_AddRefs(temp));
|
||||
node = do_QueryInterface(temp);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTextEditRules::WillRedo(nsIDOMSelection *aSelection, PRBool *aCancel)
|
||||
{
|
||||
if (!aSelection || !aCancel) { return NS_ERROR_NULL_POINTER; }
|
||||
// initialize out param
|
||||
*aCancel = PR_FALSE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTextEditRules::DidRedo(nsIDOMSelection *aSelection, nsresult aResult)
|
||||
{
|
||||
nsresult result = aResult; // if aResult is an error, we return it.
|
||||
if (!aSelection) { return NS_ERROR_NULL_POINTER; }
|
||||
if (NS_SUCCEEDED(result))
|
||||
{
|
||||
if (mBogusNode) {
|
||||
mBogusNode = do_QueryInterface(nsnull);
|
||||
}
|
||||
else
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode>node;
|
||||
PRInt32 offset;
|
||||
nsresult result = aSelection->GetAnchorNodeAndOffset(getter_AddRefs(node), &offset);
|
||||
while ((NS_SUCCEEDED(result)) && node)
|
||||
{
|
||||
nsCOMPtr<nsIDOMElement>element;
|
||||
element = do_QueryInterface(node);
|
||||
if (element)
|
||||
{
|
||||
nsAutoString att(kMOZEditorBogusNodeAttr);
|
||||
nsAutoString val;
|
||||
nsresult result = element->GetAttribute(att, val);
|
||||
if (val.Equals(kMOZEditorBogusNodeValue)) {
|
||||
mBogusNode = do_QueryInterface(element);
|
||||
}
|
||||
}
|
||||
nsCOMPtr<nsIDOMNode> temp;
|
||||
result = node->GetParentNode(getter_AddRefs(temp));
|
||||
node = do_QueryInterface(temp);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -63,6 +63,12 @@ public:
|
|||
NS_IMETHOD WillDeleteSelection(nsIDOMSelection *aSelection, PRBool *aCancel);
|
||||
NS_IMETHOD DidDeleteSelection(nsIDOMSelection *aSelection, nsresult aResult);
|
||||
|
||||
NS_IMETHOD WillUndo(nsIDOMSelection *aSelection, PRBool *aCancel);
|
||||
NS_IMETHOD DidUndo(nsIDOMSelection *aSelection, nsresult aResult);
|
||||
|
||||
NS_IMETHOD WillRedo(nsIDOMSelection *aSelection, PRBool *aCancel);
|
||||
NS_IMETHOD DidRedo(nsIDOMSelection *aSelection, nsresult aResult);
|
||||
|
||||
protected:
|
||||
|
||||
nsTextEditor *mEditor; // note that we do not refcount the editor
|
||||
|
|
|
@ -440,7 +440,7 @@ NS_IMETHODIMP nsTextEditor::InsertText(const nsString& aStringToInsert)
|
|||
nsAutoString stringToInsert;
|
||||
PlaceholderTxn *placeholderTxn=nsnull;
|
||||
nsresult result = mRules->WillInsertText(selection, aStringToInsert, &cancel, stringToInsert,
|
||||
&placeholderTxn);
|
||||
&placeholderTxn);
|
||||
if ((PR_FALSE==cancel) && (NS_SUCCEEDED(result)))
|
||||
{
|
||||
result = nsEditor::InsertText(stringToInsert);
|
||||
|
@ -519,7 +519,19 @@ NS_IMETHODIMP nsTextEditor::EnableUndo(PRBool aEnable)
|
|||
|
||||
NS_IMETHODIMP nsTextEditor::Undo(PRUint32 aCount)
|
||||
{
|
||||
return nsEditor::Undo(aCount);
|
||||
nsCOMPtr<nsIDOMSelection> selection;
|
||||
PRBool cancel= PR_FALSE;
|
||||
|
||||
// pre-process
|
||||
nsEditor::GetSelection(getter_AddRefs(selection));
|
||||
nsresult result = mRules->WillUndo(selection, &cancel);
|
||||
if ((PR_FALSE==cancel) && (NS_SUCCEEDED(result)))
|
||||
{
|
||||
result = nsEditor::Undo(aCount);
|
||||
nsEditor::GetSelection(getter_AddRefs(selection));
|
||||
result = mRules->DidUndo(selection, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsTextEditor::CanUndo(PRBool &aIsEnabled, PRBool &aCanUndo)
|
||||
|
@ -529,7 +541,19 @@ NS_IMETHODIMP nsTextEditor::CanUndo(PRBool &aIsEnabled, PRBool &aCanUndo)
|
|||
|
||||
NS_IMETHODIMP nsTextEditor::Redo(PRUint32 aCount)
|
||||
{
|
||||
return nsEditor::Redo(aCount);
|
||||
nsCOMPtr<nsIDOMSelection> selection;
|
||||
PRBool cancel= PR_FALSE;
|
||||
|
||||
// pre-process
|
||||
nsEditor::GetSelection(getter_AddRefs(selection));
|
||||
nsresult result = mRules->WillRedo(selection, &cancel);
|
||||
if ((PR_FALSE==cancel) && (NS_SUCCEEDED(result)))
|
||||
{
|
||||
result = nsEditor::Redo(aCount);
|
||||
nsEditor::GetSelection(getter_AddRefs(selection));
|
||||
result = mRules->DidRedo(selection, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsTextEditor::CanRedo(PRBool &aIsEnabled, PRBool &aCanRedo)
|
||||
|
|
|
@ -1083,8 +1083,6 @@ NS_IMETHODIMP nsEditor::DoInitialInsert(const nsString & aStringToInsert)
|
|||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
BeginTransaction();
|
||||
|
||||
nsCOMPtr<nsIDOMNodeList>nodeList;
|
||||
nsAutoString bodyTag = "body";
|
||||
nsresult result = mDoc->GetElementsByTagName(bodyTag, getter_AddRefs(nodeList));
|
||||
|
@ -1128,7 +1126,6 @@ NS_IMETHODIMP nsEditor::DoInitialInsert(const nsString & aStringToInsert)
|
|||
}
|
||||
}
|
||||
}
|
||||
EndTransaction();
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -124,6 +124,10 @@ nsTextEditRules::WillInsert(nsIDOMSelection *aSelection, PRBool *aCancel)
|
|||
mEditor->DeleteNode(mBogusNode);
|
||||
mBogusNode = do_QueryInterface(nsnull);
|
||||
// there is no longer any legit selection, so clear it.
|
||||
// BEGIN HACK -- ClearSelection does not remove the anchor! Subsequent code depends on
|
||||
// ClearSelection making it so IsCollapsed returns TRUE
|
||||
aSelection->Collapse(mBogusNode, 0);
|
||||
// END HACK
|
||||
aSelection->ClearSelection();
|
||||
}
|
||||
|
||||
|
@ -188,7 +192,7 @@ nsTextEditRules::DidInsertBreak(nsIDOMSelection *aSelection, nsresult aResult)
|
|||
NS_ASSERTION(PR_TRUE==isCollapsed, "selection not collapsed after insert break.");
|
||||
// if the insert break resulted in consecutive BR tags,
|
||||
// collapse the two BR tags into a single P
|
||||
if (NS_SUCCEEDED(aResult)) // note we're checking aResult, the param that tells us if the insert break happened or not
|
||||
if (NS_SUCCEEDED(result))
|
||||
{
|
||||
nsCOMPtr<nsIEnumerator> enumerator;
|
||||
enumerator = do_QueryInterface(aSelection,&result);
|
||||
|
@ -384,6 +388,103 @@ nsTextEditRules::DidDeleteSelection(nsIDOMSelection *aSelection, nsresult aResul
|
|||
return result;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTextEditRules::WillUndo(nsIDOMSelection *aSelection, PRBool *aCancel)
|
||||
{
|
||||
if (!aSelection || !aCancel) { return NS_ERROR_NULL_POINTER; }
|
||||
// initialize out param
|
||||
*aCancel = PR_FALSE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* the idea here is to see if the magic empty node has suddenly reappeared as the result of the undo.
|
||||
* if it has, set our state so we remember it.
|
||||
* There is a tradeoff between doing here and at redo, or doing it everywhere else that might care.
|
||||
* Since undo and redo are relatively rare, it makes sense to take the (small) performance hit here.
|
||||
*/
|
||||
NS_IMETHODIMP
|
||||
nsTextEditRules:: DidUndo(nsIDOMSelection *aSelection, nsresult aResult)
|
||||
{
|
||||
nsresult result = aResult; // if aResult is an error, we return it.
|
||||
if (!aSelection) { return NS_ERROR_NULL_POINTER; }
|
||||
if (NS_SUCCEEDED(result))
|
||||
{
|
||||
if (mBogusNode) {
|
||||
mBogusNode = do_QueryInterface(nsnull);
|
||||
}
|
||||
else
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode>node;
|
||||
PRInt32 offset;
|
||||
nsresult result = aSelection->GetAnchorNodeAndOffset(getter_AddRefs(node), &offset);
|
||||
while ((NS_SUCCEEDED(result)) && node)
|
||||
{
|
||||
nsCOMPtr<nsIDOMElement>element;
|
||||
element = do_QueryInterface(node);
|
||||
if (element)
|
||||
{
|
||||
nsAutoString att(kMOZEditorBogusNodeAttr);
|
||||
nsAutoString val;
|
||||
nsresult result = element->GetAttribute(att, val);
|
||||
if (val.Equals(kMOZEditorBogusNodeValue)) {
|
||||
mBogusNode = do_QueryInterface(element);
|
||||
}
|
||||
}
|
||||
nsCOMPtr<nsIDOMNode> temp;
|
||||
result = node->GetParentNode(getter_AddRefs(temp));
|
||||
node = do_QueryInterface(temp);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTextEditRules::WillRedo(nsIDOMSelection *aSelection, PRBool *aCancel)
|
||||
{
|
||||
if (!aSelection || !aCancel) { return NS_ERROR_NULL_POINTER; }
|
||||
// initialize out param
|
||||
*aCancel = PR_FALSE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTextEditRules::DidRedo(nsIDOMSelection *aSelection, nsresult aResult)
|
||||
{
|
||||
nsresult result = aResult; // if aResult is an error, we return it.
|
||||
if (!aSelection) { return NS_ERROR_NULL_POINTER; }
|
||||
if (NS_SUCCEEDED(result))
|
||||
{
|
||||
if (mBogusNode) {
|
||||
mBogusNode = do_QueryInterface(nsnull);
|
||||
}
|
||||
else
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode>node;
|
||||
PRInt32 offset;
|
||||
nsresult result = aSelection->GetAnchorNodeAndOffset(getter_AddRefs(node), &offset);
|
||||
while ((NS_SUCCEEDED(result)) && node)
|
||||
{
|
||||
nsCOMPtr<nsIDOMElement>element;
|
||||
element = do_QueryInterface(node);
|
||||
if (element)
|
||||
{
|
||||
nsAutoString att(kMOZEditorBogusNodeAttr);
|
||||
nsAutoString val;
|
||||
nsresult result = element->GetAttribute(att, val);
|
||||
if (val.Equals(kMOZEditorBogusNodeValue)) {
|
||||
mBogusNode = do_QueryInterface(element);
|
||||
}
|
||||
}
|
||||
nsCOMPtr<nsIDOMNode> temp;
|
||||
result = node->GetParentNode(getter_AddRefs(temp));
|
||||
node = do_QueryInterface(temp);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -63,6 +63,12 @@ public:
|
|||
NS_IMETHOD WillDeleteSelection(nsIDOMSelection *aSelection, PRBool *aCancel);
|
||||
NS_IMETHOD DidDeleteSelection(nsIDOMSelection *aSelection, nsresult aResult);
|
||||
|
||||
NS_IMETHOD WillUndo(nsIDOMSelection *aSelection, PRBool *aCancel);
|
||||
NS_IMETHOD DidUndo(nsIDOMSelection *aSelection, nsresult aResult);
|
||||
|
||||
NS_IMETHOD WillRedo(nsIDOMSelection *aSelection, PRBool *aCancel);
|
||||
NS_IMETHOD DidRedo(nsIDOMSelection *aSelection, nsresult aResult);
|
||||
|
||||
protected:
|
||||
|
||||
nsTextEditor *mEditor; // note that we do not refcount the editor
|
||||
|
|
Загрузка…
Ссылка в новой задаче