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: import ;
59: import ;
60: import ;
61: import ;
62: import ;
63: import ;
64: import ;
65: import ;
66: import ;
67: import ;
68: import ;
69: import ;
70:
71:
84: public class HTMLDocument extends DefaultStyledDocument
85: {
86:
89: public static final String AdditionalComments = "AdditionalComments";
90: URL baseURL = null;
91: boolean preservesUnknownTags = true;
92: int tokenThreshold = Integer.MAX_VALUE;
93: HTMLEditorKit.Parser parser;
94:
95:
98: private boolean frameDocument;
99:
100:
103: String baseTarget;
104:
105:
109: public HTMLDocument()
110: {
111: this(new GapContent(BUFFER_SIZE_DEFAULT), new StyleSheet());
112: }
113:
114:
120: public HTMLDocument(StyleSheet styles)
121: {
122: this(new GapContent(BUFFER_SIZE_DEFAULT), styles);
123: }
124:
125:
132: public HTMLDocument(AbstractDocument.Content c, StyleSheet styles)
133: {
134: super(c, styles);
135: }
136:
137:
143: public StyleSheet getStyleSheet()
144: {
145: return (StyleSheet) getAttributeContext();
146: }
147:
148:
153: protected AbstractElement createDefaultRoot()
154: {
155: AbstractDocument.AttributeContext ctx = getAttributeContext();
156:
157:
158: AttributeSet atts = ctx.getEmptySet();
159: atts = ctx.addAttribute(atts, StyleConstants.NameAttribute, HTML.Tag.HTML);
160: BranchElement html = (BranchElement) createBranchElement(null, atts);
161:
162:
163: atts = ctx.getEmptySet();
164: atts = ctx.addAttribute(atts, StyleConstants.NameAttribute, HTML.Tag.BODY);
165: BranchElement body = (BranchElement) createBranchElement(html, atts);
166: html.replace(0, 0, new Element[] { body });
167:
168:
169: atts = ctx.getEmptySet();
170: atts = ctx.addAttribute(atts, StyleConstants.NameAttribute, HTML.Tag.P);
171: BranchElement p = (BranchElement) createBranchElement(body, atts);
172: body.replace(0, 0, new Element[] { p });
173:
174:
175: atts = ctx.getEmptySet();
176: atts = ctx.addAttribute(atts, StyleConstants.NameAttribute,
177: HTML.Tag.CONTENT);
178: Element leaf = createLeafElement(p, atts, 0, 1);
179: p.replace(0, 0, new Element[]{ leaf });
180:
181: return html;
182: }
183:
184:
196: protected Element createLeafElement(Element parent, AttributeSet a, int p0,
197: int p1)
198: {
199: return new RunElement(parent, a, p0, p1);
200: }
201:
202:
211: protected Element createBranchElement(Element parent, AttributeSet a)
212: {
213: return new BlockElement(parent, a);
214: }
215:
216:
221: public HTMLEditorKit.Parser getParser()
222: {
223: return parser;
224: }
225:
226:
231: public void setParser (HTMLEditorKit.Parser p)
232: {
233: parser = p;
234: }
235:
241: public void setTokenThreshold (int n)
242: {
243: tokenThreshold = n;
244: }
245:
246:
252: public int getTokenThreshold ()
253: {
254: return tokenThreshold;
255: }
256:
257:
263: public URL getBase()
264: {
265: return baseURL;
266: }
267:
268:
272: public void setBase(URL u)
273: {
274: baseURL = u;
275: getStyleSheet().setBase(u);
276: }
277:
278:
282: public boolean getPreservesUnknownTags()
283: {
284: return preservesUnknownTags;
285: }
286:
287:
291: public void setPreservesUnknownTags(boolean preservesTags)
292: {
293: preservesUnknownTags = preservesTags;
294: }
295:
296:
299: class LeafIterator extends Iterator
300: {
301: HTML.Tag tag;
302: HTMLDocument doc;
303: ElementIterator it;
304:
305: public LeafIterator (HTML.Tag t, HTMLDocument d)
306: {
307: doc = d;
308: tag = t;
309: it = new ElementIterator(doc);
310: }
311:
312:
316: public AttributeSet getAttributes()
317: {
318: if (it.current() != null)
319: return it.current().getAttributes();
320: return null;
321: }
322:
323:
328: public int getEndOffset()
329: {
330: if (it.current() != null)
331: return it.current().getEndOffset();
332: return -1;
333: }
334:
335:
340:
341: public int getStartOffset()
342: {
343: if (it.current() != null)
344: return it.current().getStartOffset();
345: return -1;
346: }
347:
348:
351: public void next()
352: {
353: it.next();
354: while (it.current()!= null && !it.current().isLeaf())
355: it.next();
356: }
357:
358:
364: public boolean isValid()
365: {
366: return it.current() != null;
367: }
368:
369:
372: public Tag getTag()
373: {
374: return tag;
375: }
376:
377: }
378:
379: public void processHTMLFrameHyperlinkEvent(HTMLFrameHyperlinkEvent event)
380: {
381: String target = event.getTarget();
382: Element el = event.getSourceElement();
383: URL url = event.getURL();
384: if (target.equals("_self"))
385: {
386: updateFrame(el, url);
387: }
388: else if (target.equals("_parent"))
389: {
390: updateFrameSet(el.getParentElement(), url);
391: }
392: else
393: {
394: Element targetFrame = findFrame(target);
395: if (targetFrame != null)
396: updateFrame(targetFrame, url);
397: }
398: }
399:
400:
408: private Element findFrame(String target)
409: {
410: ElementIterator i = new ElementIterator(this);
411: Element next = null;
412: while ((next = i.next()) != null)
413: {
414: AttributeSet atts = next.getAttributes();
415: if (atts.getAttribute(StyleConstants.NameAttribute) == HTML.Tag.FRAME)
416: {
417: String name = (String) atts.getAttribute(HTML.Attribute.NAME);
418: if (name != null && name.equals(target))
419: break;
420: }
421: }
422: return next;
423: }
424:
425:
432: private void updateFrame(Element el, URL url)
433: {
434: try
435: {
436: writeLock();
437: DefaultDocumentEvent ev =
438: new DefaultDocumentEvent(el.getStartOffset(), 1,
439: DocumentEvent.EventType.CHANGE);
440: AttributeSet elAtts = el.getAttributes();
441: AttributeSet copy = elAtts.copyAttributes();
442: MutableAttributeSet matts = (MutableAttributeSet) elAtts;
443: ev.addEdit(new AttributeUndoableEdit(el, copy, false));
444: matts.removeAttribute(HTML.Attribute.SRC);
445: matts.addAttribute(HTML.Attribute.SRC, url.toString());
446: ev.end();
447: fireChangedUpdate(ev);
448: fireUndoableEditUpdate(new UndoableEditEvent(this, ev));
449: }
450: finally
451: {
452: writeUnlock();
453: }
454: }
455:
456:
463: private void updateFrameSet(Element el, URL url)
464: {
465: int start = el.getStartOffset();
466: int end = el.getEndOffset();
467:
468: StringBuilder html = new StringBuilder();
469: html.append("<frame");
470: if (url != null)
471: {
472: html.append(" src=\"");
473: html.append(url.toString());
474: html.append("\"");
475: }
476: html.append('>');
477: if (getParser() == null)
478: setParser(new HTMLEditorKit().getParser());
479: try
480: {
481: setOuterHTML(el, html.toString());
482: }
483: catch (BadLocationException ex)
484: {
485: ex.printStackTrace();
486: }
487: catch (IOException ex)
488: {
489: ex.printStackTrace();
490: }
491: }
492:
493:
498: public HTMLDocument.Iterator getIterator (HTML.Tag t)
499: {
500: return new HTMLDocument.LeafIterator(t, this);
501: }
502:
503:
506: public abstract static class Iterator
507: {
508:
512: public abstract AttributeSet getAttributes();
513:
514:
519: public abstract int getEndOffset();
520:
521:
526: public abstract int getStartOffset();
527:
528:
531: public abstract void next();
532:
533:
539: public abstract boolean isValid();
540:
541:
545: public abstract HTML.Tag getTag();
546: }
547:
548: public class BlockElement extends AbstractDocument.BranchElement
549: {
550: public BlockElement (Element parent, AttributeSet a)
551: {
552: super(parent, a);
553: }
554:
555:
559: public AttributeSet getResolveParent()
560: {
561: return null;
562: }
563:
564:
569: public String getName()
570: {
571: Object tag = getAttribute(StyleConstants.NameAttribute);
572: String name = null;
573: if (tag != null)
574: name = tag.toString();
575: if (name == null)
576: name = super.getName();
577: return name;
578: }
579: }
580:
581:
585: public class RunElement extends AbstractDocument.LeafElement
586: {
587:
588:
597: public RunElement(Element parent, AttributeSet a, int start, int end)
598: {
599: super(parent, a, start, end);
600: }
601:
602:
607: public String getName()
608: {
609: Object tag = getAttribute(StyleConstants.NameAttribute);
610: String name = null;
611: if (tag != null)
612: name = tag.toString();
613: if (name == null)
614: name = super.getName();
615: return name;
616: }
617:
618:
624: public AttributeSet getResolveParent()
625: {
626: return null;
627: }
628: }
629:
630:
635: public class HTMLReader extends HTMLEditorKit.ParserCallback
636: {
637:
640: private static final int MAX_THRESHOLD = 10000;
641:
642:
645: private static final int GROW_THRESHOLD = 5;
646:
647:
650: protected MutableAttributeSet charAttr = new SimpleAttributeSet();
651:
652: protected Vector<ElementSpec> parseBuffer = new Vector<ElementSpec>();
653:
654:
657: private Stack<HTML.Tag> parseStack = new Stack<HTML.Tag>();
658:
659:
662: Stack charAttrStack = new Stack();
663:
664:
665: HashMap tagToAction;
666:
667:
668: boolean endHTMLEncountered = false;
669:
670:
673: int popDepth;
674:
675:
678: int pushDepth;
679:
680:
683: int offset;
684:
685:
688: HTML.Tag insertTag;
689:
690:
693: boolean insertTagEncountered;
694:
695:
696:
697: boolean debug = false;
698:
699:
702: boolean inPreTag = false;
703:
704:
710: boolean inStyleTag = false;
711:
712:
718: boolean inTextArea = false;
719:
720:
725: ArrayList styles;
726:
727:
732: ResetablePlainDocument textAreaDocument;
733:
734:
738: Object selectModel;
739:
740:
743: Option option;
744:
745:
748: int numOptions;
749:
750:
753: HashMap buttonGroups;
754:
755:
758: private int threshold;
759:
760: public class TagAction
761: {
762:
766: public void start(HTML.Tag t, MutableAttributeSet a)
767: {
768:
769: }
770:
771:
775: public void end(HTML.Tag t)
776: {
777:
778: }
779: }
780:
781: public class BlockAction extends TagAction
782: {
783:
787: public void start(HTML.Tag t, MutableAttributeSet a)
788: {
789:
790: blockOpen(t, a);
791: }
792:
793:
797: public void end(HTML.Tag t)
798: {
799:
800: blockClose(t);
801: }
802: }
803:
804: public class CharacterAction extends TagAction
805: {
806:
810: public void start(HTML.Tag t, MutableAttributeSet a)
811: {
812:
813: pushCharacterStyle();
814:
815:
816: if (t == HTML.Tag.A)
817: a.addAttribute(HTML.Attribute.PSEUDO_CLASS, "link");
818:
819:
820: charAttr.addAttribute(t, a.copyAttributes());
821: }
822:
823:
827: public void end(HTML.Tag t)
828: {
829: popCharacterStyle();
830: }
831: }
832:
833:
837: public class FormAction extends SpecialAction
838: {
839:
843: public void start(HTML.Tag t, MutableAttributeSet a)
844: {
845: if (t == HTML.Tag.INPUT)
846: {
847: String type = (String) a.getAttribute(HTML.Attribute.TYPE);
848: if (type == null)
849: {
850: type = "text";
851: a.addAttribute(HTML.Attribute.TYPE, type);
852: }
853: setModel(type, a);
854: }
855: else if (t == HTML.Tag.TEXTAREA)
856: {
857: inTextArea = true;
858: textAreaDocument = new ResetablePlainDocument();
859: a.addAttribute(StyleConstants.ModelAttribute, textAreaDocument);
860: }
861: else if (t == HTML.Tag.SELECT)
862: {
863: int size = HTML.getIntegerAttributeValue(a, HTML.Attribute.SIZE,
864: 1);
865: boolean multi = a.getAttribute(HTML.Attribute.MULTIPLE) != null;
866: if (size > 1 || multi)
867: {
868: SelectListModel m = new SelectListModel();
869: if (multi)
870: m.getSelectionModel().setSelectionMode(ListSelectionModel
871: .MULTIPLE_INTERVAL_SELECTION);
872: selectModel = m;
873: }
874: else
875: {
876: selectModel = new SelectComboBoxModel();
877: }
878: a.addAttribute(StyleConstants.ModelAttribute, selectModel);
879: }
880: if (t == HTML.Tag.OPTION)
881: {
882: option = new Option(a);
883: if (selectModel instanceof SelectListModel)
884: {
885: SelectListModel m = (SelectListModel) selectModel;
886: m.addElement(option);
887: if (option.isSelected())
888: {
889: m.getSelectionModel().addSelectionInterval(numOptions,
890: numOptions);
891: m.addInitialSelection(numOptions);
892: }
893: }
894: else if (selectModel instanceof SelectComboBoxModel)
895: {
896: SelectComboBoxModel m = (SelectComboBoxModel) selectModel;
897: m.addElement(option);
898: if (option.isSelected())
899: {
900: m.setSelectedItem(option);
901: m.setInitialSelection(option);
902: }
903: }
904: numOptions++;
905: }
906: else
907: {
908:
909: super.start(t, a);
910: }
911: }
912:
913:
917: public void end(HTML.Tag t)
918: {
919: if (t == HTML.Tag.OPTION)
920: {
921: option = null;
922: }
923: else
924: {
925: if (t == HTML.Tag.TEXTAREA)
926: {
927: inTextArea = false;
928: }
929: else if (t == HTML.Tag.SELECT)
930: {
931: selectModel = null;
932: numOptions = 0;
933: }
934:
935: super.end(t);
936: }
937: }
938:
939: private void setModel(String type, MutableAttributeSet attrs)
940: {
941: if (type.equals("submit") || type.equals("reset")
942: || type.equals("image"))
943: {
944:
945: attrs.addAttribute(StyleConstants.ModelAttribute,
946: new DefaultButtonModel());
947: }
948: else if (type.equals("text") || type.equals("password"))
949: {
950: String text = (String) attrs.getAttribute(HTML.Attribute.VALUE);
951: ResetablePlainDocument doc = new ResetablePlainDocument();
952: if (text != null)
953: {
954: doc.setInitialText(text);
955: try
956: {
957: doc.insertString(0, text, null);
958: }
959: catch (BadLocationException ex)
960: {
961:
962: assert false;
963: }
964: }
965: attrs.addAttribute(StyleConstants.ModelAttribute, doc);
966: }
967: else if (type.equals("file"))
968: {
969: attrs.addAttribute(StyleConstants.ModelAttribute,
970: new PlainDocument());
971: }
972: else if (type.equals("checkbox") || type.equals("radio"))
973: {
974: ResetableToggleButtonModel model =
975: new ResetableToggleButtonModel();
976: if (attrs.getAttribute(HTML.Attribute.SELECTED) != null)
977: {
978: model.setSelected(true);
979: model.setInitial(true);
980: }
981: if (type.equals("radio"))
982: {
983: String name = (String) attrs.getAttribute(HTML.Attribute.NAME);
984: if (name != null)
985: {
986: if (buttonGroups == null)
987: buttonGroups = new HashMap();
988: ButtonGroup group = (ButtonGroup) buttonGroups.get(name);
989: if (group == null)
990: {
991: group = new ButtonGroup();
992: buttonGroups.put(name, group);
993: }
994: model.setGroup(group);
995: }
996: }
997: attrs.addAttribute(StyleConstants.ModelAttribute, model);
998: }
999: }
1000: }
1001:
1002:
1005: class FormTagAction
1006: extends BlockAction
1007: {
1008:
1011: public void end(HTML.Tag t)
1012: {
1013: super.end(t);
1014: buttonGroups = null;
1015: }
1016: }
1017:
1018:
1027: public class HiddenAction
1028: extends TagAction
1029: {
1030:
1034: public void start(HTML.Tag t, MutableAttributeSet a)
1035: {
1036: blockOpen(t, a);
1037: }
1038:
1039:
1043: public void end(HTML.Tag t)
1044: {
1045: blockClose(t);
1046: }
1047: }
1048:
1049:
1052: public class IsindexAction extends TagAction
1053: {
1054:
1058: public void start(HTML.Tag t, MutableAttributeSet a)
1059: {
1060: blockOpen(HTML.Tag.IMPLIED, new SimpleAttributeSet());
1061: addSpecialElement(t, a);
1062: blockClose(HTML.Tag.IMPLIED);
1063: }
1064: }
1065:
1066: public class ParagraphAction extends BlockAction
1067: {
1068:
1072: public void start(HTML.Tag t, MutableAttributeSet a)
1073: {
1074: super.start(t, a);
1075: }
1076:
1077:
1081: public void end(HTML.Tag t)
1082: {
1083: super.end(t);
1084: }
1085: }
1086:
1087:
1090: public class PreAction extends BlockAction
1091: {
1092:
1096: public void start(HTML.Tag t, MutableAttributeSet a)
1097: {
1098: inPreTag = true;
1099: blockOpen(t, a);
1100: a.addAttribute(CSS.Attribute.WHITE_SPACE, "pre");
1101: blockOpen(HTML.Tag.IMPLIED, a);
1102: }
1103:
1104:
1108: public void end(HTML.Tag t)
1109: {
1110: blockClose(HTML.Tag.IMPLIED);
1111: inPreTag = false;
1112: blockClose(t);
1113: }
1114: }
1115:
1116:
1123: public class SpecialAction extends TagAction
1124: {
1125:
1128: public void start(HTML.Tag t, MutableAttributeSet a)
1129: {
1130: addSpecialElement(t, a);
1131: }
1132: }
1133:
1134: class AreaAction extends TagAction
1135: {
1136:
1140: public void start(HTML.Tag t, MutableAttributeSet a)
1141: throws NotImplementedException
1142: {
1143:
1144: }
1145:
1146:
1150: public void end(HTML.Tag t)
1151: throws NotImplementedException
1152: {
1153:
1154: }
1155: }
1156:
1157:
1160: class ConvertAction
1161: extends TagAction
1162: {
1163:
1164: public void start(HTML.Tag tag, MutableAttributeSet atts)
1165: {
1166: pushCharacterStyle();
1167: charAttr.addAttribute(tag, atts.copyAttributes());
1168: StyleSheet styleSheet = getStyleSheet();
1169:
1170: if (tag == HTML.Tag.FONT)
1171: {
1172: String color = (String) atts.getAttribute(HTML.Attribute.COLOR);
1173: if (color != null)
1174: styleSheet.addCSSAttribute(charAttr, CSS.Attribute.COLOR, color);
1175: String face = (String) atts.getAttribute(HTML.Attribute.FACE);
1176: if (face != null)
1177: styleSheet.addCSSAttribute(charAttr, CSS.Attribute.FONT_FAMILY,
1178: face);
1179: String size = (String) atts.getAttribute(HTML.Attribute.SIZE);
1180: if (size != null)
1181: styleSheet.addCSSAttribute(charAttr, CSS.Attribute.FONT_SIZE,
1182: size);
1183: }
1184: }
1185:
1186: public void end(HTML.Tag tag)
1187: {
1188: popCharacterStyle();
1189: }
1190: }
1191:
1192: class BaseAction extends TagAction
1193: {
1194:
1198: public void start(HTML.Tag t, MutableAttributeSet a)
1199: {
1200: baseTarget = (String) a.getAttribute(HTML.Attribute.TARGET);
1201: }
1202: }
1203:
1204: class HeadAction extends BlockAction
1205: {
1206:
1210: public void start(HTML.Tag t, MutableAttributeSet a)
1211: throws NotImplementedException
1212: {
1213:
1214: super.start(t, a);
1215: }
1216:
1217:
1221: public void end(HTML.Tag t)
1222: {
1223:
1224:
1225: if (styles != null)
1226: {
1227: int numStyles = styles.size();
1228: for (int i = 0; i < numStyles; i++)
1229: {
1230: String style = (String) styles.get(i);
1231: getStyleSheet().addRule(style);
1232: }
1233: }
1234: super.end(t);
1235: }
1236: }
1237:
1238: class LinkAction extends HiddenAction
1239: {
1240:
1244: public void start(HTML.Tag t, MutableAttributeSet a)
1245: {
1246: super.start(t, a);
1247: String type = (String) a.getAttribute(HTML.Attribute.TYPE);
1248: if (type == null)
1249: type = "text/css";
1250: if (type.equals("text/css"))
1251: {
1252: String rel = (String) a.getAttribute(HTML.Attribute.REL);
1253: String media = (String) a.getAttribute(HTML.Attribute.MEDIA);
1254: String title = (String) a.getAttribute(HTML.Attribute.TITLE);
1255: if (media == null)
1256: media = "all";
1257: else
1258: media = media.toLowerCase();
1259: if (rel != null)
1260: {
1261: rel = rel.toLowerCase();
1262: if ((media.indexOf("all") != -1
1263: || media.indexOf("screen") != -1)
1264: && (rel.equals("stylesheet")))
1265: {
1266: String href = (String) a.getAttribute(HTML.Attribute.HREF);
1267: URL url = null;
1268: try
1269: {
1270: url = new URL(baseURL, href);
1271: }
1272: catch (MalformedURLException ex)
1273: {
1274: try
1275: {
1276: url = new URL(href);
1277: }
1278: catch (MalformedURLException ex2)
1279: {
1280: url = null;
1281: }
1282: }
1283: if (url != null)
1284: {
1285: try
1286: {
1287: getStyleSheet().importStyleSheet(url);
1288: }
1289: catch (Exception ex)
1290: {
1291:
1292:
1293:
1294:
1295: ex.printStackTrace();
1296: }
1297: }
1298: }
1299: }
1300: }
1301: }
1302:
1303: }
1304:
1305: class MapAction extends TagAction
1306: {
1307:
1311: public void start(HTML.Tag t, MutableAttributeSet a)
1312: throws NotImplementedException
1313: {
1314:
1315: }
1316:
1317:
1321: public void end(HTML.Tag t)
1322: throws NotImplementedException
1323: {
1324:
1325: }
1326: }
1327:
1328: class MetaAction extends TagAction
1329: {
1330:
1334: public void start(HTML.Tag t, MutableAttributeSet a)
1335: throws NotImplementedException
1336: {
1337:
1338: }
1339:
1340:
1344: public void end(HTML.Tag t)
1345: throws NotImplementedException
1346: {
1347:
1348: }
1349: }
1350:
1351: class StyleAction extends TagAction
1352: {
1353:
1357: public void start(HTML.Tag t, MutableAttributeSet a)
1358: {
1359: inStyleTag = true;
1360: }
1361:
1362:
1366: public void end(HTML.Tag t)
1367: {
1368: inStyleTag = false;
1369: }
1370: }
1371:
1372: class TitleAction extends TagAction
1373: {
1374:
1378: public void start(HTML.Tag t, MutableAttributeSet a)
1379: throws NotImplementedException
1380: {
1381:
1382: }
1383:
1384:
1388: public void end(HTML.Tag t)
1389: throws NotImplementedException
1390: {
1391:
1392: }
1393: }
1394:
1395: public HTMLReader(int offset)
1396: {
1397: this (offset, 0, 0, null);
1398: }
1399:
1400: public HTMLReader(int offset, int popDepth, int pushDepth,
1401: HTML.Tag insertTag)
1402: {
1403: this.insertTag = insertTag;
1404: this.offset = offset;
1405: this.popDepth = popDepth;
1406: this.pushDepth = pushDepth;
1407: threshold = getTokenThreshold();
1408: initTags();
1409: }
1410:
1411: void initTags()
1412: {
1413: tagToAction = new HashMap(72);
1414: CharacterAction characterAction = new CharacterAction();
1415: HiddenAction hiddenAction = new HiddenAction();
1416: AreaAction areaAction = new AreaAction();
1417: BaseAction baseAction = new BaseAction();
1418: BlockAction blockAction = new BlockAction();
1419: SpecialAction specialAction = new SpecialAction();
1420: ParagraphAction paragraphAction = new ParagraphAction();
1421: HeadAction headAction = new HeadAction();
1422: FormAction formAction = new FormAction();
1423: IsindexAction isindexAction = new IsindexAction();
1424: LinkAction linkAction = new LinkAction();
1425: MapAction mapAction = new MapAction();
1426: PreAction preAction = new PreAction();
1427: MetaAction metaAction = new MetaAction();
1428: StyleAction styleAction = new StyleAction();
1429: TitleAction titleAction = new TitleAction();
1430:
1431: ConvertAction convertAction = new ConvertAction();
1432: tagToAction.put(HTML.Tag.A, characterAction);
1433: tagToAction.put(HTML.Tag.ADDRESS, characterAction);
1434: tagToAction.put(HTML.Tag.APPLET, hiddenAction);
1435: tagToAction.put(HTML.Tag.AREA, areaAction);
1436: tagToAction.put(HTML.Tag.B, characterAction);
1437: tagToAction.put(HTML.Tag.BASE, baseAction);
1438: tagToAction.put(HTML.Tag.BASEFONT, characterAction);
1439: tagToAction.put(HTML.Tag.BIG, characterAction);
1440: tagToAction.put(HTML.Tag.BLOCKQUOTE, blockAction);
1441: tagToAction.put(HTML.Tag.BODY, blockAction);
1442: tagToAction.put(HTML.Tag.BR, specialAction);
1443: tagToAction.put(HTML.Tag.CAPTION, blockAction);
1444: tagToAction.put(HTML.Tag.CENTER, blockAction);
1445: tagToAction.put(HTML.Tag.CITE, characterAction);
1446: tagToAction.put(HTML.Tag.CODE, characterAction);
1447: tagToAction.put(HTML.Tag.DD, blockAction);
1448: tagToAction.put(HTML.Tag.DFN, characterAction);
1449: tagToAction.put(HTML.Tag.DIR, blockAction);
1450: tagToAction.put(HTML.Tag.DIV, blockAction);
1451: tagToAction.put(HTML.Tag.DL, blockAction);
1452: tagToAction.put(HTML.Tag.DT, paragraphAction);
1453: tagToAction.put(HTML.Tag.EM, characterAction);
1454: tagToAction.put(HTML.Tag.FONT, convertAction);
1455: tagToAction.put(HTML.Tag.FORM, new FormTagAction());
1456: tagToAction.put(HTML.Tag.FRAME, specialAction);
1457: tagToAction.put(HTML.Tag.FRAMESET, blockAction);
1458: tagToAction.put(HTML.Tag.H1, paragraphAction);
1459: tagToAction.put(HTML.Tag.H2, paragraphAction);
1460: tagToAction.put(HTML.Tag.H3, paragraphAction);
1461: tagToAction.put(HTML.Tag.H4, paragraphAction);
1462: tagToAction.put(HTML.Tag.H5, paragraphAction);
1463: tagToAction.put(HTML.Tag.H6, paragraphAction);
1464: tagToAction.put(HTML.Tag.HEAD, headAction);
1465: tagToAction.put(HTML.Tag.HR, specialAction);
1466: tagToAction.put(HTML.Tag.HTML, blockAction);
1467: tagToAction.put(HTML.Tag.I, characterAction);
1468: tagToAction.put(HTML.Tag.IMG, specialAction);
1469: tagToAction.put(HTML.Tag.INPUT, formAction);
1470: tagToAction.put(HTML.Tag.ISINDEX, isindexAction);
1471: tagToAction.put(HTML.Tag.KBD, characterAction);
1472: tagToAction.put(HTML.Tag.LI, blockAction);
1473: tagToAction.put(HTML.Tag.LINK, linkAction);
1474: tagToAction.put(HTML.Tag.MAP, mapAction);
1475: tagToAction.put(HTML.Tag.MENU, blockAction);
1476: tagToAction.put(HTML.Tag.META, metaAction);
1477: tagToAction.put(HTML.Tag.NOFRAMES, blockAction);
1478: tagToAction.put(HTML.Tag.OBJECT, specialAction);
1479: tagToAction.put(HTML.Tag.OL, blockAction);
1480: tagToAction.put(HTML.Tag.OPTION, formAction);
1481: tagToAction.put(HTML.Tag.P, paragraphAction);
1482: tagToAction.put(HTML.Tag.PARAM, hiddenAction);
1483: tagToAction.put(HTML.Tag.PRE, preAction);
1484: tagToAction.put(HTML.Tag.SAMP, characterAction);
1485: tagToAction.put(HTML.Tag.SCRIPT, hiddenAction);
1486: tagToAction.put(HTML.Tag.SELECT, formAction);
1487: tagToAction.put(HTML.Tag.SMALL, characterAction);
1488: tagToAction.put(HTML.Tag.STRIKE, characterAction);
1489: tagToAction.put(HTML.Tag.S, characterAction);
1490: tagToAction.put(HTML.Tag.STRONG, characterAction);
1491: tagToAction.put(HTML.Tag.STYLE, styleAction);
1492: tagToAction.put(HTML.Tag.SUB, characterAction);
1493: tagToAction.put(HTML.Tag.SUP, characterAction);
1494: tagToAction.put(HTML.Tag.TABLE, blockAction);
1495: tagToAction.put(HTML.Tag.TD, blockAction);
1496: tagToAction.put(HTML.Tag.TEXTAREA, formAction);
1497: tagToAction.put(HTML.Tag.TH, blockAction);
1498: tagToAction.put(HTML.Tag.TITLE, titleAction);
1499: tagToAction.put(HTML.Tag.TR, blockAction);
1500: tagToAction.put(HTML.Tag.TT, characterAction);
1501: tagToAction.put(HTML.Tag.U, characterAction);
1502: tagToAction.put(HTML.Tag.UL, blockAction);
1503: tagToAction.put(HTML.Tag.VAR, characterAction);
1504: }
1505:
1506:
1510: protected void pushCharacterStyle()
1511: {
1512: charAttrStack.push(charAttr.copyAttributes());
1513: }
1514:
1515:
1520: protected void popCharacterStyle()
1521: {
1522: if (!charAttrStack.isEmpty())
1523: charAttr = (MutableAttributeSet) charAttrStack.pop();
1524: }
1525:
1526:
1534: protected void registerTag(HTML.Tag t, HTMLDocument.HTMLReader.TagAction a)
1535: {
1536: tagToAction.put (t, a);
1537: }
1538:
1539:
1543: public void flush() throws BadLocationException
1544: {
1545: flushImpl();
1546: }
1547:
1548:
1552: private void flushImpl()
1553: throws BadLocationException
1554: {
1555: int oldLen = getLength();
1556: int size = parseBuffer.size();
1557: ElementSpec[] elems = new ElementSpec[size];
1558: parseBuffer.copyInto(elems);
1559: if (oldLen == 0)
1560: create(elems);
1561: else
1562: insert(offset, elems);
1563: parseBuffer.removeAllElements();
1564: offset += getLength() - oldLen;
1565: }
1566:
1567:
1574: public void handleText(char[] data, int pos)
1575: {
1576: if (shouldInsert() && data != null && data.length > 0)
1577: {
1578: if (inTextArea)
1579: textAreaContent(data);
1580: else if (inPreTag)
1581: preContent(data);
1582: else if (option != null)
1583: option.setLabel(new String(data));
1584: else if (inStyleTag)
1585: {
1586: if (styles == null)
1587: styles = new ArrayList();
1588: styles.add(new String(data));
1589: }
1590: else
1591: addContent(data, 0, data.length);
1592:
1593: }
1594: }
1595:
1596:
1603: private boolean shouldInsert()
1604: {
1605: return ! endHTMLEncountered
1606: && (insertTagEncountered || insertTag == null);
1607: }
1608:
1609:
1617: public void handleStartTag(HTML.Tag t, MutableAttributeSet a, int pos)
1618: {
1619: if (t == insertTag)
1620: insertTagEncountered = true;
1621:
1622: if (shouldInsert())
1623: {
1624: TagAction action = (TagAction) tagToAction.get(t);
1625: if (action != null)
1626: action.start(t, a);
1627: }
1628: }
1629:
1630:
1636: public void handleComment(char[] data, int pos)
1637: {
1638: if (shouldInsert())
1639: {
1640: TagAction action = (TagAction) tagToAction.get(HTML.Tag.COMMENT);
1641: if (action != null)
1642: {
1643: action.start(HTML.Tag.COMMENT, new SimpleAttributeSet());
1644: action.end(HTML.Tag.COMMENT);
1645: }
1646: }
1647: }
1648:
1649:
1656: public void handleEndTag(HTML.Tag t, int pos)
1657: {
1658: if (shouldInsert())
1659: {
1660:
1661: if (t == HTML.Tag.HTML)
1662: endHTMLEncountered = true;
1663:
1664: TagAction action = (TagAction) tagToAction.get(t);
1665: if (action != null)
1666: action.end(t);
1667: }
1668: }
1669:
1670:
1678: public void handleSimpleTag(HTML.Tag t, MutableAttributeSet a, int pos)
1679: {
1680: if (t == insertTag)
1681: insertTagEncountered = true;
1682:
1683: if (shouldInsert())
1684: {
1685: TagAction action = (TagAction) tagToAction.get(t);
1686: if (action != null)
1687: {
1688: action.start(t, a);
1689: action.end(t);
1690: }
1691: }
1692: }
1693:
1694:
1702: public void handleEndOfLineString(String eol)
1703: {
1704:
1705: }
1706:
1707:
1713: protected void textAreaContent(char[] data)
1714: {
1715: try
1716: {
1717: int offset = textAreaDocument.getLength();
1718: String text = new String(data);
1719: textAreaDocument.setInitialText(text);
1720: textAreaDocument.insertString(offset, text, null);
1721: }
1722: catch (BadLocationException ex)
1723: {
1724:
1725:
1726: assert false;
1727: }
1728: }
1729:
1730:
1736: protected void preContent(char[] data)
1737: {
1738: int start = 0;
1739: for (int i = 0; i < data.length; i++)
1740: {
1741: if (data[i] == '\n')
1742: {
1743: addContent(data, start, i - start + 1);
1744: blockClose(HTML.Tag.IMPLIED);
1745: MutableAttributeSet atts = new SimpleAttributeSet();
1746: atts.addAttribute(CSS.Attribute.WHITE_SPACE, "pre");
1747: blockOpen(HTML.Tag.IMPLIED, atts);
1748: start = i + 1;
1749: }
1750: }
1751: if (start < data.length)
1752: {
1753:
1754: addContent(data, start, data.length - start);
1755: }
1756: }
1757:
1758:
1765: protected void blockOpen(HTML.Tag t, MutableAttributeSet attr)
1766: {
1767: if (inImpliedParagraph())
1768: blockClose(HTML.Tag.IMPLIED);
1769:
1770:
1771: parseStack.push(t);
1772:
1773: DefaultStyledDocument.ElementSpec element;
1774:
1775: AbstractDocument.AttributeContext ctx = getAttributeContext();
1776: AttributeSet copy = attr.copyAttributes();
1777: copy = ctx.addAttribute(copy, StyleConstants.NameAttribute, t);
1778: element = new DefaultStyledDocument.ElementSpec(copy,
1779: DefaultStyledDocument.ElementSpec.StartTagType);
1780: parseBuffer.addElement(element);
1781: }
1782:
1783:
1789: private boolean inParagraph()
1790: {
1791: boolean inParagraph = false;
1792: if (! parseStack.isEmpty())
1793: {
1794: HTML.Tag top = parseStack.peek();
1795: inParagraph = top == HTML.Tag.P || top == HTML.Tag.IMPLIED;
1796: }
1797: return inParagraph;
1798: }
1799:
1800: private boolean inImpliedParagraph()
1801: {
1802: boolean inParagraph = false;
1803: if (! parseStack.isEmpty())
1804: {
1805: HTML.Tag top = parseStack.peek();
1806: inParagraph = top == HTML.Tag.IMPLIED;
1807: }
1808: return inParagraph;
1809: }
1810:
1811:
1817: protected void blockClose(HTML.Tag t)
1818: {
1819: DefaultStyledDocument.ElementSpec element;
1820:
1821: if (inImpliedParagraph() && t != HTML.Tag.IMPLIED)
1822: blockClose(HTML.Tag.IMPLIED);
1823:
1824:
1825: if (! parseStack.isEmpty())
1826: parseStack.pop();
1827:
1828:
1829:
1830: DefaultStyledDocument.ElementSpec prev;
1831: prev = parseBuffer.size() > 0 ? (DefaultStyledDocument.ElementSpec)
1832: parseBuffer.get(parseBuffer.size() - 1) : null;
1833: if (prev != null &&
1834: prev.getType() == DefaultStyledDocument.ElementSpec.StartTagType)
1835: {
1836: addContent(new char[]{' '}, 0, 1);
1837: }
1838:
1839: element = new DefaultStyledDocument.ElementSpec(null,
1840: DefaultStyledDocument.ElementSpec.EndTagType);
1841: parseBuffer.addElement(element);
1842: }
1843:
1844:
1852: protected void addContent(char[] data, int offs, int length)
1853: {
1854: addContent(data, offs, length, true);
1855: }
1856:
1857:
1867: protected void addContent(char[] data, int offs, int length,
1868: boolean generateImpliedPIfNecessary)
1869: {
1870: if (generateImpliedPIfNecessary && ! inParagraph())
1871: {
1872: blockOpen(HTML.Tag.IMPLIED, new SimpleAttributeSet());
1873: }
1874:
1875: AbstractDocument.AttributeContext ctx = getAttributeContext();
1876: DefaultStyledDocument.ElementSpec element;
1877: AttributeSet attributes = null;
1878:
1879:
1880:
1881: if (charAttr != null)
1882: attributes = charAttr.copyAttributes();
1883: else
1884: attributes = ctx.getEmptySet();
1885: attributes = ctx.addAttribute(attributes, StyleConstants.NameAttribute,
1886: HTML.Tag.CONTENT);
1887: element = new DefaultStyledDocument.ElementSpec(attributes,
1888: DefaultStyledDocument.ElementSpec.ContentType,
1889: data, offs, length);
1890:
1891:
1892: parseBuffer.addElement(element);
1893:
1894: if (parseBuffer.size() > threshold)
1895: {
1896: if (threshold <= MAX_THRESHOLD)
1897: threshold *= GROW_THRESHOLD;
1898: try
1899: {
1900: flushImpl();
1901: }
1902: catch (BadLocationException ble)
1903: {
1904:
1905: }
1906: }
1907: }
1908:
1909:
1915: protected void addSpecialElement(HTML.Tag t, MutableAttributeSet a)
1916: {
1917: if (t != HTML.Tag.FRAME && ! inParagraph())
1918: {
1919: blockOpen(HTML.Tag.IMPLIED, new SimpleAttributeSet());
1920: }
1921:
1922: a.addAttribute(StyleConstants.NameAttribute, t);
1923:
1924:
1925:
1926:
1927: DefaultStyledDocument.ElementSpec spec =
1928: new DefaultStyledDocument.ElementSpec(a.copyAttributes(),
1929: DefaultStyledDocument.ElementSpec.ContentType,
1930: new char[] {' '}, 0, 1 );
1931: parseBuffer.add(spec);
1932: }
1933:
1934: }
1935:
1936:
1942: public HTMLEditorKit.ParserCallback getReader(int pos)
1943: {
1944: return new HTMLReader(pos);
1945: }
1946:
1947:
1958: public HTMLEditorKit.ParserCallback getReader(int pos,
1959: int popDepth,
1960: int pushDepth,
1961: HTML.Tag insertTag)
1962: {
1963: return new HTMLReader(pos, popDepth, pushDepth, insertTag);
1964: }
1965:
1966:
1983: public HTMLEditorKit.ParserCallback getInsertingReader(int pos, int popDepth,
1984: int pushDepth,
1985: HTML.Tag insertTag,
1986: final Element parent)
1987: throws IllegalStateException
1988: {
1989: if (parser == null)
1990: throw new IllegalStateException("Parser has not been set");
1991:
1992: HTMLReader reader = new HTMLReader(pos, popDepth, pushDepth, insertTag)
1993: {
1994:
1997: public void handleStartTag(HTML.Tag t, MutableAttributeSet a, int pos)
1998: {
1999: if (t != HTML.Tag.BODY)
2000: super.handleStartTag(t, a, pos);
2001: }
2002:
2003:
2006: public void handleEndTag(HTML.Tag t, int pos)
2007: {
2008: if (t != HTML.Tag.BODY)
2009: super.handleEndTag(t, pos);
2010: }
2011: };
2012:
2013: return reader;
2014: }
2015:
2016:
2026: public Element getElement(Element e, Object attribute, Object value)
2027: {
2028: if (e != null)
2029: {
2030: if (e.getAttributes().containsAttribute(attribute, value))
2031: return e;
2032:
2033: int count = e.getElementCount();
2034: for (int j = 0; j < count; j++)
2035: {
2036: Element child = e.getElement(j);
2037: if (child.getAttributes().containsAttribute(attribute, value))
2038: return child;
2039:
2040: Element grandChild = getElement(child, attribute, value);
2041: if (grandChild != null)
2042: return grandChild;
2043: }
2044: }
2045: return null;
2046: }
2047:
2048:
2057: public Element getElement(String attrId)
2058: {
2059: return getElement(getDefaultRootElement(), HTML.Attribute.ID,
2060: attrId);
2061: }
2062:
2063:
2075: public void setInnerHTML(Element elem, String htmlText)
2076: throws BadLocationException, IOException
2077: {
2078: if (elem.isLeaf())
2079: throw new IllegalArgumentException("Element is a leaf");
2080:
2081: int start = elem.getStartOffset();
2082: int end = elem.getEndOffset();
2083:
2084: HTMLEditorKit.ParserCallback reader = getInsertingReader(
2085: end, 0, 0, HTML.Tag.BODY, elem);
2086:
2087:
2088: getParser().parse(new StringReader(htmlText), reader, true);
2089:
2090:
2091: remove(start, end - start);
2092: }
2093:
2094:
2107: public void setOuterHTML(Element elem, String htmlText)
2108: throws BadLocationException, IOException
2109: {
2110:
2111: int start = elem.getStartOffset();
2112: int end = elem.getEndOffset();
2113:
2114: remove(start, end-start);
2115:
2116: HTMLEditorKit.ParserCallback reader = getInsertingReader(
2117: start, 0, 0, HTML.Tag.BODY, elem);
2118:
2119:
2120: getParser().parse(new StringReader(htmlText), reader, true);
2121: }
2122:
2123:
2133: public void insertBeforeStart(Element elem, String htmlText)
2134: throws BadLocationException, IOException
2135: {
2136: HTMLEditorKit.ParserCallback reader = getInsertingReader(
2137: elem.getStartOffset(), 0, 0, HTML.Tag.BODY, elem);
2138:
2139:
2140: getParser().parse(new StringReader(htmlText), reader, true);
2141: }
2142:
2143:
2154: public void insertBeforeEnd(Element elem, String htmlText)
2155: throws BadLocationException, IOException
2156: {
2157: HTMLEditorKit.ParserCallback reader = getInsertingReader(
2158: elem.getEndOffset(), 0, 0, HTML.Tag.BODY, elem);
2159:
2160:
2161: getParser().parse(new StringReader(htmlText), reader, true);
2162:
2163: }
2164:
2165:
2175: public void insertAfterEnd(Element elem, String htmlText)
2176: throws BadLocationException, IOException
2177: {
2178: HTMLEditorKit.ParserCallback reader = getInsertingReader(
2179: elem.getEndOffset(), 0, 0, HTML.Tag.BODY, elem);
2180:
2181:
2182: getParser().parse(new StringReader(htmlText), reader, true);
2183: }
2184:
2185:
2195: public void insertAfterStart(Element elem, String htmlText)
2196: throws BadLocationException, IOException
2197: {
2198: HTMLEditorKit.ParserCallback reader = getInsertingReader(
2199: elem.getStartOffset(), 0, 0, HTML.Tag.BODY, elem);
2200:
2201:
2202: getParser().parse(new StringReader(htmlText), reader, true);
2203: }
2204:
2205:
2209: protected void insertUpdate(DefaultDocumentEvent evt, AttributeSet att)
2210: {
2211: if (att == null)
2212: {
2213: SimpleAttributeSet sas = new SimpleAttributeSet();
2214: sas.addAttribute(StyleConstants.NameAttribute, HTML.Tag.CONTENT);
2215: att = sas;
2216: }
2217: super.insertUpdate(evt, att);
2218: }
2219:
2220:
2227: boolean isFrameDocument()
2228: {
2229: return frameDocument;
2230: }
2231:
2232:
2239: void setFrameDocument(boolean frameDoc)
2240: {
2241: frameDocument = frameDoc;
2242: }
2243:
2244:
2249: String getBaseTarget()
2250: {
2251: return baseTarget;
2252: }
2253:
2254:
2261: void updateSpecialClass(Element el, HTML.Attribute cl, String value)
2262: {
2263: try
2264: {
2265: writeLock();
2266: DefaultDocumentEvent ev =
2267: new DefaultDocumentEvent(el.getStartOffset(), 1,
2268: DocumentEvent.EventType.CHANGE);
2269: AttributeSet elAtts = el.getAttributes();
2270: AttributeSet anchorAtts = (AttributeSet) elAtts.getAttribute(HTML.Tag.A);
2271: if (anchorAtts != null)
2272: {
2273: AttributeSet copy = elAtts.copyAttributes();
2274: StyleSheet ss = getStyleSheet();
2275: if (value != null)
2276: {
2277: anchorAtts = ss.addAttribute(anchorAtts, cl, value);
2278: }
2279: else
2280: {
2281: anchorAtts = ss.removeAttribute(anchorAtts, cl);
2282: }
2283: MutableAttributeSet matts = (MutableAttributeSet) elAtts;
2284: ev.addEdit(new AttributeUndoableEdit(el, copy, false));
2285: matts.removeAttribute(HTML.Tag.A);
2286: matts.addAttribute(HTML.Tag.A, anchorAtts);
2287: ev.end();
2288: fireChangedUpdate(ev);
2289: fireUndoableEditUpdate(new UndoableEditEvent(this, ev));
2290: }
2291: }
2292: finally
2293: {
2294: writeUnlock();
2295: }
2296: }
2297:
2298: }