|
Lines 12-19
Link Here
|
| 12 |
package org.eclipse.jface.text; |
12 |
package org.eclipse.jface.text; |
| 13 |
|
13 |
|
| 14 |
|
14 |
|
|
|
15 |
import java.io.ByteArrayInputStream; |
| 16 |
import java.io.ByteArrayOutputStream; |
| 17 |
import java.io.File; |
| 18 |
import java.io.IOException; |
| 19 |
import java.io.ObjectInputStream; |
| 20 |
import java.io.ObjectOutputStream; |
| 21 |
import java.io.RandomAccessFile; |
| 22 |
import java.io.Serializable; |
| 15 |
import java.util.ArrayList; |
23 |
import java.util.ArrayList; |
|
|
24 |
import java.util.LinkedHashMap; |
| 16 |
import java.util.List; |
25 |
import java.util.List; |
|
|
26 |
import java.util.Map; |
| 27 |
|
| 28 |
import org.eclipse.core.runtime.IPath; |
| 29 |
import org.eclipse.core.runtime.Platform; |
| 17 |
import org.eclipse.swt.SWT; |
30 |
import org.eclipse.swt.SWT; |
| 18 |
import org.eclipse.swt.custom.StyledText; |
31 |
import org.eclipse.swt.custom.StyledText; |
| 19 |
import org.eclipse.swt.events.KeyEvent; |
32 |
import org.eclipse.swt.events.KeyEvent; |
|
Lines 41-51
Link Here
|
| 41 |
* @see KeyListener |
54 |
* @see KeyListener |
| 42 |
*/ |
55 |
*/ |
| 43 |
public class DefaultUndoManager implements IUndoManager { |
56 |
public class DefaultUndoManager implements IUndoManager { |
|
|
57 |
|
| 58 |
/** |
| 59 |
* A file that holds undo commands on disk and allow random access to |
| 60 |
* commands via their offset in the file. |
| 61 |
*/ |
| 62 |
static class PersistenceFile { |
| 63 |
private RandomAccessFile fFile; |
| 64 |
|
| 65 |
PersistenceFile() throws IOException { |
| 66 |
|
| 67 |
IPath path= Platform.getLocation().append(".metadata").append(".undo"); //$NON-NLS-1$ //$NON-NLS-2$ |
| 68 |
File f= path.toFile(); |
| 69 |
|
| 70 |
// Scrap the last session's undo log. |
| 71 |
if (f.exists()) |
| 72 |
f.delete(); |
| 73 |
|
| 74 |
fFile= new RandomAccessFile(f, "rw"); //$NON-NLS-1$ |
| 75 |
} |
| 76 |
|
| 77 |
/** |
| 78 |
* Put an object in the file and return its offset. |
| 79 |
* @param s The object to store |
| 80 |
* @return The offset of the object in the file. |
| 81 |
* @throws IOException |
| 82 |
*/ |
| 83 |
public synchronized Long put(Serializable s) throws IOException { |
| 84 |
byte[] bs= toByteArray(s); |
| 85 |
long index= fFile.length(); |
| 86 |
fFile.seek(index); |
| 87 |
fFile.writeInt(bs.length); |
| 88 |
fFile.write(bs); |
| 89 |
return new Long(index); |
| 90 |
} |
| 91 |
|
| 92 |
/** |
| 93 |
* Get the object at the givne offset. |
| 94 |
* @param index The offset of the object to get. |
| 95 |
* @return The object that was at the offset. |
| 96 |
* @throws IOException |
| 97 |
*/ |
| 98 |
public synchronized Serializable get(Long index) throws IOException { |
| 99 |
fFile.seek(index.longValue()); |
| 100 |
int l= fFile.readInt(); |
| 101 |
byte[] bs= new byte[l]; |
| 102 |
fFile.readFully(bs); |
| 103 |
return toObject(bs); |
| 104 |
} |
| 105 |
|
| 106 |
/** |
| 107 |
* Serialize an object into a byte array. |
| 108 |
* @param s The object to serialize. |
| 109 |
* @return The byte array that holds the object. |
| 110 |
* @throws IOException |
| 111 |
*/ |
| 112 |
byte[] toByteArray(Serializable s) throws IOException { |
| 113 |
ByteArrayOutputStream baos= new ByteArrayOutputStream(); |
| 114 |
ObjectOutputStream oos= new ObjectOutputStream(baos); |
| 115 |
oos.writeObject(s); |
| 116 |
return baos.toByteArray(); |
| 117 |
} |
| 118 |
|
| 119 |
/** |
| 120 |
* Convert a serialized object in a byte array to an object. |
| 121 |
* @param bs The byte array holdinghte serialized object. |
| 122 |
* @return The object. |
| 123 |
* @throws IOException |
| 124 |
*/ |
| 125 |
Serializable toObject(byte[] bs) throws IOException { |
| 126 |
try { |
| 127 |
ByteArrayInputStream bais= new ByteArrayInputStream(bs); |
| 128 |
ObjectInputStream ois= new ObjectInputStream(bais); |
| 129 |
return (Serializable)ois.readObject(); |
| 130 |
} |
| 131 |
catch (ClassNotFoundException cnfe) { |
| 132 |
// Can't happen. |
| 133 |
throw new RuntimeException("", cnfe); //$NON-NLS-1$ |
| 134 |
} |
| 135 |
} |
| 136 |
} |
| 137 |
|
| 138 |
/** |
| 139 |
* Caching layer that wraps PersistenceFile to avoid disk lookups |
| 140 |
* for recent changes. |
| 141 |
*/ |
| 142 |
static class PersistenceCache { |
| 143 |
private PersistenceFile fFile; |
| 144 |
|
| 145 |
/** |
| 146 |
* LRU cache of undo commands. |
| 147 |
*/ |
| 148 |
private LinkedHashMap lru= new LinkedHashMap(25, .75F, true) { |
| 149 |
/** |
| 150 |
* Shut up eclipse's warnings. |
| 151 |
*/ |
| 152 |
private static final long serialVersionUID = 6009335074727417445L; |
| 153 |
|
| 154 |
/** |
| 155 |
* Limit the number of entries in the cache. |
| 156 |
*/ |
| 157 |
public boolean removeEldestEntry(Map.Entry eldest) { |
| 158 |
return size() > 25; |
| 159 |
} |
| 160 |
}; |
| 161 |
|
| 162 |
PersistenceCache() { |
| 163 |
try { |
| 164 |
fFile= new PersistenceFile(); |
| 165 |
} |
| 166 |
catch (IOException ioe) { |
| 167 |
ioe.printStackTrace(); |
| 168 |
|
| 169 |
throw new RuntimeException("", ioe); //$NON-NLS-1$ |
| 170 |
} |
| 171 |
} |
| 172 |
|
| 173 |
/** |
| 174 |
* Put an object in the file and return its offset. |
| 175 |
* @param s The object to store |
| 176 |
* @return The offset of the object in the file. |
| 177 |
* @throws IOException |
| 178 |
*/ |
| 179 |
public synchronized Long put(Serializable s) throws IOException { |
| 180 |
Long l= fFile.put(s); |
| 181 |
lru.put(l, s); |
| 182 |
return l; |
| 183 |
} |
| 184 |
|
| 185 |
/** |
| 186 |
* Get the object at the givne offset. |
| 187 |
* @param index The offset of the object to get. |
| 188 |
* @return The object that was at the offset. |
| 189 |
* @throws IOException |
| 190 |
*/ |
| 191 |
public synchronized Serializable get(Long index) throws IOException { |
| 192 |
Serializable s= (Serializable) lru.get(index); |
| 193 |
if (s == null) { |
| 194 |
s= fFile.get(index); |
| 195 |
lru.put(index, s); |
| 196 |
} |
| 197 |
return s; |
| 198 |
} |
| 199 |
|
| 200 |
/** |
| 201 |
* Clear the <b>cache</b>. Does <b>not</b> clear/empty the underlying |
| 202 |
* file. Used to remove references that would prevent GC. |
| 203 |
*/ |
| 204 |
public synchronized void clear() { |
| 205 |
lru.clear(); |
| 206 |
} |
| 207 |
} |
| 208 |
|
| 209 |
/** |
| 210 |
* Per document undo stack. |
| 211 |
*/ |
| 212 |
class CommandStack { |
| 213 |
/** |
| 214 |
* Undo stack. Contains offsets in the persistence file of the undo |
| 215 |
* commands. |
| 216 |
*/ |
| 217 |
private List fIndex = new ArrayList(); |
| 218 |
|
| 219 |
/** |
| 220 |
* Add an entry to the stack at the given position. |
| 221 |
* @param a The position to add the entry to the stack. |
| 222 |
* @param s The entry to add to the stack. |
| 223 |
*/ |
| 224 |
private void add(int a, Serializable s) { |
| 225 |
try { |
| 226 |
Long i = persistenceCache.put(s); |
| 227 |
fIndex.add(a, i); |
| 228 |
} |
| 229 |
catch (IOException ioe) { |
| 230 |
ioe.printStackTrace(); |
| 231 |
|
| 232 |
// undo stack is corrupt, wipe it to avoid further damage. |
| 233 |
fIndex.clear(); |
| 234 |
} |
| 235 |
} |
| 236 |
|
| 237 |
/** |
| 238 |
* Add an entry to the top of the stack. |
| 239 |
* @param s The entry to put on top of the stack. |
| 240 |
*/ |
| 241 |
private void add(TextCommand s) { |
| 242 |
try { |
| 243 |
Long i = persistenceCache.put(s); |
| 244 |
fIndex.add(i); |
| 245 |
} |
| 246 |
catch (IOException ioe) { |
| 247 |
ioe.printStackTrace(); |
| 248 |
|
| 249 |
// undo stack is corrupt, wipe it to avoid further damage. |
| 250 |
fIndex.clear(); |
| 251 |
} |
| 252 |
} |
| 253 |
|
| 254 |
/** |
| 255 |
* Get the undo command at the requested postition in the stack. |
| 256 |
* @param counter The position of the requested command. |
| 257 |
* @return The command at that position. |
| 258 |
*/ |
| 259 |
private TextCommand get(int counter) { |
| 260 |
try { |
| 261 |
Long i = (Long)fIndex.get(counter); |
| 262 |
TextCommand tc= (TextCommand) persistenceCache.get(i); |
| 263 |
|
| 264 |
// Replace the transient field that may be lost during serialization. |
| 265 |
tc.setUndoManager(DefaultUndoManager.this); |
| 266 |
|
| 267 |
return tc; |
| 268 |
} |
| 269 |
catch (IOException ioe) { |
| 270 |
ioe.printStackTrace(); |
| 271 |
|
| 272 |
throw new RuntimeException("", ioe); //$NON-NLS-1$ |
| 273 |
} |
| 274 |
} |
| 275 |
|
| 276 |
/** |
| 277 |
* Truncate the stack to the parameter size. Entries will be |
| 278 |
* removed fro mthe otp of the stack. |
| 279 |
* @param size The size of the stack after the truncation. |
| 280 |
*/ |
| 281 |
private void truncate(int size) { |
| 282 |
while (fIndex.size() > size) { |
| 283 |
fIndex.remove(size); |
| 284 |
} |
| 285 |
} |
| 286 |
|
| 287 |
/** |
| 288 |
* The stack's size. |
| 289 |
* @return The size of the stack. |
| 290 |
*/ |
| 291 |
private int size() { |
| 292 |
return fIndex.size(); |
| 293 |
} |
| 294 |
} |
| 295 |
|
| 296 |
/** |
| 297 |
* The range of chars in the document that was changed by an edit. |
| 298 |
*/ |
| 299 |
static class Range implements Cloneable { |
| 300 |
int fStart; |
| 301 |
int fEnd; |
| 302 |
int fOverwritten; |
| 303 |
int fCursor; |
| 304 |
|
| 305 |
public Object clone() { |
| 306 |
try { |
| 307 |
return super.clone(); |
| 308 |
} catch (CloneNotSupportedException clnse) { |
| 309 |
throw new RuntimeException(clnse); |
| 310 |
} |
| 311 |
} |
| 312 |
} |
| 44 |
|
313 |
|
| 45 |
/** |
314 |
/** |
| 46 |
* Represents an undo-able edit command. |
315 |
* Represents an undo-able edit command. |
| 47 |
*/ |
316 |
*/ |
| 48 |
class TextCommand { |
317 |
static class TextCommand implements Serializable { |
|
|
318 |
|
| 319 |
/** |
| 320 |
* Silence Eclipse's warnings. |
| 321 |
*/ |
| 322 |
private static final long serialVersionUID = 6009335074727417445L; |
| 323 |
|
| 324 |
/** |
| 325 |
* Psuedo-inner class. Allow us to serialize the command without |
| 326 |
* serializing the undo manager. |
| 327 |
*/ |
| 328 |
transient DefaultUndoManager fParent; |
| 49 |
|
329 |
|
| 50 |
/** The start index of the replaced text */ |
330 |
/** The start index of the replaced text */ |
| 51 |
protected int fStart= -1; |
331 |
protected int fStart= -1; |
|
Lines 55-60
Link Here
|
| 55 |
protected String fText; |
335 |
protected String fText; |
| 56 |
/** The replaced text */ |
336 |
/** The replaced text */ |
| 57 |
protected String fPreservedText; |
337 |
protected String fPreservedText; |
|
|
338 |
/** Was the text typed rather that pasted */ |
| 339 |
protected boolean fTyped= false; |
| 340 |
|
| 341 |
TextCommand(DefaultUndoManager parent) { |
| 342 |
this.fParent= parent; |
| 343 |
} |
| 344 |
|
| 345 |
/** |
| 346 |
* Used when deserializing the command. |
| 347 |
* @param um The undo-manager this command is part of. |
| 348 |
*/ |
| 349 |
void setUndoManager(DefaultUndoManager um) { |
| 350 |
fParent= um; |
| 351 |
} |
| 58 |
|
352 |
|
| 59 |
/** |
353 |
/** |
| 60 |
* Re-initializes this text command. |
354 |
* Re-initializes this text command. |
|
Lines 84-90
Link Here
|
| 84 |
*/ |
378 |
*/ |
| 85 |
protected void undoTextChange() { |
379 |
protected void undoTextChange() { |
| 86 |
try { |
380 |
try { |
| 87 |
fTextViewer.getDocument().replace(fStart, fText.length(), fPreservedText); |
381 |
fParent.fTextViewer.getDocument().replace(fStart, fText.length(), fPreservedText); |
| 88 |
} catch (BadLocationException x) { |
382 |
} catch (BadLocationException x) { |
| 89 |
} |
383 |
} |
| 90 |
} |
384 |
} |
|
Lines 95-101
Link Here
|
| 95 |
*/ |
389 |
*/ |
| 96 |
protected void undo() { |
390 |
protected void undo() { |
| 97 |
undoTextChange(); |
391 |
undoTextChange(); |
| 98 |
selectAndReveal(fStart, fPreservedText == null ? 0 : fPreservedText.length()); |
392 |
fParent.selectAndReveal(fStart, fPreservedText == null ? 0 : fPreservedText.length()); |
| 99 |
} |
393 |
} |
| 100 |
|
394 |
|
| 101 |
/** |
395 |
/** |
|
Lines 105-111
Link Here
|
| 105 |
*/ |
399 |
*/ |
| 106 |
protected void redoTextChange() { |
400 |
protected void redoTextChange() { |
| 107 |
try { |
401 |
try { |
| 108 |
fTextViewer.getDocument().replace(fStart, fEnd - fStart, fText); |
402 |
fParent.fTextViewer.getDocument().replace(fStart, fEnd - fStart, fText); |
| 109 |
} catch (BadLocationException x) { |
403 |
} catch (BadLocationException x) { |
| 110 |
} |
404 |
} |
| 111 |
} |
405 |
} |
|
Lines 116-122
Link Here
|
| 116 |
*/ |
410 |
*/ |
| 117 |
protected void redo() { |
411 |
protected void redo() { |
| 118 |
redoTextChange(); |
412 |
redoTextChange(); |
| 119 |
selectAndReveal(fStart, fText == null ? 0 : fText.length()); |
413 |
fParent.selectAndReveal(fStart, fText == null ? 0 : fText.length()); |
| 120 |
} |
414 |
} |
| 121 |
|
415 |
|
| 122 |
/** |
416 |
/** |
|
Lines 125-140
Link Here
|
| 125 |
*/ |
419 |
*/ |
| 126 |
protected void updateCommandStack() { |
420 |
protected void updateCommandStack() { |
| 127 |
|
421 |
|
| 128 |
int length= fCommandStack.size(); |
422 |
fParent.fCommandStack.truncate(fParent.fCommandCounter + 1); |
| 129 |
for (int i= fCommandCounter + 1; i < length; i++) |
|
|
| 130 |
fCommandStack.remove(fCommandCounter + 1); |
| 131 |
|
423 |
|
| 132 |
fCommandStack.add(this); |
424 |
fParent.fCommandStack.add(this); |
| 133 |
|
425 |
|
| 134 |
while (fCommandStack.size() > fUndoLevel) |
426 |
fParent.fCommandCounter++; |
| 135 |
fCommandStack.remove(0); |
|
|
| 136 |
|
| 137 |
fCommandCounter= fCommandStack.size() - 1; |
| 138 |
} |
427 |
} |
| 139 |
|
428 |
|
| 140 |
/** |
429 |
/** |
|
Lines 144-150
Link Here
|
| 144 |
* @return a new, uncommitted text command or a compound text command |
433 |
* @return a new, uncommitted text command or a compound text command |
| 145 |
*/ |
434 |
*/ |
| 146 |
protected TextCommand createCurrent() { |
435 |
protected TextCommand createCurrent() { |
| 147 |
return fFoldingIntoCompoundChange ? new CompoundTextCommand() : new TextCommand(); |
436 |
return fParent.fFoldingIntoCompoundChange ? new CompoundTextCommand(fParent) : new TextCommand(fParent); |
|
|
437 |
} |
| 438 |
|
| 439 |
/** |
| 440 |
* Replaces sequential commands at the top of the stack with a single |
| 441 |
* command if they are on the same line and we have started a new line. |
| 442 |
*/ |
| 443 |
protected void collateStack() { |
| 444 |
if (fParent.fCommandCounter < 1) |
| 445 |
return; |
| 446 |
|
| 447 |
// If this previous command is collateable with this one then we |
| 448 |
// haven't reached the end of a line and don't want to collate yet. |
| 449 |
TextCommand previous= fParent.fCommandStack.get(fParent.fCommandCounter); |
| 450 |
if (previous.isCollatable(this)) |
| 451 |
return; |
| 452 |
|
| 453 |
// if the current command cannot be collated with any preceding ones |
| 454 |
// then collate all the preceding ones that are on the same line. |
| 455 |
|
| 456 |
CompoundTextCommand compoundTextCommand= new CompoundTextCommand(fParent); |
| 457 |
int counter= fParent.fCommandCounter; |
| 458 |
|
| 459 |
TextCommand lastTc= null; |
| 460 |
while (counter >= 0) { |
| 461 |
TextCommand top= fParent.fCommandStack.get(counter); |
| 462 |
|
| 463 |
if (top.isCollatable(lastTc)) { |
| 464 |
counter--; |
| 465 |
top.addSelf(compoundTextCommand.fCommands); |
| 466 |
lastTc= top; |
| 467 |
} else { |
| 468 |
break; |
| 469 |
} |
| 470 |
} |
| 471 |
|
| 472 |
if (counter < fParent.fCommandCounter - 1) { |
| 473 |
// Note: all the entries higher in the stack will be |
| 474 |
// overwritten/truncated by updateCommandStack(). |
| 475 |
fParent.fCommandStack.add(counter + 1, compoundTextCommand); |
| 476 |
fParent.fCommandCounter= counter + 1; |
| 477 |
|
| 478 |
// Keep on collating until there is nothing left to do. |
| 479 |
collateStack(); |
| 480 |
} |
| 148 |
} |
481 |
} |
| 149 |
|
482 |
|
| 150 |
/** |
483 |
/** |
|
Lines 156-170
Link Here
|
| 156 |
reinitialize(); |
489 |
reinitialize(); |
| 157 |
} else { |
490 |
} else { |
| 158 |
|
491 |
|
| 159 |
fText= fTextBuffer.toString(); |
492 |
fText= fParent.fTextBuffer.toString(); |
| 160 |
fTextBuffer.setLength(0); |
493 |
fParent.fTextBuffer.setLength(0); |
| 161 |
fPreservedText= fPreservedTextBuffer.toString(); |
494 |
fPreservedText= fParent.fPreservedTextBuffer.toString(); |
| 162 |
fPreservedTextBuffer.setLength(0); |
495 |
fParent.fPreservedTextBuffer.setLength(0); |
| 163 |
|
496 |
|
|
|
497 |
if (fParent.fAutoCollate) { |
| 498 |
collateStack(); |
| 499 |
} |
| 164 |
updateCommandStack(); |
500 |
updateCommandStack(); |
| 165 |
} |
501 |
} |
| 166 |
|
502 |
|
| 167 |
fCurrent= createCurrent(); |
503 |
fParent.fCurrent= createCurrent(); |
|
|
504 |
} |
| 505 |
|
| 506 |
/** |
| 507 |
* Is this a chunk that can be collated into another to form one line. |
| 508 |
* |
| 509 |
* @param next a TextCommand to test for collatability with this one. |
| 510 |
* @return true if this TextCommand is collateable with <code>next</code> |
| 511 |
*/ |
| 512 |
protected boolean isCollatable(TextCommand next) { |
| 513 |
|
| 514 |
if (next != null) { |
| 515 |
Range range= new Range(); |
| 516 |
range.fStart= fStart; |
| 517 |
range.fEnd= fStart + fText.length(); |
| 518 |
if (!next.isCollatable()) |
| 519 |
return false; |
| 520 |
if (!next.isOverlapping(range, false)) |
| 521 |
return false; |
| 522 |
} |
| 523 |
|
| 524 |
return isCollatable(); |
| 525 |
} |
| 526 |
|
| 527 |
/** |
| 528 |
* Is it possible that this command can be collated with others. |
| 529 |
* @return true if it can be collated. |
| 530 |
*/ |
| 531 |
protected boolean isCollatable() { |
| 532 |
|
| 533 |
// A deletion of text, do not allow this to be |
| 534 |
// confused with eating code-complete or lost to over-zelaous |
| 535 |
// collation. |
| 536 |
if (fPreservedText.length() > 0 && fText.length() == 0) { |
| 537 |
return false; |
| 538 |
} |
| 539 |
|
| 540 |
String[] delimiters= fParent.fTextViewer.getDocument().getLegalLineDelimiters(); |
| 541 |
int[] idxs= TextUtilities.indexOf(delimiters, fText, 0); |
| 542 |
if (idxs[0] != -1 || idxs[1] != -1) { |
| 543 |
return false; |
| 544 |
} |
| 545 |
|
| 546 |
delimiters= fParent.fTextViewer.getDocument().getLegalLineDelimiters(); |
| 547 |
idxs= TextUtilities.indexOf(delimiters, fPreservedText, 0); |
| 548 |
if (idxs[0] != -1 || idxs[1] != -1) { |
| 549 |
return false; |
| 550 |
} |
| 551 |
|
| 552 |
return true; |
| 553 |
} |
| 554 |
|
| 555 |
/** |
| 556 |
* Does the range of chars this command overlap with the range passed |
| 557 |
* in. |
| 558 |
* |
| 559 |
* @param range The range to test for overlap with this one. |
| 560 |
* @param start The edit may have changed the positions of chars |
| 561 |
* after this undo. If true compare the overlap using the original |
| 562 |
* document (before the edit which created the undo) as a reference. |
| 563 |
* If false use the document after the edit. |
| 564 |
* @return Whether the parameter range overlaps this one. |
| 565 |
*/ |
| 566 |
protected boolean isOverlapping(Range range, boolean start) { |
| 567 |
|
| 568 |
int localEnd; |
| 569 |
if (start) { |
| 570 |
localEnd= fStart + fPreservedText.length(); |
| 571 |
} |
| 572 |
else { |
| 573 |
localEnd= fStart + fText.length(); |
| 574 |
} |
| 575 |
return ((range.fStart <= fStart && fStart <= range.fEnd) || |
| 576 |
(range.fStart <= localEnd && localEnd <= range.fEnd)); |
| 577 |
} |
| 578 |
|
| 579 |
/** |
| 580 |
* Take a range and 'expand' the range to include the range covered by |
| 581 |
* this undo command. In other words: return a range that is the |
| 582 |
* combination of the parameter range and this undo command's range. |
| 583 |
* |
| 584 |
* @param range The range to combine with this undo's range. |
| 585 |
* @return A range which includes both the parameter range and this undo's |
| 586 |
* range. |
| 587 |
*/ |
| 588 |
protected Range expandRange(Range range) { |
| 589 |
if (range == null) { |
| 590 |
range= new Range(); |
| 591 |
range.fStart= fStart; |
| 592 |
range.fEnd= fStart + fText.length(); |
| 593 |
range.fCursor= fStart; |
| 594 |
range.fOverwritten= fPreservedText.length(); |
| 595 |
|
| 596 |
return range; |
| 597 |
} |
| 598 |
|
| 599 |
if (fStart < range.fStart) { |
| 600 |
range.fStart= fStart; |
| 601 |
} |
| 602 |
|
| 603 |
if (fStart + fText.length() > range.fCursor) { |
| 604 |
int overlap= (fStart + fText.length() - range.fCursor); |
| 605 |
|
| 606 |
if (overlap > range.fOverwritten) { |
| 607 |
range.fEnd= range.fEnd + overlap - range.fOverwritten; |
| 608 |
range.fOverwritten= 0; |
| 609 |
} else { |
| 610 |
range.fOverwritten -= overlap; |
| 611 |
} |
| 612 |
} |
| 613 |
|
| 614 |
range.fOverwritten += fPreservedText.length(); |
| 615 |
|
| 616 |
range.fCursor= fStart; |
| 617 |
|
| 618 |
return range; |
| 619 |
} |
| 620 |
|
| 621 |
/** |
| 622 |
* Add this command to the parameter list. |
| 623 |
* @param commands The list to add this command to. |
| 624 |
*/ |
| 625 |
protected void addSelf(List commands) { |
| 626 |
commands.add(0, this); |
| 168 |
} |
627 |
} |
| 169 |
} |
628 |
} |
| 170 |
|
629 |
|
|
Lines 172-182
Link Here
|
| 172 |
* Represents an undo-able edit command consisting of several |
631 |
* Represents an undo-able edit command consisting of several |
| 173 |
* individual edit commands. |
632 |
* individual edit commands. |
| 174 |
*/ |
633 |
*/ |
| 175 |
class CompoundTextCommand extends TextCommand { |
634 |
static class CompoundTextCommand extends TextCommand { |
|
|
635 |
|
| 636 |
/** |
| 637 |
* Silence Eclipse warning. |
| 638 |
*/ |
| 639 |
private static final long serialVersionUID = 6009335074727417445L; |
| 176 |
|
640 |
|
| 177 |
/** The list of individual commands */ |
641 |
/** The list of individual commands */ |
| 178 |
private List fCommands= new ArrayList(); |
642 |
private List fCommands= new ArrayList(); |
| 179 |
|
643 |
|
|
|
644 |
CompoundTextCommand(DefaultUndoManager parent) { |
| 645 |
super(parent); |
| 646 |
} |
| 647 |
|
| 648 |
/* (non-Javadoc) |
| 649 |
* @see org.eclipse.jface.text.DefaultUndoManager.TextCommand#setUndoManager(org.eclipse.jface.text.DefaultUndoManager) |
| 650 |
*/ |
| 651 |
void setUndoManager(DefaultUndoManager um) { |
| 652 |
super.setUndoManager(um); |
| 653 |
for (int i= 0; i < fCommands.size(); i++) { |
| 654 |
((TextCommand)fCommands.get(i)).setUndoManager(um); |
| 655 |
} |
| 656 |
} |
| 657 |
|
| 180 |
/** |
658 |
/** |
| 181 |
* Adds a new individual command to this compound command. |
659 |
* Adds a new individual command to this compound command. |
| 182 |
* |
660 |
* |
|
Lines 191-198
Link Here
|
| 191 |
*/ |
669 |
*/ |
| 192 |
protected void undo() { |
670 |
protected void undo() { |
| 193 |
ITextViewerExtension extension= null; |
671 |
ITextViewerExtension extension= null; |
| 194 |
if (fTextViewer instanceof ITextViewerExtension) |
672 |
if (fParent.fTextViewer instanceof ITextViewerExtension) |
| 195 |
extension= (ITextViewerExtension) fTextViewer; |
673 |
extension= (ITextViewerExtension) fParent.fTextViewer; |
| 196 |
|
674 |
|
| 197 |
if (extension != null) |
675 |
if (extension != null) |
| 198 |
extension.setRedraw(false); |
676 |
extension.setRedraw(false); |
|
Lines 225-232
Link Here
|
| 225 |
protected void redo() { |
703 |
protected void redo() { |
| 226 |
|
704 |
|
| 227 |
ITextViewerExtension extension= null; |
705 |
ITextViewerExtension extension= null; |
| 228 |
if (fTextViewer instanceof ITextViewerExtension) |
706 |
if (fParent.fTextViewer instanceof ITextViewerExtension) |
| 229 |
extension= (ITextViewerExtension) fTextViewer; |
707 |
extension= (ITextViewerExtension) fParent.fTextViewer; |
| 230 |
|
708 |
|
| 231 |
if (extension != null) |
709 |
if (extension != null) |
| 232 |
extension.setRedraw(false); |
710 |
extension.setRedraw(false); |
|
Lines 257-263
Link Here
|
| 257 |
* @see TextCommand#updateCommandStack |
735 |
* @see TextCommand#updateCommandStack |
| 258 |
*/ |
736 |
*/ |
| 259 |
protected void updateCommandStack() { |
737 |
protected void updateCommandStack() { |
| 260 |
TextCommand c= new TextCommand(); |
738 |
TextCommand c= new TextCommand(fParent); |
| 261 |
c.fStart= fStart; |
739 |
c.fStart= fStart; |
| 262 |
c.fEnd= fEnd; |
740 |
c.fEnd= fEnd; |
| 263 |
c.fText= fText; |
741 |
c.fText= fText; |
|
Lines 265-271
Link Here
|
| 265 |
|
743 |
|
| 266 |
add(c); |
744 |
add(c); |
| 267 |
|
745 |
|
| 268 |
if (!fFoldingIntoCompoundChange) |
746 |
if (!fParent.fFoldingIntoCompoundChange) |
| 269 |
super.updateCommandStack(); |
747 |
super.updateCommandStack(); |
| 270 |
} |
748 |
} |
| 271 |
|
749 |
|
|
Lines 274-281
Link Here
|
| 274 |
*/ |
752 |
*/ |
| 275 |
protected TextCommand createCurrent() { |
753 |
protected TextCommand createCurrent() { |
| 276 |
|
754 |
|
| 277 |
if (!fFoldingIntoCompoundChange) |
755 |
if (!fParent.fFoldingIntoCompoundChange) |
| 278 |
return new TextCommand(); |
756 |
return new TextCommand(fParent); |
| 279 |
|
757 |
|
| 280 |
reinitialize(); |
758 |
reinitialize(); |
| 281 |
return this; |
759 |
return this; |
|
Lines 286-299
Link Here
|
| 286 |
*/ |
764 |
*/ |
| 287 |
protected void commit() { |
765 |
protected void commit() { |
| 288 |
if (fStart < 0) { |
766 |
if (fStart < 0) { |
| 289 |
if (fCommands.size() > 0 && !fFoldingIntoCompoundChange) { |
767 |
if (fCommands.size() > 0 && !fParent.fFoldingIntoCompoundChange) { |
| 290 |
super.updateCommandStack(); |
768 |
super.updateCommandStack(); |
| 291 |
fCurrent= createCurrent(); |
769 |
fParent.fCurrent= createCurrent(); |
| 292 |
return; |
770 |
return; |
| 293 |
} |
771 |
} |
| 294 |
} |
772 |
} |
| 295 |
super.commit(); |
773 |
super.commit(); |
| 296 |
} |
774 |
} |
|
|
775 |
|
| 776 |
/* (non-Javadoc) |
| 777 |
* @see org.eclipse.jface.text.DefaultUndoManager.TextCommand#isCollatable(org.eclipse.jface.text.DefaultUndoManager.TextCommand) |
| 778 |
*/ |
| 779 |
protected boolean isCollatable(TextCommand next) { |
| 780 |
|
| 781 |
Range currentRange= null; |
| 782 |
|
| 783 |
if (next != null) { |
| 784 |
currentRange= next.expandRange(null); |
| 785 |
} |
| 786 |
|
| 787 |
// See if the param range is collatable with all the component |
| 788 |
// commands in order. |
| 789 |
for (int i= fCommands.size() - 1; i >= 0; i--) { |
| 790 |
TextCommand tc= (TextCommand) fCommands.get(i); |
| 791 |
|
| 792 |
if (!tc.isCollatable()) { |
| 793 |
return false; |
| 794 |
} |
| 795 |
if (currentRange != null && !tc.isOverlapping(currentRange, false)) { |
| 796 |
return false; |
| 797 |
} |
| 798 |
|
| 799 |
currentRange= tc.expandRange(currentRange); |
| 800 |
} |
| 801 |
|
| 802 |
return true; |
| 803 |
} |
| 804 |
|
| 805 |
/* (non-Javadoc) |
| 806 |
* @see org.eclipse.jface.text.DefaultUndoManager.TextCommand#isOverlapping(org.eclipse.jface.text.DefaultUndoManager.Range, boolean) |
| 807 |
*/ |
| 808 |
protected boolean isOverlapping(Range range, boolean start) { |
| 809 |
|
| 810 |
Range localRange= (Range)range.clone(); |
| 811 |
|
| 812 |
for (int i= fCommands.size() - 1; i >= 0; i--) { |
| 813 |
TextCommand tc= (TextCommand) fCommands.get(i); |
| 814 |
|
| 815 |
if (!tc.isOverlapping(localRange, start)) { |
| 816 |
return false; |
| 817 |
} |
| 818 |
|
| 819 |
localRange= tc.expandRange(localRange); |
| 820 |
} |
| 821 |
|
| 822 |
return true; |
| 823 |
} |
| 824 |
|
| 825 |
/* (non-Javadoc) |
| 826 |
* @see org.eclipse.jface.text.DefaultUndoManager.TextCommand#isCollatable() |
| 827 |
*/ |
| 828 |
protected boolean isCollatable() { |
| 829 |
|
| 830 |
for (int i= fCommands.size() - 1; i >= 0; i--) { |
| 831 |
TextCommand tc= (TextCommand) fCommands.get(i); |
| 832 |
|
| 833 |
if (!tc.isCollatable()) { |
| 834 |
return false; |
| 835 |
} |
| 836 |
} |
| 837 |
|
| 838 |
return true; |
| 839 |
} |
| 840 |
|
| 841 |
/* (non-Javadoc) |
| 842 |
* @see org.eclipse.jface.text.DefaultUndoManager.TextCommand#expandRange(org.eclipse.jface.text.DefaultUndoManager.Range) |
| 843 |
*/ |
| 844 |
protected Range expandRange(Range range) { |
| 845 |
for (int i= fCommands.size() - 1; i >= 0; i--) { |
| 846 |
TextCommand tc= (TextCommand) fCommands.get(i); |
| 847 |
|
| 848 |
range= tc.expandRange(range); |
| 849 |
} |
| 850 |
|
| 851 |
return range; |
| 852 |
} |
| 853 |
|
| 854 |
/* (non-Javadoc) |
| 855 |
* @see org.eclipse.jface.text.DefaultUndoManager.TextCommand#addSelf(java.util.List) |
| 856 |
*/ |
| 857 |
protected void addSelf(List commands) { |
| 858 |
int length= fCommands.size(); |
| 859 |
for (int i= length - 1; i >= 0; i--) { |
| 860 |
TextCommand tc= (TextCommand)fCommands.get(i); |
| 861 |
tc.addSelf(commands); |
| 862 |
} |
| 863 |
} |
| 297 |
} |
864 |
} |
| 298 |
|
865 |
|
| 299 |
/** |
866 |
/** |
|
Lines 408-413
Link Here
|
| 408 |
|
975 |
|
| 409 |
} |
976 |
} |
| 410 |
|
977 |
|
|
|
978 |
private static PersistenceCache persistenceCache = new PersistenceCache(); |
| 979 |
|
| 411 |
|
980 |
|
| 412 |
/** Text buffer to collect text which is inserted into the viewer */ |
981 |
/** Text buffer to collect text which is inserted into the viewer */ |
| 413 |
private StringBuffer fTextBuffer= new StringBuffer(); |
982 |
private StringBuffer fTextBuffer= new StringBuffer(); |
|
Lines 423-430
Link Here
|
| 423 |
private TextInputListener fTextInputListener; |
992 |
private TextInputListener fTextInputListener; |
| 424 |
|
993 |
|
| 425 |
|
994 |
|
| 426 |
/** Indicates inserting state */ |
|
|
| 427 |
private boolean fInserting= false; |
| 428 |
/** Indicates overwriting state */ |
995 |
/** Indicates overwriting state */ |
| 429 |
private boolean fOverwriting= false; |
996 |
private boolean fOverwriting= false; |
| 430 |
/** Indicates whether the current change belongs to a compound change */ |
997 |
/** Indicates whether the current change belongs to a compound change */ |
|
Lines 433-449
Link Here
|
| 433 |
/** The text viewer the undo manager is connected to */ |
1000 |
/** The text viewer the undo manager is connected to */ |
| 434 |
private ITextViewer fTextViewer; |
1001 |
private ITextViewer fTextViewer; |
| 435 |
|
1002 |
|
| 436 |
/** Supported undo level */ |
|
|
| 437 |
private int fUndoLevel; |
| 438 |
/** The list of undo-able edit commands */ |
1003 |
/** The list of undo-able edit commands */ |
| 439 |
private List fCommandStack; |
1004 |
private CommandStack fCommandStack; |
| 440 |
/** The currently constructed edit command */ |
1005 |
/** The currently constructed edit command */ |
| 441 |
private TextCommand fCurrent; |
1006 |
private TextCommand fCurrent; |
| 442 |
/** The last delete edit command */ |
1007 |
/** The last delete edit command */ |
| 443 |
private TextCommand fPreviousDelete; |
1008 |
private TextCommand fPreviousDelete; |
| 444 |
/** Command counter into the edit command stack */ |
1009 |
/** Command counter into the edit command stack */ |
| 445 |
private int fCommandCounter= -1; |
1010 |
private int fCommandCounter= -1; |
| 446 |
|
1011 |
|
|
|
1012 |
/** Split words into chunks. */ |
| 1013 |
private boolean fChunkWords; |
| 1014 |
/** Split lines into chunks. */ |
| 1015 |
private boolean fChunkLines; |
| 1016 |
/** Join together chunks on line-breaks. */ |
| 1017 |
private boolean fAutoCollate; |
| 447 |
|
1018 |
|
| 448 |
/** |
1019 |
/** |
| 449 |
* Creates a new undo manager who remembers the specified number of edit commands. |
1020 |
* Creates a new undo manager who remembers the specified number of edit commands. |
|
Lines 451-457
Link Here
|
| 451 |
* @param undoLevel the length of this manager's history |
1022 |
* @param undoLevel the length of this manager's history |
| 452 |
*/ |
1023 |
*/ |
| 453 |
public DefaultUndoManager(int undoLevel) { |
1024 |
public DefaultUndoManager(int undoLevel) { |
| 454 |
setMaximalUndoLevel(undoLevel); |
1025 |
this(true, true, true); |
|
|
1026 |
} |
| 1027 |
|
| 1028 |
/** |
| 1029 |
* Creates a new undo manager. |
| 1030 |
* <p> |
| 1031 |
* The only valid combinations of (chunkWords, chunkLines, autoCollate) are: |
| 1032 |
* <ul> |
| 1033 |
* <li>(true, true, false) - Fine-grain undo |
| 1034 |
* <li>(true, true, true) - Smart undo (recommended) |
| 1035 |
* <li>(false, false, false) - Course-grain undo (classic Eclipse undo) |
| 1036 |
* </ul> |
| 1037 |
* Using other combinations may not produce satisfying undos. |
| 1038 |
* |
| 1039 |
* @param chunkWords Split words into chunks. |
| 1040 |
* @param chunkLines Split lines into chunks. |
| 1041 |
* @param autoCollate Join together chunks on line-breaks. |
| 1042 |
*/ |
| 1043 |
public DefaultUndoManager(boolean chunkWords, boolean chunkLines, boolean autoCollate) { |
| 1044 |
this.fChunkLines= chunkLines; |
| 1045 |
this.fChunkWords= chunkWords; |
| 1046 |
this.fAutoCollate= autoCollate; |
| 455 |
} |
1047 |
} |
| 456 |
|
1048 |
|
| 457 |
/** |
1049 |
/** |
|
Lines 542-548
Link Here
|
| 542 |
*/ |
1134 |
*/ |
| 543 |
private void commit() { |
1135 |
private void commit() { |
| 544 |
|
1136 |
|
| 545 |
fInserting= false; |
|
|
| 546 |
fOverwriting= false; |
1137 |
fOverwriting= false; |
| 547 |
fPreviousDelete.reinitialize(); |
1138 |
fPreviousDelete.reinitialize(); |
| 548 |
|
1139 |
|
|
Lines 554-580
Link Here
|
| 554 |
*/ |
1145 |
*/ |
| 555 |
private void internalRedo() { |
1146 |
private void internalRedo() { |
| 556 |
++fCommandCounter; |
1147 |
++fCommandCounter; |
| 557 |
TextCommand cmd= (TextCommand) fCommandStack.get(fCommandCounter); |
1148 |
TextCommand cmd= fCommandStack.get(fCommandCounter); |
| 558 |
|
1149 |
|
| 559 |
listenToTextChanges(false); |
1150 |
listenToTextChanges(false); |
| 560 |
cmd.redo(); |
1151 |
cmd.redo(); |
| 561 |
listenToTextChanges(true); |
1152 |
listenToTextChanges(true); |
| 562 |
|
1153 |
|
| 563 |
fCurrent= new TextCommand(); |
1154 |
fCurrent= new TextCommand(this); |
| 564 |
} |
1155 |
} |
| 565 |
|
1156 |
|
| 566 |
/** |
1157 |
/** |
| 567 |
* Does undo the last editing command. |
1158 |
* Does undo the last editing command. |
| 568 |
*/ |
1159 |
*/ |
| 569 |
private void internalUndo() { |
1160 |
private void internalUndo() { |
| 570 |
TextCommand cmd= (TextCommand) fCommandStack.get(fCommandCounter); |
1161 |
TextCommand cmd= fCommandStack.get(fCommandCounter); |
| 571 |
-- fCommandCounter; |
1162 |
-- fCommandCounter; |
| 572 |
|
1163 |
|
| 573 |
listenToTextChanges(false); |
1164 |
listenToTextChanges(false); |
| 574 |
cmd.undo(); |
1165 |
cmd.undo(); |
| 575 |
listenToTextChanges(true); |
1166 |
listenToTextChanges(true); |
| 576 |
|
1167 |
|
| 577 |
fCurrent= new TextCommand(); |
1168 |
fCurrent= new TextCommand(this); |
| 578 |
} |
1169 |
} |
| 579 |
|
1170 |
|
| 580 |
/** |
1171 |
/** |
|
Lines 616-623
Link Here
|
| 616 |
fPretendedState.cmdCounter= fCommandCounter; |
1207 |
fPretendedState.cmdCounter= fCommandCounter; |
| 617 |
} else { |
1208 |
} else { |
| 618 |
int sz= Math.max(fCommandCounter, 0) + 1; |
1209 |
int sz= Math.max(fCommandCounter, 0) + 1; |
| 619 |
if (sz > fUndoLevel) |
|
|
| 620 |
sz -= fUndoLevel; |
| 621 |
fPretendedState.stackSize= sz; |
1210 |
fPretendedState.stackSize= sz; |
| 622 |
fPretendedState.cmdCounter= sz - 1; |
1211 |
fPretendedState.cmdCounter= sz - 1; |
| 623 |
} |
1212 |
} |
|
Lines 646-659
Link Here
|
| 646 |
// text will be inserted |
1235 |
// text will be inserted |
| 647 |
if ((length == 1) || isWhitespaceText(insertedText)) { |
1236 |
if ((length == 1) || isWhitespaceText(insertedText)) { |
| 648 |
// by typing or model manipulation |
1237 |
// by typing or model manipulation |
| 649 |
if (!fInserting || (modelStart != fCurrent.fStart + fTextBuffer.length())) { |
1238 |
if (!fCurrent.fTyped || (modelStart != fCurrent.fStart + fTextBuffer.length()) || (isWhitespaceText(insertedText) && fChunkLines)) { |
| 650 |
commit(); |
1239 |
commit(); |
| 651 |
fInserting= true; |
1240 |
fCurrent.fTyped= true; |
| 652 |
} |
1241 |
} else if (fTextBuffer.length() > 0 && Character.isLetterOrDigit(fTextBuffer.charAt(fTextBuffer.length() - 1))) { |
|
|
1242 |
// chunk at the end of words |
| 1243 |
if (!Character.isLetterOrDigit(insertedText.charAt(0)) && fChunkWords) { |
| 1244 |
commit(); |
| 1245 |
fCurrent.fTyped= true; |
| 1246 |
} |
| 1247 |
} |
| 1248 |
|
| 653 |
if (fCurrent.fStart < 0) |
1249 |
if (fCurrent.fStart < 0) |
| 654 |
fCurrent.fStart= fCurrent.fEnd= modelStart; |
1250 |
fCurrent.fStart= fCurrent.fEnd= modelStart; |
| 655 |
if (length > 0) |
1251 |
|
| 656 |
fTextBuffer.append(insertedText); |
1252 |
fTextBuffer.append(insertedText); |
|
|
1253 |
if (isWhitespaceText(insertedText) && fChunkLines) { |
| 1254 |
commit(); |
| 1255 |
} |
| 657 |
} else if (length > 0) { |
1256 |
} else if (length > 0) { |
| 658 |
// by pasting |
1257 |
// by pasting |
| 659 |
commit(); |
1258 |
commit(); |
|
Lines 671-676
Link Here
|
| 671 |
|
1270 |
|
| 672 |
// whereby selection is empty |
1271 |
// whereby selection is empty |
| 673 |
|
1272 |
|
|
|
1273 |
// Chunk lines |
| 1274 |
if (isWhitespaceText(replacedText) && fChunkLines) { |
| 1275 |
commit(); |
| 1276 |
} |
| 1277 |
|
| 674 |
if (fPreviousDelete.fStart == modelStart && fPreviousDelete.fEnd == modelEnd) { |
1278 |
if (fPreviousDelete.fStart == modelStart && fPreviousDelete.fEnd == modelEnd) { |
| 675 |
// repeated DEL |
1279 |
// repeated DEL |
| 676 |
|
1280 |
|
|
Lines 739-744
Link Here
|
| 739 |
fCurrent.fEnd= modelEnd; |
1343 |
fCurrent.fEnd= modelEnd; |
| 740 |
fTextBuffer.append(insertedText); |
1344 |
fTextBuffer.append(insertedText); |
| 741 |
fPreservedTextBuffer.append(replacedText); |
1345 |
fPreservedTextBuffer.append(replacedText); |
|
|
1346 |
|
| 1347 |
if (insertedText.length() == 1) { |
| 1348 |
fCurrent.fTyped= true; |
| 1349 |
} |
| 742 |
} |
1350 |
} |
| 743 |
} |
1351 |
} |
| 744 |
} |
1352 |
} |
|
Lines 747-753
Link Here
|
| 747 |
* @see org.eclipse.jface.text.IUndoManager#setMaximalUndoLevel(int) |
1355 |
* @see org.eclipse.jface.text.IUndoManager#setMaximalUndoLevel(int) |
| 748 |
*/ |
1356 |
*/ |
| 749 |
public void setMaximalUndoLevel(int undoLevel) { |
1357 |
public void setMaximalUndoLevel(int undoLevel) { |
| 750 |
fUndoLevel= undoLevel; |
1358 |
// Ignored |
| 751 |
} |
1359 |
} |
| 752 |
|
1360 |
|
| 753 |
/* |
1361 |
/* |
|
Lines 756-764
Link Here
|
| 756 |
public void connect(ITextViewer textViewer) { |
1364 |
public void connect(ITextViewer textViewer) { |
| 757 |
if (fTextViewer == null && textViewer != null) { |
1365 |
if (fTextViewer == null && textViewer != null) { |
| 758 |
fTextViewer= textViewer; |
1366 |
fTextViewer= textViewer; |
| 759 |
fCommandStack= new ArrayList(); |
1367 |
fCommandStack= new CommandStack(); |
| 760 |
fCurrent= new TextCommand(); |
1368 |
fCurrent= new TextCommand(this); |
| 761 |
fPreviousDelete= new TextCommand(); |
1369 |
fPreviousDelete= new TextCommand(this); |
| 762 |
addListeners(); |
1370 |
addListeners(); |
| 763 |
} |
1371 |
} |
| 764 |
} |
1372 |
} |
|
Lines 773-780
Link Here
|
| 773 |
|
1381 |
|
| 774 |
fCurrent= null; |
1382 |
fCurrent= null; |
| 775 |
if (fCommandStack != null) { |
1383 |
if (fCommandStack != null) { |
| 776 |
fCommandStack.clear(); |
1384 |
fCommandStack.truncate(0); |
| 777 |
fCommandStack= null; |
1385 |
fCommandStack= null; |
|
|
1386 |
|
| 1387 |
// Allow the GC to collect us. |
| 1388 |
persistenceCache.clear(); |
| 778 |
} |
1389 |
} |
| 779 |
fTextBuffer= null; |
1390 |
fTextBuffer= null; |
| 780 |
fPreservedTextBuffer= null; |
1391 |
fPreservedTextBuffer= null; |
|
Lines 787-799
Link Here
|
| 787 |
*/ |
1398 |
*/ |
| 788 |
public void reset() { |
1399 |
public void reset() { |
| 789 |
if (isConnected()) { |
1400 |
if (isConnected()) { |
| 790 |
if (fCommandStack != null) |
1401 |
if (fCommandStack != null) |
| 791 |
fCommandStack.clear(); |
1402 |
fCommandStack.truncate(0); |
| 792 |
fCommandCounter= -1; |
1403 |
fCommandCounter= -1; |
| 793 |
if (fCurrent != null) |
1404 |
if (fCurrent != null) |
| 794 |
fCurrent.reinitialize(); |
1405 |
fCurrent.reinitialize(); |
| 795 |
fFoldingIntoCompoundChange= false; |
1406 |
fFoldingIntoCompoundChange= false; |
| 796 |
fInserting= false; |
|
|
| 797 |
fOverwriting= false; |
1407 |
fOverwriting= false; |
| 798 |
fTextBuffer.setLength(0); |
1408 |
fTextBuffer.setLength(0); |
| 799 |
fPreservedTextBuffer.setLength(0); |
1409 |
fPreservedTextBuffer.setLength(0); |