Home | History | Annotate | Download | only in editing
      1 /*
      2  * Copyright (C) 2006, 2007 Apple, Inc.  All rights reserved.
      3  * Copyright (C) 2012 Google, Inc.  All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions
      7  * are met:
      8  * 1. Redistributions of source code must retain the above copyright
      9  *    notice, this list of conditions and the following disclaimer.
     10  * 2. Redistributions in binary form must reproduce the above copyright
     11  *    notice, this list of conditions and the following disclaimer in the
     12  *    documentation and/or other materials provided with the distribution.
     13  *
     14  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
     15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     17  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
     18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     21  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
     22  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     25  */
     26 
     27 #include "config.h"
     28 #include "UndoStack.h"
     29 
     30 #include "core/dom/ContainerNode.h"
     31 #include "core/editing/UndoStep.h"
     32 #include "wtf/TemporaryChange.h"
     33 
     34 namespace WebCore {
     35 
     36 // Arbitrary depth limit for the undo stack, to keep it from using
     37 // unbounded memory. This is the maximum number of distinct undoable
     38 // actions -- unbroken stretches of typed characters are coalesced
     39 // into a single action.
     40 static const size_t maximumUndoStackDepth = 1000;
     41 
     42 UndoStack::UndoStack()
     43     : m_inRedo(false)
     44 {
     45 }
     46 
     47 UndoStack::~UndoStack()
     48 {
     49 }
     50 
     51 PassOwnPtr<UndoStack> UndoStack::create()
     52 {
     53     return adoptPtr(new UndoStack());
     54 }
     55 
     56 void UndoStack::registerUndoStep(PassRefPtr<UndoStep> step)
     57 {
     58     if (m_undoStack.size() == maximumUndoStackDepth)
     59         m_undoStack.removeFirst(); // drop oldest item off the far end
     60     if (!m_inRedo)
     61         m_redoStack.clear();
     62     m_undoStack.append(step);
     63 }
     64 
     65 void UndoStack::registerRedoStep(PassRefPtr<UndoStep> step)
     66 {
     67     m_redoStack.append(step);
     68 }
     69 
     70 void UndoStack::didUnloadFrame(const Frame& frame)
     71 {
     72     NoEventDispatchAssertion assertNoEventDispatch;
     73     filterOutUndoSteps(m_undoStack, frame);
     74     filterOutUndoSteps(m_redoStack, frame);
     75 }
     76 
     77 void UndoStack::filterOutUndoSteps(UndoStepStack& stack, const Frame& frame)
     78 {
     79     UndoStepStack newStack;
     80     while (!stack.isEmpty()) {
     81         UndoStep* step = stack.first().get();
     82         if (!step->belongsTo(frame))
     83             newStack.append(step);
     84         stack.removeFirst();
     85     }
     86     stack.swap(newStack);
     87 }
     88 
     89 bool UndoStack::canUndo() const
     90 {
     91     return !m_undoStack.isEmpty();
     92 }
     93 
     94 bool UndoStack::canRedo() const
     95 {
     96     return !m_redoStack.isEmpty();
     97 }
     98 
     99 void UndoStack::undo()
    100 {
    101     if (canUndo()) {
    102         UndoStepStack::iterator back = --m_undoStack.end();
    103         RefPtr<UndoStep> step(*back);
    104         m_undoStack.remove(back);
    105         step->unapply();
    106         // unapply will call us back to push this command onto the redo stack.
    107     }
    108 }
    109 
    110 void UndoStack::redo()
    111 {
    112     if (canRedo()) {
    113         UndoStepStack::iterator back = --m_redoStack.end();
    114         RefPtr<UndoStep> step(*back);
    115         m_redoStack.remove(back);
    116 
    117         ASSERT(!m_inRedo);
    118         TemporaryChange<bool> redoScope(m_inRedo, true);
    119         step->reapply();
    120         // reapply will call us back to push this command onto the undo stack.
    121     }
    122 }
    123 
    124 } // namesace WebCore
    125