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.
26 void viewstate::AddViewLineFromView(CBaseView
*pView
, int nViewLine
, bool bAddEmptyLine
)
28 // is undo good place for this ?
29 if (!pView
|| !pView
->m_pViewData
)
31 replacedlines
[nViewLine
] = pView
->m_pViewData
->GetData(nViewLine
);
34 addedlines
.push_back(nViewLine
+ 1);
35 pView
->AddEmptyViewLine(nViewLine
);
39 void viewstate::Clear()
49 replacedlines
.clear();
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
;
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();
96 bool CUndo::Undo(CBaseView
* pLeft
, CBaseView
* pRight
, CBaseView
* pBottom
)
101 if (m_groups
.size() && m_groups
.back() == m_caretpoints
.size())
104 std::list
<int>::size_type b
= m_groups
.back();
105 m_redogroups
.push_back(b
);
106 m_redogroups
.push_back(m_caretpoints
.size());
108 while (b
< m_caretpoints
.size())
109 UndoOne(pLeft
, pRight
, pBottom
);
112 UndoOne(pLeft
, pRight
, pBottom
);
114 updateActiveView(pLeft
, pRight
, pBottom
);
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
)
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
);
164 RedoOne(pLeft
, pRight
, pBottom
);
166 updateActiveView(pLeft
, pRight
, pBottom
);
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
;
213 // if (pLeft && pLeft->IsTarget())
220 pActiveView
->ClearSelection();
221 pActiveView
->BuildAllScreen2ViewVector();
222 pActiveView
->RecalcAllVertScrollBars();
223 pActiveView
->RecalcAllHorzScrollBars();
224 pActiveView
->EnsureCaretVisible();
225 pActiveView
->UpdateCaret();
229 pLeft
->SetModified(m_originalstateLeft
!= 0);
230 pLeft
->ClearStepModifiedMark();
234 pRight
->SetModified(m_originalstateRight
!= 0);
235 pRight
->ClearStepModifiedMark();
239 pBottom
->SetModified(m_originalstateBottom
!= 0);
240 pBottom
->ClearStepModifiedMark();
242 pActiveView
->RefreshViews();
245 viewstate
CUndo::Do(const viewstate
& state
, CBaseView
* pView
, const POINT
& pt
)
250 CViewData
* viewData
= pView
->m_pViewData
;
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();
308 m_viewstates
.clear();
309 m_caretpoints
.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;