1 22 23 package org.gjt.sp.jedit.buffer; 24 25 import org.gjt.sp.util.Log; 27 29 40 public class UndoManager 41 { 42 public UndoManager(JEditBuffer buffer) 44 { 45 this.buffer = buffer; 46 } 48 public void setLimit(int limit) 50 { 51 this.limit = limit; 52 } 54 public void clear() 56 { 57 undosFirst = undosLast = redosFirst = redosLast = null; 58 undoCount = 0; 59 } 61 public int undo() 63 { 64 if(insideCompoundEdit()) 65 throw new InternalError ("Unbalanced begin/endCompoundEdit()"); 66 67 if(undosLast == null) 68 return -1; 69 else 70 { 71 undoCount--; 72 73 int caret = undosLast.undo(); 74 redosFirst = undosLast; 75 undosLast = undosLast.prev; 76 if(undosLast == null) 77 undosFirst = null; 78 return caret; 79 } 80 } 82 public int redo() 84 { 85 if(insideCompoundEdit()) 86 throw new InternalError ("Unbalanced begin/endCompoundEdit()"); 87 88 if(redosFirst == null) 89 return -1; 90 else 91 { 92 undoCount++; 93 94 int caret = redosFirst.redo(); 95 undosLast = redosFirst; 96 if(undosFirst == null) 97 undosFirst = undosLast; 98 redosFirst = redosFirst.next; 99 return caret; 100 } 101 } 103 public void beginCompoundEdit() 105 { 106 if(compoundEditCount == 0) 107 compoundEdit = new CompoundEdit(); 108 109 compoundEditCount++; 110 } 112 public void endCompoundEdit() 114 { 115 if(compoundEditCount == 0) 116 { 117 Log.log(Log.WARNING,this,new Exception ("Unbalanced begin/endCompoundEdit()")); 118 return; 119 } 120 else if(compoundEditCount == 1) 121 { 122 if(compoundEdit.first == null) 123 ; 124 else if(compoundEdit.first == compoundEdit.last) 125 addEdit(compoundEdit.first); 126 else 127 addEdit(compoundEdit); 128 129 compoundEdit = null; 130 } 131 132 compoundEditCount--; 133 } 135 public boolean insideCompoundEdit() 137 { 138 return compoundEditCount != 0; 139 } 141 public void contentInserted(int offset, int length, String text, boolean clearDirty) 143 { 144 Edit last = getLastEdit(); 145 Edit toMerge = getMergeEdit(); 146 147 if(!clearDirty && toMerge instanceof Insert 148 && redosFirst == null) 149 { 150 Insert ins = (Insert)toMerge; 151 if(ins.offset == offset) 152 { 153 ins.str = text.concat(ins.str); 154 ins.length += length; 155 return; 156 } 157 else if(ins.offset + ins.length == offset) 158 { 159 ins.str = ins.str.concat(text); 160 ins.length += length; 161 return; 162 } 163 } 164 165 Insert ins = new Insert(this,offset,length,text); 166 167 if(clearDirty) 168 { 169 redoClearDirty = last; 170 undoClearDirty = ins; 171 } 172 173 if(compoundEdit != null) 174 compoundEdit.add(ins); 175 else 176 addEdit(ins); 177 } 179 public void contentRemoved(int offset, int length, String text, boolean clearDirty) 181 { 182 Edit last = getLastEdit(); 183 Edit toMerge = getMergeEdit(); 184 185 if(!clearDirty && toMerge instanceof Remove 186 && redosFirst == null) 187 { 188 Remove rem = (Remove)toMerge; 189 if(rem.offset == offset) 190 { 191 rem.str = rem.str.concat(text); 192 rem.hashcode = rem.str.hashCode(); 193 rem.length += length; 194 KillRing.getInstance().changed(rem); 195 return; 196 } 197 else if(offset + length == rem.offset) 198 { 199 rem.str = text.concat(rem.str); 200 rem.hashcode = rem.str.hashCode(); 201 rem.length += length; 202 rem.offset = offset; 203 KillRing.getInstance().changed(rem); 204 return; 205 } 206 } 207 208 Remove rem = new Remove(this,offset,length,text); 209 if(clearDirty) 210 { 211 redoClearDirty = last; 212 undoClearDirty = rem; 213 } 214 215 if(compoundEdit != null) 216 compoundEdit.add(rem); 217 else 218 addEdit(rem); 219 220 KillRing.getInstance().add(rem); 221 } 223 public void bufferSaved() 225 { 226 redoClearDirty = getLastEdit(); 227 if(redosFirst instanceof CompoundEdit) 228 undoClearDirty = ((CompoundEdit)redosFirst).first; 229 else 230 undoClearDirty = redosFirst; 231 } 233 235 private JEditBuffer buffer; 237 238 private Edit undosFirst; 240 private Edit undosLast; 241 242 private Edit redosFirst; 244 private Edit redosLast; 245 246 private int limit; 247 private int undoCount; 248 private int compoundEditCount; 249 private CompoundEdit compoundEdit; 250 private Edit undoClearDirty, redoClearDirty; 251 253 private void addEdit(Edit edit) 255 { 256 if(undosFirst == null) 257 undosFirst = undosLast = edit; 258 else 259 { 260 undosLast.next = edit; 261 edit.prev = undosLast; 262 undosLast = edit; 263 } 264 265 redosFirst = redosLast = null; 266 267 undoCount++; 268 269 while(undoCount > limit) 270 { 271 undoCount--; 272 273 if(undosFirst == undosLast) 274 undosFirst = undosLast = null; 275 else 276 { 277 undosFirst.next.prev = null; 278 undosFirst = undosFirst.next; 279 } 280 } 281 } 283 private Edit getMergeEdit() 285 { 286 Edit last = getLastEdit(); 287 return (compoundEdit != null ? compoundEdit.last : last); 288 } 290 private Edit getLastEdit() 292 { 293 if(undosLast instanceof CompoundEdit) 294 return ((CompoundEdit)undosLast).last; 295 else 296 return undosLast; 297 } 299 301 303 abstract static class Edit 305 { 306 Edit prev, next; 307 308 abstract int undo(); 310 312 abstract int redo(); 314 } 317 static class Insert extends Edit 319 { 320 Insert(UndoManager mgr, int offset, int length, String str) 322 { 323 this.mgr = mgr; 324 this.offset = offset; 325 this.length = length; 326 this.str = str; 327 } 329 int undo() 331 { 332 mgr.buffer.remove(offset,length); 333 if(mgr.undoClearDirty == this) 334 mgr.buffer.setDirty(false); 335 return offset; 336 } 338 int redo() 340 { 341 mgr.buffer.insert(offset,str); 342 if(mgr.redoClearDirty == this) 343 mgr.buffer.setDirty(false); 344 return offset + length; 345 } 347 UndoManager mgr; 348 int offset; 349 int length; 350 String str; 351 } 353 public static class Remove extends Edit 355 { 356 Remove(UndoManager mgr, int offset, int length, String str) 358 { 359 this.mgr = mgr; 360 this.offset = offset; 361 this.length = length; 362 this.str = str; 363 hashcode = str.hashCode(); 364 } 366 int undo() 368 { 369 mgr.buffer.insert(offset,str); 370 if(mgr.undoClearDirty == this) 371 mgr.buffer.setDirty(false); 372 return offset + length; 373 } 375 int redo() 377 { 378 mgr.buffer.remove(offset,length); 379 if(mgr.redoClearDirty == this) 380 mgr.buffer.setDirty(false); 381 return offset; 382 } 384 public String toString() 386 { 387 return str; 388 } 390 UndoManager mgr; 391 int offset; 392 int length; 393 String str; 394 int hashcode; 395 boolean inKillRing; 396 } 398 static class CompoundEdit extends Edit 400 { 401 public int undo() 403 { 404 int retVal = -1; 405 Edit edit = last; 406 while(edit != null) 407 { 408 retVal = edit.undo(); 409 edit = edit.prev; 410 } 411 return retVal; 412 } 414 public int redo() 416 { 417 int retVal = -1; 418 Edit edit = first; 419 while(edit != null) 420 { 421 retVal = edit.redo(); 422 edit = edit.next; 423 } 424 return retVal; 425 } 427 public void add(Edit edit) 429 { 430 if(first == null) 431 first = last = edit; 432 else 433 { 434 edit.prev = last; 435 last.next = edit; 436 last = edit; 437 } 438 } 440 Edit first, last; 441 } 443 } 445 | Popular Tags |