kateundo.cpp
00001 /* This file is part of the KDE libraries 00002 Copyright (C) 2002 John Firebaugh <jfirebaugh@kde.org> 00003 Copyright (C) 2001 Christoph Cullmann <cullmann@kde.org> 00004 Copyright (C) 2001 Joseph Wenninger <jowenn@kde.org> 00005 00006 This library is free software; you can redistribute it and/or 00007 modify it under the terms of the GNU Library General Public 00008 License version 2 as published by the Free Software Foundation. 00009 00010 This library is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 Library General Public License for more details. 00014 00015 You should have received a copy of the GNU Library General Public License 00016 along with this library; see the file COPYING.LIB. If not, write to 00017 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00018 Boston, MA 02110-1301, USA. 00019 */ 00020 00021 #include "kateundo.h" 00022 00023 #include "katedocument.h" 00024 #include "kateview.h" 00025 #include "katecursor.h" 00026 00030 class KateUndo 00031 { 00032 public: 00041 KateUndo (KateUndoGroup::UndoType type, uint line, uint col, uint len, const TQString &text); 00042 00046 ~KateUndo (); 00047 00048 public: 00055 bool isValid(); 00056 00063 bool merge(KateUndo* u); 00064 00069 void undo (KateDocument *doc); 00070 00075 void redo (KateDocument *doc); 00076 00080 KateTextCursor cursorBefore() const; 00081 00085 KateTextCursor cursorAfter() const; 00086 00091 inline KateUndoGroup::UndoType type() const { return m_type; } 00092 00097 inline uint line () const { return m_line; } 00098 00103 inline uint col () const { return m_col; } 00104 00109 inline uint len() const { return m_len; } 00110 00115 inline const TQString& text() const { return m_text; }; 00116 00117 private: 00121 KateUndoGroup::UndoType m_type; 00122 00126 uint m_line; 00127 00131 uint m_col; 00132 00136 uint m_len; 00137 00141 TQString m_text; 00142 }; 00143 00144 KateUndo::KateUndo (KateUndoGroup::UndoType type, uint line, uint col, uint len, const TQString &text) 00145 : m_type (type), 00146 m_line (line), 00147 m_col (col), 00148 m_len (len), 00149 m_text (text) 00150 { 00151 } 00152 00153 KateUndo::~KateUndo () 00154 { 00155 } 00156 00157 bool KateUndo::isValid() 00158 { 00159 if (m_type == KateUndoGroup::editInsertText || m_type == KateUndoGroup::editRemoveText) 00160 if (len() == 0) 00161 return false; 00162 00163 return true; 00164 } 00165 00166 bool KateUndo::merge(KateUndo* u) 00167 { 00168 if (m_type != u->type()) 00169 return false; 00170 00171 if (m_type == KateUndoGroup::editInsertText 00172 && m_line == u->line() 00173 && (m_col + m_len) == u->col()) 00174 { 00175 m_text += u->text(); 00176 m_len += u->len(); 00177 return true; 00178 } 00179 else if (m_type == KateUndoGroup::editRemoveText 00180 && m_line == u->line() 00181 && m_col == (u->col() + u->len())) 00182 { 00183 m_text.prepend(u->text()); 00184 m_col = u->col(); 00185 m_len += u->len(); 00186 return true; 00187 } 00188 00189 return false; 00190 } 00191 00192 void KateUndo::undo (KateDocument *doc) 00193 { 00194 if (m_type == KateUndoGroup::editInsertText) 00195 { 00196 doc->editRemoveText (m_line, m_col, m_len); 00197 } 00198 else if (m_type == KateUndoGroup::editRemoveText) 00199 { 00200 doc->editInsertText (m_line, m_col, m_text); 00201 } 00202 else if (m_type == KateUndoGroup::editWrapLine) 00203 { 00204 doc->editUnWrapLine (m_line, (m_text == "1"), m_len); 00205 } 00206 else if (m_type == KateUndoGroup::editUnWrapLine) 00207 { 00208 doc->editWrapLine (m_line, m_col, (m_text == "1")); 00209 } 00210 else if (m_type == KateUndoGroup::editInsertLine) 00211 { 00212 doc->editRemoveLine (m_line); 00213 } 00214 else if (m_type == KateUndoGroup::editRemoveLine) 00215 { 00216 doc->editInsertLine (m_line, m_text); 00217 } 00218 else if (m_type == KateUndoGroup::editMarkLineAutoWrapped) 00219 { 00220 doc->editMarkLineAutoWrapped (m_line, m_col == 0); 00221 } 00222 } 00223 00224 void KateUndo::redo (KateDocument *doc) 00225 { 00226 if (m_type == KateUndoGroup::editRemoveText) 00227 { 00228 doc->editRemoveText (m_line, m_col, m_len); 00229 } 00230 else if (m_type == KateUndoGroup::editInsertText) 00231 { 00232 doc->editInsertText (m_line, m_col, m_text); 00233 } 00234 else if (m_type == KateUndoGroup::editUnWrapLine) 00235 { 00236 doc->editUnWrapLine (m_line, (m_text == "1"), m_len); 00237 } 00238 else if (m_type == KateUndoGroup::editWrapLine) 00239 { 00240 doc->editWrapLine (m_line, m_col, (m_text == "1")); 00241 } 00242 else if (m_type == KateUndoGroup::editRemoveLine) 00243 { 00244 doc->editRemoveLine (m_line); 00245 } 00246 else if (m_type == KateUndoGroup::editInsertLine) 00247 { 00248 doc->editInsertLine (m_line, m_text); 00249 } 00250 else if (m_type == KateUndoGroup::editMarkLineAutoWrapped) 00251 { 00252 doc->editMarkLineAutoWrapped (m_line, m_col == 1); 00253 } 00254 } 00255 00256 KateTextCursor KateUndo::cursorBefore() const 00257 { 00258 if (m_type == KateUndoGroup::editInsertLine || m_type == KateUndoGroup::editUnWrapLine) 00259 return KateTextCursor(m_line+1, m_col); 00260 else if (m_type == KateUndoGroup::editRemoveText) 00261 return KateTextCursor(m_line, m_col+m_len); 00262 00263 return KateTextCursor(m_line, m_col); 00264 } 00265 00266 KateTextCursor KateUndo::cursorAfter() const 00267 { 00268 if (m_type == KateUndoGroup::editRemoveLine || m_type == KateUndoGroup::editWrapLine) 00269 return KateTextCursor(m_line+1, m_col); 00270 else if (m_type == KateUndoGroup::editInsertText) 00271 return KateTextCursor(m_line, m_col+m_len); 00272 00273 return KateTextCursor(m_line, m_col); 00274 } 00275 00276 KateUndoGroup::KateUndoGroup (KateDocument *doc) 00277 : m_doc (doc),m_safePoint(false) 00278 { 00279 m_items.setAutoDelete (true); 00280 } 00281 00282 KateUndoGroup::~KateUndoGroup () 00283 { 00284 } 00285 00286 void KateUndoGroup::undo () 00287 { 00288 if (m_items.count() == 0) 00289 return; 00290 00291 m_doc->editStart (false); 00292 00293 for (KateUndo* u = m_items.last(); u; u = m_items.prev()) 00294 u->undo(m_doc); 00295 00296 if (m_doc->activeView()) 00297 { 00298 for (uint z=0; z < m_items.count(); z++) 00299 if (m_items.at(z)->type() != KateUndoGroup::editMarkLineAutoWrapped) 00300 { 00301 m_doc->activeView()->editSetCursor (m_items.at(z)->cursorBefore()); 00302 break; 00303 } 00304 } 00305 00306 m_doc->editEnd (); 00307 } 00308 00309 void KateUndoGroup::redo () 00310 { 00311 if (m_items.count() == 0) 00312 return; 00313 00314 m_doc->editStart (false); 00315 00316 for (KateUndo* u = m_items.first(); u; u = m_items.next()) 00317 u->redo(m_doc); 00318 00319 if (m_doc->activeView()) 00320 { 00321 for (uint z=0; z < m_items.count(); z++) 00322 if (m_items.at(z)->type() != KateUndoGroup::editMarkLineAutoWrapped) 00323 { 00324 m_doc->activeView()->editSetCursor (m_items.at(z)->cursorAfter()); 00325 break; 00326 } 00327 } 00328 00329 m_doc->editEnd (); 00330 } 00331 00332 void KateUndoGroup::addItem (KateUndoGroup::UndoType type, uint line, uint col, uint len, const TQString &text) 00333 { 00334 addItem(new KateUndo(type, line, col, len, text)); 00335 } 00336 00337 void KateUndoGroup::addItem(KateUndo* u) 00338 { 00339 if (!u->isValid()) 00340 delete u; 00341 else if (m_items.last() && m_items.last()->merge(u)) 00342 delete u; 00343 else 00344 m_items.append(u); 00345 } 00346 00347 bool KateUndoGroup::merge(KateUndoGroup* newGroup,bool complex) 00348 { 00349 if (m_safePoint) return false; 00350 if (newGroup->isOnlyType(singleType()) || complex) { 00351 // Take all of its items first -> last 00352 KateUndo* u = newGroup->m_items.take(0); 00353 while (u) { 00354 addItem(u); 00355 u = newGroup->m_items.take(0); 00356 } 00357 if (newGroup->m_safePoint) safePoint(); 00358 return true; 00359 } 00360 return false; 00361 } 00362 00363 void KateUndoGroup::safePoint (bool safePoint) { 00364 m_safePoint=safePoint; 00365 } 00366 00367 KateUndoGroup::UndoType KateUndoGroup::singleType() 00368 { 00369 KateUndoGroup::UndoType ret = editInvalid; 00370 00371 for (KateUndo* u = m_items.first(); u; u = m_items.next()) { 00372 if (ret == editInvalid) 00373 ret = u->type(); 00374 else if (ret != u->type()) 00375 return editInvalid; 00376 } 00377 00378 return ret; 00379 } 00380 00381 bool KateUndoGroup::isOnlyType(KateUndoGroup::UndoType type) 00382 { 00383 if (type == editInvalid) return false; 00384 00385 for (KateUndo* u = m_items.first(); u; u = m_items.next()) 00386 if (u->type() != type) 00387 return false; 00388 00389 return true; 00390 } 00391 00392 // kate: space-indent on; indent-width 2; replace-tabs on;