1 7 package javax.swing.text; 8 9 import java.util.Vector ; 10 import java.io.Serializable ; 11 import javax.swing.undo.*; 12 import javax.swing.SwingUtilities ; 13 14 36 public final class StringContent implements AbstractDocument.Content , Serializable { 37 38 41 public StringContent() { 42 this(10); 43 } 44 45 51 public StringContent(int initialLength) { 52 if (initialLength < 1) { 53 initialLength = 1; 54 } 55 data = new char[initialLength]; 56 data[0] = '\n'; 57 count = 1; 58 } 59 60 66 public int length() { 67 return count; 68 } 69 70 79 public UndoableEdit insertString(int where, String str) throws BadLocationException { 80 if (where >= count || where < 0) { 81 throw new BadLocationException ("Invalid location", count); 82 } 83 char[] chars = str.toCharArray(); 84 replace(where, 0, chars, 0, chars.length); 85 if (marks != null) { 86 updateMarksForInsert(where, str.length()); 87 } 88 return new InsertUndo(where, str.length()); 89 } 90 91 100 public UndoableEdit remove(int where, int nitems) throws BadLocationException { 101 if (where + nitems >= count) { 102 throw new BadLocationException ("Invalid range", count); 103 } 104 String removedString = getString(where, nitems); 105 UndoableEdit edit = new RemoveUndo(where, removedString); 106 replace(where, nitems, empty, 0, 0); 107 if (marks != null) { 108 updateMarksForRemove(where, nitems); 109 } 110 return edit; 111 112 } 113 114 123 public String getString(int where, int len) throws BadLocationException { 124 if (where + len > count) { 125 throw new BadLocationException ("Invalid range", count); 126 } 127 return new String (data, where, len); 128 } 129 130 139 public void getChars(int where, int len, Segment chars) throws BadLocationException { 140 if (where + len > count) { 141 throw new BadLocationException ("Invalid location", count); 142 } 143 chars.array = data; 144 chars.offset = where; 145 chars.count = len; 146 } 147 148 156 public Position createPosition(int offset) throws BadLocationException { 157 if (marks == null) { 160 marks = new Vector (); 161 } 162 return new StickyPosition(offset); 163 } 164 165 167 176 void replace(int offset, int length, 177 char[] replArray, int replOffset, int replLength) { 178 int delta = replLength - length; 179 int src = offset + length; 180 int nmove = count - src; 181 int dest = src + delta; 182 if ((count + delta) >= data.length) { 183 int newLength = Math.max(2*data.length, count + delta); 185 char[] newData = new char[newLength]; 186 System.arraycopy(data, 0, newData, 0, offset); 187 System.arraycopy(replArray, replOffset, newData, offset, replLength); 188 System.arraycopy(data, src, newData, dest, nmove); 189 data = newData; 190 } else { 191 System.arraycopy(data, src, data, dest, nmove); 193 System.arraycopy(replArray, replOffset, data, offset, replLength); 194 } 195 count = count + delta; 196 } 197 198 void resize(int ncount) { 199 char[] ndata = new char[ncount]; 200 System.arraycopy(data, 0, ndata, 0, Math.min(ncount, count)); 201 data = ndata; 202 } 203 204 synchronized void updateMarksForInsert(int offset, int length) { 205 if (offset == 0) { 206 offset = 1; 209 } 210 int n = marks.size(); 211 for (int i = 0; i < n; i++) { 212 PosRec mark = (PosRec) marks.elementAt(i); 213 if (mark.unused) { 214 marks.removeElementAt(i); 216 i -= 1; 217 n -= 1; 218 } else if (mark.offset >= offset) { 219 mark.offset += length; 220 } 221 } 222 } 223 224 synchronized void updateMarksForRemove(int offset, int length) { 225 int n = marks.size(); 226 for (int i = 0; i < n; i++) { 227 PosRec mark = (PosRec) marks.elementAt(i); 228 if (mark.unused) { 229 marks.removeElementAt(i); 231 i -= 1; 232 n -= 1; 233 } else if (mark.offset >= (offset + length)) { 234 mark.offset -= length; 235 } else if (mark.offset >= offset) { 236 mark.offset = offset; 237 } 238 } 239 } 240 241 256 protected Vector getPositionsInRange(Vector v, int offset, 257 int length) { 258 int n = marks.size(); 259 int end = offset + length; 260 Vector placeIn = (v == null) ? new Vector () : v; 261 for (int i = 0; i < n; i++) { 262 PosRec mark = (PosRec) marks.elementAt(i); 263 if (mark.unused) { 264 marks.removeElementAt(i); 266 i -= 1; 267 n -= 1; 268 } else if(mark.offset >= offset && mark.offset <= end) 269 placeIn.addElement(new UndoPosRef(mark)); 270 } 271 return placeIn; 272 } 273 274 283 protected void updateUndoPositions(Vector positions) { 284 for(int counter = positions.size() - 1; counter >= 0; counter--) { 285 UndoPosRef ref = (UndoPosRef)positions.elementAt(counter); 286 if(ref.rec.unused) { 288 positions.removeElementAt(counter); 289 } 290 else 291 ref.resetLocation(); 292 } 293 } 294 295 private static final char[] empty = new char[0]; 296 private char[] data; 297 private int count; 298 transient Vector marks; 299 300 307 final class PosRec { 308 309 PosRec(int offset) { 310 this.offset = offset; 311 } 312 313 int offset; 314 boolean unused; 315 } 316 317 323 final class StickyPosition implements Position { 324 325 StickyPosition(int offset) { 326 rec = new PosRec(offset); 327 marks.addElement(rec); 328 } 329 330 public int getOffset() { 331 return rec.offset; 332 } 333 334 protected void finalize() throws Throwable { 335 rec.unused = true; 338 } 339 340 public String toString() { 341 return Integer.toString(getOffset()); 342 } 343 344 PosRec rec; 345 } 346 347 351 final class UndoPosRef { 352 UndoPosRef(PosRec rec) { 353 this.rec = rec; 354 this.undoLocation = rec.offset; 355 } 356 357 361 protected void resetLocation() { 362 rec.offset = undoLocation; 363 } 364 365 366 protected int undoLocation; 367 368 protected PosRec rec; 369 } 370 371 374 class InsertUndo extends AbstractUndoableEdit { 375 protected InsertUndo(int offset, int length) { 376 super(); 377 this.offset = offset; 378 this.length = length; 379 } 380 381 public void undo() throws CannotUndoException { 382 super.undo(); 383 try { 384 synchronized(StringContent.this) { 385 if(marks != null) 387 posRefs = getPositionsInRange(null, offset, length); 388 string = getString(offset, length); 389 remove(offset, length); 390 } 391 } catch (BadLocationException bl) { 392 throw new CannotUndoException(); 393 } 394 } 395 396 public void redo() throws CannotRedoException { 397 super.redo(); 398 try { 399 synchronized(StringContent.this) { 400 insertString(offset, string); 401 string = null; 402 if(posRefs != null) { 404 updateUndoPositions(posRefs); 405 posRefs = null; 406 } 407 } 408 } catch (BadLocationException bl) { 409 throw new CannotRedoException(); 410 } 411 } 412 413 protected int offset; 415 protected int length; 417 protected String string; 420 protected Vector posRefs; 423 } 424 425 426 429 class RemoveUndo extends AbstractUndoableEdit { 430 protected RemoveUndo(int offset, String string) { 431 super(); 432 this.offset = offset; 433 this.string = string; 434 this.length = string.length(); 435 if(marks != null) 436 posRefs = getPositionsInRange(null, offset, length); 437 } 438 439 public void undo() throws CannotUndoException { 440 super.undo(); 441 try { 442 synchronized(StringContent.this) { 443 insertString(offset, string); 444 if(posRefs != null) { 446 updateUndoPositions(posRefs); 447 posRefs = null; 448 } 449 string = null; 450 } 451 } catch (BadLocationException bl) { 452 throw new CannotUndoException(); 453 } 454 } 455 456 public void redo() throws CannotRedoException { 457 super.redo(); 458 try { 459 synchronized(StringContent.this) { 460 string = getString(offset, length); 461 if(marks != null) 463 posRefs = getPositionsInRange(null, offset, length); 464 remove(offset, length); 465 } 466 } catch (BadLocationException bl) { 467 throw new CannotRedoException(); 468 } 469 } 470 471 protected int offset; 473 protected int length; 475 protected String string; 477 protected Vector posRefs; 480 } 481 } 482 | Popular Tags |