Source Code Cross Referenced for HTMLDocument.java in  » Apache-Harmony-Java-SE » javax-package » javax » swing » text » html » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Apache Harmony Java SE » javax package » javax.swing.text.html 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         *  Licensed to the Apache Software Foundation (ASF) under one or more
0003:         *  contributor license agreements.  See the NOTICE file distributed with
0004:         *  this work for additional information regarding copyright ownership.
0005:         *  The ASF licenses this file to You under the Apache License, Version 2.0
0006:         *  (the "License"); you may not use this file except in compliance with
0007:         *  the License.  You may obtain a copy of the License at
0008:         *
0009:         *     http://www.apache.org/licenses/LICENSE-2.0
0010:         *
0011:         *  Unless required by applicable law or agreed to in writing, software
0012:         *  distributed under the License is distributed on an "AS IS" BASIS,
0013:         *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014:         *  See the License for the specific language governing permissions and
0015:         *  limitations under the License.
0016:         */
0017:        /**
0018:         * @author Alexander T. Simbirtsev
0019:         * @version $Revision$
0020:         */package javax.swing.text.html;
0021:
0022:        import java.io.BufferedReader;
0023:        import java.io.IOException;
0024:        import java.io.InputStreamReader;
0025:        import java.io.StringReader;
0026:        import java.net.URL;
0027:        import java.util.HashMap;
0028:        import java.util.HashSet;
0029:        import java.util.Set;
0030:        import java.util.Stack;
0031:        import java.util.Vector;
0032:
0033:        import javax.swing.ButtonGroup;
0034:        import javax.swing.event.DocumentEvent.EventType;
0035:        import javax.swing.text.AttributeSet;
0036:        import javax.swing.text.BadLocationException;
0037:        import javax.swing.text.DefaultEditorKit;
0038:        import javax.swing.text.DefaultStyledDocument;
0039:        import javax.swing.text.Element;
0040:        import javax.swing.text.ElementIterator;
0041:        import javax.swing.text.MutableAttributeSet;
0042:        import javax.swing.text.SimpleAttributeSet;
0043:        import javax.swing.text.StyleConstants;
0044:        import javax.swing.text.html.HTML.Tag;
0045:        import javax.swing.text.html.HTMLEditorKit.Parser;
0046:        import javax.swing.text.html.parser.ParserDelegator;
0047:
0048:        import org.apache.harmony.x.swing.text.html.form.Form;
0049:        import org.apache.harmony.x.swing.text.html.form.FormAttributes;
0050:        import org.apache.harmony.x.swing.text.html.form.FormButtonModel;
0051:        import org.apache.harmony.x.swing.text.html.form.FormElement;
0052:        import org.apache.harmony.x.swing.text.html.form.FormFieldsetModel;
0053:        import org.apache.harmony.x.swing.text.html.form.FormOption;
0054:        import org.apache.harmony.x.swing.text.html.form.FormOptionGroup;
0055:        import org.apache.harmony.x.swing.text.html.form.FormSelectComboBoxModel;
0056:        import org.apache.harmony.x.swing.text.html.form.FormSelectListModel;
0057:        import org.apache.harmony.x.swing.text.html.form.FormSelectModel;
0058:        import org.apache.harmony.x.swing.text.html.form.FormTextModel;
0059:        import org.apache.harmony.x.swing.text.html.form.FormToggleButtonModel;
0060:
0061:        import org.apache.harmony.x.swing.internal.nls.Messages;
0062:
0063:        public class HTMLDocument extends DefaultStyledDocument {
0064:
0065:            public class BlockElement extends BranchElement {
0066:                public BlockElement(final Element parent,
0067:                        final AttributeSet attr) {
0068:                    super (parent, attr);
0069:                }
0070:
0071:                public String getName() {
0072:                    final Object tag = getAttribute(StyleConstants.NameAttribute);
0073:                    return tag != null ? tag.toString() : super .getName();
0074:                }
0075:
0076:                public AttributeSet getResolveParent() {
0077:                    return null;
0078:                }
0079:            }
0080:
0081:            public class RunElement extends LeafElement {
0082:                public RunElement(final Element parent, final AttributeSet a,
0083:                        final int start, final int end) {
0084:                    super (parent, a, start, end);
0085:                }
0086:
0087:                public String getName() {
0088:                    final Object tag = getAttribute(StyleConstants.NameAttribute);
0089:                    return tag != null ? tag.toString() : super .getName();
0090:                }
0091:
0092:                public AttributeSet getResolveParent() {
0093:                    return null;
0094:                }
0095:            }
0096:
0097:            public class HTMLReader extends HTMLEditorKit.ParserCallback {
0098:
0099:                private boolean anchorReferenceEncountered = false;
0100:
0101:                public class TagAction {
0102:                    public void start(final Tag tag,
0103:                            final MutableAttributeSet attr) {
0104:                    }
0105:
0106:                    public void end(final Tag tag) {
0107:                    }
0108:                }
0109:
0110:                public class BlockAction extends TagAction {
0111:                    public void start(final Tag tag,
0112:                            final MutableAttributeSet attr) {
0113:                        addJoinPreviousSpec = true;
0114:                        checkInsertTag(tag);
0115:                        skipAddingBlockSpec = false;
0116:                        blockOpen(tag, attr);
0117:                    }
0118:
0119:                    public void end(final Tag tag) {
0120:                        blockClose(tag);
0121:                    }
0122:                }
0123:
0124:                public class CharacterAction extends TagAction {
0125:                    public void start(final Tag tag,
0126:                            final MutableAttributeSet attr) {
0127:                        addJoinPreviousSpec = true;
0128:                        checkInsertTag(tag);
0129:                        pushCharacterStyle();
0130:                        charAttr.addAttribute(tag, attr.copyAttributes());
0131:                    }
0132:
0133:                    public void end(final Tag tag) {
0134:                        popCharacterStyle();
0135:                    }
0136:                }
0137:
0138:                public class FormAction extends SpecialAction {
0139:                    private static final String NO_NAME_ATTRIBUTE = "___no_name___";
0140:
0141:                    private Form currentForm;
0142:                    private HashMap radioGroupped = new HashMap();
0143:
0144:                    public void start(final Tag tag,
0145:                            final MutableAttributeSet attr) {
0146:                        if (Tag.OPTION.equals(tag) || Tag.OPTGROUP.equals(tag)) {
0147:                            checkInsertTag(tag);
0148:                            handleOption(tag, attr);
0149:                            return;
0150:                        }
0151:                        super .start(tag, attr);
0152:
0153:                        final ElementSpec spec = getLastSpec();
0154:                        assert spec != null : "we've just created a spec in super.start()";
0155:                        FormElement model = null;
0156:                        final MutableAttributeSet specAttr = (MutableAttributeSet) spec
0157:                                .getAttributes();
0158:                        if (Tag.INPUT.equals(tag)) {
0159:                            model = handleInput(attr, specAttr);
0160:                        } else if (Tag.TEXTAREA.equals(tag)) {
0161:                            model = new FormTextModel(getCurrentForm(), attr);
0162:                            openedBlocks.add(Tag.TEXTAREA);
0163:                        } else if (Tag.BUTTON.equals(tag)) {
0164:                            model = new FormButtonModel(getCurrentForm(), attr);
0165:                            openedBlocks.add(Tag.BUTTON);
0166:                        } else if (Tag.LEGEND.equals(tag)) {
0167:                            openedBlocks.add(Tag.LEGEND);
0168:                            if (openedBlocks.contains(Tag.FIELDSET)) {
0169:                                handleLegend(null, specAttr);
0170:                            }
0171:                        } else if (Tag.FIELDSET.equals(tag)) {
0172:                            model = new FormFieldsetModel(getCurrentForm(),
0173:                                    attr);
0174:                            openedBlocks.add(Tag.FIELDSET);
0175:                        } else if (Tag.SELECT.equals(tag)) {
0176:                            if (FormAttributes.isListSelect(specAttr)) {
0177:                                selectModel = new FormSelectListModel(
0178:                                        getCurrentForm(), attr);
0179:                            } else {
0180:                                selectModel = new FormSelectComboBoxModel(
0181:                                        getCurrentForm(), attr);
0182:                            }
0183:                            model = selectModel;
0184:                            openedBlocks.add(Tag.SELECT);
0185:                        }
0186:                        if (model != null) {
0187:                            specAttr.addAttribute(
0188:                                    StyleConstants.ModelAttribute, model);
0189:                            assert currentForm != null : "creating model with getCurrentForm() in constructor assures this";
0190:                            currentForm.addElement(model);
0191:                        }
0192:                    }
0193:
0194:                    public void end(final Tag tag) {
0195:                        openedBlocks.remove(tag);
0196:                        if (Tag.SELECT.equals(tag)) {
0197:                            selectModel = null;
0198:                        } else if (Tag.OPTGROUP.equals(tag)) {
0199:                            if (selectModel != null) {
0200:                                selectModel.getRootOptionGroup().popGroup();
0201:                            }
0202:                        }
0203:                    }
0204:
0205:                    void openForm(final AttributeSet attr) {
0206:                        currentForm = new Form(attr);
0207:                    }
0208:
0209:                    void closeForm() {
0210:                        currentForm = null;
0211:                        selectModel = null;
0212:                        radioGroupped.clear();
0213:                    }
0214:
0215:                    private FormElement handleInput(final AttributeSet attr,
0216:                            final MutableAttributeSet specAttr) {
0217:                        FormElement result = null;
0218:                        String inputType = (String) attr
0219:                                .getAttribute(HTML.Attribute.TYPE);
0220:                        if (inputType == null) {
0221:                            inputType = FormAttributes.INPUT_TYPE_TEXT;
0222:                            specAttr.addAttribute(HTML.Attribute.TYPE,
0223:                                    inputType);
0224:                        }
0225:                        int inputTypeIndex = FormAttributes
0226:                                .getTypeAttributeIndex((String) inputType);
0227:
0228:                        switch (inputTypeIndex) {
0229:                        case FormAttributes.INPUT_TYPE_TEXT_INDEX:
0230:                        case FormAttributes.INPUT_TYPE_PASSWORD_INDEX:
0231:                            result = new FormTextModel(getCurrentForm(), attr,
0232:                                    FormTextModel.ENABLE_MAX_LENGTH_BOUND);
0233:                            break;
0234:                        case FormAttributes.INPUT_TYPE_FILE_INDEX:
0235:                            result = new FormTextModel(getCurrentForm(), attr);
0236:                            break;
0237:                        case FormAttributes.INPUT_TYPE_SUBMIT_INDEX:
0238:                        case FormAttributes.INPUT_TYPE_RESET_INDEX:
0239:                        case FormAttributes.INPUT_TYPE_BUTTON_INDEX:
0240:                        case FormAttributes.INPUT_TYPE_IMAGE_INDEX:
0241:                            result = new FormButtonModel(getCurrentForm(), attr);
0242:                            break;
0243:                        case FormAttributes.INPUT_TYPE_RADIO_INDEX:
0244:                            FormToggleButtonModel buttonModel = new FormToggleButtonModel(
0245:                                    getCurrentForm(), attr);
0246:                            manageRadioGroup(attr, buttonModel);
0247:                            result = buttonModel;
0248:                            break;
0249:                        case FormAttributes.INPUT_TYPE_CHECKBOX_INDEX:
0250:                            result = new FormToggleButtonModel(
0251:                                    getCurrentForm(), attr);
0252:                            break;
0253:                        default:
0254:                            break;
0255:                        }
0256:                        return result;
0257:                    }
0258:
0259:                    private void manageRadioGroup(final AttributeSet attr,
0260:                            final FormToggleButtonModel buttonModel) {
0261:                        String name = (String) attr
0262:                                .getAttribute(HTML.Attribute.NAME);
0263:                        if (name == null) {
0264:                            name = NO_NAME_ATTRIBUTE;
0265:                        }
0266:                        Object groupped = radioGroupped.get(name);
0267:                        if (groupped instanceof  FormToggleButtonModel) {
0268:                            FormToggleButtonModel grouppedModel = (FormToggleButtonModel) groupped;
0269:                            ButtonGroup buttonGroup;
0270:                            if (grouppedModel.getGroup() != null) {
0271:                                buttonGroup = grouppedModel.getGroup();
0272:                            } else {
0273:                                buttonGroup = new ButtonGroup();
0274:                                grouppedModel.setGroup(buttonGroup);
0275:                            }
0276:                            buttonModel.setGroup(buttonGroup);
0277:                        } else {
0278:                            radioGroupped.put(name, buttonModel);
0279:                        }
0280:                    }
0281:
0282:                    private void handleOption(final Tag tag,
0283:                            final AttributeSet attr) {
0284:                        FormOption option = null;
0285:                        FormOptionGroup currentGroup = (selectModel != null) ? selectModel
0286:                                .getRootOptionGroup().getCurrentGroup()
0287:                                : null;
0288:
0289:                        if (Tag.OPTION.equals(tag)) {
0290:                            option = new FormOption(currentGroup, attr);
0291:                            openedBlocks.add(Tag.OPTION);
0292:                        } else if (Tag.OPTGROUP.equals(tag)) {
0293:                            currentGroup = new FormOptionGroup(currentGroup,
0294:                                    attr);
0295:                            option = currentGroup;
0296:                        }
0297:
0298:                        if (option != null && selectModel != null) {
0299:                            selectModel.addOption(option);
0300:                            selectModel.getRootOptionGroup().pushGroup(
0301:                                    currentGroup);
0302:                        }
0303:                    }
0304:
0305:                    private ElementSpec getLastSpec() {
0306:                        return !parseBuffer.isEmpty() ? (ElementSpec) parseBuffer
0307:                                .get(parseBuffer.size() - 1)
0308:                                : null;
0309:                    }
0310:
0311:                    private Form getCurrentForm() {
0312:                        return (currentForm != null) ? currentForm
0313:                                : (currentForm = new Form(
0314:                                        SimpleAttributeSet.EMPTY));
0315:                    }
0316:                }
0317:
0318:                public class HiddenAction extends TagAction {
0319:                    public void start(final Tag tag,
0320:                            final MutableAttributeSet attr) {
0321:                        addSpecialElement(tag, attr);
0322:                    }
0323:
0324:                    public void end(final Tag tag) {
0325:                        addSpecialElement(tag, createMutableSet(
0326:                                HTML.Attribute.ENDTAG, Boolean.TRUE));
0327:                    }
0328:                }
0329:
0330:                public class IsindexAction extends TagAction {
0331:                    public void start(final Tag tag,
0332:                            final MutableAttributeSet attr) {
0333:                        addJoinPreviousSpec = true;
0334:                        checkInsertTag(tag);
0335:                        blockOpen(Tag.IMPLIED, new SimpleAttributeSet());
0336:                        addSpecialElement(tag, attr);
0337:                        blockClose(Tag.IMPLIED);
0338:                    }
0339:
0340:                }
0341:
0342:                public class ParagraphAction extends BlockAction {
0343:                    public void start(final Tag tag,
0344:                            final MutableAttributeSet attr) {
0345:                        super .start(tag, attr);
0346:                        openedBlocks.add(PARAGRAPH_TAG);
0347:                    }
0348:
0349:                    public void end(final Tag tag) {
0350:                        super .end(tag);
0351:                        openedBlocks.remove(PARAGRAPH_TAG);
0352:                    }
0353:                }
0354:
0355:                public class PreAction extends BlockAction {
0356:                    public void start(final Tag tag,
0357:                            final MutableAttributeSet attr) {
0358:                        super .start(tag, attr);
0359:                        MutableAttributeSet blockAttr = new SimpleAttributeSet(
0360:                                attr);
0361:                        SimpleAttributeSet defaultAttr = getDefaultCSSAttributes(tag);
0362:                        if (defaultAttr != null) {
0363:                            blockAttr.addAttributes(defaultAttr);
0364:                        }
0365:                        blockOpen(Tag.IMPLIED, blockAttr);
0366:                        impliedBlockOpen = true;
0367:                        needImpliedNewLine = true;
0368:                    }
0369:
0370:                    public void end(final Tag tag) {
0371:                        blockClose(Tag.IMPLIED);
0372:                        super .end(tag);
0373:                    }
0374:                }
0375:
0376:                public class SpecialAction extends TagAction {
0377:                    public void start(final Tag tag,
0378:                            final MutableAttributeSet attr) {
0379:                        addJoinPreviousSpec = true;
0380:                        addSpecialElement(tag, attr);
0381:                    }
0382:                }
0383:
0384:                class AdvancedCharacterAction extends CharacterAction {
0385:                    public void start(final Tag tag,
0386:                            final MutableAttributeSet attr) {
0387:                        super .start(tag, attr);
0388:                        final AttributeSet attrs = getDefaultCSSAttributes(tag);
0389:                        if (attrs != null) {
0390:                            charAttr.addAttributes(attrs);
0391:                        }
0392:                    }
0393:                }
0394:
0395:                class LabelAction extends BlockAction {
0396:                    // TODO
0397:                }
0398:
0399:                class AnchorAction extends CharacterAction {
0400:                    public void start(final Tag tag,
0401:                            final MutableAttributeSet attr) {
0402:                        anchorReferenceEncountered = attr
0403:                                .isDefined(HTML.Attribute.HREF);
0404:                        //anchorReferenceEncountered verification added according to H4606
0405:                        if (anchorReferenceEncountered) {
0406:                            super .start(tag, attr);
0407:                            openedBlocks.add(Tag.A);
0408:                        }
0409:                    }
0410:
0411:                    public void end(final Tag tag) {
0412:                        // According to H4574 Empty AncorTextEncoured verification has
0413:                        // been removed, but according H4606 anchorReferenceEncountered
0414:                        // has been added
0415:                        if (anchorReferenceEncountered) {
0416:                            super .end(tag);
0417:                            openedBlocks.remove(Tag.A);
0418:                            anchorReferenceEncountered = false;
0419:                        }
0420:                    }
0421:                }
0422:
0423:                class FontAction extends CharacterAction {
0424:                    final HTML.Attribute[] specialHTMLAttributes = new HTML.Attribute[] {
0425:                            HTML.Attribute.FACE, HTML.Attribute.COLOR,
0426:                            HTML.Attribute.SIZE };
0427:
0428:                    final CSS.Attribute[] specialCSSAttributes = new CSS.Attribute[] {
0429:                            CSS.Attribute.FONT_FAMILY, CSS.Attribute.COLOR,
0430:                            CSS.Attribute.FONT_SIZE };
0431:
0432:                    public void start(final Tag tag,
0433:                            final MutableAttributeSet attr) {
0434:                        super .start(tag, attr);
0435:
0436:                        final StyleSheet styleSheet = getStyleSheet();
0437:                        for (int i = 0; i < specialHTMLAttributes.length; i++) {
0438:                            final String value = (String) attr
0439:                                    .getAttribute(specialHTMLAttributes[i]);
0440:                            if (value != null) {
0441:                                styleSheet.addCSSAttributeFromHTML(charAttr,
0442:                                        specialCSSAttributes[i], value);
0443:                            }
0444:                        }
0445:                    }
0446:                }
0447:
0448:                class FormTagAction extends BlockAction {
0449:                    private Tag[] formActionTags = new Tag[] { Tag.TEXTAREA,
0450:                            Tag.SELECT, Tag.INPUT, Tag.OPTION, Tag.OPTGROUP,
0451:                            Tag.BUTTON, Tag.LEGEND, Tag.FIELDSET };
0452:
0453:                    public void start(final Tag tag,
0454:                            final MutableAttributeSet attr) {
0455:                        super .start(tag, attr);
0456:                        FormAction formAction = getFormAction();
0457:                        if (formAction != null) {
0458:                            formAction.openForm(attr);
0459:                        }
0460:                    }
0461:
0462:                    public void end(final Tag tag) {
0463:                        super .end(tag);
0464:                        FormAction formAction = getFormAction();
0465:                        if (formAction != null) {
0466:                            formAction.closeForm();
0467:                        }
0468:                    }
0469:
0470:                    private FormAction getFormAction() {
0471:                        for (int i = 0; i < formActionTags.length; i++) {
0472:                            final Tag tag = formActionTags[i];
0473:                            TagAction action = getAction(tag);
0474:                            if (action instanceof  FormAction) {
0475:                                return (FormAction) action;
0476:                            }
0477:                        }
0478:                        return null;
0479:                    }
0480:                }
0481:
0482:                class ImageAction extends SpecialAction {
0483:
0484:                    @Override
0485:                    public void start(Tag tag, MutableAttributeSet attr) {
0486:
0487:                        if (anchorReferenceEncountered) {
0488:
0489:                            attr.addAttributes(charAttr.copyAttributes());
0490:                        }
0491:
0492:                        super .start(tag, attr);
0493:                    }
0494:                }
0495:
0496:                class BaseAction extends TagAction {
0497:                    public void start(final Tag tag,
0498:                            final MutableAttributeSet attr) {
0499:                        checkInsertTag(tag);
0500:                        if (attr == null) {
0501:                            return;
0502:                        }
0503:                        final String href = (String) attr
0504:                                .getAttribute(HTML.Attribute.HREF);
0505:                        if (href == null) {
0506:                            return;
0507:                        }
0508:
0509:                        final URL url = HTML.resolveURL(href, getBase());
0510:                        setBase(url);
0511:                        putProperty(INITIAL_BASE_PROPERTY, url);
0512:                    }
0513:                }
0514:
0515:                class HeadAction extends BlockAction {
0516:                    public void end(final Tag tag) {
0517:                        super .end(tag);
0518:                        if (styleRule != null) {
0519:                            getStyleSheet().addRule(styleRule);
0520:                            styleRule = null;
0521:                        }
0522:                    }
0523:                }
0524:
0525:                class TitleAction extends BlockAction {
0526:                    public void start(final Tag tag,
0527:                            final MutableAttributeSet attr) {
0528:                        addJoinPreviousSpec = true;
0529:                        checkInsertTag(tag);
0530:                        addSpecialElement(tag, attr);
0531:                        openedBlocks.add(Tag.TITLE);
0532:                    }
0533:
0534:                    public void end(final Tag tag) {
0535:                        addSpecialElement(tag, createMutableSet(
0536:                                HTML.Attribute.ENDTAG, Boolean.TRUE));
0537:                        openedBlocks.remove(Tag.TITLE);
0538:                    }
0539:                }
0540:
0541:                class AppletAction extends HiddenAction {
0542:                    // TODO: implement
0543:                    public void start(final Tag tag,
0544:                            final MutableAttributeSet attr) {
0545:                        addJoinPreviousSpec = true;
0546:                        super .start(tag, attr);
0547:                    }
0548:                }
0549:
0550:                class AreaAction extends HiddenAction {
0551:                    // TODO: implement
0552:                }
0553:
0554:                class MapAction extends HiddenAction {
0555:                    // TODO: implement
0556:                }
0557:
0558:                class ScriptAction extends HiddenAction {
0559:                    // TODO: implement
0560:                    public void start(final Tag tag,
0561:                            final MutableAttributeSet attr) {
0562:                        addJoinPreviousSpec = true;
0563:                        super .start(tag, attr);
0564:                    }
0565:                }
0566:
0567:                class LinkAction extends HiddenAction {
0568:                    public void start(final Tag tag,
0569:                            final MutableAttributeSet attr) {
0570:                        addJoinPreviousSpec = true;
0571:                        super .start(tag, attr);
0572:                        if (attr.containsAttribute(HTML.Attribute.TYPE,
0573:                                "text/css")) {
0574:                            loadCSS(attr);
0575:                        }
0576:                    }
0577:
0578:                    public void end(final Tag tag) {
0579:                    }
0580:
0581:                    private void loadCSS(final AttributeSet attr) {
0582:                        String href = (String) attr
0583:                                .getAttribute(HTML.Attribute.HREF);
0584:                        final URL url = HTML.resolveURL(href, getBase());
0585:                        try {
0586:                            getStyleSheet().loadRules(
0587:                                    new BufferedReader(new InputStreamReader(
0588:                                            url.openStream())), url);
0589:                        } catch (IOException e) {
0590:                        }
0591:                    }
0592:                }
0593:
0594:                class MetaAction extends SpecialAction {
0595:                    public void end(final Tag tag) {
0596:                    }
0597:                }
0598:
0599:                class StyleAction extends TagAction {
0600:                    public void start(Tag tag, MutableAttributeSet attr) {
0601:                        checkInsertTag(tag);
0602:                        openedBlocks.add(Tag.STYLE);
0603:                    }
0604:
0605:                    public void end(Tag tag) {
0606:                        openedBlocks.remove(Tag.STYLE);
0607:                    }
0608:                }
0609:
0610:                protected MutableAttributeSet charAttr = new SimpleAttributeSet();
0611:
0612:                protected Vector<DefaultStyledDocument.ElementSpec> parseBuffer = new Vector<DefaultStyledDocument.ElementSpec>();
0613:
0614:                private static final String PARAGRAPH_TAG = "_paragraph_tag_";
0615:                private static final int IMPLIED_HTML_DOCUMENT_START_SPECS_NUMBER = 8;
0616:                private static final int TOKEN_THRESHOLD_MULTIPLIER = 5;
0617:
0618:                private final HashMap tagActionMap = new HashMap();
0619:                private final TagAction emptyAction = new TagAction();
0620:                private final Stack attrStack = new Stack();
0621:                private final Set openedBlocks = new HashSet();
0622:                private boolean impliedBlockOpen;
0623:                private int numBlocksOpen;
0624:
0625:                private boolean needImpliedNewLine;
0626:                private String styleRule;
0627:                private FormSelectModel selectModel;
0628:                private int tokenThreshold;
0629:
0630:                private int offset;
0631:                private int popDepth;
0632:                private int pushDepth;
0633:                private Tag insertTag;
0634:                private boolean insertTagFound;
0635:                private boolean implicitSpecsRemove;
0636:                private boolean skipAddingBlockSpec;
0637:                private boolean addJoinPreviousSpec;
0638:                private int specsCount;
0639:
0640:                public HTMLReader(final int offset) {
0641:                    this (offset, 0, 0, null);
0642:                }
0643:
0644:                public HTMLReader(final int offset, final int popDepth,
0645:                        final int pushDepth, final Tag insertTag) {
0646:                    this .offset = offset;
0647:                    this .popDepth = popDepth;
0648:                    this .pushDepth = pushDepth;
0649:                    this .insertTag = insertTag;
0650:                    insertTagFound = (insertTag == null);
0651:                    tokenThreshold = getTokenThreshold();
0652:                    fillTagActionMap();
0653:                }
0654:
0655:                public void handleComment(final char[] data, final int pos) {
0656:                    final String comment = new String(data);
0657:                    if (openedBlocks.contains(Tag.P)) {
0658:                        addSpecialElement(Tag.COMMENT, createMutableSet(
0659:                                HTML.Attribute.COMMENT, comment));
0660:                    } else {
0661:                        Vector comments = (Vector) getProperty(AdditionalComments);
0662:                        if (comments == null) {
0663:                            comments = new Vector();
0664:                            putProperty(AdditionalComments, comments);
0665:                        }
0666:                        comments.add(comment);
0667:                    }
0668:                }
0669:
0670:                public void handleEndOfLineString(final String eol) {
0671:                    putProperty(DefaultEditorKit.EndOfLineStringProperty, eol);
0672:                }
0673:
0674:                public void handleSimpleTag(final Tag tag,
0675:                        final MutableAttributeSet attr, final int pos) {
0676:                    final TagAction action = getAction(tag);
0677:                    MutableAttributeSet tagAttr = handleStyleAttribute(attr);
0678:                    if (action != emptyAction || !getPreservesUnknownTags()) {
0679:                        action.start(tag, tagAttr);
0680:                        action.end(tag);
0681:                    } else {
0682:                        addSpecialElement(tag, tagAttr);
0683:                    }
0684:                }
0685:
0686:                public void handleStartTag(final Tag tag,
0687:                        final MutableAttributeSet attr, final int pos) {
0688:                    final TagAction action = getAction(tag);
0689:                    action.start(tag, handleStyleAttribute(attr));
0690:                }
0691:
0692:                public void handleEndTag(final Tag tag, final int pos) {
0693:                    final TagAction action = getAction(tag);
0694:                    action.end(tag);
0695:                }
0696:
0697:                public void handleText(final char[] data, final int pos) {
0698:                    if (openedBlocks.contains(Tag.TITLE)) {
0699:                        putProperty(TitleProperty, new String(data));
0700:                        return;
0701:                    }
0702:                    if (openedBlocks.contains(Tag.STYLE)
0703:                            && openedBlocks.contains(Tag.HEAD)) {
0704:                        final String newStyle = new String(data);
0705:                        if (styleRule == null) {
0706:                            styleRule = newStyle;
0707:                        } else {
0708:                            styleRule += newStyle;
0709:                        }
0710:                        return;
0711:                    }
0712:                    if (openedBlocks.contains(Tag.TEXTAREA)) {
0713:                        textAreaContent(data);
0714:                        return;
0715:                    }
0716:                    if (openedBlocks.contains(Tag.PRE)) {
0717:                        preContent(data);
0718:                        return;
0719:                    }
0720:                    if (openedBlocks.contains(Tag.OPTION)
0721:                            && openedBlocks.contains(Tag.SELECT)) {
0722:                        final Option option = selectModel.getLastOption();
0723:                        if (option != null
0724:                                && !(option instanceof  FormOptionGroup)) {
0725:                            option.setLabel(new String(data));
0726:                        }
0727:                    }
0728:                    if (openedBlocks.contains(Tag.LEGEND)
0729:                            && openedBlocks.contains(Tag.FIELDSET)) {
0730:                        if (handleLegend(new String(data), null)) {
0731:                            return;
0732:                        }
0733:                    }
0734:                    if (numBlocksOpen > 0) {
0735:                        addContent(data, 0, data.length);
0736:                    }
0737:                }
0738:
0739:                public void flush() throws BadLocationException {
0740:                    flushImpl(true);
0741:                }
0742:
0743:                protected void registerTag(final Tag tag, final TagAction action) {
0744:                    tagActionMap.put(tag, action);
0745:                }
0746:
0747:                protected void pushCharacterStyle() {
0748:                    if (charAttr == null) {
0749:                        throw new NullPointerException();
0750:                    }
0751:                    attrStack.push(charAttr.copyAttributes());
0752:                }
0753:
0754:                protected void popCharacterStyle() {
0755:                    if (!attrStack.empty()) {
0756:                        charAttr = (MutableAttributeSet) attrStack.pop();
0757:                    }
0758:                }
0759:
0760:                protected void preContent(char[] data) {
0761:                    int offset = 0;
0762:
0763:                    for (int i = 0; i < data.length; i++) {
0764:                        if ((data[i] == '\n') || (data[i] == '\r')) {
0765:                            addContent(data, offset, i - offset);
0766:                            blockClose(HTML.Tag.IMPLIED);
0767:
0768:                            blockOpen(HTML.Tag.IMPLIED,
0769:                                    new SimpleAttributeSet());
0770:                            offset = i + 1;
0771:                        }
0772:                    }
0773:
0774:                    if (offset < data.length) {
0775:                        addContent(data, offset, data.length - offset);
0776:                    }
0777:                }
0778:
0779:                protected void addContent(final char[] data, final int offset,
0780:                        final int length) {
0781:                    addContent(data, offset, length, true);
0782:                }
0783:
0784:                protected void addContent(final char[] data, final int offset,
0785:                        final int length,
0786:                        final boolean createImpliedPIfNecessary) {
0787:                    addContentSpec(Tag.CONTENT, data, offset, length, charAttr,
0788:                            createImpliedPIfNecessary);
0789:
0790:                    if (parseBuffer.size() > tokenThreshold) {
0791:                        try {
0792:                            flushImpl(false);
0793:                        } catch (BadLocationException e) {
0794:                        }
0795:                        tokenThreshold *= TOKEN_THRESHOLD_MULTIPLIER;
0796:                    }
0797:                }
0798:
0799:                protected void addSpecialElement(final Tag tag,
0800:                        final MutableAttributeSet attr) {
0801:                    final boolean needImpliedBlock = !Tag.FRAME.equals(tag);
0802:                    if (!needImpliedBlock) {
0803:                        needImpliedNewLine = false;
0804:                    }
0805:                    addContentSpec(tag, new char[] { ' ' }, 0, 1, attr,
0806:                            needImpliedBlock);
0807:                }
0808:
0809:                protected void textAreaContent(final char[] data) {
0810:                    final ElementSpec textareaSpec = findLastSpec(Tag.TEXTAREA);
0811:                    if (textareaSpec == null) {
0812:                        return;
0813:                    }
0814:                    FormTextModel doc = (FormTextModel) getModel(textareaSpec);
0815:                    if (doc != null) {
0816:                        doc.setInitialContent(new String(data));
0817:                    }
0818:                }
0819:
0820:                protected void blockOpen(final Tag tag,
0821:                        final MutableAttributeSet attr) {
0822:                    if (impliedBlockOpen && !Tag.IMPLIED.equals(tag)) {
0823:                        blockClose(Tag.IMPLIED);
0824:                        impliedBlockOpen = false;
0825:                    }
0826:                    if (!skipAddingBlockSpec) {
0827:                        ElementSpec blockSpec = new ElementSpec(
0828:                                deriveSpecAttributes(tag, attr),
0829:                                ElementSpec.StartTagType);
0830:                        addSpec(blockSpec);
0831:                    }
0832:                    skipAddingBlockSpec = false;
0833:                    needImpliedNewLine = true;
0834:                    openedBlocks.add(tag);
0835:                    numBlocksOpen++;
0836:                }
0837:
0838:                protected void blockClose(final Tag tag) {
0839:                    if (needImpliedNewLine) {
0840:                        addImpliedNewLine();
0841:                        if (impliedBlockOpen && !Tag.IMPLIED.equals(tag)) {
0842:                            blockClose(Tag.IMPLIED);
0843:                            impliedBlockOpen = false;
0844:                        }
0845:                    }
0846:                    numBlocksOpen--;
0847:                    openedBlocks.remove(tag);
0848:                    addSpec(new ElementSpec(null, ElementSpec.EndTagType));
0849:                }
0850:
0851:                private Object getModel(final ElementSpec spec) {
0852:                    return spec.getAttributes().getAttribute(
0853:                            StyleConstants.ModelAttribute);
0854:                }
0855:
0856:                private void addImpliedNewLine() {
0857:                    pushCharacterStyle();
0858:                    charAttr.addAttribute(HTML.Attribute.IMPLIED_NEW_LINE,
0859:                            Boolean.TRUE);
0860:                    addContent(new char[] { '\n' }, 0, 1, true);
0861:                    popCharacterStyle();
0862:                    needImpliedNewLine = false;
0863:                }
0864:
0865:                private MutableAttributeSet handleStyleAttribute(
0866:                        final MutableAttributeSet attr) {
0867:                    final String style = (String) attr
0868:                            .getAttribute(HTML.Attribute.STYLE);
0869:                    if (style != null) {
0870:                        attr.addAttributes(getStyleSheet()
0871:                                .getDeclaration(style));
0872:                        attr.removeAttribute(HTML.Attribute.STYLE);
0873:                    }
0874:                    return attr;
0875:                }
0876:
0877:                private void createImpliedBlock() {
0878:                    if (paragraphOpened()) {
0879:                        return;
0880:                    }
0881:                    blockOpen(Tag.IMPLIED, new SimpleAttributeSet());
0882:                    impliedBlockOpen = true;
0883:                }
0884:
0885:                private MutableAttributeSet createMutableSet(final Object key,
0886:                        final Object value) {
0887:                    MutableAttributeSet specAttr = new SimpleAttributeSet();
0888:                    specAttr.addAttribute(key, value);
0889:                    return specAttr;
0890:                }
0891:
0892:                private boolean paragraphOpened() {
0893:                    return openedBlocks.contains(PARAGRAPH_TAG)
0894:                            || openedBlocks.contains(Tag.IMPLIED)
0895:                            && impliedBlockOpen;
0896:                }
0897:
0898:                private boolean handleLegend(final String legend,
0899:                        final MutableAttributeSet legendAttr) {
0900:                    final ElementSpec fieldSetSpec = findLastSpec(Tag.FIELDSET);
0901:                    FormFieldsetModel fieldSet = (FormFieldsetModel) getModel(fieldSetSpec);
0902:                    if (fieldSet == null || fieldSet.getLegend() != null) {
0903:                        return false;
0904:                    }
0905:                    if (legend != null) {
0906:                        fieldSet.setLegend(legend);
0907:                    }
0908:                    if (legendAttr != null) {
0909:                        fieldSet.setLegendAttributes(legendAttr);
0910:                    }
0911:                    return true;
0912:                }
0913:
0914:                private void setRemoveImplicitSpecs(
0915:                        final boolean implicitSpecsRemove) {
0916:                    this .implicitSpecsRemove = implicitSpecsRemove;
0917:                }
0918:
0919:                private void flushImpl(final boolean isFinal)
0920:                        throws BadLocationException {
0921:                    if (parseBuffer.isEmpty()) {
0922:                        return;
0923:                    }
0924:                    if (isCreate()) {
0925:                        ElementSpec[] specs = vectorToArray(parseBuffer);
0926:                        create(specs);
0927:                        removeDefaultBody();
0928:                    } else {
0929:                        if (needAddingPopPushSpecs()) {
0930:                            addPopPushSpecs(parseBuffer);
0931:                        }
0932:                        ElementSpec[] specs = isFinal ? trimEndSpecs(parseBuffer)
0933:                                : vectorToArray(parseBuffer);
0934:                        insert(offset, specs);
0935:                    }
0936:
0937:                    parseBuffer.clear();
0938:                }
0939:
0940:                private void removeDefaultBody() {
0941:                    Element impliedLF = getCharacterElement(getLength() - 1);
0942:                    try {
0943:                        remove(getLength() - 1, 1);
0944:                    } catch (BadLocationException e) {
0945:                    }
0946:                    BranchElement root = (BranchElement) getDefaultRootElement();
0947:                    final int oddBodyIndex = root.getElementCount() - 1;
0948:                    Element oddBody = root.getElement(oddBodyIndex);
0949:                    final Element[] emptyArray = new Element[0];
0950:                    root.replace(oddBodyIndex, 1, emptyArray);
0951:
0952:                    Element lf = getCharacterElement(getLength());
0953:                    writeLock();
0954:                    try {
0955:                        ((MutableAttributeSet) lf).removeAttributes(lf
0956:                                .getAttributes().getAttributeNames());
0957:                        ((MutableAttributeSet) lf).addAttributes(impliedLF
0958:                                .getAttributes());
0959:                    } finally {
0960:                        writeUnlock();
0961:                    }
0962:
0963:                    final DefaultDocumentEvent removeEvent = new DefaultDocumentEvent(
0964:                            oddBody.getStartOffset(), oddBody.getEndOffset()
0965:                                    - oddBody.getStartOffset(),
0966:                            EventType.REMOVE);
0967:                    removeEvent.addEdit(new ElementEdit(root, oddBodyIndex,
0968:                            new Element[] { oddBody }, emptyArray));
0969:                    fireRemoveUpdate(removeEvent);
0970:                }
0971:
0972:                private boolean isCreate() {
0973:                    return offset == 0 && insertTag == null && getLength() == 0
0974:                            && !implicitSpecsRemove;
0975:                }
0976:
0977:                private ElementSpec[] trimEndSpecs(final Vector buffer) {
0978:                    if ((implicitSpecsRemove || insertTag != null
0979:                            && insertTagFound)) {
0980:                        for (int i = 0; i < 4; i++) {
0981:                            buffer.remove(buffer.size() - 1);
0982:                        }
0983:                    }
0984:                    return vectorToArray(buffer);
0985:                }
0986:
0987:                private ElementSpec[] vectorToArray(final Vector buffer) {
0988:                    return (ElementSpec[]) buffer
0989:                            .toArray(new ElementSpec[buffer.size()]);
0990:                }
0991:
0992:                private boolean needAddingPopPushSpecs() {
0993:                    return (insertTag != null && insertTagFound || insertTag == null)
0994:                            && (popDepth != 0 || pushDepth != 0);
0995:                }
0996:
0997:                private void addContentSpec(final Tag tag, final char[] data,
0998:                        final int offset, final int length,
0999:                        final MutableAttributeSet attr,
1000:                        final boolean createImpliedBlock) {
1001:                    if (createImpliedBlock) {
1002:                        createImpliedBlock();
1003:                    }
1004:                    checkInsertTag(tag);
1005:                    addSpec(new ElementSpec(deriveSpecAttributes(tag, attr),
1006:                            ElementSpec.ContentType, data, offset, length));
1007:                }
1008:
1009:                private SimpleAttributeSet deriveSpecAttributes(final Tag tag,
1010:                        final MutableAttributeSet attr) {
1011:                    attr.removeAttribute(IMPLIED);
1012:                    attr.addAttribute(StyleConstants.NameAttribute, tag);
1013:                    return new SimpleAttributeSet(attr);
1014:                }
1015:
1016:                private void addSpec(final ElementSpec spec) {
1017:                    if (insertTagFound
1018:                            && (!implicitSpecsRemove || specsCount >= IMPLIED_HTML_DOCUMENT_START_SPECS_NUMBER)) {
1019:                        parseBuffer.add(spec);
1020:                    }
1021:                    specsCount++;
1022:                }
1023:
1024:                private void fillTagActionMap() {
1025:                    HiddenAction hiddenAction = new HiddenAction();
1026:                    CharacterAction characterAction = new CharacterAction();
1027:                    AdvancedCharacterAction advancedCharacterAction = new AdvancedCharacterAction();
1028:                    BlockAction blockAction = new BlockAction();
1029:                    ParagraphAction paragraphAction = new ParagraphAction();
1030:                    SpecialAction specialAction = new SpecialAction();
1031:                    FormAction formAction = new FormAction();
1032:
1033:                    tagActionMap.put(Tag.A, new AnchorAction());
1034:                    tagActionMap.put(Tag.ABBR, characterAction);
1035:                    tagActionMap.put(Tag.ACRONYM, characterAction);
1036:                    tagActionMap.put(Tag.ADDRESS, characterAction);
1037:                    tagActionMap.put(Tag.APPLET, new AppletAction());
1038:                    tagActionMap.put(Tag.AREA, new AreaAction());
1039:                    tagActionMap.put(Tag.B, advancedCharacterAction);
1040:                    tagActionMap.put(Tag.BASE, new BaseAction());
1041:                    tagActionMap.put(Tag.BASEFONT, characterAction);
1042:                    tagActionMap.put(Tag.BIG, characterAction);
1043:                    tagActionMap.put(Tag.BDO, characterAction);
1044:                    tagActionMap.put(Tag.BLOCKQUOTE, blockAction);
1045:                    tagActionMap.put(Tag.BODY, blockAction);
1046:                    tagActionMap.put(Tag.BR, specialAction);
1047:                    tagActionMap.put(Tag.BUTTON, formAction);
1048:                    tagActionMap.put(Tag.CAPTION, blockAction);
1049:                    tagActionMap.put(Tag.CENTER, blockAction);
1050:                    tagActionMap.put(Tag.CITE, characterAction);
1051:                    tagActionMap.put(Tag.CODE, characterAction);
1052:                    tagActionMap.put(Tag.COL, hiddenAction);
1053:                    tagActionMap.put(Tag.COLGROUP, hiddenAction);
1054:                    tagActionMap.put(Tag.DD, blockAction);
1055:                    tagActionMap.put(Tag.DFN, characterAction);
1056:                    tagActionMap.put(Tag.DEL, characterAction);
1057:                    tagActionMap.put(Tag.DIR, blockAction);
1058:                    tagActionMap.put(Tag.DIV, blockAction);
1059:                    tagActionMap.put(Tag.DL, blockAction);
1060:                    tagActionMap.put(Tag.DT, paragraphAction);
1061:                    tagActionMap.put(Tag.EM, characterAction);
1062:                    tagActionMap.put(Tag.FIELDSET, formAction);
1063:                    tagActionMap.put(Tag.FONT, new FontAction());
1064:                    tagActionMap.put(Tag.FORM, new FormTagAction());
1065:                    tagActionMap.put(Tag.FRAME, specialAction);
1066:                    tagActionMap.put(Tag.FRAMESET, blockAction);
1067:                    tagActionMap.put(Tag.H1, paragraphAction);
1068:                    tagActionMap.put(Tag.H2, paragraphAction);
1069:                    tagActionMap.put(Tag.H3, paragraphAction);
1070:                    tagActionMap.put(Tag.H4, paragraphAction);
1071:                    tagActionMap.put(Tag.H5, paragraphAction);
1072:                    tagActionMap.put(Tag.H6, paragraphAction);
1073:                    tagActionMap.put(Tag.HEAD, new HeadAction());
1074:                    tagActionMap.put(Tag.HR, specialAction);
1075:                    tagActionMap.put(Tag.HTML, blockAction);
1076:                    tagActionMap.put(Tag.I, advancedCharacterAction);
1077:                    tagActionMap.put(Tag.IFRAME, hiddenAction);
1078:                    tagActionMap.put(Tag.IMG, new ImageAction());
1079:                    tagActionMap.put(Tag.INPUT, formAction);
1080:                    tagActionMap.put(Tag.INS, characterAction);
1081:                    tagActionMap.put(Tag.ISINDEX, new IsindexAction());
1082:                    tagActionMap.put(Tag.KBD, characterAction);
1083:                    tagActionMap.put(Tag.LABEL, new LabelAction());
1084:                    tagActionMap.put(Tag.LEGEND, formAction);
1085:                    tagActionMap.put(Tag.LI, blockAction);
1086:                    tagActionMap.put(Tag.LINK, new LinkAction());
1087:                    tagActionMap.put(Tag.MAP, new MapAction());
1088:                    tagActionMap.put(Tag.MENU, blockAction);
1089:                    tagActionMap.put(Tag.META, new MetaAction());
1090:                    tagActionMap.put(Tag.NOFRAMES, blockAction);
1091:                    tagActionMap.put(Tag.NOSCRIPT, blockAction);
1092:                    tagActionMap.put(Tag.OBJECT, specialAction);
1093:                    tagActionMap.put(Tag.OL, blockAction);
1094:                    tagActionMap.put(Tag.OPTION, formAction);
1095:                    tagActionMap.put(Tag.OPTGROUP, formAction);
1096:                    tagActionMap.put(Tag.P, paragraphAction);
1097:                    tagActionMap.put(Tag.PARAM, hiddenAction);
1098:                    tagActionMap.put(Tag.PRE, new PreAction());
1099:                    tagActionMap.put(Tag.Q, characterAction);
1100:                    tagActionMap.put(Tag.SAMP, characterAction);
1101:                    tagActionMap.put(Tag.SCRIPT, new ScriptAction());
1102:                    tagActionMap.put(Tag.SELECT, formAction);
1103:                    tagActionMap.put(Tag.SMALL, characterAction);
1104:                    tagActionMap.put(Tag.STRIKE, advancedCharacterAction);
1105:                    tagActionMap.put(Tag.S, characterAction);
1106:                    tagActionMap.put(Tag.SPAN, characterAction);
1107:                    tagActionMap.put(Tag.STRONG, characterAction);
1108:                    tagActionMap.put(Tag.STYLE, new StyleAction());
1109:                    tagActionMap.put(Tag.SUB, advancedCharacterAction);
1110:                    tagActionMap.put(Tag.SUP, advancedCharacterAction);
1111:                    tagActionMap.put(Tag.TABLE, blockAction);
1112:                    tagActionMap.put(Tag.TBODY, blockAction);
1113:                    tagActionMap.put(Tag.TD, blockAction);
1114:                    tagActionMap.put(Tag.TEXTAREA, formAction);
1115:                    tagActionMap.put(Tag.TFOOT, blockAction);
1116:                    tagActionMap.put(Tag.THEAD, blockAction);
1117:                    tagActionMap.put(Tag.TH, blockAction);
1118:                    tagActionMap.put(Tag.TITLE, new TitleAction());
1119:                    tagActionMap.put(Tag.TR, blockAction);
1120:                    tagActionMap.put(Tag.TT, characterAction);
1121:                    tagActionMap.put(Tag.U, advancedCharacterAction);
1122:                    tagActionMap.put(Tag.UL, blockAction);
1123:                    tagActionMap.put(Tag.VAR, characterAction);
1124:                }
1125:
1126:                private TagAction getAction(final Tag tag) {
1127:                    TagAction action = (TagAction) tagActionMap.get(tag);
1128:                    if (action == null) {
1129:                        action = emptyAction;
1130:                    }
1131:                    return action;
1132:                }
1133:
1134:                private ElementSpec findLastSpec(final Tag tag) {
1135:                    for (int i = parseBuffer.size() - 1; i >= 0; i--) {
1136:                        ElementSpec spec = (ElementSpec) parseBuffer.get(i);
1137:                        final AttributeSet specAttr = spec.getAttributes();
1138:                        if (specAttr != null
1139:                                && specAttr.containsAttribute(
1140:                                        StyleConstants.NameAttribute, tag)) {
1141:                            return spec;
1142:                        }
1143:                    }
1144:                    return null;
1145:                }
1146:
1147:                private boolean checkInsertTag(final Tag tag) {
1148:                    if (!insertTagFound && insertTag.equals(tag)) {
1149:                        insertTagFound = true;
1150:                        skipAddingBlockSpec = true;
1151:                        addPopPushSpecs(parseBuffer);
1152:                    }
1153:
1154:                    return insertTagFound;
1155:                }
1156:
1157:                private void addPopPushSpecs(final Vector buffer) {
1158:                    addJoinPreviousSpec &= (pushDepth > 0 || popDepth > 0);
1159:                    //            boolean addNewLineTag = (pushDepth == 0 && popDepth > 0);
1160:                    //            if (addNewLineTag && !implicitSpecsRemove && offset == 0) {
1161:                    //                parseBuffer.add(0, new ElementSpec(null, ElementSpec.ContentType, new char[] {'\n'}, 0, 1));
1162:                    //            }
1163:                    for (int i = 0; i < pushDepth; i++) {
1164:                        final ElementSpec pushSpec = new ElementSpec(null,
1165:                                ElementSpec.StartTagType);
1166:                        pushSpec.setDirection(ElementSpec.JoinNextDirection);
1167:                        buffer.add(0, pushSpec);
1168:                    }
1169:                    pushDepth = 0;
1170:                    for (int i = 0; i < popDepth; i++) {
1171:                        final ElementSpec popSpec = new ElementSpec(null,
1172:                                ElementSpec.EndTagType);
1173:                        buffer.add(0, popSpec);
1174:                    }
1175:                    popDepth = 0;
1176:                    if (addJoinPreviousSpec && !implicitSpecsRemove
1177:                            && offset == 0) {
1178:                        ElementSpec joinPreviousSpec = new ElementSpec(null,
1179:                                ElementSpec.ContentType, new char[] { '\n' },
1180:                                0, 1);
1181:                        joinPreviousSpec
1182:                                .setDirection(ElementSpec.JoinPreviousDirection);
1183:                        parseBuffer.add(0, joinPreviousSpec);
1184:                        addJoinPreviousSpec = false;
1185:                    }
1186:                }
1187:            }
1188:
1189:            public abstract static class Iterator {
1190:                public abstract AttributeSet getAttributes();
1191:
1192:                public abstract int getEndOffset();
1193:
1194:                public abstract int getStartOffset();
1195:
1196:                public abstract Tag getTag();
1197:
1198:                public abstract boolean isValid();
1199:
1200:                public abstract void next();
1201:            }
1202:
1203:            public static final String AdditionalComments = "AdditionalComments";
1204:            static final String INITIAL_BASE_PROPERTY = "_initialBase_";
1205:
1206:            private static final String TARGET_TOP = "_top";
1207:            private static final String TARGET_SELF = "_self";
1208:            private static final String TARGET_PARENT = "_parent";
1209:
1210:            private static final SimpleAttributeSet DEFAULT_CHARACTER_ATTRIBUTES = new SimpleAttributeSet();
1211:
1212:            private URL base;
1213:            private Parser parser;
1214:            private boolean preservesUnknownTags = true;
1215:            private int threshold = Integer.MAX_VALUE;
1216:
1217:            static {
1218:                initDefaultCharacterAttributes();
1219:            }
1220:
1221:            public HTMLDocument(final Content c, final StyleSheet styles) {
1222:                super (c, styles);
1223:            }
1224:
1225:            public HTMLDocument(final StyleSheet styles) {
1226:                super (styles);
1227:            }
1228:
1229:            public HTMLDocument() {
1230:                super (new StyleSheet());
1231:            }
1232:
1233:            public void setBase(final URL base) {
1234:                this .base = base;
1235:                getStyleSheet().setBase(base);
1236:            }
1237:
1238:            public URL getBase() {
1239:                return base;
1240:            }
1241:
1242:            public void setParser(final HTMLEditorKit.Parser parser) {
1243:                this .parser = parser;
1244:            }
1245:
1246:            public HTMLEditorKit.Parser getParser() {
1247:                return parser;
1248:            }
1249:
1250:            public void setPreservesUnknownTags(final boolean preservesTags) {
1251:                preservesUnknownTags = preservesTags;
1252:            }
1253:
1254:            public boolean getPreservesUnknownTags() {
1255:                return preservesUnknownTags;
1256:            }
1257:
1258:            public void setTokenThreshold(final int threshold) {
1259:                this .threshold = threshold;
1260:            }
1261:
1262:            public int getTokenThreshold() {
1263:                return threshold;
1264:            }
1265:
1266:            public Element getElement(final Element e, final Object attribute,
1267:                    final Object value) {
1268:                final ElementIterator it = new ElementIterator(e);
1269:                while (it.next() != null) {
1270:                    final Element current = it.current();
1271:                    if (current.getAttributes().containsAttribute(attribute,
1272:                            value)) {
1273:                        return current;
1274:                    }
1275:                }
1276:                return null;
1277:            }
1278:
1279:            public Element getElement(final String id) {
1280:                return getElement(getDefaultRootElement(), HTML.Attribute.ID,
1281:                        id);
1282:            }
1283:
1284:            public Iterator getIterator(final Tag tag) {
1285:                return new TagIterator(tag, this );
1286:            }
1287:
1288:            public HTMLEditorKit.ParserCallback getReader(final int pos,
1289:                    final int popDepth, final int pushDepth, final Tag insertTag) {
1290:                return new HTMLReader(pos, popDepth, pushDepth, insertTag);
1291:            }
1292:
1293:            public HTMLEditorKit.ParserCallback getReader(final int pos) {
1294:                return new HTMLReader(pos);
1295:            }
1296:
1297:            public StyleSheet getStyleSheet() {
1298:                return (StyleSheet) getAttributeContext();
1299:            }
1300:
1301:            public void insertBeforeEnd(final Element elem,
1302:                    final String htmlText) throws BadLocationException,
1303:                    IOException {
1304:                checkParser();
1305:                checkLeaf(elem);
1306:                int offset = isParagraph(elem) ? elem.getEndOffset() - 1 : elem
1307:                        .getEndOffset();
1308:                insertHTMLText(elem, offset, htmlText);
1309:            }
1310:
1311:            private boolean isParagraph(final Element elem) {
1312:                final AttributeSet attr = elem.getAttributes();
1313:                return attr != null
1314:                        && Tag.P.equals(attr
1315:                                .getAttribute(StyleConstants.NameAttribute));
1316:            }
1317:
1318:            public void insertAfterEnd(final Element elem, final String htmlText)
1319:                    throws BadLocationException, IOException {
1320:                checkParser();
1321:                if (elem == null) {
1322:                    return;
1323:                }
1324:                int offset = elem.getEndOffset() > getLength() ? getLength()
1325:                        : elem.getEndOffset();
1326:                insertHTMLText(elem.getParentElement(), offset, htmlText);
1327:            }
1328:
1329:            public void insertBeforeStart(final Element elem,
1330:                    final String htmlText) throws BadLocationException,
1331:                    IOException {
1332:                checkParser();
1333:                if (elem == null) {
1334:                    return;
1335:                }
1336:                insertHTMLText(elem.getParentElement(), elem.getStartOffset(),
1337:                        htmlText);
1338:            }
1339:
1340:            public void insertAfterStart(final Element elem,
1341:                    final String htmlText) throws BadLocationException,
1342:                    IOException {
1343:                checkParser();
1344:                checkLeaf(elem);
1345:                insertHTMLText(elem, elem.getStartOffset(), htmlText);
1346:            }
1347:
1348:            public void setInnerHTML(final Element elem, final String htmlText)
1349:                    throws BadLocationException, IOException {
1350:                checkParser();
1351:                if (elem == null) {
1352:                    return;
1353:                }
1354:                checkLeaf(elem);
1355:
1356:                int numRemovingElements = elem.getElementCount();
1357:                insertHTMLText(elem, elem.getStartOffset(), htmlText);
1358:                removeElements(elem, elem.getElementCount()
1359:                        - numRemovingElements, numRemovingElements);
1360:                throw new UnsupportedOperationException(Messages
1361:                        .getString("swing.27")); //$NON-NLS-1$
1362:            }
1363:
1364:            public void setOuterHTML(final Element elem, final String htmlText)
1365:                    throws BadLocationException, IOException {
1366:                checkParser();
1367:                if (elem == null) {
1368:                    return;
1369:                }
1370:
1371:                int length = elem.getEndOffset() - elem.getStartOffset() - 1;
1372:                final BranchElement parent = (BranchElement) elem
1373:                        .getParentElement();
1374:                final int indexBefore = getElementIndex(parent, elem);
1375:                final int numElementsBefore = parent.getElementCount();
1376:                insertHTMLText(elem.getParentElement(), elem.getStartOffset(),
1377:                        htmlText);
1378:                removeElements(parent, indexBefore
1379:                        + (parent.getElementCount() - numElementsBefore), 1);
1380:                throw new UnsupportedOperationException(Messages
1381:                        .getString("swing.27")); //$NON-NLS-1$
1382:            }
1383:
1384:            public void processHTMLFrameHyperlinkEvent(
1385:                    final HTMLFrameHyperlinkEvent event) {
1386:                final String target = event.getTarget();
1387:
1388:                if (TARGET_TOP.equals(target)) {
1389:                    return;
1390:                }
1391:
1392:                final Element source = event.getSourceElement();
1393:                final String src = event.getURL().toString();
1394:                if (source != null && TARGET_SELF.equals(target)) {
1395:                    processTarget(source, src);
1396:                } else if (source != null && TARGET_PARENT.equals(target)) {
1397:                    final Element parent = source.getParentElement();
1398:                    if (getParser() == null) {
1399:                        setParser(new ParserDelegator());
1400:                    }
1401:                    try {
1402:                        setOuterHTML(parent, "<frame src=\"" + src + "\">");
1403:                    } catch (BadLocationException e) {
1404:                    } catch (IOException e) {
1405:                    }
1406:                } else {
1407:                    final ElementIterator frameIterator = new ElementIterator(
1408:                            getDefaultRootElement());
1409:                    if (frameIterator != null) {
1410:                        while (frameIterator.next() != null) {
1411:                            final Element element = frameIterator.current();
1412:                            if (Tag.FRAME.equals(element.getName())
1413:                                    && element
1414:                                            .getAttributes()
1415:                                            .containsAttribute(
1416:                                                    HTML.Attribute.NAME, target)) {
1417:
1418:                                processTarget(element, src);
1419:                            }
1420:                        }
1421:                    }
1422:                }
1423:            }
1424:
1425:            protected AbstractElement createDefaultRoot() {
1426:                final BlockElement root = new BlockElement(null, null);
1427:                writeLock();
1428:                try {
1429:                    root.addAttribute(StyleConstants.NameAttribute, Tag.HTML);
1430:                    AttributeSet attr = getAttributeContext().getEmptySet();
1431:                    final BranchElement body = (BranchElement) createBranchElement(
1432:                            root, null);
1433:                    body.addAttribute(StyleConstants.NameAttribute, Tag.BODY);
1434:
1435:                    final BranchElement p = (BranchElement) createBranchElement(
1436:                            body, null);
1437:                    p.addAttribute(StyleConstants.NameAttribute, Tag.P);
1438:                    p.addAttribute(CSS.Attribute.MARGIN_TOP,
1439:                            CSS.Attribute.MARGIN_TOP.getDefaultValue());
1440:
1441:                    final LeafElement content = (LeafElement) createLeafElement(
1442:                            p, null, getStartPosition().getOffset(),
1443:                            getEndPosition().getOffset());
1444:                    content.addAttribute(StyleConstants.NameAttribute,
1445:                            Tag.CONTENT);
1446:                    p.replace(0, 0, new Element[] { content });
1447:                    body.replace(0, 0, new Element[] { p });
1448:                    root.replace(0, 0, new Element[] { body });
1449:                } finally {
1450:                    writeUnlock();
1451:                }
1452:                return root;
1453:            }
1454:
1455:            protected Element createLeafElement(final Element parent,
1456:                    final AttributeSet a, final int start, final int end) {
1457:                return new RunElement(parent, a, start, end);
1458:            }
1459:
1460:            protected Element createBranchElement(final Element parent,
1461:                    final AttributeSet attr) {
1462:                return new BlockElement(parent, attr);
1463:            }
1464:
1465:            protected void insertUpdate(final DefaultDocumentEvent event,
1466:                    final AttributeSet attrs) {
1467:                AttributeSet contentAttr = attrs;
1468:                if (contentAttr == null) {
1469:                    contentAttr = new SimpleAttributeSet();
1470:                    ((SimpleAttributeSet) contentAttr).addAttribute(
1471:                            StyleConstants.NameAttribute, Tag.CONTENT);
1472:                }
1473:                super .insertUpdate(event, contentAttr);
1474:            }
1475:
1476:            private void processTarget(final Element target, final String src) {
1477:                final MutableAttributeSet targetAttr = (MutableAttributeSet) target
1478:                        .getAttributes();
1479:                writeLock();
1480:                try {
1481:                    targetAttr.addAttribute(HTML.Attribute.SRC, src);
1482:                } finally {
1483:                    writeUnlock();
1484:                }
1485:                fireChangedUpdate(new DefaultDocumentEvent(target
1486:                        .getStartOffset(), target.getEndOffset()
1487:                        - target.getStartOffset(), EventType.CHANGE));
1488:            }
1489:
1490:            private void removeElements(final Element parent,
1491:                    final int startRemoveIndex, final int numRemoved) {
1492:                final Element[] emptyArray = new Element[0];
1493:                final Element[] removedArray = new Element[numRemoved];
1494:                final BranchElement branch = (BranchElement) parent;
1495:                final int numElements = branch.getElementCount();
1496:                for (int i = 0; i < numRemoved; i++) {
1497:                    removedArray[i] = branch.getElement(startRemoveIndex + i);
1498:                }
1499:                branch.replace(startRemoveIndex, numRemoved, emptyArray);
1500:                final int eventLength = removedArray[numRemoved - 1]
1501:                        .getEndOffset()
1502:                        - removedArray[0].getStartOffset();
1503:                DefaultDocumentEvent removeEvent = new DefaultDocumentEvent(
1504:                        removedArray[0].getStartOffset(), eventLength,
1505:                        EventType.REMOVE);
1506:                removeEvent.addEdit(new ElementEdit(parent, startRemoveIndex,
1507:                        removedArray, emptyArray));
1508:                fireRemoveUpdate(removeEvent);
1509:            }
1510:
1511:            private void insertHTMLText(final Element elem, final int offset,
1512:                    final String htmlText) throws IOException {
1513:                Element preceedBranch = getInsertionStartElement(offset - 1);
1514:                int pop = -1;
1515:                int push = -1;
1516:                do {
1517:                    pop++;
1518:                    preceedBranch = preceedBranch.getParentElement();
1519:                    push = getAncestorDepth(preceedBranch, elem);
1520:                } while (preceedBranch != null && push < 0);
1521:                if (push == -1) {
1522:                    return;
1523:                }
1524:
1525:                final HTMLReader reader = new HTMLReader(offset, pop, push,
1526:                        null);
1527:                reader.setRemoveImplicitSpecs(true);
1528:                parser.parse(new StringReader(htmlText), reader, true);
1529:                try {
1530:                    reader.flush();
1531:                } catch (BadLocationException e) {
1532:                    e.printStackTrace();
1533:                }
1534:            }
1535:
1536:            private void checkParser() {
1537:                if (parser == null) {
1538:                    throw new IllegalStateException(Messages
1539:                            .getString("swing.9D")); //$NON-NLS-1$
1540:                }
1541:            }
1542:
1543:            private void checkLeaf(final Element elem) {
1544:                if (elem.isLeaf()) {
1545:                    throw new IllegalArgumentException(Messages
1546:                            .getString("swing.9E")); //$NON-NLS-1$
1547:                }
1548:            }
1549:
1550:            private int getElementIndex(final BranchElement branch,
1551:                    final Element child) {
1552:                final int numChildren = branch.getElementCount();
1553:                for (int i = 0; i < numChildren; i++) {
1554:                    if (branch.getElement(i) == child) {
1555:                        return i;
1556:                    }
1557:                }
1558:                return -1;
1559:            }
1560:
1561:            private Element getInsertionStartElement(final int offset) {
1562:                Element result = getDefaultRootElement();
1563:                do {
1564:                    result = result.getElement(result.getElementIndex(offset));
1565:                } while (!result.isLeaf());
1566:
1567:                return result;
1568:            }
1569:
1570:            private int getAncestorDepth(final Element elem, final Element child) {
1571:                int depth = 0;
1572:                Element parent = child;
1573:                while (parent != null) {
1574:                    if (elem == parent) {
1575:                        return depth;
1576:                    }
1577:                    depth++;
1578:                    parent = parent.getParentElement();
1579:                }
1580:                return -1;
1581:            }
1582:
1583:            private static void initDefaultCharacterAttributes() {
1584:                addDefaultCSSAttribute(Tag.B, CSS.Attribute.FONT_WEIGHT, "bold");
1585:                addDefaultCSSAttribute(Tag.I, CSS.Attribute.FONT_STYLE,
1586:                        "italic");
1587:                addDefaultCSSAttribute(Tag.STRIKE,
1588:                        CSS.Attribute.TEXT_DECORATION, "line-through");
1589:                addDefaultCSSAttribute(Tag.SUB, CSS.Attribute.VERTICAL_ALIGN,
1590:                        "sub");
1591:                addDefaultCSSAttribute(Tag.SUP, CSS.Attribute.VERTICAL_ALIGN,
1592:                        "super");
1593:                addDefaultCSSAttribute(Tag.U, CSS.Attribute.TEXT_DECORATION,
1594:                        "underline");
1595:                addDefaultCSSAttribute(Tag.PRE, CSS.Attribute.WHITE_SPACE,
1596:                        "pre");
1597:            }
1598:
1599:            private static void addDefaultCSSAttribute(final Tag tag,
1600:                    final CSS.Attribute attr, final String value) {
1601:                SimpleAttributeSet attrSet = new SimpleAttributeSet();
1602:                attrSet.addAttribute(attr, attr.getConverter().toCSS(value));
1603:                DEFAULT_CHARACTER_ATTRIBUTES.addAttribute(tag, attrSet);
1604:            }
1605:
1606:            private static SimpleAttributeSet getDefaultCSSAttributes(
1607:                    final Tag tag) {
1608:                return (SimpleAttributeSet) DEFAULT_CHARACTER_ATTRIBUTES
1609:                        .getAttribute(tag);
1610:            }
1611:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.