LCOV - code coverage report
Current view: top level - editor/libeditor - PlaceholderTransaction.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 25 117 21.4 %
Date: 2017-07-14 16:53:18 Functions: 9 19 47.4 %
Legend: Lines: hit not hit

          Line data    Source code
       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/. */
       5             : 
       6             : #include "PlaceholderTransaction.h"
       7             : 
       8             : #include "CompositionTransaction.h"
       9             : #include "mozilla/EditorBase.h"
      10             : #include "mozilla/dom/Selection.h"
      11             : #include "mozilla/Move.h"
      12             : #include "nsGkAtoms.h"
      13             : #include "nsQueryObject.h"
      14             : 
      15             : namespace mozilla {
      16             : 
      17             : using namespace dom;
      18             : 
      19           1 : PlaceholderTransaction::PlaceholderTransaction(
      20             :                           EditorBase& aEditorBase,
      21             :                           nsIAtom* aName,
      22           1 :                           UniquePtr<SelectionState> aSelState)
      23             :   : mAbsorb(true)
      24             :   , mForwarding(nullptr)
      25             :   , mCompositionTransaction(nullptr)
      26             :   , mCommitted(false)
      27           1 :   , mStartSel(Move(aSelState))
      28           2 :   , mEditorBase(&aEditorBase)
      29             : {
      30           1 :   mName = aName;
      31           1 : }
      32             : 
      33           2 : PlaceholderTransaction::~PlaceholderTransaction()
      34             : {
      35           3 : }
      36             : 
      37             : NS_IMPL_CYCLE_COLLECTION_CLASS(PlaceholderTransaction)
      38             : 
      39           0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(PlaceholderTransaction,
      40             :                                                 EditAggregateTransaction)
      41           0 :   if (tmp->mStartSel) {
      42           0 :     ImplCycleCollectionUnlink(*tmp->mStartSel);
      43             :   }
      44           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mEditorBase);
      45           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mEndSel);
      46           0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
      47             : 
      48           0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(PlaceholderTransaction,
      49             :                                                   EditAggregateTransaction)
      50           0 :   if (tmp->mStartSel) {
      51           0 :     ImplCycleCollectionTraverse(cb, *tmp->mStartSel, "mStartSel", 0);
      52             :   }
      53           0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEditorBase);
      54           0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEndSel);
      55           0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
      56             : 
      57           7 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PlaceholderTransaction)
      58           2 :   NS_INTERFACE_MAP_ENTRY(nsIAbsorbingTransaction)
      59           2 : NS_INTERFACE_MAP_END_INHERITING(EditAggregateTransaction)
      60             : 
      61           6 : NS_IMPL_ADDREF_INHERITED(PlaceholderTransaction, EditAggregateTransaction)
      62           6 : NS_IMPL_RELEASE_INHERITED(PlaceholderTransaction, EditAggregateTransaction)
      63             : 
      64             : NS_IMETHODIMP
      65           1 : PlaceholderTransaction::DoTransaction()
      66             : {
      67           1 :   return NS_OK;
      68             : }
      69             : 
      70             : NS_IMETHODIMP
      71           0 : PlaceholderTransaction::UndoTransaction()
      72             : {
      73           0 :   if (NS_WARN_IF(!mEditorBase)) {
      74           0 :     return NS_ERROR_NOT_INITIALIZED;
      75             :   }
      76             : 
      77             :   // Undo transactions.
      78           0 :   nsresult rv = EditAggregateTransaction::UndoTransaction();
      79           0 :   NS_ENSURE_SUCCESS(rv, rv);
      80             : 
      81           0 :   NS_ENSURE_TRUE(mStartSel, NS_ERROR_NULL_POINTER);
      82             : 
      83             :   // now restore selection
      84           0 :   RefPtr<Selection> selection = mEditorBase->GetSelection();
      85           0 :   NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
      86           0 :   return mStartSel->RestoreSelection(selection);
      87             : }
      88             : 
      89             : NS_IMETHODIMP
      90           0 : PlaceholderTransaction::RedoTransaction()
      91             : {
      92           0 :   if (NS_WARN_IF(!mEditorBase)) {
      93           0 :     return NS_ERROR_NOT_INITIALIZED;
      94             :   }
      95             : 
      96             :   // Redo transactions.
      97           0 :   nsresult rv = EditAggregateTransaction::RedoTransaction();
      98           0 :   NS_ENSURE_SUCCESS(rv, rv);
      99             : 
     100             :   // now restore selection
     101           0 :   RefPtr<Selection> selection = mEditorBase->GetSelection();
     102           0 :   NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
     103           0 :   return mEndSel.RestoreSelection(selection);
     104             : }
     105             : 
     106             : 
     107             : NS_IMETHODIMP
     108           0 : PlaceholderTransaction::Merge(nsITransaction* aTransaction,
     109             :                               bool* aDidMerge)
     110             : {
     111           0 :   NS_ENSURE_TRUE(aDidMerge && aTransaction, NS_ERROR_NULL_POINTER);
     112             : 
     113             :   // set out param default value
     114           0 :   *aDidMerge=false;
     115             : 
     116           0 :   if (mForwarding) {
     117           0 :     NS_NOTREACHED("tried to merge into a placeholder that was in forwarding mode!");
     118           0 :     return NS_ERROR_FAILURE;
     119             :   }
     120             : 
     121             :   // check to see if aTransaction is one of the editor's
     122             :   // private transactions. If not, we want to avoid merging
     123             :   // the foreign transaction into our placeholder since we
     124             :   // don't know what it does.
     125             : 
     126           0 :   nsCOMPtr<nsPIEditorTransaction> pTxn = do_QueryInterface(aTransaction);
     127           0 :   NS_ENSURE_TRUE(pTxn, NS_OK); // it's foreign so just bail!
     128             : 
     129             :   // XXX: hack, not safe!  need nsIEditTransaction!
     130           0 :   EditTransactionBase* editTransactionBase = (EditTransactionBase*)aTransaction;
     131             :   // determine if this incoming txn is a placeholder txn
     132             :   nsCOMPtr<nsIAbsorbingTransaction> absorbingTransaction =
     133           0 :     do_QueryObject(editTransactionBase);
     134             : 
     135             :   // We are absorbing all transactions if mAbsorb is lit.
     136           0 :   if (mAbsorb) {
     137             :     RefPtr<CompositionTransaction> otherTransaction =
     138           0 :       do_QueryObject(aTransaction);
     139           0 :     if (otherTransaction) {
     140             :       // special handling for CompositionTransaction's: they need to merge with
     141             :       // any previous CompositionTransaction in this placeholder, if possible.
     142           0 :       if (!mCompositionTransaction) {
     143             :         // this is the first IME txn in the placeholder
     144           0 :         mCompositionTransaction = otherTransaction;
     145           0 :         AppendChild(editTransactionBase);
     146             :       } else {
     147             :         bool didMerge;
     148           0 :         mCompositionTransaction->Merge(otherTransaction, &didMerge);
     149           0 :         if (!didMerge) {
     150             :           // it wouldn't merge.  Earlier IME txn is already committed and will
     151             :           // not absorb further IME txns.  So just stack this one after it
     152             :           // and remember it as a candidate for further merges.
     153           0 :           mCompositionTransaction = otherTransaction;
     154           0 :           AppendChild(editTransactionBase);
     155             :         }
     156             :       }
     157           0 :     } else if (!absorbingTransaction) {
     158             :       // See bug 171243: just drop incoming placeholders on the floor.
     159             :       // Their children will be swallowed by this preexisting one.
     160           0 :       AppendChild(editTransactionBase);
     161             :     }
     162           0 :     *aDidMerge = true;
     163             : //  RememberEndingSelection();
     164             : //  efficiency hack: no need to remember selection here, as we haven't yet
     165             : //  finished the initial batch and we know we will be told when the batch ends.
     166             : //  we can remeber the selection then.
     167             :   } else {
     168             :     // merge typing or IME or deletion transactions if the selection matches
     169           0 :     if ((mName.get() == nsGkAtoms::TypingTxnName ||
     170           0 :          mName.get() == nsGkAtoms::IMETxnName    ||
     171           0 :          mName.get() == nsGkAtoms::DeleteTxnName) && !mCommitted) {
     172           0 :       if (absorbingTransaction) {
     173           0 :         nsCOMPtr<nsIAtom> atom;
     174           0 :         absorbingTransaction->GetTxnName(getter_AddRefs(atom));
     175           0 :         if (atom && atom == mName) {
     176             :           // check if start selection of next placeholder matches
     177             :           // end selection of this placeholder
     178             :           bool isSame;
     179           0 :           absorbingTransaction->StartSelectionEquals(&mEndSel, &isSame);
     180           0 :           if (isSame) {
     181           0 :             mAbsorb = true;  // we need to start absorbing again
     182           0 :             absorbingTransaction->ForwardEndBatchTo(this);
     183             :             // AppendChild(editTransactionBase);
     184             :             // see bug 171243: we don't need to merge placeholders
     185             :             // into placeholders.  We just reactivate merging in the pre-existing
     186             :             // placeholder and drop the new one on the floor.  The EndPlaceHolderBatch()
     187             :             // call on the new placeholder will be forwarded to this older one.
     188           0 :             RememberEndingSelection();
     189           0 :             *aDidMerge = true;
     190             :           }
     191             :         }
     192             :       }
     193             :     }
     194             :   }
     195           0 :   return NS_OK;
     196             : }
     197             : 
     198             : NS_IMETHODIMP
     199           0 : PlaceholderTransaction::GetTxnDescription(nsAString& aString)
     200             : {
     201           0 :   aString.AssignLiteral("PlaceholderTransaction: ");
     202             : 
     203           0 :   if (mName) {
     204           0 :     nsAutoString name;
     205           0 :     mName->ToString(name);
     206           0 :     aString += name;
     207             :   }
     208             : 
     209           0 :   return NS_OK;
     210             : }
     211             : 
     212             : NS_IMETHODIMP
     213           0 : PlaceholderTransaction::GetTxnName(nsIAtom** aName)
     214             : {
     215           0 :   return GetName(aName);
     216             : }
     217             : 
     218             : NS_IMETHODIMP
     219           0 : PlaceholderTransaction::StartSelectionEquals(SelectionState* aSelState,
     220             :                                              bool* aResult)
     221             : {
     222             :   // determine if starting selection matches the given selection state.
     223             :   // note that we only care about collapsed selections.
     224           0 :   NS_ENSURE_TRUE(aResult && aSelState, NS_ERROR_NULL_POINTER);
     225           0 :   if (!mStartSel->IsCollapsed() || !aSelState->IsCollapsed()) {
     226           0 :     *aResult = false;
     227           0 :     return NS_OK;
     228             :   }
     229           0 :   *aResult = mStartSel->IsEqual(aSelState);
     230           0 :   return NS_OK;
     231             : }
     232             : 
     233             : NS_IMETHODIMP
     234           1 : PlaceholderTransaction::EndPlaceHolderBatch()
     235             : {
     236           1 :   mAbsorb = false;
     237             : 
     238           1 :   if (mForwarding) {
     239           0 :     nsCOMPtr<nsIAbsorbingTransaction> plcTxn = do_QueryReferent(mForwarding);
     240           0 :     if (plcTxn) {
     241           0 :       plcTxn->EndPlaceHolderBatch();
     242             :     }
     243             :   }
     244             :   // remember our selection state.
     245           1 :   return RememberEndingSelection();
     246             : }
     247             : 
     248             : NS_IMETHODIMP
     249           0 : PlaceholderTransaction::ForwardEndBatchTo(
     250             :                           nsIAbsorbingTransaction* aForwardingAddress)
     251             : {
     252           0 :   mForwarding = do_GetWeakReference(aForwardingAddress);
     253           0 :   return NS_OK;
     254             : }
     255             : 
     256             : NS_IMETHODIMP
     257           0 : PlaceholderTransaction::Commit()
     258             : {
     259           0 :   mCommitted = true;
     260           0 :   return NS_OK;
     261             : }
     262             : 
     263             : nsresult
     264           1 : PlaceholderTransaction::RememberEndingSelection()
     265             : {
     266           1 :   if (NS_WARN_IF(!mEditorBase)) {
     267           0 :     return NS_ERROR_NOT_INITIALIZED;
     268             :   }
     269             : 
     270           2 :   RefPtr<Selection> selection = mEditorBase->GetSelection();
     271           1 :   NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
     272           1 :   mEndSel.SaveSelection(selection);
     273           1 :   return NS_OK;
     274             : }
     275             : 
     276             : } // namespace mozilla

Generated by: LCOV version 1.13