Fix typos
[TortoiseGit.git] / src / TortoiseMerge / Undo.cpp
blob7afd9e198c9803310e8f0b87cea1334c679bb5e0
1 // TortoiseGitMerge - a Diff/Patch program
3 // Copyright (C) 2023 - TortoiseGit
4 // Copyright (C) 2006-2007, 2010-2011, 2013,2015, 2021-2022 - TortoiseSVN
6 // This program is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU General Public License
8 // as published by the Free Software Foundation; either version 2
9 // of the License, or (at your option) any later version.
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software Foundation,
18 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 #include "stdafx.h"
22 #include "Undo.h"
24 #include "BaseView.h"
26 void viewstate::AddViewLineFromView(CBaseView *pView, int nViewLine, bool bAddEmptyLine)
28 // is undo good place for this ?
29 if (!pView || !pView->m_pViewData)
30 return;
31 replacedlines[nViewLine] = pView->m_pViewData->GetData(nViewLine);
32 if (bAddEmptyLine)
34 addedlines.push_back(nViewLine + 1);
35 pView->AddEmptyViewLine(nViewLine);
39 void viewstate::Clear()
41 difflines.clear();
42 linestates.clear();
43 linelines.clear();
44 linesEOL.clear();
45 markedlines.clear();
46 addedlines.clear();
48 removedlines.clear();
49 replacedlines.clear();
50 modifies = false;
53 void CUndo::MarkAsOriginalState(bool bLeft, bool bRight, bool bBottom)
55 // find highest index of changing step
56 if (bLeft) // left is selected for mark
57 m_originalstateLeft = 0;
58 if (bRight) // right is selected for mark
59 m_originalstateRight = 0;
60 if (bBottom) // bottom is selected for mark
61 m_originalstateBottom = 0;
64 CUndo& CUndo::GetInstance()
66 static CUndo instance;
67 return instance;
70 CUndo::CUndo()
74 CUndo::~CUndo()
78 void CUndo::AddState(const allviewstate& allstate, POINT pt)
80 if (allstate.left.modifies)
81 ++m_originalstateLeft;
82 if (allstate.right.modifies)
83 ++m_originalstateRight;
84 if (allstate.bottom.modifies)
85 ++m_originalstateBottom;
87 m_viewstates.push_back(allstate);
88 m_caretpoints.push_back(pt);
89 // a new action that can be undone clears the redo since
90 // after this there is nothing to redo anymore
91 m_redoviewstates.clear();
92 m_redocaretpoints.clear();
93 m_redogroups.clear();
96 bool CUndo::Undo(CBaseView * pLeft, CBaseView * pRight, CBaseView * pBottom)
98 if (!CanUndo())
99 return false;
101 if (m_groups.size() && m_groups.back() == m_caretpoints.size())
103 m_groups.pop_back();
104 std::list<int>::size_type b = m_groups.back();
105 m_redogroups.push_back(b);
106 m_redogroups.push_back(m_caretpoints.size());
107 m_groups.pop_back();
108 while (b < m_caretpoints.size())
109 UndoOne(pLeft, pRight, pBottom);
111 else
112 UndoOne(pLeft, pRight, pBottom);
114 updateActiveView(pLeft, pRight, pBottom);
116 return true;
119 void CUndo::UndoOne(CBaseView * pLeft, CBaseView * pRight, CBaseView * pBottom)
121 allviewstate allstate = m_viewstates.back();
122 POINT pt = m_caretpoints.back();
124 if (pLeft->IsTarget())
125 m_redocaretpoints.push_back(pLeft->GetCaretPosition());
126 else if (pRight->IsTarget())
127 m_redocaretpoints.push_back(pRight->GetCaretPosition());
128 else if (pBottom->IsTarget())
129 m_redocaretpoints.push_back(pBottom->GetCaretPosition());
131 if (allstate.left.modifies)
132 --m_originalstateLeft;
133 if (allstate.right.modifies)
134 --m_originalstateRight;
135 if (allstate.bottom.modifies)
136 --m_originalstateBottom;
138 allstate.left = Do(allstate.left, pLeft, pt);
139 allstate.right = Do(allstate.right, pRight, pt);
140 allstate.bottom = Do(allstate.bottom, pBottom, pt);
142 m_redoviewstates.push_back(allstate);
144 m_viewstates.pop_back();
145 m_caretpoints.pop_back();
148 bool CUndo::Redo(CBaseView * pLeft, CBaseView * pRight, CBaseView * pBottom)
150 if (!CanRedo())
151 return false;
153 if (m_redogroups.size() && m_redogroups.back() == m_redocaretpoints.size())
155 m_redogroups.pop_back();
156 std::list<int>::size_type b = m_redogroups.back();
157 m_groups.push_back(b);
158 m_groups.push_back(m_redocaretpoints.size());
159 m_redogroups.pop_back();
160 while (b < m_redocaretpoints.size())
161 RedoOne(pLeft, pRight, pBottom);
163 else
164 RedoOne(pLeft, pRight, pBottom);
166 updateActiveView(pLeft, pRight, pBottom);
168 return true;
171 void CUndo::RedoOne(CBaseView* pLeft, CBaseView* pRight, CBaseView* pBottom)
173 allviewstate allstate = m_redoviewstates.back();
174 POINT pt = m_redocaretpoints.back();
176 if (pLeft->IsTarget())
177 m_caretpoints.push_back(pLeft->GetCaretPosition());
178 else if (pRight->IsTarget())
179 m_caretpoints.push_back(pRight->GetCaretPosition());
180 else if (pBottom->IsTarget())
181 m_caretpoints.push_back(pBottom->GetCaretPosition());
183 if (allstate.left.modifies)
184 ++m_originalstateLeft;
185 if (allstate.right.modifies)
186 ++m_originalstateRight;
187 if (allstate.bottom.modifies)
188 ++m_originalstateBottom;
190 allstate.left = Do(allstate.left, pLeft, pt);
191 allstate.right = Do(allstate.right, pRight, pt);
192 allstate.bottom = Do(allstate.bottom, pBottom, pt);
194 m_viewstates.push_back(allstate);
196 m_redoviewstates.pop_back();
197 m_redocaretpoints.pop_back();
200 void CUndo::updateActiveView(CBaseView* pLeft, CBaseView* pRight, CBaseView* pBottom) const
202 CBaseView* pActiveView = nullptr;
204 if (pBottom && pBottom->IsTarget())
206 pActiveView = pBottom;
208 else if (pRight && pRight->IsTarget())
210 pActiveView = pRight;
212 else
213 // if (pLeft && pLeft->IsTarget())
215 pActiveView = pLeft;
218 if (pActiveView)
220 pActiveView->ClearSelection();
221 pActiveView->BuildAllScreen2ViewVector();
222 pActiveView->RecalcAllVertScrollBars();
223 pActiveView->RecalcAllHorzScrollBars();
224 pActiveView->EnsureCaretVisible();
225 pActiveView->UpdateCaret();
227 if (pLeft)
229 pLeft->SetModified(m_originalstateLeft != 0);
230 pLeft->ClearStepModifiedMark();
232 if (pRight)
234 pRight->SetModified(m_originalstateRight != 0);
235 pRight->ClearStepModifiedMark();
237 if (pBottom)
239 pBottom->SetModified(m_originalstateBottom != 0);
240 pBottom->ClearStepModifiedMark();
242 pActiveView->RefreshViews();
245 viewstate CUndo::Do(const viewstate& state, CBaseView * pView, const POINT& pt)
247 if (!pView)
248 return state;
250 CViewData* viewData = pView->m_pViewData;
251 if (!viewData)
252 return state;
254 viewstate revstate; // the reversed viewstate
255 revstate.modifies = state.modifies;
257 for (std::list<int>::const_reverse_iterator it = state.addedlines.rbegin(); it != state.addedlines.rend(); ++it)
259 revstate.removedlines[*it] = viewData->GetData(*it);
260 viewData->RemoveData(*it);
262 for (std::map<int, DWORD>::const_iterator it = state.linelines.begin(); it != state.linelines.end(); ++it)
264 revstate.linelines[it->first] = viewData->GetLineNumber(it->first);
265 viewData->SetLineNumber(it->first, it->second);
267 for (auto it = state.linestates.cbegin(); it != state.linestates.cend(); ++it)
269 revstate.linestates[it->first] = viewData->GetState(it->first);
270 viewData->SetState(it->first, it->second);
272 for (std::map<int, EOL>::const_iterator it = state.linesEOL.begin(); it != state.linesEOL.end(); ++it)
274 revstate.linesEOL[it->first] = viewData->GetLineEnding(it->first);
275 viewData->SetLineEnding(it->first, it->second);
277 for (std::map<int, bool>::const_iterator it = state.markedlines.begin(); it != state.markedlines.end(); ++it)
279 revstate.markedlines[it->first] = viewData->GetMarked(it->first);
280 viewData->SetMarked(it->first, it->second);
282 for (std::map<int, CString>::const_iterator it = state.difflines.begin(); it != state.difflines.end(); ++it)
284 revstate.difflines[it->first] = viewData->GetLine(it->first);
285 viewData->SetLine(it->first, it->second);
287 for (std::map<int, viewdata>::const_iterator it = state.removedlines.begin(); it != state.removedlines.end(); ++it)
289 revstate.addedlines.push_back(it->first);
290 viewData->InsertData(it->first, it->second);
292 for (std::map<int, viewdata>::const_iterator it = state.replacedlines.begin(); it != state.replacedlines.end(); ++it)
294 revstate.replacedlines[it->first] = viewData->GetData(it->first);
295 viewData->SetData(it->first, it->second);
298 if (pView->IsTarget())
300 pView->SetCaretViewPosition(pt);
301 pView->EnsureCaretVisible();
303 return revstate;
306 void CUndo::Clear()
308 m_viewstates.clear();
309 m_caretpoints.clear();
310 m_groups.clear();
311 m_redoviewstates.clear();
312 m_redocaretpoints.clear();
313 m_redogroups.clear();
314 m_originalstateLeft = 0;
315 m_originalstateRight = 0;
316 m_originalstateBottom = 0;
317 m_groupCount = 0;