editor/libeditor/base/SplitElementTxn.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 #include <stdio.h>                      // for printf
     8 #include "SplitElementTxn.h"
     9 #include "nsAString.h"
    10 #include "nsDebug.h"                    // for NS_ASSERTION, etc
    11 #include "nsEditor.h"                   // for nsEditor
    12 #include "nsError.h"                    // for NS_ERROR_NOT_INITIALIZED, etc
    13 #include "nsIDOMCharacterData.h"        // for nsIDOMCharacterData
    14 #include "nsIDOMNode.h"                 // for nsIDOMNode
    15 #include "nsIEditor.h"                  // for nsEditor::DebugDumpContent, etc
    16 #include "nsISelection.h"               // for nsISelection
    17 #include "nsISupportsUtils.h"           // for NS_ADDREF
    19 // note that aEditor is not refcounted
    20 SplitElementTxn::SplitElementTxn()
    21   : EditTxn()
    22 {
    23 }
    25 NS_IMPL_CYCLE_COLLECTION_INHERITED(SplitElementTxn, EditTxn,
    26                                    mParent,
    27                                    mNewLeftNode)
    29 NS_IMPL_ADDREF_INHERITED(SplitElementTxn, EditTxn)
    30 NS_IMPL_RELEASE_INHERITED(SplitElementTxn, EditTxn)
    31 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(SplitElementTxn)
    32 NS_INTERFACE_MAP_END_INHERITING(EditTxn)
    34 NS_IMETHODIMP SplitElementTxn::Init(nsEditor   *aEditor,
    35                                     nsIDOMNode *aNode,
    36                                     int32_t     aOffset)
    37 {
    38   NS_ASSERTION(aEditor && aNode, "bad args");
    39   if (!aEditor || !aNode) { return NS_ERROR_NOT_INITIALIZED; }
    41   mEditor = aEditor;
    42   mExistingRightNode = do_QueryInterface(aNode);
    43   mOffset = aOffset;
    44   return NS_OK;
    45 }
    47 NS_IMETHODIMP SplitElementTxn::DoTransaction(void)
    48 {
    49   NS_ASSERTION(mExistingRightNode && mEditor, "bad state");
    50   if (!mExistingRightNode || !mEditor) { return NS_ERROR_NOT_INITIALIZED; }
    52   // create a new node
    53   nsresult result = mExistingRightNode->CloneNode(false, 1, getter_AddRefs(mNewLeftNode));
    54   NS_ASSERTION(((NS_SUCCEEDED(result)) && (mNewLeftNode)), "could not create element.");
    55   NS_ENSURE_SUCCESS(result, result);
    56   NS_ENSURE_TRUE(mNewLeftNode, NS_ERROR_NULL_POINTER);
    57   mEditor->MarkNodeDirty(mExistingRightNode);
    59   // get the parent node
    60   result = mExistingRightNode->GetParentNode(getter_AddRefs(mParent));
    61   NS_ENSURE_SUCCESS(result, result);
    62   NS_ENSURE_TRUE(mParent, NS_ERROR_NULL_POINTER);
    64   // insert the new node
    65   result = mEditor->SplitNodeImpl(mExistingRightNode, mOffset, mNewLeftNode, mParent);
    66   if (mNewLeftNode) {
    67     bool bAdjustSelection;
    68     mEditor->ShouldTxnSetSelection(&bAdjustSelection);
    69     if (bAdjustSelection)
    70     {
    71       nsCOMPtr<nsISelection> selection;
    72       result = mEditor->GetSelection(getter_AddRefs(selection));
    73       NS_ENSURE_SUCCESS(result, result);
    74       NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
    75       result = selection->Collapse(mNewLeftNode, mOffset);
    76     }
    77     else
    78     {
    79       // do nothing - dom range gravity will adjust selection
    80     }
    81   }
    82   return result;
    83 }
    85 NS_IMETHODIMP SplitElementTxn::UndoTransaction(void)
    86 {
    87   NS_ASSERTION(mEditor && mExistingRightNode && mNewLeftNode && mParent, "bad state");
    88   if (!mEditor || !mExistingRightNode || !mNewLeftNode || !mParent) {
    89     return NS_ERROR_NOT_INITIALIZED;
    90   }
    92   // this assumes Do inserted the new node in front of the prior existing node
    93   nsCOMPtr<nsINode> rightNode = do_QueryInterface(mExistingRightNode);
    94   nsCOMPtr<nsINode> leftNode = do_QueryInterface(mNewLeftNode);
    95   nsCOMPtr<nsINode> parent = do_QueryInterface(mParent);
    96   NS_ENSURE_TRUE(rightNode && leftNode && parent, NS_ERROR_FAILURE);
    97   return mEditor->JoinNodesImpl(rightNode, leftNode, parent);
    98 }
   100 /* redo cannot simply resplit the right node, because subsequent transactions
   101  * on the redo stack may depend on the left node existing in its previous state.
   102  */
   103 NS_IMETHODIMP SplitElementTxn::RedoTransaction(void)
   104 {
   105   NS_ASSERTION(mEditor && mExistingRightNode && mNewLeftNode && mParent, "bad state");
   106   if (!mEditor || !mExistingRightNode || !mNewLeftNode || !mParent) {
   107     return NS_ERROR_NOT_INITIALIZED;
   108   }
   110   nsresult result;
   111   nsCOMPtr<nsIDOMNode>resultNode;
   112   // first, massage the existing node so it is in its post-split state
   113   nsCOMPtr<nsIDOMCharacterData>rightNodeAsText = do_QueryInterface(mExistingRightNode);
   114   if (rightNodeAsText)
   115   {
   116     nsresult result = rightNodeAsText->DeleteData(0, mOffset);
   117     NS_ENSURE_SUCCESS(result, result);
   118   }
   119   else
   120   {
   121     nsCOMPtr<nsIDOMNode>child;
   122     nsCOMPtr<nsIDOMNode>nextSibling;
   123     result = mExistingRightNode->GetFirstChild(getter_AddRefs(child));
   124     int32_t i;
   125     for (i=0; i<mOffset; i++)
   126     {
   127       if (NS_FAILED(result)) {return result;}
   128       if (!child) {return NS_ERROR_NULL_POINTER;}
   129       child->GetNextSibling(getter_AddRefs(nextSibling));
   130       result = mExistingRightNode->RemoveChild(child, getter_AddRefs(resultNode));
   131       if (NS_SUCCEEDED(result)) 
   132       {
   133         result = mNewLeftNode->AppendChild(child, getter_AddRefs(resultNode));
   134       }
   135       child = do_QueryInterface(nextSibling);
   136     }
   137   }
   138   // second, re-insert the left node into the tree 
   139   result = mParent->InsertBefore(mNewLeftNode, mExistingRightNode, getter_AddRefs(resultNode));
   140   return result;
   141 }
   144 NS_IMETHODIMP SplitElementTxn::GetTxnDescription(nsAString& aString)
   145 {
   146   aString.AssignLiteral("SplitElementTxn");
   147   return NS_OK;
   148 }
   150 NS_IMETHODIMP SplitElementTxn::GetNewNode(nsIDOMNode **aNewNode)
   151 {
   152   NS_ENSURE_TRUE(aNewNode, NS_ERROR_NULL_POINTER);
   153   NS_ENSURE_TRUE(mNewLeftNode, NS_ERROR_NOT_INITIALIZED);
   154   *aNewNode = mNewLeftNode;
   155   NS_ADDREF(*aNewNode);
   156   return NS_OK;
   157 }

mercurial