1 // TortoiseGitMerge - a Diff/Patch program
3 // Copyright (C) 2006-2007, 2010-2011, 2013,2015 - TortoiseSVN
5 // This program is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License
7 // as published by the Free Software Foundation; either version 2
8 // of the License, or (at your option) any later version.
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software Foundation,
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25 void viewstate::AddViewLineFromView(CBaseView
*pView
, int nViewLine
, bool bAddEmptyLine
)
27 // is undo good place for this ?
28 if (!pView
|| !pView
->m_pViewData
)
30 replacedlines
[nViewLine
] = pView
->m_pViewData
->GetData(nViewLine
);
33 addedlines
.push_back(nViewLine
+ 1);
34 pView
->AddEmptyViewLine(nViewLine
);
38 void viewstate::Clear()
48 replacedlines
.clear();
52 void CUndo::MarkAsOriginalState(bool bLeft
, bool bRight
, bool bBottom
)
54 // TODO reduce code duplication
55 // find highest index of changing step
56 if (bLeft
) // left is selected for mark
58 m_originalstateLeft
= m_viewstates
.size();
59 std::list
<allviewstate
>::reverse_iterator i
= m_viewstates
.rbegin();
60 while (i
!= m_viewstates
.rend() && !i
->left
.modifies
)
63 --m_originalstateLeft
;
66 if (bRight
) // right is selected for mark
68 m_originalstateRight
= m_viewstates
.size();
69 std::list
<allviewstate
>::reverse_iterator i
= m_viewstates
.rbegin();
70 while (i
!= m_viewstates
.rend() && !i
->right
.modifies
)
73 --m_originalstateRight
;
76 if (bBottom
) // bottom is selected for mark
78 m_originalstateBottom
= m_viewstates
.size();
79 std::list
<allviewstate
>::reverse_iterator i
= m_viewstates
.rbegin();
80 while (i
!= m_viewstates
.rend() && !i
->bottom
.modifies
)
83 --m_originalstateBottom
;
88 CUndo
& CUndo::GetInstance()
90 static CUndo instance
;
103 void CUndo::AddState(const allviewstate
& allstate
, POINT pt
)
105 m_viewstates
.push_back(allstate
);
106 m_caretpoints
.push_back(pt
);
107 // a new action that can be undone clears the redo since
108 // after this there is nothing to redo anymore
109 m_redoviewstates
.clear();
110 m_redocaretpoints
.clear();
111 m_redogroups
.clear();
114 bool CUndo::Undo(CBaseView
* pLeft
, CBaseView
* pRight
, CBaseView
* pBottom
)
119 if (m_groups
.size() && m_groups
.back() == m_caretpoints
.size())
122 std::list
<int>::size_type b
= m_groups
.back();
123 m_redogroups
.push_back(b
);
124 m_redogroups
.push_back(m_caretpoints
.size());
126 while (b
< m_caretpoints
.size())
127 UndoOne(pLeft
, pRight
, pBottom
);
130 UndoOne(pLeft
, pRight
, pBottom
);
132 CBaseView
* pActiveView
= nullptr;
134 if (pBottom
&& pBottom
->IsTarget())
136 pActiveView
= pBottom
;
139 if (pRight
&& pRight
->IsTarget())
141 pActiveView
= pRight
;
144 //if (pLeft && pLeft->IsTarget())
151 pActiveView
->ClearSelection();
152 pActiveView
->BuildAllScreen2ViewVector();
153 pActiveView
->RecalcAllVertScrollBars();
154 pActiveView
->RecalcAllHorzScrollBars();
155 pActiveView
->EnsureCaretVisible();
156 pActiveView
->UpdateCaret();
158 // TODO reduce code duplication
159 if (m_viewstates
.size() < m_originalstateLeft
)
161 // Left can never get back to original state now
162 m_originalstateLeft
= (size_t)-1;
166 bool bModified
= (m_originalstateLeft
==(size_t)-1);
169 std::list
<allviewstate
>::iterator i
= m_viewstates
.begin();
170 std::advance(i
, m_originalstateLeft
);
171 for (; i
!=m_viewstates
.end(); ++i
)
173 if (i
->left
.modifies
)
180 pLeft
->SetModified(bModified
);
181 pLeft
->ClearStepModifiedMark();
183 if (m_viewstates
.size() < m_originalstateRight
)
185 // Right can never get back to original state now
186 m_originalstateRight
= (size_t)-1;
190 bool bModified
= (m_originalstateRight
==(size_t)-1);
193 std::list
<allviewstate
>::iterator i
= m_viewstates
.begin();
194 std::advance(i
, m_originalstateRight
);
195 for (; i
!=m_viewstates
.end() && !i
->right
.modifies
; ++i
) ;
196 bModified
= i
!=m_viewstates
.end();
198 pRight
->SetModified(bModified
);
199 pRight
->ClearStepModifiedMark();
201 if (m_viewstates
.size() < m_originalstateBottom
)
203 // Bottom can never get back to original state now
204 m_originalstateBottom
= (size_t)-1;
208 bool bModified
= (m_originalstateBottom
==(size_t)-1);
211 std::list
<allviewstate
>::iterator i
= m_viewstates
.begin();
212 std::advance(i
, m_originalstateBottom
);
213 for (; i
!=m_viewstates
.end(); ++i
)
215 if (i
->bottom
.modifies
)
222 pBottom
->SetModified(bModified
);
223 pBottom
->ClearStepModifiedMark();
225 pActiveView
->RefreshViews();
231 void CUndo::UndoOne(CBaseView
* pLeft
, CBaseView
* pRight
, CBaseView
* pBottom
)
233 allviewstate allstate
= m_viewstates
.back();
234 POINT pt
= m_caretpoints
.back();
236 if (pLeft
->IsTarget())
237 m_redocaretpoints
.push_back(pLeft
->GetCaretPosition());
238 else if (pRight
->IsTarget())
239 m_redocaretpoints
.push_back(pRight
->GetCaretPosition());
240 else if (pBottom
->IsTarget())
241 m_redocaretpoints
.push_back(pBottom
->GetCaretPosition());
243 allstate
.left
= Do(allstate
.left
, pLeft
, pt
);
244 allstate
.right
= Do(allstate
.right
, pRight
, pt
);
245 allstate
.bottom
= Do(allstate
.bottom
, pBottom
, pt
);
247 m_redoviewstates
.push_back(allstate
);
249 m_viewstates
.pop_back();
250 m_caretpoints
.pop_back();
253 bool CUndo::Redo(CBaseView
* pLeft
, CBaseView
* pRight
, CBaseView
* pBottom
)
258 if (m_redogroups
.size() && m_redogroups
.back() == m_redocaretpoints
.size())
260 m_redogroups
.pop_back();
261 std::list
<int>::size_type b
= m_redogroups
.back();
262 m_groups
.push_back(b
);
263 m_groups
.push_back(m_redocaretpoints
.size());
264 m_redogroups
.pop_back();
265 while (b
< m_redocaretpoints
.size())
266 RedoOne(pLeft
, pRight
, pBottom
);
269 RedoOne(pLeft
, pRight
, pBottom
);
271 CBaseView
* pActiveView
= nullptr;
273 if (pBottom
&& pBottom
->IsTarget())
275 pActiveView
= pBottom
;
278 if (pRight
&& pRight
->IsTarget())
280 pActiveView
= pRight
;
283 //if (pLeft && pLeft->IsTarget())
291 pActiveView
->ClearSelection();
292 pActiveView
->BuildAllScreen2ViewVector();
293 pActiveView
->RecalcAllVertScrollBars();
294 pActiveView
->RecalcAllHorzScrollBars();
295 pActiveView
->EnsureCaretVisible();
296 pActiveView
->UpdateCaret();
298 // TODO reduce code duplication
299 if (m_redoviewstates
.size() < m_originalstateLeft
)
301 // Left can never get back to original state now
302 m_originalstateLeft
= (size_t)-1;
306 bool bModified
= (m_originalstateLeft
== (size_t)-1);
309 std::list
<allviewstate
>::iterator i
= m_redoviewstates
.begin();
310 std::advance(i
, m_originalstateLeft
);
311 for (; i
!= m_redoviewstates
.end(); ++i
)
313 if (i
->left
.modifies
)
320 pLeft
->SetModified(bModified
);
321 pLeft
->ClearStepModifiedMark();
323 if (m_redoviewstates
.size() < m_originalstateRight
)
325 // Right can never get back to original state now
326 m_originalstateRight
= (size_t)-1;
330 bool bModified
= (m_originalstateRight
== (size_t)-1);
333 std::list
<allviewstate
>::iterator i
= m_redoviewstates
.begin();
334 std::advance(i
, m_originalstateRight
);
335 for (; i
!= m_redoviewstates
.end() && !i
->right
.modifies
; ++i
);
336 bModified
= i
!= m_redoviewstates
.end();
338 pRight
->SetModified(bModified
);
339 pRight
->ClearStepModifiedMark();
341 if (m_redoviewstates
.size() < m_originalstateBottom
)
343 // Bottom can never get back to original state now
344 m_originalstateBottom
= (size_t)-1;
348 bool bModified
= (m_originalstateBottom
== (size_t)-1);
351 std::list
<allviewstate
>::iterator i
= m_redoviewstates
.begin();
352 std::advance(i
, m_originalstateBottom
);
353 for (; i
!= m_redoviewstates
.end(); ++i
)
355 if (i
->bottom
.modifies
)
362 pBottom
->SetModified(bModified
);
363 pBottom
->ClearStepModifiedMark();
365 pActiveView
->RefreshViews();
371 void CUndo::RedoOne(CBaseView
* pLeft
, CBaseView
* pRight
, CBaseView
* pBottom
)
373 allviewstate allstate
= m_redoviewstates
.back();
374 POINT pt
= m_redocaretpoints
.back();
376 if (pLeft
->IsTarget())
377 m_caretpoints
.push_back(pLeft
->GetCaretPosition());
378 else if (pRight
->IsTarget())
379 m_caretpoints
.push_back(pRight
->GetCaretPosition());
380 else if (pBottom
->IsTarget())
381 m_caretpoints
.push_back(pBottom
->GetCaretPosition());
383 allstate
.left
= Do(allstate
.left
, pLeft
, pt
);
384 allstate
.right
= Do(allstate
.right
, pRight
, pt
);
385 allstate
.bottom
= Do(allstate
.bottom
, pBottom
, pt
);
387 m_viewstates
.push_back(allstate
);
389 m_redoviewstates
.pop_back();
390 m_redocaretpoints
.pop_back();
392 viewstate
CUndo::Do(const viewstate
& state
, CBaseView
* pView
, const POINT
& pt
)
397 CViewData
* viewData
= pView
->m_pViewData
;
401 viewstate revstate
; // the reversed viewstate
403 for (std::list
<int>::const_reverse_iterator it
= state
.addedlines
.rbegin(); it
!= state
.addedlines
.rend(); ++it
)
405 revstate
.removedlines
[*it
] = viewData
->GetData(*it
);
406 viewData
->RemoveData(*it
);
408 for (std::map
<int, DWORD
>::const_iterator it
= state
.linelines
.begin(); it
!= state
.linelines
.end(); ++it
)
410 revstate
.linelines
[it
->first
] = viewData
->GetLineNumber(it
->first
);
411 viewData
->SetLineNumber(it
->first
, it
->second
);
413 for (std::map
<int, DWORD
>::const_iterator it
= state
.linestates
.begin(); it
!= state
.linestates
.end(); ++it
)
415 revstate
.linestates
[it
->first
] = viewData
->GetState(it
->first
);
416 viewData
->SetState(it
->first
, (DiffStates
)it
->second
);
418 for (std::map
<int, EOL
>::const_iterator it
= state
.linesEOL
.begin(); it
!= state
.linesEOL
.end(); ++it
)
420 revstate
.linesEOL
[it
->first
] = viewData
->GetLineEnding(it
->first
);
421 viewData
->SetLineEnding(it
->first
, it
->second
);
423 for (std::map
<int, bool>::const_iterator it
= state
.markedlines
.begin(); it
!= state
.markedlines
.end(); ++it
)
425 revstate
.markedlines
[it
->first
] = viewData
->GetMarked(it
->first
);
426 viewData
->SetMarked(it
->first
, it
->second
);
428 for (std::map
<int, CString
>::const_iterator it
= state
.difflines
.begin(); it
!= state
.difflines
.end(); ++it
)
430 revstate
.difflines
[it
->first
] = viewData
->GetLine(it
->first
);
431 viewData
->SetLine(it
->first
, it
->second
);
433 for (std::map
<int, viewdata
>::const_iterator it
= state
.removedlines
.begin(); it
!= state
.removedlines
.end(); ++it
)
435 revstate
.addedlines
.push_back(it
->first
);
436 viewData
->InsertData(it
->first
, it
->second
);
438 for (std::map
<int, viewdata
>::const_iterator it
= state
.replacedlines
.begin(); it
!= state
.replacedlines
.end(); ++it
)
440 revstate
.replacedlines
[it
->first
] = viewData
->GetData(it
->first
);
441 viewData
->SetData(it
->first
, it
->second
);
444 if (pView
->IsTarget())
446 pView
->SetCaretViewPosition(pt
);
447 pView
->EnsureCaretVisible();
454 m_viewstates
.clear();
455 m_caretpoints
.clear();
457 m_redoviewstates
.clear();
458 m_redocaretpoints
.clear();
459 m_redogroups
.clear();
460 m_originalstateLeft
= 0;
461 m_originalstateRight
= 0;
462 m_originalstateBottom
= 0;