summaryrefslogtreecommitdiff
path: root/src/generic/util/undo.cc
blob: 6a285b39c6ce56f1ffc1f50afaadadb7075ec418 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
// undo.cc
//
//  Copyright 2000 Daniel Burrows
//
//  Implementations of stuff for undo.h

#include "undo.h"

#include <cwidget/generic/util/eassert.h>

using namespace std;

void undo_list::undo()
{
  if(items.size()>floors.back())
    {
      items.front()->undo();
      delete items.front();
      items.pop_front();
    }

  changed();
}

void undo_list::clear_items()
{
  for(list<undoable *>::iterator i=items.begin(); i!=items.end(); i++)
    delete(*i);

  // FIXME: these tests on the size shouldn't be necessary..I'm trying to
  //       debug a weird problem.
  if(items.size()!=0)
    items.erase(items.begin(), items.end());
  if(floors.size()!=0)
    floors.erase(floors.begin(), floors.end());

  floors.push_back(0);

  eassert(items.size()==0);
  eassert(floors.size()==1);

  changed();
}

void undo_list::collapse_to(unsigned int prev_size)
{
  if(items.size()>prev_size)
    {
      eassert(prev_size>=floors.back());

      undo_group *new_item=new undo_group;

      while(items.size()>prev_size)
	{
	  new_item->add_item(items.front());
	  items.pop_front();
	}

      items.push_front(new_item);
    }

  changed();
}

void undo_list::revert_to(unsigned int prev_size)
{
  eassert(prev_size>=floors.back());

  while(items.size()>prev_size)
    undo();

  changed();
}

void undo_list::push_floor(unsigned int floor)
{
  eassert(floor<=items.size());
  floors.push_back(floor);
}

void undo_list::pop_floor()
{
  floors.pop_back();
}