1:
37:
38:
39: package ;
40:
41: import ;
42:
43: import ;
44: import ;
45: import ;
46: import ;
47: import ;
48: import ;
49: import ;
50: import ;
51:
52: import ;
53: import ;
54: import ;
55: import ;
56: import ;
57: import ;
58:
59:
69: public class DefaultStyledDocument extends AbstractDocument implements
70: StyledDocument
71: {
72:
73:
78: public static class AttributeUndoableEdit extends AbstractUndoableEdit
79: {
80:
83: protected AttributeSet copy;
84:
85:
88: protected AttributeSet newAttributes;
89:
90:
94: protected boolean isReplacing;
95:
96:
99: protected Element element;
100:
101:
111: public AttributeUndoableEdit(Element el, AttributeSet newAtts,
112: boolean replacing)
113: {
114: element = el;
115: newAttributes = newAtts;
116: isReplacing = replacing;
117: copy = el.getAttributes().copyAttributes();
118: }
119:
120:
124: public void undo()
125: {
126: super.undo();
127: AttributeSet atts = element.getAttributes();
128: if (atts instanceof MutableAttributeSet)
129: {
130: MutableAttributeSet mutable = (MutableAttributeSet) atts;
131: mutable.removeAttributes(atts);
132: mutable.addAttributes(copy);
133: }
134: }
135:
136:
141: public void redo()
142: {
143: super.undo();
144: AttributeSet atts = element.getAttributes();
145: if (atts instanceof MutableAttributeSet)
146: {
147: MutableAttributeSet mutable = (MutableAttributeSet) atts;
148: if (isReplacing)
149: mutable.removeAttributes(atts);
150: mutable.addAttributes(newAttributes);
151: }
152: }
153: }
154:
155:
160: public static class ElementSpec
161: {
162:
165: public static final short StartTagType = 1;
166:
167:
170: public static final short EndTagType = 2;
171:
172:
176: public static final short ContentType = 3;
177:
178:
182: public static final short JoinPreviousDirection = 4;
183:
184:
188: public static final short JoinNextDirection = 5;
189:
190:
194: public static final short OriginateDirection = 6;
195:
196:
201: public static final short JoinFractureDirection = 7;
202:
203:
206: short type;
207:
208:
211: short direction;
212:
213:
216: int offset;
217:
218:
221: int length;
222:
223:
226: char[] content;
227:
228:
231: AttributeSet attributes;
232:
233:
242: public ElementSpec(AttributeSet a, short type)
243: {
244: this(a, type, 0);
245: }
246:
247:
259: public ElementSpec(AttributeSet a, short type, int len)
260: {
261: this(a, type, null, 0, len);
262: }
263:
264:
278: public ElementSpec(AttributeSet a, short type, char[] txt, int offs, int len)
279: {
280: attributes = a;
281: this.type = type;
282: offset = offs;
283: length = len;
284: content = txt;
285: direction = OriginateDirection;
286: }
287:
288:
294: public void setType(short type)
295: {
296: this.type = type;
297: }
298:
299:
304: public short getType()
305: {
306: return type;
307: }
308:
309:
315: public void setDirection(short dir)
316: {
317: direction = dir;
318: }
319:
320:
325: public short getDirection()
326: {
327: return direction;
328: }
329:
330:
335: public AttributeSet getAttributes()
336: {
337: return attributes;
338: }
339:
340:
345: public char[] getArray()
346: {
347: return content;
348: }
349:
350:
355: public int getOffset()
356: {
357: return offset;
358: }
359:
360:
365: public int getLength()
366: {
367: return length;
368: }
369:
370:
377: public String toString()
378: {
379: CPStringBuilder b = new CPStringBuilder();
380: switch (type)
381: {
382: case StartTagType:
383: b.append("StartTag");
384: break;
385: case EndTagType:
386: b.append("EndTag");
387: break;
388: case ContentType:
389: b.append("Content");
390: break;
391: default:
392: b.append("??");
393: break;
394: }
395:
396: b.append(':');
397:
398: switch (direction)
399: {
400: case JoinPreviousDirection:
401: b.append("JoinPrevious");
402: break;
403: case JoinNextDirection:
404: b.append("JoinNext");
405: break;
406: case OriginateDirection:
407: b.append("Originate");
408: break;
409: case JoinFractureDirection:
410: b.append("Fracture");
411: break;
412: default:
413: b.append("??");
414: break;
415: }
416:
417: b.append(':');
418: b.append(length);
419:
420: return b.toString();
421: }
422: }
423:
424:
429: public class ElementBuffer implements Serializable
430: {
431:
437: class Edit
438: {
439:
440: Element e;
441:
442:
443: int index;
444:
445:
446: ArrayList removed = new ArrayList();
447:
448:
449: ArrayList added = new ArrayList();
450:
451:
454: boolean isFracture;
455:
456:
462: Edit(Element el, int i)
463: {
464: this(el, i, false);
465: }
466:
467:
474: Edit(Element el, int i, boolean frac)
475: {
476: e = el;
477: index = i;
478: isFracture = frac;
479: }
480:
481: }
482:
483:
484: private static final long serialVersionUID = 1688745877691146623L;
485:
486:
487: private Element root;
488:
489:
490: private int offset;
491:
492:
493: private int endOffset;
494:
495:
496: private int length;
497:
498:
499: private int pos;
500:
501:
504: private Element fracturedParent;
505:
506:
509: private Element fracturedChild;
510:
511:
514: private boolean createdFracture;
515:
516:
520: private Stack elementStack;
521:
522: private Edit[] insertPath;
523:
524: private boolean recreateLeafs;
525:
526:
529: private ArrayList edits;
530:
531: private boolean offsetLastIndex;
532: private boolean offsetLastIndexReplace;
533:
534:
541: public ElementBuffer(Element root)
542: {
543: this.root = root;
544: }
545:
546:
551: public Element getRootElement()
552: {
553: return root;
554: }
555:
556:
567: public void remove(int offs, int len, DefaultDocumentEvent ev)
568: {
569: prepareEdit(offs, len);
570: removeUpdate();
571: finishEdit(ev);
572: }
573:
574:
579: protected void removeUpdate()
580: {
581: removeElements(root, offset, endOffset);
582: }
583:
584: private boolean removeElements(Element elem, int rmOffs0, int rmOffs1)
585: {
586: boolean ret = false;
587: if (! elem.isLeaf())
588: {
589:
590: int index0 = elem.getElementIndex(rmOffs0);
591: int index1 = elem.getElementIndex(rmOffs1);
592: elementStack.push(new Edit(elem, index0));
593: Edit ec = (Edit) elementStack.peek();
594:
595:
596:
597: if (index0 == index1)
598: {
599: Element child0 = elem.getElement(index0);
600: if(rmOffs0 <= child0.getStartOffset()
601: && rmOffs1 >= child0.getEndOffset())
602: {
603:
604: ec.removed.add(child0);
605: }
606: else if (removeElements(child0, rmOffs0, rmOffs1))
607: {
608: ec.removed.add(child0);
609: }
610: }
611: else
612: {
613:
614:
615:
616: Element child0 = elem.getElement(index0);
617: Element child1 = elem.getElement(index1);
618: boolean containsOffs1 = (rmOffs1 < elem.getEndOffset());
619: if (containsOffs1 && canJoin(child0, child1))
620: {
621:
622: for (int i = index0; i <= index1; i++)
623: {
624: ec.removed.add(elem.getElement(i));
625: }
626: Element e = join(elem, child0, child1, rmOffs0, rmOffs1);
627: ec.added.add(e);
628: }
629: else
630: {
631:
632: int rmIndex0 = index0 + 1;
633: int rmIndex1 = index1 - 1;
634: if (child0.getStartOffset() == rmOffs0
635: || (index0 == 0 && child0.getStartOffset() > rmOffs0
636: && child0.getEndOffset() <= rmOffs1))
637: {
638:
639: child0 = null;
640: rmIndex0 = index0;
641: }
642: if (! containsOffs1)
643: {
644: child1 = null;
645: rmIndex1++;
646: }
647: else if (child1.getStartOffset() == rmOffs1)
648: {
649:
650: child1 = null;
651: }
652: if (rmIndex0 <= rmIndex1)
653: {
654: ec.index = rmIndex0;
655: }
656: for (int i = rmIndex0; i <= rmIndex1; i++)
657: {
658: ec.removed.add(elem.getElement(i));
659: }
660: if (child0 != null)
661: {
662: if(removeElements(child0, rmOffs0, rmOffs1))
663: {
664: ec.removed.add(0, child0);
665: ec.index = index0;
666: }
667: }
668: if (child1 != null)
669: {
670: if(removeElements(child1, rmOffs0, rmOffs1))
671: {
672: ec.removed.add(child1);
673: }
674: }
675: }
676: }
677:
678:
679: pop();
680:
681:
682: if(elem.getElementCount() == (ec.removed.size() - ec.added.size()))
683: ret = true;
684: }
685: return ret;
686: }
687:
688:
696: void create(int len, ElementSpec[] data, DefaultDocumentEvent ev)
697: {
698: prepareEdit(offset, len);
699: Element el = root;
700: int index = el.getElementIndex(0);
701: while (! el.isLeaf())
702: {
703: Element child = el.getElement(index);
704: Edit edit = new Edit(el, index, false);
705: elementStack.push(edit);
706: el = child;
707: index = el.getElementIndex(0);
708: }
709: Edit ed = (Edit) elementStack.peek();
710: Element child = ed.e.getElement(ed.index);
711: ed.added.add(createLeafElement(ed.e, child.getAttributes(), getLength(),
712: child.getEndOffset()));
713: ed.removed.add(child);
714: while (elementStack.size() > 1)
715: pop();
716: int n = data.length;
717:
718:
719: AttributeSet newAtts = null;
720: if (n > 0 && data[0].getType() == ElementSpec.StartTagType)
721: newAtts = data[0].getAttributes();
722: if (newAtts == null)
723: newAtts = SimpleAttributeSet.EMPTY;
724: MutableAttributeSet mAtts = (MutableAttributeSet) root.getAttributes();
725: ev.addEdit(new AttributeUndoableEdit(root, newAtts, true));
726: mAtts.removeAttributes(mAtts);
727: mAtts.addAttributes(newAtts);
728:
729:
730: for (int i = 1; i < n; i++)
731: insertElement(data[i]);
732:
733:
734: while (elementStack.size() > 0)
735: pop();
736:
737: finishEdit(ev);
738: }
739:
740: private boolean canJoin(Element e0, Element e1)
741: {
742: boolean ret = false;
743: if ((e0 != null) && (e1 != null))
744: {
745:
746: boolean isLeaf0 = e0.isLeaf();
747: boolean isLeaf1 = e1.isLeaf();
748: if(isLeaf0 == isLeaf1)
749: {
750: if (isLeaf0)
751: {
752:
753:
754: ret = e0.getAttributes().isEqual(e1.getAttributes());
755: }
756: else
757: {
758:
759:
760:
761: String name0 = e0.getName();
762: String name1 = e1.getName();
763: if (name0 != null)
764: ret = name0.equals(name1);
765: else if (name1 != null)
766: ret = name1.equals(name0);
767: else
768: ret = true;
769: }
770: }
771: }
772: return ret;
773: }
774:
775: private Element join(Element p, Element left, Element right, int rmOffs0,
776: int rmOffs1)
777: {
778: Element joined = null;
779: if (left.isLeaf() && right.isLeaf())
780: {
781: joined = createLeafElement(p, left.getAttributes(),
782: left.getStartOffset(),
783: right.getEndOffset());
784: }
785: else if ((! left.isLeaf()) && (! right.isLeaf()))
786: {
787:
788:
789:
790:
791: joined = createBranchElement(p, left.getAttributes());
792: int ljIndex = left.getElementIndex(rmOffs0);
793: int rjIndex = right.getElementIndex(rmOffs1);
794: Element lj = left.getElement(ljIndex);
795: if (lj.getStartOffset() >= rmOffs0)
796: {
797: lj = null;
798: }
799: Element rj = right.getElement(rjIndex);
800: if (rj.getStartOffset() == rmOffs1)
801: {
802: rj = null;
803: }
804: ArrayList children = new ArrayList();
805:
806: for (int i = 0; i < ljIndex; i++)
807: {
808: children.add(clone(joined, left.getElement(i)));
809: }
810:
811:
812: if (canJoin(lj, rj))
813: {
814: Element e = join(joined, lj, rj, rmOffs0, rmOffs1);
815: children.add(e);
816: }
817: else
818: {
819: if (lj != null)
820: {
821: children.add(cloneAsNecessary(joined, lj, rmOffs0, rmOffs1));
822: }
823: if (rj != null)
824: {
825: children.add(cloneAsNecessary(joined, rj, rmOffs0, rmOffs1));
826: }
827: }
828:
829:
830: int n = right.getElementCount();
831: for (int i = (rj == null) ? rjIndex : rjIndex + 1; i < n; i++)
832: {
833: children.add(clone(joined, right.getElement(i)));
834: }
835:
836:
837: Element[] c = new Element[children.size()];
838: c = (Element[]) children.toArray(c);
839: ((BranchElement) joined).replace(0, 0, c);
840: }
841: else
842: {
843: assert false : "Must not happen";
844: }
845: return joined;
846: }
847:
848:
853: protected void changeUpdate()
854: {
855: boolean didEnd = split(offset, length);
856: if (! didEnd)
857: {
858:
859: while (elementStack.size() != 0)
860: {
861: pop();
862: }
863: split(offset + length, 0);
864: }
865: while (elementStack.size() != 0)
866: {
867: pop();
868: }
869: }
870:
871:
885: public void change(int offset, int length, DefaultDocumentEvent ev)
886: {
887: prepareEdit(offset, length);
888: changeUpdate();
889: finishEdit(ev);
890: }
891:
892:
904: public Element clone(Element parent, Element clonee)
905: {
906: Element clone = clonee;
907:
908: if (clonee instanceof BranchElement)
909: {
910: BranchElement branchEl = (BranchElement) clonee;
911: BranchElement branchClone =
912: new BranchElement(parent, branchEl.getAttributes());
913:
914: int numChildren = branchClone.getElementCount();
915: Element[] cloneChildren = new Element[numChildren];
916: for (int i = 0; i < numChildren; ++i)
917: {
918: cloneChildren[i] = clone(branchClone,
919: branchClone.getElement(i));
920: }
921: branchClone.replace(0, 0, cloneChildren);
922: clone = branchClone;
923: }
924: else if (clonee instanceof LeafElement)
925: {
926: clone = new LeafElement(parent, clonee.getAttributes(),
927: clonee.getStartOffset(),
928: clonee.getEndOffset());
929: }
930: return clone;
931: }
932:
933: private Element cloneAsNecessary(Element parent, Element clonee,
934: int rmOffs0, int rmOffs1)
935: {
936: Element cloned;
937: if (clonee.isLeaf())
938: {
939: cloned = createLeafElement(parent, clonee.getAttributes(),
940: clonee.getStartOffset(),
941: clonee.getEndOffset());
942: }
943: else
944: {
945: Element e = createBranchElement(parent, clonee.getAttributes());
946: int n = clonee.getElementCount();
947: ArrayList childrenList = new ArrayList(n);
948: for (int i = 0; i < n; i++)
949: {
950: Element elem = clonee.getElement(i);
951: if (elem.getStartOffset() < rmOffs0
952: || elem.getEndOffset() > rmOffs1)
953: {
954: childrenList.add(cloneAsNecessary(e, elem, rmOffs0,
955: rmOffs1));
956: }
957: }
958: Element[] children = new Element[childrenList.size()];
959: children = (Element[]) childrenList.toArray(children);
960: ((BranchElement) e).replace(0, 0, children);
961: cloned = e;
962: }
963: return cloned;
964: }
965:
966:
981: public void insert(int offset, int length, ElementSpec[] data,
982: DefaultDocumentEvent ev)
983: {
984: if (length > 0)
985: {
986: prepareEdit(offset, length);
987: insertUpdate(data);
988: finishEdit(ev);
989: }
990: }
991:
992:
998: private void prepareEdit(int offset, int length)
999: {
1000: this.offset = offset;
1001: this.pos = offset;
1002: this.endOffset = offset + length;
1003: this.length = length;
1004:
1005: if (edits == null)
1006: edits = new ArrayList();
1007: else
1008: edits.clear();
1009:
1010: if (elementStack == null)
1011: elementStack = new Stack();
1012: else
1013: elementStack.clear();
1014:
1015: fracturedParent = null;
1016: fracturedChild = null;
1017: offsetLastIndex = false;
1018: offsetLastIndexReplace = false;
1019: }
1020:
1021:
1027: private void finishEdit(DefaultDocumentEvent ev)
1028: {
1029:
1030:
1031: for (Iterator i = edits.iterator(); i.hasNext();)
1032: {
1033: Edit edits = (Edit) i.next();
1034: Element[] removed = new Element[edits.removed.size()];
1035: removed = (Element[]) edits.removed.toArray(removed);
1036: Element[] added = new Element[edits.added.size()];
1037: added = (Element[]) edits.added.toArray(added);
1038: int index = edits.index;
1039: BranchElement parent = (BranchElement) edits.e;
1040: parent.replace(index, removed.length, added);
1041: ElementEdit ee = new ElementEdit(parent, index, removed, added);
1042: ev.addEdit(ee);
1043: }
1044: edits.clear();
1045: elementStack.clear();
1046: }
1047:
1048:
1053: protected void insertUpdate(ElementSpec[] data)
1054: {
1055:
1056: Element current = root;
1057: int index = current.getElementIndex(offset);
1058: while (! current.isLeaf())
1059: {
1060: Element child = current.getElement(index);
1061: int editIndex = child.isLeaf() ? index : index + 1;
1062: Edit edit = new Edit(current, editIndex);
1063: elementStack.push(edit);
1064: current = child;
1065: index = current.getElementIndex(offset);
1066: }
1067:
1068:
1069: insertPath = new Edit[elementStack.size()];
1070: insertPath = (Edit[]) elementStack.toArray(insertPath);
1071:
1072:
1073: createdFracture = false;
1074:
1075:
1076: int i = 0;
1077: recreateLeafs = false;
1078: int type = data[0].getType();
1079: if (type == ElementSpec.ContentType)
1080: {
1081:
1082:
1083:
1084: insertFirstContentTag(data);
1085: pos += data[0].length;
1086: i = 1;
1087: }
1088: else
1089: {
1090: createFracture(data);
1091: i = 0;
1092: }
1093:
1094:
1095: for (; i < data.length; i++)
1096: {
1097: insertElement(data[i]);
1098: }
1099:
1100:
1101: if (! createdFracture)
1102: fracture(-1);
1103:
1104:
1105: while (elementStack.size() != 0)
1106: pop();
1107:
1108:
1109: if (offsetLastIndex && offsetLastIndexReplace)
1110: insertPath[insertPath.length - 1].index++;
1111:
1112:
1113: for (int p = insertPath.length - 1; p >= 0; p--)
1114: {
1115: Edit edit = insertPath[p];
1116: if (edit.e == fracturedParent)
1117: edit.added.add(fracturedChild);
1118: if ((edit.added.size() > 0 || edit.removed.size() > 0)
1119: && ! edits.contains(edit))
1120: edits.add(edit);
1121: }
1122:
1123:
1124:
1125: if (offset == 0 && fracturedParent != null
1126: && data[0].getType() == ElementSpec.EndTagType)
1127: {
1128: int p;
1129: for (p = 0;
1130: p < data.length && data[p].getType() == ElementSpec.EndTagType;
1131: p++)
1132: ;
1133:
1134: Edit edit = insertPath[insertPath.length - p - 1];
1135: edit.index--;
1136: edit.removed.add(0, edit.e.getElement(edit.index));
1137: }
1138: }
1139:
1140: private void pop()
1141: {
1142: Edit edit = (Edit) elementStack.peek();
1143: elementStack.pop();
1144: if ((edit.added.size() > 0) || (edit.removed.size() > 0))
1145: {
1146: edits.add(edit);
1147: }
1148: else if (! elementStack.isEmpty())
1149: {
1150: Element e = edit.e;
1151: if (e.getElementCount() == 0)
1152: {
1153:
1154:
1155: edit = (Edit) elementStack.peek();
1156: edit.added.remove(e);
1157: }
1158: }
1159: }
1160:
1161: private void insertElement(ElementSpec spec)
1162: {
1163: if (elementStack.isEmpty())
1164: return;
1165:
1166: Edit edit = (Edit) elementStack.peek();
1167: switch (spec.getType())
1168: {
1169: case ElementSpec.StartTagType:
1170: switch (spec.getDirection())
1171: {
1172: case ElementSpec.JoinFractureDirection:
1173:
1174:
1175: if (! createdFracture)
1176: {
1177: fracture(elementStack.size() - 1);
1178: }
1179: if (! edit.isFracture)
1180: {
1181:
1182:
1183: Edit newEdit = new Edit(fracturedChild, 0, true);
1184: elementStack.push(newEdit);
1185: }
1186: else
1187: {
1188:
1189: Element el = edit.e.getElement(0);
1190: Edit newEdit = new Edit(el, 0, true);
1191: elementStack.push(newEdit);
1192: }
1193: break;
1194: case ElementSpec.JoinNextDirection:
1195:
1196:
1197: Element parent = edit.e.getElement(edit.index);
1198: if (parent.isLeaf())
1199: {
1200: if (edit.index + 1 < edit.e.getElementCount())
1201: parent = edit.e.getElement(edit.index + 1);
1202: else
1203: assert false;
1204: }
1205: elementStack.push(new Edit(parent, 0, true));
1206: break;
1207: default:
1208: Element branch = createBranchElement(edit.e,
1209: spec.getAttributes());
1210: edit.added.add(branch);
1211: elementStack.push(new Edit(branch, 0));
1212: break;
1213: }
1214: break;
1215: case ElementSpec.EndTagType:
1216: pop();
1217: break;
1218: case ElementSpec.ContentType:
1219: insertContentTag(spec, edit);
1220: break;
1221: }
1222: }
1223:
1224:
1230: private void insertFirstContentTag(ElementSpec[] data)
1231: {
1232: ElementSpec first = data[0];
1233: Edit edit = (Edit) elementStack.peek();
1234: Element current = edit.e.getElement(edit.index);
1235: int firstEndOffset = offset + first.length;
1236: boolean onlyContent = data.length == 1;
1237: switch (first.getDirection())
1238: {
1239: case ElementSpec.JoinPreviousDirection:
1240: if (current.getEndOffset() != firstEndOffset && ! onlyContent)
1241: {
1242: Element newEl1 = createLeafElement(edit.e,
1243: current.getAttributes(),
1244: current.getStartOffset(),
1245: firstEndOffset);
1246: edit.added.add(newEl1);
1247: edit.removed.add(current);
1248: if (current.getEndOffset() != endOffset)
1249: recreateLeafs = true;
1250: else
1251: offsetLastIndex = true;
1252: }
1253: else
1254: {
1255: offsetLastIndex = true;
1256: offsetLastIndexReplace = true;
1257: }
1258: break;
1259: case ElementSpec.JoinNextDirection:
1260: if (offset != 0)
1261: {
1262: Element newEl1 = createLeafElement(edit.e,
1263: current.getAttributes(),
1264: current.getStartOffset(),
1265: offset);
1266: edit.added.add(newEl1);
1267: Element next = edit.e.getElement(edit.index + 1);
1268: if (onlyContent)
1269: newEl1 = createLeafElement(edit.e, next.getAttributes(),
1270: offset, next.getEndOffset());
1271: else
1272: {
1273: newEl1 = createLeafElement(edit.e, next.getAttributes(),
1274: offset, firstEndOffset);
1275: }
1276: edit.added.add(newEl1);
1277: edit.removed.add(current);
1278: edit.removed.add(next);
1279: }
1280: break;
1281: default:
1282: if (current.getStartOffset() != offset)
1283: {
1284: Element newEl = createLeafElement(edit.e,
1285: current.getAttributes(),
1286: current.getStartOffset(),
1287: offset);
1288: edit.added.add(newEl);
1289: }
1290: edit.removed.add(current);
1291: Element newEl1 = createLeafElement(edit.e, first.getAttributes(),
1292: offset, firstEndOffset);
1293: edit.added.add(newEl1);
1294: if (current.getEndOffset() != endOffset)
1295: recreateLeafs = true;
1296: else
1297: offsetLastIndex = true;
1298: break;
1299: }
1300: }
1301:
1302:
1308: private void insertContentTag(ElementSpec tag, Edit edit)
1309: {
1310: int len = tag.getLength();
1311: int dir = tag.getDirection();
1312: if (dir == ElementSpec.JoinNextDirection)
1313: {
1314: if (! edit.isFracture)
1315: {
1316: Element first = null;
1317: if (insertPath != null)
1318: {
1319: for (int p = insertPath.length - 1; p >= 0; p--)
1320: {
1321: if (insertPath[p] == edit)
1322: {
1323: if (p != insertPath.length - 1)
1324: first = edit.e.getElement(edit.index);
1325: break;
1326: }
1327: }
1328: }
1329: if (first == null)
1330: first = edit.e.getElement(edit.index + 1);
1331: Element leaf = createLeafElement(edit.e, first.getAttributes(),
1332: pos, first.getEndOffset());
1333: edit.added.add(leaf);
1334: edit.removed.add(first);
1335: }
1336: else
1337: {
1338: Element first = edit.e.getElement(0);
1339: Element leaf = createLeafElement(edit.e, first.getAttributes(),
1340: pos, first.getEndOffset());
1341: edit.added.add(leaf);
1342: edit.removed.add(first);
1343: }
1344: }
1345: else
1346: {
1347: Element leaf = createLeafElement(edit.e, tag.getAttributes(), pos,
1348: pos + len);
1349: edit.added.add(leaf);
1350: }
1351:
1352: pos += len;
1353:
1354: }
1355:
1356:
1363: private void createFracture(ElementSpec[] data)
1364: {
1365: Edit edit = (Edit) elementStack.peek();
1366: Element child = edit.e.getElement(edit.index);
1367: if (offset != 0)
1368: {
1369: Element newChild = createLeafElement(edit.e, child.getAttributes(),
1370: child.getStartOffset(), offset);
1371: edit.added.add(newChild);
1372: }
1373: edit.removed.add(child);
1374: if (child.getEndOffset() != endOffset)
1375: recreateLeafs = true;
1376: else
1377: offsetLastIndex = true;
1378: }
1379:
1380: private void fracture(int depth)
1381: {
1382: int len = insertPath.length;
1383: int lastIndex = -1;
1384: boolean recreate = recreateLeafs;
1385: Edit lastEdit = insertPath[len - 1];
1386: boolean childChanged = lastEdit.index + 1 < lastEdit.e.getElementCount();
1387: int deepestChangedIndex = recreate ? len : - 1;
1388: int lastChangedIndex = len - 1;
1389: createdFracture = true;
1390: for (int i = len - 2; i >= 0; i--)
1391: {
1392: Edit edit = insertPath[i];
1393: if (edit.added.size() > 0 || i == depth)
1394: {
1395: lastIndex = i;
1396: if (! recreate && childChanged)
1397: {
1398: recreate = true;
1399: if (deepestChangedIndex == -1)
1400: deepestChangedIndex = lastChangedIndex + 1;
1401: }
1402: }
1403: if (! childChanged && edit.index < edit.e.getElementCount())
1404: {
1405: childChanged = true;
1406: lastChangedIndex = i;
1407: }
1408: }
1409: if (recreate)
1410: {
1411: if (lastIndex == -1)
1412: lastIndex = len - 1;
1413: recreate(lastIndex, deepestChangedIndex);
1414: }
1415: }
1416:
1417: private void recreate(int startIndex, int endIndex)
1418: {
1419:
1420: Edit edit = insertPath[startIndex];
1421: Element child;
1422: Element newChild;
1423: int changeLength = insertPath.length;
1424:
1425: if (startIndex + 1 == changeLength)
1426: child = edit.e.getElement(edit.index);
1427: else
1428: child = edit.e.getElement(edit.index - 1);
1429:
1430: if(child.isLeaf())
1431: {
1432: newChild = createLeafElement(edit.e, child.getAttributes(),
1433: Math.max(endOffset, child.getStartOffset()),
1434: child.getEndOffset());
1435: }
1436: else
1437: {
1438: newChild = createBranchElement(edit.e, child.getAttributes());
1439: }
1440: fracturedParent = edit.e;
1441: fracturedChild = newChild;
1442:
1443:
1444: Element parent = newChild;
1445: while (++startIndex < endIndex)
1446: {
1447: boolean isEnd = (startIndex + 1) == endIndex;
1448: boolean isEndLeaf = (startIndex + 1) == changeLength;
1449:
1450:
1451:
1452:
1453: edit = insertPath[startIndex];
1454:
1455:
1456:
1457: if(isEnd)
1458: {
1459: if(offsetLastIndex || ! isEndLeaf)
1460: child = null;
1461: else
1462: child = edit.e.getElement(edit.index);
1463: }
1464: else
1465: {
1466: child = edit.e.getElement(edit.index - 1);
1467: }
1468:
1469:
1470: if(child != null)
1471: {
1472: if(child.isLeaf())
1473: {
1474: newChild = createLeafElement(parent, child.getAttributes(),
1475: Math.max(endOffset, child.getStartOffset()),
1476: child.getEndOffset());
1477: }
1478: else
1479: {
1480: newChild = createBranchElement(parent,
1481: child.getAttributes());
1482: }
1483: }
1484: else
1485: newChild = null;
1486:
1487:
1488: int childrenToMove = edit.e.getElementCount() - edit.index;
1489: Element[] children;
1490: int moveStartIndex;
1491: int childStartIndex = 1;
1492:
1493: if (newChild == null)
1494: {
1495:
1496: if (isEndLeaf)
1497: {
1498: childrenToMove--;
1499: moveStartIndex = edit.index + 1;
1500: }
1501: else
1502: {
1503: moveStartIndex = edit.index;
1504: }
1505: childStartIndex = 0;
1506: children = new Element[childrenToMove];
1507: }
1508: else
1509: {
1510: if (! isEnd)
1511: {
1512:
1513: childrenToMove++;
1514: moveStartIndex = edit.index;
1515: }
1516: else
1517: {
1518:
1519: moveStartIndex = edit.index + 1;
1520: }
1521: children = new Element[childrenToMove];
1522: children[0] = newChild;
1523: }
1524:
1525: for (int c = childStartIndex; c < childrenToMove; c++)
1526: {
1527: Element toMove = edit.e.getElement(moveStartIndex++);
1528: children[c] = recreateFracturedElement(parent, toMove);
1529: edit.removed.add(toMove);
1530: }
1531: ((BranchElement) parent).replace(0, 0, children);
1532: parent = newChild;
1533: }
1534:
1535: }
1536:
1537: private Element recreateFracturedElement(Element parent, Element toCopy)
1538: {
1539: Element recreated;
1540: if(toCopy.isLeaf())
1541: {
1542: recreated = createLeafElement(parent, toCopy.getAttributes(),
1543: Math.max(toCopy.getStartOffset(), endOffset),
1544: toCopy.getEndOffset());
1545: }
1546: else
1547: {
1548: Element newParent = createBranchElement(parent,
1549: toCopy.getAttributes());
1550: int childCount = toCopy.getElementCount();
1551: Element[] newChildren = new Element[childCount];
1552: for (int i = 0; i < childCount; i++)
1553: {
1554: newChildren[i] = recreateFracturedElement(newParent,
1555: toCopy.getElement(i));
1556: }
1557: ((BranchElement) newParent).replace(0, 0, newChildren);
1558: recreated = newParent;
1559: }
1560: return recreated;
1561: }
1562:
1563: private boolean split(int offs, int len)
1564: {
1565: boolean splitEnd = false;
1566:
1567: Element e = root;
1568: int index = e.getElementIndex(offs);
1569: while (! e.isLeaf())
1570: {
1571: elementStack.push(new Edit(e, index));
1572: e = e.getElement(index);
1573: index = e.getElementIndex(offs);
1574: }
1575:
1576: Edit ec = (Edit) elementStack.peek();
1577: Element child = ec.e.getElement(ec.index);
1578:
1579:
1580:
1581: if (child.getStartOffset() < offs && offs < child.getEndOffset())
1582: {
1583:
1584:
1585: int index0 = ec.index;
1586: int index1 = index0;
1587: if (((offs + len) < ec.e.getEndOffset()) && (len != 0))
1588: {
1589:
1590: index1 = ec.e.getElementIndex(offs+len);
1591: if (index1 == index0)
1592: {
1593:
1594: ec.removed.add(child);
1595: e = createLeafElement(ec.e, child.getAttributes(),
1596: child.getStartOffset(), offs);
1597: ec.added.add(e);
1598: e = createLeafElement(ec.e, child.getAttributes(),
1599: offs, offs + len);
1600: ec.added.add(e);
1601: e = createLeafElement(ec.e, child.getAttributes(),
1602: offs + len, child.getEndOffset());
1603: ec.added.add(e);
1604: return true;
1605: }
1606: else
1607: {
1608: child = ec.e.getElement(index1);
1609: if ((offs + len) == child.getStartOffset())
1610: {
1611:
1612: index1 = index0;
1613: }
1614: }
1615: splitEnd = true;
1616: }
1617:
1618:
1619: pos = offs;
1620: child = ec.e.getElement(index0);
1621: ec.removed.add(child);
1622: e = createLeafElement(ec.e, child.getAttributes(),
1623: child.getStartOffset(), pos);
1624: ec.added.add(e);
1625: e = createLeafElement(ec.e, child.getAttributes(),
1626: pos, child.getEndOffset());
1627: ec.added.add(e);
1628:
1629:
1630: for (int i = index0 + 1; i < index1; i++)
1631: {
1632: child = ec.e.getElement(i);
1633: ec.removed.add(child);
1634: ec.added.add(child);
1635: }
1636:
1637: if (index1 != index0)
1638: {
1639: child = ec.e.getElement(index1);
1640: pos = offs + len;
1641: ec.removed.add(child);
1642: e = createLeafElement(ec.e, child.getAttributes(),
1643: child.getStartOffset(), pos);
1644: ec.added.add(e);
1645: e = createLeafElement(ec.e, child.getAttributes(),
1646: pos, child.getEndOffset());
1647:
1648: ec.added.add(e);
1649: }
1650: }
1651: return splitEnd;
1652:
1653: }
1654:
1655: }
1656:
1657:
1658:
1662: protected class SectionElement extends BranchElement
1663: {
1664:
1667: public SectionElement()
1668: {
1669: super(null, null);
1670: }
1671:
1672:
1678: public String getName()
1679: {
1680: return SectionElementName;
1681: }
1682: }
1683:
1684:
1690: private class StyleChangeListener implements ChangeListener
1691: {
1692:
1693:
1700: public void stateChanged(ChangeEvent event)
1701: {
1702: Style style = (Style) event.getSource();
1703: styleChanged(style);
1704: }
1705: }
1706:
1707:
1708: private static final long serialVersionUID = 940485415728614849L;
1709:
1710:
1713: public static final int BUFFER_SIZE_DEFAULT = 4096;
1714:
1715:
1719: protected DefaultStyledDocument.ElementBuffer buffer;
1720:
1721:
1724: private StyleChangeListener styleChangeListener;
1725:
1726:
1729: public DefaultStyledDocument()
1730: {
1731: this(new GapContent(BUFFER_SIZE_DEFAULT), new StyleContext());
1732: }
1733:
1734:
1741: public DefaultStyledDocument(StyleContext context)
1742: {
1743: this(new GapContent(BUFFER_SIZE_DEFAULT), context);
1744: }
1745:
1746:
1755: public DefaultStyledDocument(AbstractDocument.Content content,
1756: StyleContext context)
1757: {
1758: super(content, context);
1759: buffer = new ElementBuffer(createDefaultRoot());
1760: setLogicalStyle(0, context.getStyle(StyleContext.DEFAULT_STYLE));
1761: }
1762:
1763:
1778: public Style addStyle(String nm, Style parent)
1779: {
1780: StyleContext context = (StyleContext) getAttributeContext();
1781: Style newStyle = context.addStyle(nm, parent);
1782:
1783:
1784: if (styleChangeListener == null)
1785: styleChangeListener = new StyleChangeListener();
1786: newStyle.addChangeListener(styleChangeListener);
1787:
1788: return newStyle;
1789: }
1790:
1791:
1796: protected AbstractDocument.AbstractElement createDefaultRoot()
1797: {
1798: Element[] tmp;
1799: SectionElement section = new SectionElement();
1800:
1801: BranchElement paragraph = new BranchElement(section, null);
1802: tmp = new Element[1];
1803: tmp[0] = paragraph;
1804: section.replace(0, 0, tmp);
1805:
1806: Element leaf = new LeafElement(paragraph, null, 0, 1);
1807: tmp = new Element[1];
1808: tmp[0] = leaf;
1809: paragraph.replace(0, 0, tmp);
1810:
1811: return section;
1812: }
1813:
1814:
1824: public Element getCharacterElement(int position)
1825: {
1826: Element element = getDefaultRootElement();
1827:
1828: while (!element.isLeaf())
1829: {
1830: int index = element.getElementIndex(position);
1831: element = element.getElement(index);
1832: }
1833:
1834: return element;
1835: }
1836:
1837:
1844: public Color getBackground(AttributeSet attributes)
1845: {
1846: StyleContext context = (StyleContext) getAttributeContext();
1847: return context.getBackground(attributes);
1848: }
1849:
1850:
1855: public Element getDefaultRootElement()
1856: {
1857: return buffer.getRootElement();
1858: }
1859:
1860:
1867: public Font getFont(AttributeSet attributes)
1868: {
1869: StyleContext context = (StyleContext) getAttributeContext();
1870: return context.getFont(attributes);
1871: }
1872:
1873:
1880: public Color getForeground(AttributeSet attributes)
1881: {
1882: StyleContext context = (StyleContext) getAttributeContext();
1883: return context.getForeground(attributes);
1884: }
1885:
1886:
1893: public Style getLogicalStyle(int position)
1894: {
1895: Element paragraph = getParagraphElement(position);
1896: AttributeSet attributes = paragraph.getAttributes();
1897: AttributeSet a = attributes.getResolveParent();
1898:
1899: if (a instanceof Style)
1900: return (Style) a;
1901: return null;
1902: }
1903:
1904:
1915: public Element getParagraphElement(int position)
1916: {
1917: Element e = getDefaultRootElement();
1918: while (!e.isLeaf())
1919: e = e.getElement(e.getElementIndex(position));
1920:
1921: if (e != null)
1922: return e.getParentElement();
1923: return e;
1924: }
1925:
1926:
1934: public Style getStyle(String nm)
1935: {
1936: StyleContext context = (StyleContext) getAttributeContext();
1937: return context.getStyle(nm);
1938: }
1939:
1940:
1946: public void removeStyle(String nm)
1947: {
1948: StyleContext context = (StyleContext) getAttributeContext();
1949: context.removeStyle(nm);
1950: }
1951:
1952:
1966: public void setCharacterAttributes(int offset, int length,
1967: AttributeSet attributes, boolean replace)
1968: {
1969:
1970: if (length == 0)
1971: return;
1972: try
1973: {
1974:
1975:
1976:
1977: writeLock();
1978: DefaultDocumentEvent ev = new DefaultDocumentEvent(offset,
1979: length,
1980: DocumentEvent.EventType.CHANGE);
1981:
1982:
1983:
1984:
1985: buffer.change(offset, length, ev);
1986:
1987:
1988: int end = offset + length;
1989: Element curr;
1990: for (int pos = offset; pos < end;)
1991: {
1992:
1993: curr = getCharacterElement(pos);
1994: if (pos == curr.getEndOffset())
1995: break;
1996:
1997: MutableAttributeSet a = (MutableAttributeSet) curr.getAttributes();
1998: ev.addEdit(new AttributeUndoableEdit(curr, attributes, replace));
1999:
2000: if (replace)
2001: a.removeAttributes(a);
2002:
2003: a.addAttributes(attributes);
2004:
2005: pos = curr.getEndOffset();
2006: }
2007: fireChangedUpdate(ev);
2008: fireUndoableEditUpdate(new UndoableEditEvent(this, ev));
2009: }
2010: finally
2011: {
2012: writeUnlock();
2013: }
2014: }
2015:
2016:
2024: public void setLogicalStyle(int position, Style style)
2025: {
2026: Element el = getParagraphElement(position);
2027:
2028:
2029: if (el == null)
2030: return;
2031: try
2032: {
2033: writeLock();
2034: if (el instanceof AbstractElement)
2035: {
2036: AbstractElement ael = (AbstractElement) el;
2037: ael.setResolveParent(style);
2038: int start = el.getStartOffset();
2039: int end = el.getEndOffset();
2040: DefaultDocumentEvent ev = new DefaultDocumentEvent(start,
2041: end - start,
2042: DocumentEvent.EventType.CHANGE);
2043: fireChangedUpdate(ev);
2044: fireUndoableEditUpdate(new UndoableEditEvent(this, ev));
2045: }
2046: else
2047: throw new AssertionError(
2048: "paragraph elements are expected to be"
2049: + "instances of AbstractDocument.AbstractElement");
2050: }
2051: finally
2052: {
2053: writeUnlock();
2054: }
2055: }
2056:
2057:
2070: public void setParagraphAttributes(int offset, int length,
2071: AttributeSet attributes, boolean replace)
2072: {
2073: try
2074: {
2075:
2076:
2077:
2078: writeLock();
2079:
2080:
2081: DefaultDocumentEvent ev = new DefaultDocumentEvent(offset,
2082: length,
2083: DocumentEvent.EventType.CHANGE);
2084:
2085:
2086:
2087:
2088: Element rootElement = getDefaultRootElement();
2089: int startElement = rootElement.getElementIndex(offset);
2090: int endElement = rootElement.getElementIndex(offset + length - 1);
2091: if (endElement < startElement)
2092: endElement = startElement;
2093:
2094: for (int i = startElement; i <= endElement; i++)
2095: {
2096: Element par = rootElement.getElement(i);
2097: MutableAttributeSet a = (MutableAttributeSet) par.getAttributes();
2098:
2099: ev.addEdit(new AttributeUndoableEdit(par, attributes, replace));
2100:
2101: if (replace)
2102: a.removeAttributes(a);
2103:
2104: a.addAttributes(attributes);
2105: }
2106: fireChangedUpdate(ev);
2107: fireUndoableEditUpdate(new UndoableEditEvent(this, ev));
2108: }
2109: finally
2110: {
2111: writeUnlock();
2112: }
2113: }
2114:
2115:
2124: protected void insertUpdate(DefaultDocumentEvent ev, AttributeSet attr)
2125: {
2126: int offs = ev.getOffset();
2127: int len = ev.getLength();
2128: int endOffs = offs + len;
2129: if (attr == null)
2130: attr = SimpleAttributeSet.EMPTY;
2131:
2132:
2133: Element paragraph = getParagraphElement(endOffs);
2134: AttributeSet pAttr = paragraph.getAttributes();
2135:
2136: Element paragraph2 = getParagraphElement(offs);
2137: int contIndex = paragraph2.getElementIndex(offs);
2138: Element content = paragraph2.getElement(contIndex);
2139: AttributeSet cAttr = content.getAttributes();
2140:
2141: boolean insertAtBoundary = content.getEndOffset() == endOffs;
2142: try
2143: {
2144: Segment s = new Segment();
2145: ArrayList buf = new ArrayList();
2146: ElementSpec lastStartTag = null;
2147: boolean insertAfterNewline = false;
2148: short lastStartDir = ElementSpec.OriginateDirection;
2149:
2150:
2151: if (offs > 0)
2152: {
2153: getText(offs - 1, 1, s);
2154: if (s.array[s.offset] == '\n')
2155: {
2156: insertAfterNewline = true;
2157: lastStartDir = insertAfterNewline(paragraph, paragraph2,
2158: pAttr, buf, offs,
2159: endOffs);
2160:
2161: for (int i = buf.size() - 1; i >= 0 && lastStartTag == null;
2162: i--)
2163: {
2164: ElementSpec tag = (ElementSpec) buf.get(i);
2165: if (tag.getType() == ElementSpec.StartTagType)
2166: {
2167: lastStartTag = tag;
2168: }
2169: }
2170: }
2171:
2172: }
2173:
2174:
2175:
2176: if (! insertAfterNewline)
2177: pAttr = paragraph2.getAttributes();
2178:
2179:
2180: getText(offs, len, s);
2181: int end = s.offset + s.count;
2182: int last = s.offset;
2183: for (int i = s.offset; i < end; i++)
2184: {
2185: if (s.array[i] == '\n')
2186: {
2187: int breakOffs = i + 1;
2188: buf.add(new ElementSpec(attr, ElementSpec.ContentType,
2189: breakOffs - last));
2190: buf.add(new ElementSpec(null, ElementSpec.EndTagType));
2191: lastStartTag = new ElementSpec(pAttr,
2192: ElementSpec.StartTagType);
2193: buf.add(lastStartTag);
2194: last = breakOffs;
2195: }
2196: }
2197:
2198:
2199: if (last < end)
2200: {
2201: buf.add(new ElementSpec(attr, ElementSpec.ContentType,
2202: end - last));
2203: }
2204:
2205:
2206: ElementSpec first = (ElementSpec) buf.get(0);
2207: int doclen = getLength();
2208:
2209:
2210:
2211: if (first.getType() == ElementSpec.ContentType && cAttr.isEqual(attr))
2212: first.setDirection(ElementSpec.JoinPreviousDirection);
2213:
2214:
2215: if (lastStartTag != null)
2216: {
2217: if (insertAfterNewline)
2218: lastStartTag.setDirection(lastStartDir);
2219: else if (paragraph2.getEndOffset() != endOffs)
2220: lastStartTag.setDirection(ElementSpec.JoinFractureDirection);
2221: else
2222: {
2223: Element par = paragraph2.getParentElement();
2224: int par2Index = par.getElementIndex(offs);
2225: if (par2Index + 1 < par.getElementCount()
2226: && ! par.getElement(par2Index + 1).isLeaf())
2227: lastStartTag.setDirection(ElementSpec.JoinNextDirection);
2228: }
2229: }
2230:
2231:
2232: if (insertAtBoundary && endOffs < doclen)
2233: {
2234: ElementSpec lastTag = (ElementSpec) buf.get(buf.size() - 1);
2235: if (lastTag.getType() == ElementSpec.ContentType
2236: && ((lastStartTag == null
2237: && (paragraph == paragraph2 || insertAfterNewline))
2238: || (lastStartTag != null
2239: && lastStartTag.getDirection() != ElementSpec.OriginateDirection)))
2240: {
2241: int nextIndex = paragraph.getElementIndex(endOffs);
2242: Element nextRun = paragraph.getElement(nextIndex);
2243: if (nextRun.isLeaf() && attr.isEqual(nextRun.getAttributes()))
2244: lastTag.setDirection(ElementSpec.JoinNextDirection);
2245: }
2246: }
2247:
2248: else if (! insertAtBoundary && lastStartTag != null
2249: && lastStartTag.getDirection() == ElementSpec.JoinFractureDirection)
2250: {
2251: ElementSpec lastTag = (ElementSpec) buf.get(buf.size() - 1);
2252: if (lastTag.getType() == ElementSpec.ContentType
2253: && lastTag.getDirection() != ElementSpec.JoinPreviousDirection
2254: && attr.isEqual(cAttr))
2255: {
2256: lastTag.setDirection(ElementSpec.JoinNextDirection);
2257: }
2258: }
2259:
2260: ElementSpec[] specs = new ElementSpec[buf.size()];
2261: specs = (ElementSpec[]) buf.toArray(specs);
2262: buffer.insert(offs, len, specs, ev);
2263: }
2264: catch (BadLocationException ex)
2265: {
2266:
2267: ex.printStackTrace();
2268: }
2269: super.insertUpdate(ev, attr);
2270: }
2271:
2272: private short insertAfterNewline(Element par1, Element par2,
2273: AttributeSet attr, ArrayList buf,
2274: int offs, int endOffs)
2275: {
2276: short dir = 0;
2277: if (par1.getParentElement() == par2.getParentElement())
2278: {
2279: ElementSpec tag = new ElementSpec(attr, ElementSpec.EndTagType);
2280: buf.add(tag);
2281: tag = new ElementSpec(attr, ElementSpec.StartTagType);
2282: buf.add(tag);
2283: if (par2.getEndOffset() != endOffs)
2284: dir = ElementSpec.JoinFractureDirection;
2285: else
2286: {
2287: Element par = par2.getParentElement();
2288: if (par.getElementIndex(offs) + 1 < par.getElementCount())
2289: dir = ElementSpec.JoinNextDirection;
2290: }
2291: }
2292: else
2293: {
2294:
2295:
2296: ArrayList parentsLeft = new ArrayList();
2297: ArrayList parentsRight = new ArrayList();
2298: Element e = par2;
2299: while (e != null)
2300: {
2301: parentsLeft.add(e);
2302: e = e.getParentElement();
2303: }
2304: e = par1;
2305: int leftIndex = -1;
2306: while (e != null && (leftIndex = parentsLeft.indexOf(e)) == 1)
2307: {
2308: parentsRight.add(e);
2309: e = e.getParentElement();
2310: }
2311:
2312: if (e != null)
2313:
2314: {
2315:
2316:
2317: for (int c = 0; c < leftIndex; c++)
2318: {
2319: buf.add(new ElementSpec(null, ElementSpec.EndTagType));
2320: }
2321:
2322: for (int c = parentsRight.size() - 1; c >= 0; c--)
2323: {
2324: Element el = (Element) parentsRight.get(c);
2325: ElementSpec tag = new ElementSpec(el.getAttributes(),
2326: ElementSpec.StartTagType);
2327: if (c > 0)
2328: tag.setDirection(ElementSpec.JoinNextDirection);
2329: buf.add(tag);
2330: }
2331: if (parentsRight.size() > 0)
2332: dir = ElementSpec.JoinNextDirection;
2333: else
2334: dir = ElementSpec.JoinFractureDirection;
2335: }
2336: else
2337: assert false;
2338: }
2339: return dir;
2340: }
2341:
2342:
2349: short handleInsertAfterNewline(Vector specs, int offset, int endOffset,
2350: Element prevParagraph, Element paragraph,
2351: AttributeSet a)
2352: {
2353: if (prevParagraph.getParentElement() == paragraph.getParentElement())
2354: {
2355: specs.add(new ElementSpec(a, ElementSpec.EndTagType));
2356: specs.add(new ElementSpec(a, ElementSpec.StartTagType));
2357: if (paragraph.getStartOffset() != endOffset)
2358: return ElementSpec.JoinFractureDirection;
2359:
2360: Element parent = paragraph.getParentElement();
2361: if (parent.getElementCount() > (parent.getElementIndex(offset) + 1))
2362: return ElementSpec.JoinNextDirection;
2363: }
2364: return ElementSpec.OriginateDirection;
2365: }
2366:
2367:
2376: protected void removeUpdate(DefaultDocumentEvent ev)
2377: {
2378: super.removeUpdate(ev);
2379: buffer.remove(ev.getOffset(), ev.getLength(), ev);
2380: }
2381:
2382:
2387: public Enumeration<?> getStyleNames()
2388: {
2389: StyleContext context = (StyleContext) getAttributeContext();
2390: return context.getStyleNames();
2391: }
2392:
2393:
2399: protected void styleChanged(Style style)
2400: {
2401:
2402: }
2403:
2404:
2412: protected void insert(int offset, ElementSpec[] data)
2413: throws BadLocationException
2414: {
2415: if (data == null || data.length == 0)
2416: return;
2417: try
2418: {
2419:
2420:
2421:
2422: writeLock();
2423:
2424:
2425: CPStringBuilder contentBuffer = new CPStringBuilder();
2426: for (int i = 0; i < data.length; i++)
2427: {
2428:
2429:
2430: ElementSpec spec = data[i];
2431: if (spec.getArray() != null && spec.getLength() > 0)
2432: contentBuffer.append(spec.getArray(), spec.getOffset(),
2433: spec.getLength());
2434: }
2435:
2436: int length = contentBuffer.length();
2437:
2438:
2439: if (length == 0)
2440: return;
2441:
2442: Content c = getContent();
2443: UndoableEdit edit = c.insertString(offset,
2444: contentBuffer.toString());
2445:
2446:
2447: DefaultDocumentEvent ev = new DefaultDocumentEvent(offset,
2448: length,
2449: DocumentEvent.EventType.INSERT);
2450:
2451: ev.addEdit(edit);
2452:
2453:
2454:
2455: buffer.insert(offset, length, data, ev);
2456:
2457: super.insertUpdate(ev, null);
2458:
2459: ev.end();
2460: fireInsertUpdate(ev);
2461: fireUndoableEditUpdate(new UndoableEditEvent(this, ev));
2462: }
2463: finally
2464: {
2465: writeUnlock();
2466: }
2467: }
2468:
2469:
2477: protected void create(ElementSpec[] data)
2478: {
2479: try
2480: {
2481:
2482:
2483: int len = getLength();
2484: if (len > 0)
2485: remove(0, len);
2486:
2487: writeLock();
2488:
2489:
2490: StringBuilder b = new StringBuilder();
2491: for (int i = 0; i < data.length; ++i)
2492: {
2493: ElementSpec el = data[i];
2494: if (el.getArray() != null && el.getLength() > 0)
2495: b.append(el.getArray(), el.getOffset(), el.getLength());
2496: }
2497: Content content = getContent();
2498: UndoableEdit cEdit = content.insertString(0, b.toString());
2499:
2500: len = b.length();
2501: DefaultDocumentEvent ev =
2502: new DefaultDocumentEvent(0, b.length(),
2503: DocumentEvent.EventType.INSERT);
2504: ev.addEdit(cEdit);
2505:
2506: buffer.create(len, data, ev);
2507:
2508:
2509: super.insertUpdate(ev, null);
2510:
2511: ev.end();
2512: fireInsertUpdate(ev);
2513: fireUndoableEditUpdate(new UndoableEditEvent(this, ev));
2514: }
2515: catch (BadLocationException ex)
2516: {
2517: AssertionError err = new AssertionError("Unexpected bad location");
2518: err.initCause(ex);
2519: throw err;
2520: }
2521: finally
2522: {
2523: writeUnlock();
2524: }
2525: }
2526: }