1 7 package javax.swing.text; 8 9 import java.util.*; 10 import java.io.*; 11 import java.awt.font.TextAttribute ; 12 import java.text.Bidi ; 13 14 import javax.swing.UIManager ; 15 import javax.swing.undo.*; 16 import javax.swing.event.ChangeListener ; 17 import javax.swing.event.*; 18 import javax.swing.tree.TreeNode ; 19 20 import sun.font.BidiUtils; 21 22 82 public abstract class AbstractDocument implements Document , Serializable { 83 84 90 protected AbstractDocument(Content data) { 91 this(data, StyleContext.getDefaultStyleContext()); 92 } 93 94 101 protected AbstractDocument(Content data, AttributeContext context) { 102 this.data = data; 103 this.context = context; 104 bidiRoot = new BidiRootElement(); 105 106 if (defaultI18NProperty == null) { 107 Object o = java.security.AccessController.doPrivileged( 109 new java.security.PrivilegedAction () { 110 public Object run() { 111 return System.getProperty(I18NProperty); 112 } 113 } 114 ); 115 if (o != null) { 116 defaultI18NProperty = Boolean.valueOf((String )o); 117 } else { 118 defaultI18NProperty = Boolean.FALSE; 119 } 120 } 121 putProperty( I18NProperty, defaultI18NProperty); 122 123 writeLock(); 129 try { 130 Element [] p = new Element [1]; 131 p[0] = new BidiElement( bidiRoot, 0, 1, 0 ); 132 bidiRoot.replace(0,0,p); 133 } finally { 134 writeUnlock(); 135 } 136 } 137 138 146 public Dictionary<Object ,Object > getDocumentProperties() { 147 if (documentProperties == null) { 148 documentProperties = new Hashtable(2); 149 } 150 return documentProperties; 151 } 152 153 159 public void setDocumentProperties(Dictionary<Object ,Object > x) { 160 documentProperties = x; 161 } 162 163 172 protected void fireInsertUpdate(DocumentEvent e) { 173 notifyingListeners = true; 174 try { 175 Object [] listeners = listenerList.getListenerList(); 177 for (int i = listeners.length-2; i>=0; i-=2) { 180 if (listeners[i]==DocumentListener.class) { 181 ((DocumentListener)listeners[i+1]).insertUpdate(e); 185 } 186 } 187 } finally { 188 notifyingListeners = false; 189 } 190 } 191 192 201 protected void fireChangedUpdate(DocumentEvent e) { 202 notifyingListeners = true; 203 try { 204 Object [] listeners = listenerList.getListenerList(); 206 for (int i = listeners.length-2; i>=0; i-=2) { 209 if (listeners[i]==DocumentListener.class) { 210 ((DocumentListener)listeners[i+1]).changedUpdate(e); 214 } 215 } 216 } finally { 217 notifyingListeners = false; 218 } 219 } 220 221 230 protected void fireRemoveUpdate(DocumentEvent e) { 231 notifyingListeners = true; 232 try { 233 Object [] listeners = listenerList.getListenerList(); 235 for (int i = listeners.length-2; i>=0; i-=2) { 238 if (listeners[i]==DocumentListener.class) { 239 ((DocumentListener)listeners[i+1]).removeUpdate(e); 243 } 244 } 245 } finally { 246 notifyingListeners = false; 247 } 248 } 249 250 259 protected void fireUndoableEditUpdate(UndoableEditEvent e) { 260 Object [] listeners = listenerList.getListenerList(); 262 for (int i = listeners.length-2; i>=0; i-=2) { 265 if (listeners[i]==UndoableEditListener.class) { 266 ((UndoableEditListener)listeners[i+1]).undoableEditHappened(e); 270 } 271 } 272 } 273 274 309 public <T extends EventListener> T[] getListeners(Class <T> listenerType) { 310 return listenerList.getListeners(listenerType); 311 } 312 313 320 public int getAsynchronousLoadPriority() { 321 Integer loadPriority = (Integer ) 322 getProperty(AbstractDocument.AsyncLoadPriority); 323 if (loadPriority != null) { 324 return loadPriority.intValue(); 325 } 326 return -1; 327 } 328 329 335 public void setAsynchronousLoadPriority(int p) { 336 Integer loadPriority = (p >= 0) ? new Integer (p) : null; 337 putProperty(AbstractDocument.AsyncLoadPriority, loadPriority); 338 } 339 340 350 public void setDocumentFilter(DocumentFilter filter) { 351 documentFilter = filter; 352 } 353 354 363 public DocumentFilter getDocumentFilter() { 364 return documentFilter; 365 } 366 367 369 399 public void render(Runnable r) { 400 readLock(); 401 try { 402 r.run(); 403 } finally { 404 readUnlock(); 405 } 406 } 407 408 415 public int getLength() { 416 return data.length() - 1; 417 } 418 419 425 public void addDocumentListener(DocumentListener listener) { 426 listenerList.add(DocumentListener.class, listener); 427 } 428 429 435 public void removeDocumentListener(DocumentListener listener) { 436 listenerList.remove(DocumentListener.class, listener); 437 } 438 439 451 public DocumentListener[] getDocumentListeners() { 452 return (DocumentListener[])listenerList.getListeners( 453 DocumentListener.class); 454 } 455 456 465 public void addUndoableEditListener(UndoableEditListener listener) { 466 listenerList.add(UndoableEditListener.class, listener); 467 } 468 469 475 public void removeUndoableEditListener(UndoableEditListener listener) { 476 listenerList.remove(UndoableEditListener.class, listener); 477 } 478 479 492 public UndoableEditListener[] getUndoableEditListeners() { 493 return (UndoableEditListener[])listenerList.getListeners( 494 UndoableEditListener.class); 495 } 496 497 508 public final Object getProperty(Object key) { 509 return getDocumentProperties().get(key); 510 } 511 512 513 526 public final void putProperty(Object key, Object value) { 527 if (value != null) { 528 getDocumentProperties().put(key, value); 529 } else { 530 getDocumentProperties().remove(key); 531 } 532 if( key == TextAttribute.RUN_DIRECTION 533 && Boolean.TRUE.equals(getProperty(I18NProperty)) ) 534 { 535 writeLock(); 538 try { 539 DefaultDocumentEvent e 540 = new DefaultDocumentEvent(0, getLength(), 541 DocumentEvent.EventType.INSERT); 542 updateBidi( e ); 543 } finally { 544 writeUnlock(); 545 } 546 } 547 } 548 549 566 public void remove(int offs, int len) throws BadLocationException { 567 DocumentFilter filter = getDocumentFilter(); 568 569 writeLock(); 570 try { 571 if (filter != null) { 572 filter.remove(getFilterBypass(), offs, len); 573 } 574 else { 575 handleRemove(offs, len); 576 } 577 } finally { 578 writeUnlock(); 579 } 580 } 581 582 586 void handleRemove(int offs, int len) throws BadLocationException { 587 if (len > 0) { 588 if (offs < 0 || (offs + len) > getLength()) { 589 throw new BadLocationException ("Invalid remove", 590 getLength() + 1); 591 } 592 DefaultDocumentEvent chng = 593 new DefaultDocumentEvent(offs, len, DocumentEvent.EventType.REMOVE); 594 595 boolean isComposedTextElement = false; 596 isComposedTextElement = Utilities.isComposedTextElement(this, offs); 598 599 removeUpdate(chng); 600 UndoableEdit u = data.remove(offs, len); 601 if (u != null) { 602 chng.addEdit(u); 603 } 604 postRemoveUpdate(chng); 605 chng.end(); 607 fireRemoveUpdate(chng); 608 if ((u != null) && !isComposedTextElement) { 611 fireUndoableEditUpdate(new UndoableEditEvent(this, chng)); 612 } 613 } 614 } 615 616 620 private static final boolean isComplex(char ch) { 621 return (ch >= '\u0900' && ch <= '\u0D7F') || (ch >= '\u0E00' && ch <= '\u0E7F') || (ch >= '\uD800' && ch <= '\uDFFF'); } 625 626 private static final boolean isComplex(char[] text, int start, int limit) { 627 for (int i = start; i < limit; ++i) { 628 if (isComplex(text[i])) { 629 return true; 630 } 631 } 632 return false; 633 } 634 635 655 public void replace(int offset, int length, String text, 656 AttributeSet attrs) throws BadLocationException { 657 if (length == 0 && (text == null || text.length() == 0)) { 658 return; 659 } 660 DocumentFilter filter = getDocumentFilter(); 661 662 writeLock(); 663 try { 664 if (filter != null) { 665 filter.replace(getFilterBypass(), offset, length, text, 666 attrs); 667 } 668 else { 669 if (length > 0) { 670 remove(offset, length); 671 } 672 if (text != null && text.length() > 0) { 673 insertString(offset, text, attrs); 674 } 675 } 676 } finally { 677 writeUnlock(); 678 } 679 } 680 681 699 public void insertString(int offs, String str, AttributeSet a) throws BadLocationException { 700 if ((str == null) || (str.length() == 0)) { 701 return; 702 } 703 DocumentFilter filter = getDocumentFilter(); 704 705 writeLock(); 706 try { 707 if (filter != null) { 708 filter.insertString(getFilterBypass(), offs, str, a); 709 } 710 else { 711 handleInsertString(offs, str, a); 712 } 713 } finally { 714 writeUnlock(); 715 } 716 } 717 718 722 void handleInsertString(int offs, String str, AttributeSet a) 723 throws BadLocationException { 724 if ((str == null) || (str.length() == 0)) { 725 return; 726 } 727 UndoableEdit u = data.insertString(offs, str); 728 DefaultDocumentEvent e = 729 new DefaultDocumentEvent(offs, str.length(), DocumentEvent.EventType.INSERT); 730 if (u != null) { 731 e.addEdit(u); 732 } 733 734 if( getProperty(I18NProperty).equals( Boolean.FALSE ) ) { 736 Object d = getProperty(TextAttribute.RUN_DIRECTION); 739 if ((d != null) && (d.equals(TextAttribute.RUN_DIRECTION_RTL))) { 740 putProperty( I18NProperty, Boolean.TRUE); 741 } else { 742 char[] chars = str.toCharArray(); 743 if (Bidi.requiresBidi(chars, 0, chars.length) || 744 isComplex(chars, 0, chars.length)) { 745 putProperty( I18NProperty, Boolean.TRUE); 747 } 748 } 749 } 750 751 insertUpdate(e, a); 752 e.end(); 754 fireInsertUpdate(e); 755 if (u != null && 758 (a == null || !a.isDefined(StyleConstants.ComposedTextAttribute))) { 759 fireUndoableEditUpdate(new UndoableEditEvent(this, e)); 760 } 761 } 762 763 773 public String getText(int offset, int length) throws BadLocationException { 774 if (length < 0) { 775 throw new BadLocationException ("Length must be positive", length); 776 } 777 String str = data.getString(offset, length); 778 return str; 779 } 780 781 813 public void getText(int offset, int length, Segment txt) throws BadLocationException { 814 if (length < 0) { 815 throw new BadLocationException ("Length must be positive", length); 816 } 817 data.getChars(offset, length, txt); 818 } 819 820 835 public synchronized Position createPosition(int offs) throws BadLocationException { 836 return data.createPosition(offs); 837 } 838 839 846 public final Position getStartPosition() { 847 Position p; 848 try { 849 p = createPosition(0); 850 } catch (BadLocationException bl) { 851 p = null; 852 } 853 return p; 854 } 855 856 863 public final Position getEndPosition() { 864 Position p; 865 try { 866 p = createPosition(data.length()); 867 } catch (BadLocationException bl) { 868 p = null; 869 } 870 return p; 871 } 872 873 880 public Element [] getRootElements() { 881 Element [] elems = new Element [2]; 882 elems[0] = getDefaultRootElement(); 883 elems[1] = getBidiRootElement(); 884 return elems; 885 } 886 887 895 public abstract Element getDefaultRootElement(); 896 897 899 903 private DocumentFilter.FilterBypass getFilterBypass() { 904 if (filterBypass == null) { 905 filterBypass = new DefaultFilterBypass(); 906 } 907 return filterBypass; 908 } 909 910 915 public Element getBidiRootElement() { 916 return bidiRoot; 917 } 918 919 923 boolean isLeftToRight(int p0, int p1) { 924 if(!getProperty(I18NProperty).equals(Boolean.TRUE)) { 925 return true; 926 } 927 Element bidiRoot = getBidiRootElement(); 928 int index = bidiRoot.getElementIndex(p0); 929 Element bidiElem = bidiRoot.getElement(index); 930 if(bidiElem.getEndOffset() >= p1) { 931 AttributeSet bidiAttrs = bidiElem.getAttributes(); 932 return ((StyleConstants.getBidiLevel(bidiAttrs) % 2) == 0); 933 } 934 return true; 935 } 936 937 945 public abstract Element getParagraphElement(int pos); 946 947 948 955 protected final AttributeContext getAttributeContext() { 956 return context; 957 } 958 959 968 protected void insertUpdate(DefaultDocumentEvent chng, AttributeSet attr) { 969 if( getProperty(I18NProperty).equals( Boolean.TRUE ) ) 970 updateBidi( chng ); 971 972 if (chng.type == DocumentEvent.EventType.INSERT && 974 chng.getLength() > 0 && 975 !Boolean.TRUE.equals(getProperty(MultiByteProperty))) { 976 Segment segment = SegmentCache.getSharedSegment(); 977 try { 978 getText(chng.getOffset(), chng.getLength(), segment); 979 segment.first(); 980 do { 981 if ((int)segment.current() > 255) { 982 putProperty(MultiByteProperty, Boolean.TRUE); 983 break; 984 } 985 } while (segment.next() != Segment.DONE); 986 } catch (BadLocationException ble) { 987 } 989 SegmentCache.releaseSharedSegment(segment); 990 } 991 } 992 993 1002 protected void removeUpdate(DefaultDocumentEvent chng) { 1003 } 1004 1005 1014 protected void postRemoveUpdate(DefaultDocumentEvent chng) { 1015 if( getProperty(I18NProperty).equals( Boolean.TRUE ) ) 1016 updateBidi( chng ); 1017 } 1018 1019 1020 1029 void updateBidi( DefaultDocumentEvent chng ) { 1030 1031 int firstPStart; 1033 int lastPEnd; 1034 if( chng.type == DocumentEvent.EventType.INSERT 1035 || chng.type == DocumentEvent.EventType.CHANGE ) 1036 { 1037 int chngStart = chng.getOffset(); 1038 int chngEnd = chngStart + chng.getLength(); 1039 firstPStart = getParagraphElement(chngStart).getStartOffset(); 1040 lastPEnd = getParagraphElement(chngEnd).getEndOffset(); 1041 } else if( chng.type == DocumentEvent.EventType.REMOVE ) { 1042 Element paragraph = getParagraphElement( chng.getOffset() ); 1043 firstPStart = paragraph.getStartOffset(); 1044 lastPEnd = paragraph.getEndOffset(); 1045 } else { 1046 throw new Error ("Internal error: unknown event type."); 1047 } 1048 1050 1051 byte levels[] = calculateBidiLevels( firstPStart, lastPEnd ); 1055 1056 1057 Vector newElements = new Vector(); 1058 1059 int firstSpanStart = firstPStart; 1066 int removeFromIndex = 0; 1067 if( firstSpanStart > 0 ) { 1068 int prevElemIndex = bidiRoot.getElementIndex(firstPStart-1); 1069 removeFromIndex = prevElemIndex; 1070 Element prevElem = bidiRoot.getElement(prevElemIndex); 1071 int prevLevel=StyleConstants.getBidiLevel(prevElem.getAttributes()); 1072 if( prevLevel==levels[0] ) { 1074 firstSpanStart = prevElem.getStartOffset(); 1075 } else if( prevElem.getEndOffset() > firstPStart ) { 1076 newElements.addElement(new BidiElement(bidiRoot, 1077 prevElem.getStartOffset(), 1078 firstPStart, prevLevel)); 1079 } else { 1080 removeFromIndex++; 1081 } 1082 } 1083 1084 int firstSpanEnd = 0; 1085 while((firstSpanEnd<levels.length) && (levels[firstSpanEnd]==levels[0])) 1086 firstSpanEnd++; 1087 1088 1089 int lastSpanEnd = lastPEnd; 1096 Element newNextElem = null; 1097 int removeToIndex = bidiRoot.getElementCount() - 1; 1098 if( lastSpanEnd <= getLength() ) { 1099 int nextElemIndex = bidiRoot.getElementIndex( lastPEnd ); 1100 removeToIndex = nextElemIndex; 1101 Element nextElem = bidiRoot.getElement( nextElemIndex ); 1102 int nextLevel = StyleConstants.getBidiLevel(nextElem.getAttributes()); 1103 if( nextLevel == levels[levels.length-1] ) { 1104 lastSpanEnd = nextElem.getEndOffset(); 1105 } else if( nextElem.getStartOffset() < lastPEnd ) { 1106 newNextElem = new BidiElement(bidiRoot, lastPEnd, 1107 nextElem.getEndOffset(), 1108 nextLevel); 1109 } else { 1110 removeToIndex--; 1111 } 1112 } 1113 1114 int lastSpanStart = levels.length; 1115 while( (lastSpanStart>firstSpanEnd) 1116 && (levels[lastSpanStart-1]==levels[levels.length-1]) ) 1117 lastSpanStart--; 1118 1119 1120 if((firstSpanEnd==lastSpanStart)&&(levels[0]==levels[levels.length-1])){ 1125 newElements.addElement(new BidiElement(bidiRoot, firstSpanStart, 1126 lastSpanEnd, levels[0])); 1127 } else { 1128 newElements.addElement(new BidiElement(bidiRoot, firstSpanStart, 1130 firstSpanEnd+firstPStart, 1131 levels[0])); 1132 for( int i=firstSpanEnd; i<lastSpanStart; ) { 1134 int j; 1136 for( j=i; (j<levels.length) && (levels[j] == levels[i]); j++ ); 1137 newElements.addElement(new BidiElement(bidiRoot, firstPStart+i, 1138 firstPStart+j, 1139 (int)levels[i])); 1140 i=j; 1141 } 1142 newElements.addElement(new BidiElement(bidiRoot, 1144 lastSpanStart+firstPStart, 1145 lastSpanEnd, 1146 levels[levels.length-1])); 1147 } 1148 1149 if( newNextElem != null ) 1150 newElements.addElement( newNextElem ); 1151 1152 1153 int removedElemCount = 0; 1156 if( bidiRoot.getElementCount() > 0 ) { 1157 removedElemCount = removeToIndex - removeFromIndex + 1; 1158 } 1159 Element [] removedElems = new Element [removedElemCount]; 1160 for( int i=0; i<removedElemCount; i++ ) { 1161 removedElems[i] = bidiRoot.getElement(removeFromIndex+i); 1162 } 1163 1164 Element [] addedElems = new Element [ newElements.size() ]; 1165 newElements.copyInto( addedElems ); 1166 1167 ElementEdit ee = new ElementEdit( bidiRoot, removeFromIndex, 1169 removedElems, addedElems ); 1170 chng.addEdit( ee ); 1171 1172 bidiRoot.replace( removeFromIndex, removedElems.length, addedElems ); 1174 } 1175 1176 1177 1180 private byte[] calculateBidiLevels( int firstPStart, int lastPEnd ) { 1181 1182 byte levels[] = new byte[ lastPEnd - firstPStart ]; 1183 int levelsEnd = 0; 1184 Boolean defaultDirection = null; 1185 Object d = getProperty(TextAttribute.RUN_DIRECTION); 1186 if (d instanceof Boolean ) { 1187 defaultDirection = (Boolean ) d; 1188 } 1189 1190 for(int o=firstPStart; o<lastPEnd; ) { 1193 Element p = getParagraphElement( o ); 1194 int pStart = p.getStartOffset(); 1195 int pEnd = p.getEndOffset(); 1196 1197 Boolean direction = defaultDirection; 1201 d = p.getAttributes().getAttribute(TextAttribute.RUN_DIRECTION); 1202 if (d instanceof Boolean ) { 1203 direction = (Boolean ) d; 1204 } 1205 1206 1208 Segment seg = SegmentCache.getSharedSegment(); 1211 try { 1212 getText(pStart, pEnd-pStart, seg); 1213 } catch (BadLocationException e ) { 1214 throw new Error ("Internal error: " + e.toString()); 1215 } 1216 Bidi bidiAnalyzer; 1218 int bidiflag = Bidi.DIRECTION_DEFAULT_LEFT_TO_RIGHT; 1219 if (direction != null) { 1220 if (TextAttribute.RUN_DIRECTION_LTR.equals(direction)) { 1221 bidiflag = Bidi.DIRECTION_LEFT_TO_RIGHT; 1222 } else { 1223 bidiflag = Bidi.DIRECTION_RIGHT_TO_LEFT; 1224 } 1225 } 1226 bidiAnalyzer = new Bidi (seg.array, seg.offset, null, 0, seg.count, 1227 bidiflag); 1228 BidiUtils.getLevels(bidiAnalyzer, levels, levelsEnd); 1229 levelsEnd += bidiAnalyzer.getLength(); 1230 1231 o = p.getEndOffset(); 1232 SegmentCache.releaseSharedSegment(seg); 1233 } 1234 1235 if( levelsEnd != levels.length ) 1237 throw new Error ("levelsEnd assertion failed."); 1238 1239 return levels; 1240 } 1241 1242 1247 public void dump(PrintStream out) { 1248 Element root = getDefaultRootElement(); 1249 if (root instanceof AbstractElement) { 1250 ((AbstractElement)root).dump(out, 0); 1251 } 1252 bidiRoot.dump(out,0); 1253 } 1254 1255 1260 protected final Content getContent() { 1261 return data; 1262 } 1263 1264 1279 protected Element createLeafElement(Element parent, AttributeSet a, int p0, int p1) { 1280 return new LeafElement(parent, a, p0, p1); 1281 } 1282 1283 1290 protected Element createBranchElement(Element parent, AttributeSet a) { 1291 return new BranchElement(parent, a); 1292 } 1293 1294 1296 1306 protected synchronized final Thread getCurrentWriter() { 1307 return currWriter; 1308 } 1309 1310 1335 protected synchronized final void writeLock() { 1336 try { 1337 while ((numReaders > 0) || (currWriter != null)) { 1338 if (Thread.currentThread() == currWriter) { 1339 if (notifyingListeners) { 1340 throw new IllegalStateException ( 1344 "Attempt to mutate in notification"); 1345 } 1346 numWriters++; 1347 return; 1348 } 1349 wait(); 1350 } 1351 currWriter = Thread.currentThread(); 1352 numWriters = 1; 1353 } catch (InterruptedException e) { 1354 throw new Error ("Interrupted attempt to aquire write lock"); 1355 } 1356 } 1357 1358 1365 protected synchronized final void writeUnlock() { 1366 if (--numWriters <= 0) { 1367 numWriters = 0; 1368 currWriter = null; 1369 notifyAll(); 1370 } 1371 } 1372 1373 1384 public synchronized final void readLock() { 1385 try { 1386 while (currWriter != null) { 1387 if (currWriter == Thread.currentThread()) { 1388 return; 1391 } 1392 wait(); 1393 } 1394 numReaders += 1; 1395 } catch (InterruptedException e) { 1396 throw new Error ("Interrupted attempt to aquire read lock"); 1397 } 1398 } 1399 1400 1418 public synchronized final void readUnlock() { 1419 if (currWriter == Thread.currentThread()) { 1420 return; 1423 } 1424 if (numReaders <= 0) { 1425 throw new StateInvariantError (BAD_LOCK_STATE); 1426 } 1427 numReaders -= 1; 1428 notify(); 1429 } 1430 1431 1433 private void readObject(ObjectInputStream s) 1434 throws ClassNotFoundException , IOException 1435 { 1436 s.defaultReadObject(); 1437 listenerList = new EventListenerList(); 1438 1439 bidiRoot = new BidiRootElement(); 1443 try { 1444 writeLock(); 1445 Element [] p = new Element [1]; 1446 p[0] = new BidiElement( bidiRoot, 0, 1, 0 ); 1447 bidiRoot.replace(0,0,p); 1448 } finally { 1449 writeUnlock(); 1450 } 1451 s.registerValidation(new ObjectInputValidation() { 1456 public void validateObject() { 1457 try { 1458 writeLock(); 1459 DefaultDocumentEvent e = new DefaultDocumentEvent 1460 (0, getLength(), 1461 DocumentEvent.EventType.INSERT); 1462 updateBidi( e ); 1463 } 1464 finally { 1465 writeUnlock(); 1466 } 1467 } 1468 }, 0); 1469 } 1470 1471 1473 private transient int numReaders; 1474 private transient Thread currWriter; 1475 1478 private transient int numWriters; 1479 1482 private transient boolean notifyingListeners; 1483 1484 private static Boolean defaultI18NProperty; 1485 1486 1489 private Dictionary<Object ,Object > documentProperties = null; 1490 1491 1494 protected EventListenerList listenerList = new EventListenerList(); 1495 1496 1500 private Content data; 1501 1502 1508 private AttributeContext context; 1509 1510 1514 private transient BranchElement bidiRoot; 1515 1516 1519 private DocumentFilter documentFilter; 1520 1521 1524 private transient DocumentFilter.FilterBypass filterBypass; 1525 1526 private static final String BAD_LOCK_STATE = "document lock failure"; 1527 1528 1531 protected static final String BAD_LOCATION = "document location failure"; 1532 1533 1536 public static final String ParagraphElementName = "paragraph"; 1537 1538 1541 public static final String ContentElementName = "content"; 1542 1543 1546 public static final String SectionElementName = "section"; 1547 1548 1551 public static final String BidiElementName = "bidi level"; 1552 1553 1557 public static final String ElementNameAttribute = "$ename"; 1558 1559 1569 static final String I18NProperty = "i18n"; 1570 1571 1576 static final Object MultiByteProperty = "multiByte"; 1577 1578 1582 static final String AsyncLoadPriority = "load priority"; 1583 1584 1591 public interface Content { 1592 1593 1601 public Position createPosition(int offset) throws BadLocationException ; 1602 1603 1608 public int length(); 1609 1610 1621 public UndoableEdit insertString(int where, String str) throws BadLocationException ; 1622 1623 1635 public UndoableEdit remove(int where, int nitems) throws BadLocationException ; 1636 1637 1646 public String getString(int where, int len) throws BadLocationException ; 1647 1648 1657 public void getChars(int where, int len, Segment txt) throws BadLocationException ; 1658 } 1659 1660 1679 public interface AttributeContext { 1680 1681 1691 public AttributeSet addAttribute(AttributeSet old, Object name, Object value); 1692 1693 1701 public AttributeSet addAttributes(AttributeSet old, AttributeSet attr); 1702 1703 1711 public AttributeSet removeAttribute(AttributeSet old, Object name); 1712 1713 1721 public AttributeSet removeAttributes(AttributeSet old, Enumeration<?> names); 1722 1723 1731 public AttributeSet removeAttributes(AttributeSet old, AttributeSet attrs); 1732 1733 1738 public AttributeSet getEmptySet(); 1739 1740 1749 public void reclaim(AttributeSet a); 1750 } 1751 1752 1769 public abstract class AbstractElement implements Element , MutableAttributeSet , Serializable, TreeNode { 1770 1771 1777 public AbstractElement(Element parent, AttributeSet a) { 1778 this.parent = parent; 1779 attributes = getAttributeContext().getEmptySet(); 1780 if (a != null) { 1781 addAttributes(a); 1782 } 1783 } 1784 1785 private final void indent(PrintWriter out, int n) { 1786 for (int i = 0; i < n; i++) { 1787 out.print(" "); 1788 } 1789 } 1790 1791 1797 public void dump(PrintStream psOut, int indentAmount) { 1798 PrintWriter out; 1799 try { 1800 out = new PrintWriter(new OutputStreamWriter(psOut,"JavaEsc"), 1801 true); 1802 } catch (UnsupportedEncodingException e){ 1803 out = new PrintWriter(psOut,true); 1804 } 1805 indent(out, indentAmount); 1806 if (getName() == null) { 1807 out.print("<??"); 1808 } else { 1809 out.print("<" + getName()); 1810 } 1811 if (getAttributeCount() > 0) { 1812 out.println(""); 1813 Enumeration names = attributes.getAttributeNames(); 1815 while (names.hasMoreElements()) { 1816 Object name = names.nextElement(); 1817 indent(out, indentAmount + 1); 1818 out.println(name + "=" + getAttribute(name)); 1819 } 1820 indent(out, indentAmount); 1821 } 1822 out.println(">"); 1823 1824 if (isLeaf()) { 1825 indent(out, indentAmount+1); 1826 out.print("[" + getStartOffset() + "," + getEndOffset() + "]"); 1827 Content c = getContent(); 1828 try { 1829 String contentStr = c.getString(getStartOffset(), 1830 getEndOffset() - getStartOffset()); 1831 if (contentStr.length() > 40) { 1832 contentStr = contentStr.substring(0, 40) + "..."; 1833 } 1834 out.println("["+contentStr+"]"); 1835 } catch (BadLocationException e) { 1836 ; 1837 } 1838 1839 } else { 1840 int n = getElementCount(); 1841 for (int i = 0; i < n; i++) { 1842 AbstractElement e = (AbstractElement) getElement(i); 1843 e.dump(psOut, indentAmount+1); 1844 } 1845 } 1846 } 1847 1848 1851 1857 public int getAttributeCount() { 1858 return attributes.getAttributeCount(); 1859 } 1860 1861 1868 public boolean isDefined(Object attrName) { 1869 return attributes.isDefined(attrName); 1870 } 1871 1872 1879 public boolean isEqual(AttributeSet attr) { 1880 return attributes.isEqual(attr); 1881 } 1882 1883 1889 public AttributeSet copyAttributes() { 1890 return attributes.copyAttributes(); 1891 } 1892 1893 1900 public Object getAttribute(Object attrName) { 1901 Object value = attributes.getAttribute(attrName); 1902 if (value == null) { 1903 AttributeSet a = (parent != null) ? parent.getAttributes() : null; 1907 if (a != null) { 1908 value = a.getAttribute(attrName); 1909 } 1910 } 1911 return value; 1912 } 1913 1914 1920 public Enumeration<?> getAttributeNames() { 1921 return attributes.getAttributeNames(); 1922 } 1923 1924 1932 public boolean containsAttribute(Object name, Object value) { 1933 return attributes.containsAttribute(name, value); 1934 } 1935 1936 1937 1944 public boolean containsAttributes(AttributeSet attrs) { 1945 return attributes.containsAttributes(attrs); 1946 } 1947 1948 1956 public AttributeSet getResolveParent() { 1957 AttributeSet a = attributes.getResolveParent(); 1958 if ((a == null) && (parent != null)) { 1959 a = parent.getAttributes(); 1960 } 1961 return a; 1962 } 1963 1964 1968 1975 public void addAttribute(Object name, Object value) { 1976 checkForIllegalCast(); 1977 AttributeContext context = getAttributeContext(); 1978 attributes = context.addAttribute(attributes, name, value); 1979 } 1980 1981 1987 public void addAttributes(AttributeSet attr) { 1988 checkForIllegalCast(); 1989 AttributeContext context = getAttributeContext(); 1990 attributes = context.addAttributes(attributes, attr); 1991 } 1992 1993 1999 public void removeAttribute(Object name) { 2000 checkForIllegalCast(); 2001 AttributeContext context = getAttributeContext(); 2002 attributes = context.removeAttribute(attributes, name); 2003 } 2004 2005 2011 public void removeAttributes(Enumeration<?> names) { 2012 checkForIllegalCast(); 2013 AttributeContext context = getAttributeContext(); 2014 attributes = context.removeAttributes(attributes, names); 2015 } 2016 2017 2023 public void removeAttributes(AttributeSet attrs) { 2024 checkForIllegalCast(); 2025 AttributeContext context = getAttributeContext(); 2026 if (attrs == this) { 2027 attributes = context.getEmptySet(); 2028 } else { 2029 attributes = context.removeAttributes(attributes, attrs); 2030 } 2031 } 2032 2033 2039 public void setResolveParent(AttributeSet parent) { 2040 checkForIllegalCast(); 2041 AttributeContext context = getAttributeContext(); 2042 if (parent != null) { 2043 attributes = 2044 context.addAttribute(attributes, StyleConstants.ResolveAttribute, 2045 parent); 2046 } else { 2047 attributes = 2048 context.removeAttribute(attributes, StyleConstants.ResolveAttribute); 2049 } 2050 } 2051 2052 private final void checkForIllegalCast() { 2053 Thread t = getCurrentWriter(); 2054 if ((t == null) || (t != Thread.currentThread())) { 2055 throw new StateInvariantError ("Illegal cast to MutableAttributeSet"); 2056 } 2057 } 2058 2059 2061 2066 public Document getDocument() { 2067 return AbstractDocument.this; 2068 } 2069 2070 2075 public Element getParentElement() { 2076 return parent; 2077 } 2078 2079 2084 public AttributeSet getAttributes() { 2085 return this; 2086 } 2087 2088 2093 public String getName() { 2094 if (attributes.isDefined(ElementNameAttribute)) { 2095 return (String ) attributes.getAttribute(ElementNameAttribute); 2096 } 2097 return null; 2098 } 2099 2100 2105 public abstract int getStartOffset(); 2106 2107 2112 public abstract int getEndOffset(); 2113 2114 2120 public abstract Element getElement(int index); 2121 2122 2127 public abstract int getElementCount(); 2128 2129 2135 public abstract int getElementIndex(int offset); 2136 2137 2142 public abstract boolean isLeaf(); 2143 2144 2146 2150 public TreeNode getChildAt(int childIndex) { 2151 return (TreeNode )getElement(childIndex); 2152 } 2153 2154 2160 public int getChildCount() { 2161 return getElementCount(); 2162 } 2163 2164 2168 public TreeNode getParent() { 2169 return (TreeNode )getParentElement(); 2170 } 2171 2172 2180 public int getIndex(TreeNode node) { 2181 for(int counter = getChildCount() - 1; counter >= 0; counter--) 2182 if(getChildAt(counter) == node) 2183 return counter; 2184 return -1; 2185 } 2186 2187 2191 public abstract boolean getAllowsChildren(); 2192 2193 2194 2199 public abstract Enumeration children(); 2200 2201 2202 2204 private void writeObject(ObjectOutputStream s) throws IOException { 2205 s.defaultWriteObject(); 2206 StyleContext.writeAttributeSet(s, attributes); 2207 } 2208 2209 private void readObject(ObjectInputStream s) 2210 throws ClassNotFoundException , IOException 2211 { 2212 s.defaultReadObject(); 2213 MutableAttributeSet attr = new SimpleAttributeSet (); 2214 StyleContext.readAttributeSet(s, attr); 2215 AttributeContext context = getAttributeContext(); 2216 attributes = context.addAttributes(SimpleAttributeSet.EMPTY, attr); 2217 } 2218 2219 2221 private Element parent; 2222 private transient AttributeSet attributes; 2223 2224 } 2225 2226 2238 public class BranchElement extends AbstractElement { 2239 2240 2247 public BranchElement(Element parent, AttributeSet a) { 2248 super(parent, a); 2249 children = new AbstractElement[1]; 2250 nchildren = 0; 2251 lastIndex = -1; 2252 } 2253 2254 2261 public Element positionToElement(int pos) { 2262 int index = getElementIndex(pos); 2263 Element child = children[index]; 2264 int p0 = child.getStartOffset(); 2265 int p1 = child.getEndOffset(); 2266 if ((pos >= p0) && (pos < p1)) { 2267 return child; 2268 } 2269 return null; 2270 } 2271 2272 2279 public void replace(int offset, int length, Element [] elems) { 2280 int delta = elems.length - length; 2281 int src = offset + length; 2282 int nmove = nchildren - src; 2283 int dest = src + delta; 2284 if ((nchildren + delta) >= children.length) { 2285 int newLength = Math.max(2*children.length, nchildren + delta); 2287 AbstractElement[] newChildren = new AbstractElement[newLength]; 2288 System.arraycopy(children, 0, newChildren, 0, offset); 2289 System.arraycopy(elems, 0, newChildren, offset, elems.length); 2290 System.arraycopy(children, src, newChildren, dest, nmove); 2291 children = newChildren; 2292 } else { 2293 System.arraycopy(children, src, children, dest, nmove); 2295 System.arraycopy(elems, 0, children, offset, elems.length); 2296 } 2297 nchildren = nchildren + delta; 2298 } 2299 2300 2305 public String toString() { 2306 return "BranchElement(" + getName() + ") " + getStartOffset() + "," + 2307 getEndOffset() + "\n"; 2308 } 2309 2310 2312 2317 public String getName() { 2318 String nm = super.getName(); 2319 if (nm == null) { 2320 nm = ParagraphElementName; 2321 } 2322 return nm; 2323 } 2324 2325 2330 public int getStartOffset() { 2331 return children[0].getStartOffset(); 2332 } 2333 2334 2340 public int getEndOffset() { 2341 Element child = 2342 (nchildren > 0) ? children[nchildren - 1] : children[0]; 2343 return child.getEndOffset(); 2344 } 2345 2346 2352 public Element getElement(int index) { 2353 if (index < nchildren) { 2354 return children[index]; 2355 } 2356 return null; 2357 } 2358 2359 2364 public int getElementCount() { 2365 return nchildren; 2366 } 2367 2368 2374 public int getElementIndex(int offset) { 2375 int index; 2376 int lower = 0; 2377 int upper = nchildren - 1; 2378 int mid = 0; 2379 int p0 = getStartOffset(); 2380 int p1; 2381 2382 if (nchildren == 0) { 2383 return 0; 2384 } 2385 if (offset >= getEndOffset()) { 2386 return nchildren - 1; 2387 } 2388 2389 if ((lastIndex >= lower) && (lastIndex <= upper)) { 2391 Element lastHit = children[lastIndex]; 2392 p0 = lastHit.getStartOffset(); 2393 p1 = lastHit.getEndOffset(); 2394 if ((offset >= p0) && (offset < p1)) { 2395 return lastIndex; 2396 } 2397 2398 if (offset < p0) { 2401 upper = lastIndex; 2402 } else { 2403 lower = lastIndex; 2404 } 2405 } 2406 2407 while (lower <= upper) { 2408 mid = lower + ((upper - lower) / 2); 2409 Element elem = children[mid]; 2410 p0 = elem.getStartOffset(); 2411 p1 = elem.getEndOffset(); 2412 if ((offset >= p0) && (offset < p1)) { 2413 index = mid; 2415 lastIndex = index; 2416 return index; 2417 } else if (offset < p0) { 2418 upper = mid - 1; 2419 } else { 2420 lower = mid + 1; 2421 } 2422 } 2423 2424 if (offset < p0) { 2426 index = mid; 2427 } else { 2428 index = mid + 1; 2429 } 2430 lastIndex = index; 2431 return index; 2432 } 2433 2434 2439 public boolean isLeaf() { 2440 return false; 2441 } 2442 2443 2444 2446 2450 public boolean getAllowsChildren() { 2451 return true; 2452 } 2453 2454 2455 2460 public Enumeration children() { 2461 if(nchildren == 0) 2462 return null; 2463 2464 Vector tempVector = new Vector(nchildren); 2465 2466 for(int counter = 0; counter < nchildren; counter++) 2467 tempVector.addElement(children[counter]); 2468 return tempVector.elements(); 2469 } 2470 2471 2473 private AbstractElement[] children; 2474 private int nchildren; 2475 private int lastIndex; 2476 } 2477 2478 2493 public class LeafElement extends AbstractElement { 2494 2495 2504 public LeafElement(Element parent, AttributeSet a, int offs0, int offs1) { 2505 super(parent, a); 2506 try { 2507 p0 = createPosition(offs0); 2508 p1 = createPosition(offs1); 2509 } catch (BadLocationException e) { 2510 p0 = null; 2511 p1 = null; 2512 throw new StateInvariantError ("Can't create Position references"); 2513 } 2514 } 2515 2516 2521 public String toString() { 2522 return "LeafElement(" + getName() + ") " + p0 + "," + p1 + "\n"; 2523 } 2524 2525 2527 2532 public int getStartOffset() { 2533 return p0.getOffset(); 2534 } 2535 2536 2541 public int getEndOffset() { 2542 return p1.getOffset(); 2543 } 2544 2545 2550 public String getName() { 2551 String nm = super.getName(); 2552 if (nm == null) { 2553 nm = ContentElementName; 2554 } 2555 return nm; 2556 } 2557 2558 2564 public int getElementIndex(int pos) { 2565 return -1; 2566 } 2567 2568 2574 public Element getElement(int index) { 2575 return null; 2576 } 2577 2578 2583 public int getElementCount() { 2584 return 0; 2585 } 2586 2587 2592 public boolean isLeaf() { 2593 return true; 2594 } 2595 2596 2598 2602 public boolean getAllowsChildren() { 2603 return false; 2604 } 2605 2606 2607 2612 public Enumeration children() { 2613 return null; 2614 } 2615 2616 2618 private void writeObject(ObjectOutputStream s) throws IOException { 2619 s.defaultWriteObject(); 2620 s.writeInt(p0.getOffset()); 2621 s.writeInt(p1.getOffset()); 2622 } 2623 2624 private void readObject(ObjectInputStream s) 2625 throws ClassNotFoundException , IOException 2626 { 2627 s.defaultReadObject(); 2628 2629 int off0 = s.readInt(); 2631 int off1 = s.readInt(); 2632 try { 2633 p0 = createPosition(off0); 2634 p1 = createPosition(off1); 2635 } catch (BadLocationException e) { 2636 p0 = null; 2637 p1 = null; 2638 throw new IOException("Can't restore Position references"); 2639 } 2640 } 2641 2642 2644 private transient Position p0; 2645 private transient Position p1; 2646 } 2647 2648 2653 class BidiRootElement extends BranchElement { 2654 2655 BidiRootElement() { 2656 super( null, null ); 2657 } 2658 2659 2663 public String getName() { 2664 return "bidi root"; 2665 } 2666 } 2667 2668 2671 class BidiElement extends LeafElement { 2672 2673 2676 BidiElement(Element parent, int start, int end, int level) { 2677 super(parent, new SimpleAttributeSet (), start, end); 2678 addAttribute(StyleConstants.BidiLevel, new Integer (level)); 2679 } 2682 2683 2687 public String getName() { 2688 return BidiElementName; 2689 } 2690 2691 int getLevel() { 2692 Integer o = (Integer ) getAttribute(StyleConstants.BidiLevel); 2693 if (o != null) { 2694 return o.intValue(); 2695 } 2696 return 0; } 2698 2699 boolean isLeftToRight() { 2700 return ((getLevel() % 2) == 0); 2701 } 2702 } 2703 2704 2711 public class DefaultDocumentEvent extends CompoundEdit implements DocumentEvent { 2712 2713 2720 public DefaultDocumentEvent(int offs, int len, DocumentEvent.EventType type) { 2721 super(); 2722 offset = offs; 2723 length = len; 2724 this.type = type; 2725 } 2726 2727 2732 public String toString() { 2733 return edits.toString(); 2734 } 2735 2736 2738 2747 public boolean addEdit(UndoableEdit anEdit) { 2748 if ((changeLookup == null) && (edits.size() > 10)) { 2751 changeLookup = new Hashtable(); 2752 int n = edits.size(); 2753 for (int i = 0; i < n; i++) { 2754 Object o = edits.elementAt(i); 2755 if (o instanceof DocumentEvent.ElementChange) { 2756 DocumentEvent.ElementChange ec = (DocumentEvent.ElementChange) o; 2757 changeLookup.put(ec.getElement(), ec); 2758 } 2759 } 2760 } 2761 2762 if ((changeLookup != null) && (anEdit instanceof DocumentEvent.ElementChange)) { 2765 DocumentEvent.ElementChange ec = (DocumentEvent.ElementChange) anEdit; 2766 changeLookup.put(ec.getElement(), ec); 2767 } 2768 return super.addEdit(anEdit); 2769 } 2770 2771 2776 public void redo() throws CannotRedoException { 2777 writeLock(); 2778 try { 2779 super.redo(); 2781 UndoRedoDocumentEvent ev = new UndoRedoDocumentEvent(this, false); 2783 if (type == DocumentEvent.EventType.INSERT) { 2784 fireInsertUpdate(ev); 2785 } else if (type == DocumentEvent.EventType.REMOVE) { 2786 fireRemoveUpdate(ev); 2787 } else { 2788 fireChangedUpdate(ev); 2789 } 2790 } finally { 2791 writeUnlock(); 2792 } 2793 } 2794 2795 2800 public void undo() throws CannotUndoException { 2801 writeLock(); 2802 try { 2803 super.undo(); 2805 UndoRedoDocumentEvent ev = new UndoRedoDocumentEvent(this, true); 2807 if (type == DocumentEvent.EventType.REMOVE) { 2808 fireInsertUpdate(ev); 2809 } else if (type == DocumentEvent.EventType.INSERT) { 2810 fireRemoveUpdate(ev); 2811 } else { 2812 fireChangedUpdate(ev); 2813 } 2814 } finally { 2815 writeUnlock(); 2816 } 2817 } 2818 2819 2826 public boolean isSignificant() { 2827 return true; 2828 } 2829 2830 2831 2837 public String getPresentationName() { 2838 DocumentEvent.EventType type = getType(); 2839 if(type == DocumentEvent.EventType.INSERT) 2840 return UIManager.getString("AbstractDocument.additionText"); 2841 if(type == DocumentEvent.EventType.REMOVE) 2842 return UIManager.getString("AbstractDocument.deletionText"); 2843 return UIManager.getString("AbstractDocument.styleChangeText"); 2844 } 2845 2846 2853 public String getUndoPresentationName() { 2854 return UIManager.getString("AbstractDocument.undoText") + " " + 2855 getPresentationName(); 2856 } 2857 2858 2865 public String getRedoPresentationName() { 2866 return UIManager.getString("AbstractDocument.redoText") + " " + 2867 getPresentationName(); 2868 } 2869 2870 2872 2878 public DocumentEvent.EventType getType() { 2879 return type; 2880 } 2881 2882 2888 public int getOffset() { 2889 return offset; 2890 } 2891 2892 2898 public int getLength() { 2899 return length; 2900 } 2901 2902 2908 public Document getDocument() { 2909 return AbstractDocument.this; 2910 } 2911 2912 2918 public DocumentEvent.ElementChange getChange(Element elem) { 2919 if (changeLookup != null) { 2920 return (DocumentEvent.ElementChange) changeLookup.get(elem); 2921 } 2922 int n = edits.size(); 2923 for (int i = 0; i < n; i++) { 2924 Object o = edits.elementAt(i); 2925 if (o instanceof DocumentEvent.ElementChange) { 2926 DocumentEvent.ElementChange c = (DocumentEvent.ElementChange) o; 2927 if (elem.equals(c.getElement())) { 2928 return c; 2929 } 2930 } 2931 } 2932 return null; 2933 } 2934 2935 2937 private int offset; 2938 private int length; 2939 private Hashtable changeLookup; 2940 private DocumentEvent.EventType type; 2941 2942 } 2943 2944 2950 class UndoRedoDocumentEvent implements DocumentEvent { 2951 private DefaultDocumentEvent src = null; 2952 private boolean isUndo; 2953 private EventType type = null; 2954 2955 public UndoRedoDocumentEvent(DefaultDocumentEvent src, boolean isUndo) { 2956 this.src = src; 2957 this.isUndo = isUndo; 2958 if(isUndo) { 2959 if(src.getType().equals(EventType.INSERT)) { 2960 type = EventType.REMOVE; 2961 } else if(src.getType().equals(EventType.REMOVE)) { 2962 type = EventType.INSERT; 2963 } else { 2964 type = src.getType(); 2965 } 2966 } else { 2967 type = src.getType(); 2968 } 2969 } 2970 2971 public DefaultDocumentEvent getSource() { 2972 return src; 2973 } 2974 2975 public int getOffset() { 2978 return src.getOffset(); 2979 } 2980 2981 public int getLength() { 2982 return src.getLength(); 2983 } 2984 2985 public Document getDocument() { 2986 return src.getDocument(); 2987 } 2988 2989 public DocumentEvent.EventType getType() { 2990 return type; 2991 } 2992 2993 public DocumentEvent.ElementChange getChange(Element elem) { 2994 return src.getChange(elem); 2995 } 2996 } 2997 2998 3002 public static class ElementEdit extends AbstractUndoableEdit implements DocumentEvent.ElementChange { 3003 3004 3014 public ElementEdit(Element e, int index, Element [] removed, Element [] added) { 3015 super(); 3016 this.e = e; 3017 this.index = index; 3018 this.removed = removed; 3019 this.added = added; 3020 } 3021 3022 3027 public Element getElement() { 3028 return e; 3029 } 3030 3031 3036 public int getIndex() { 3037 return index; 3038 } 3039 3040 3045 public Element [] getChildrenRemoved() { 3046 return removed; 3047 } 3048 3049 3054 public Element [] getChildrenAdded() { 3055 return added; 3056 } 3057 3058 3063 public void redo() throws CannotRedoException { 3064 super.redo(); 3065 3066 Element [] tmp = removed; 3068 removed = added; 3069 added = tmp; 3070 3071 ((AbstractDocument.BranchElement )e).replace(index, removed.length, added); 3073 } 3074 3075 3080 public void undo() throws CannotUndoException { 3081 super.undo(); 3082 ((AbstractDocument.BranchElement )e).replace(index, added.length, removed); 3084 3085 Element [] tmp = removed; 3087 removed = added; 3088 added = tmp; 3089 } 3090 3091 private Element e; 3092 private int index; 3093 private Element [] removed; 3094 private Element [] added; 3095 } 3096 3097 3098 private class DefaultFilterBypass extends DocumentFilter.FilterBypass { 3099 public Document getDocument() { 3100 return AbstractDocument.this; 3101 } 3102 3103 public void remove(int offset, int length) throws 3104 BadLocationException { 3105 handleRemove(offset, length); 3106 } 3107 3108 public void insertString(int offset, String string, 3109 AttributeSet attr) throws 3110 BadLocationException { 3111 handleInsertString(offset, string, attr); 3112 } 3113 3114 public void replace(int offset, int length, String text, 3115 AttributeSet attrs) throws BadLocationException { 3116 handleRemove(offset, length); 3117 handleInsertString(offset, text, attrs); 3118 } 3119 } 3120} 3121 3122 3123 3124 3125 3126 3127 3128 | Popular Tags |