Source for javax.swing.text.html.HTMLDocument

   1: /* HTMLDocument.java --
   2:    Copyright (C) 2005  Free Software Foundation, Inc.
   3: 
   4: This file is part of GNU Classpath.
   5: 
   6: GNU Classpath is free software; you can redistribute it and/or modify
   7: it under the terms of the GNU General Public License as published by
   8: the Free Software Foundation; either version 2, or (at your option)
   9: any later version.
  10: 
  11: GNU Classpath is distributed in the hope that it will be useful, but
  12: WITHOUT ANY WARRANTY; without even the implied warranty of
  13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14: General Public License for more details.
  15: 
  16: You should have received a copy of the GNU General Public License
  17: along with GNU Classpath; see the file COPYING.  If not, write to the
  18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  19: 02110-1301 USA.
  20: 
  21: Linking this library statically or dynamically with other modules is
  22: making a combined work based on this library.  Thus, the terms and
  23: conditions of the GNU General Public License cover the whole
  24: combination.
  25: 
  26: As a special exception, the copyright holders of this library give you
  27: permission to link this library with independent modules to produce an
  28: executable, regardless of the license terms of these independent
  29: modules, and to copy and distribute the resulting executable under
  30: terms of your choice, provided that you also meet, for each linked
  31: independent module, the terms and conditions of the license of that
  32: module.  An independent module is a module which is not derived from
  33: or based on this library.  If you modify this library, you may extend
  34: this exception to your version of the library, but you are not
  35: obligated to do so.  If you do not wish to do so, delete this
  36: exception statement from your version. */
  37: 
  38: 
  39: package javax.swing.text.html;
  40: 
  41: import java.net.URL;
  42: 
  43: import java.io.IOException;
  44: 
  45: import java.util.HashMap;
  46: import java.util.Stack;
  47: import java.util.Vector;
  48: 
  49: import javax.swing.event.DocumentEvent;
  50: import javax.swing.event.UndoableEditEvent;
  51: import javax.swing.text.AbstractDocument;
  52: import javax.swing.text.AttributeSet;
  53: import javax.swing.text.BadLocationException;
  54: import javax.swing.text.DefaultStyledDocument;
  55: import javax.swing.text.Element;
  56: import javax.swing.text.ElementIterator;
  57: import javax.swing.text.GapContent;
  58: import javax.swing.text.MutableAttributeSet;
  59: import javax.swing.text.SimpleAttributeSet;
  60: import javax.swing.text.StyleConstants;
  61: import javax.swing.text.html.HTML.Tag;
  62: 
  63: /**
  64:  * TODO: Add more comments here 
  65:  * 
  66:  * @author Audrius Meskauskas, Lithuania (AudriusA@Bioinformatics.org)
  67:  * @author Anthony Balkissoon (abalkiss@redhat.com)
  68:  * @author Lillian Angel (langel@redhat.com)
  69:  */
  70: public class HTMLDocument extends DefaultStyledDocument
  71: {
  72:   /** A key for document properies.  The value for the key is
  73:    * a Vector of Strings of comments not found in the body.
  74:    */  
  75:   public static final String AdditionalComments = "AdditionalComments";
  76:   URL baseURL = null;
  77:   boolean preservesUnknownTags = true;
  78:   int tokenThreshold = Integer.MAX_VALUE;
  79:   HTMLEditorKit.Parser parser;
  80:   StyleSheet styleSheet;
  81:   AbstractDocument.Content content;
  82:   
  83:   /**
  84:    * Constructs an HTML document using the default buffer size and a default
  85:    * StyleSheet.
  86:    */
  87:   public HTMLDocument()
  88:   {
  89:     this(null);
  90:   }
  91:   
  92:   /**
  93:    * Constructs an HTML document with the default content storage 
  94:    * implementation and the specified style/attribute storage mechanism.
  95:    * 
  96:    * @param styles - the style sheet
  97:    */
  98:   public HTMLDocument(StyleSheet styles)
  99:   {
 100:    this(new GapContent(BUFFER_SIZE_DEFAULT), styles);
 101:   }
 102:   
 103:   /**
 104:    * Constructs an HTML document with the given content storage implementation 
 105:    * and the given style/attribute storage mechanism.
 106:    * 
 107:    * @param c - the document's content
 108:    * @param styles - the style sheet
 109:    */
 110:   public HTMLDocument(AbstractDocument.Content c, StyleSheet styles)
 111:   {
 112:     this.content = c;
 113:     if (styles == null)
 114:       {
 115:         styles = new StyleSheet();
 116:         styles.importStyleSheet(getClass().getResource(HTMLEditorKit.
 117:                                                        DEFAULT_CSS));
 118:       }
 119:     this.styleSheet = styles;
 120:   }
 121:   
 122:   /**
 123:    * Gets the style sheet with the document display rules (CSS) that were specified 
 124:    * in the HTML document.
 125:    * 
 126:    * @return - the style sheet
 127:    */
 128:   public StyleSheet getStyleSheet()
 129:   {
 130:     return styleSheet;
 131:   }
 132:   
 133:   /**
 134:    * Replaces the contents of the document with the given element specifications.
 135:    * This is called before insert if the loading is done in bursts. This is the
 136:    * only method called if loading the document entirely in one burst.
 137:    * 
 138:    * @param data - the date that replaces the content of the document
 139:    */
 140:   protected void create(DefaultStyledDocument.ElementSpec[] data)
 141:   {
 142:     // FIXME: Not implemented
 143:     System.out.println("create not implemented");
 144:     super.create(data);
 145:   }
 146:   
 147:   /**
 148:    * This method creates a root element for the new document.
 149:    * 
 150:    * @return the new default root
 151:    */
 152:   protected AbstractDocument.AbstractElement createDefaultRoot()
 153:   {
 154:     // FIXME: Not implemented
 155:     System.out.println("createDefaultRoot not implemented");
 156:     return super.createDefaultRoot();
 157:   }
 158:   
 159:   /**
 160:    * This method returns an HTMLDocument.RunElement object attached to
 161:    * parent representing a run of text from p0 to p1. The run has 
 162:    * attributes described by a.
 163:    * 
 164:    * @param parent - the parent element
 165:    * @param a - the attributes for the element
 166:    * @param p0 - the beginning of the range >= 0
 167:    * @param p1 - the end of the range >= p0
 168:    * @return the new element
 169:    */
 170:   protected Element createLeafElement(Element parent, AttributeSet a, int p0,
 171:                                       int p1)
 172:   {
 173:     // FIXME: Not implemented
 174:     System.out.println("createLeafElement not implemented");
 175:     return super.createLeafElement(parent, a, p0, p1);
 176:   }
 177: 
 178:   /** This method returns an HTMLDocument.BlockElement object representing the
 179:    * attribute set a and attached to parent.
 180:    * 
 181:    * @param parent - the parent element
 182:    * @param a - the attributes for the element
 183:    * @return the new element
 184:    */
 185:   protected Element createBranchElement(Element parent, AttributeSet a)
 186:   {
 187:     // FIXME: Not implemented
 188:     System.out.println("createBranchElement not implemented");
 189:     return super.createBranchElement(parent, a);
 190:   }
 191:   
 192:   /**
 193:    * Inserts new elements in bulk. This is how elements get created in the
 194:    * document. The parsing determines what structure is needed and creates the
 195:    * specification as a set of tokens that describe the edit while leaving the
 196:    * document free of a write-lock. This method can then be called in bursts by
 197:    * the reader to acquire a write-lock for a shorter duration (i.e. while the
 198:    * document is actually being altered). 
 199:    * 
 200:    * @param offset - the starting offset 
 201:    * @param data - the element data
 202:    * @throws BadLocationException - if the given position does not
 203:    * represent a valid location in the associated document.
 204:    */
 205:   protected void insert(int offset, DefaultStyledDocument.ElementSpec[] data)
 206:     throws BadLocationException
 207:     {
 208:       super.insert(offset, data);
 209:     }
 210:   
 211:   /**
 212:    * Updates document structure as a result of text insertion. This will happen
 213:    * within a write lock. This implementation simply parses the inserted content
 214:    * for line breaks and builds up a set of instructions for the element buffer.
 215:    * 
 216:    * @param chng - a description of the document change
 217:    * @param attr - the attributes
 218:    */
 219:   protected void insertUpdate(AbstractDocument.DefaultDocumentEvent chng, 
 220:                               AttributeSet attr)
 221:   {
 222:     // FIXME: Not implemented
 223:     System.out.println("insertUpdate not implemented");
 224:     super.insertUpdate(chng, attr);    
 225:   }
 226:   
 227:   /**
 228:    * Returns the parser used by this HTMLDocument to insert HTML.
 229:    * 
 230:    * @return the parser used by this HTMLDocument to insert HTML.
 231:    */
 232:   public HTMLEditorKit.Parser getParser()
 233:   {
 234:     return parser; 
 235:   }
 236:   
 237:   /**
 238:    * Sets the parser used by this HTMLDocument to insert HTML.
 239:    * 
 240:    * @param p the parser to use
 241:    */
 242:   public void setParser (HTMLEditorKit.Parser p)
 243:   {
 244:     parser = p;
 245:   }
 246:   /**
 247:    * Sets the number of tokens to buffer before trying to display the
 248:    * Document.
 249:    * 
 250:    * @param n the number of tokens to buffer
 251:    */
 252:   public void setTokenThreshold (int n)
 253:   {
 254:     tokenThreshold = n;
 255:   }
 256:   
 257:   /**
 258:    * Returns the number of tokens that are buffered before the document
 259:    * is rendered.
 260:    * 
 261:    * @return the number of tokens buffered
 262:    */
 263:   public int getTokenThreshold ()
 264:   {
 265:     return tokenThreshold;
 266:   }
 267:   
 268:   /**
 269:    * Returns the location against which to resolve relative URLs.
 270:    * This is the document's URL if the document was loaded from a URL.
 271:    * If a <code>base</code> tag is found, it will be used.
 272:    * @return the base URL
 273:    */
 274:   public URL getBase()
 275:   {
 276:     return baseURL;
 277:   }
 278:   
 279:   /**
 280:    * Sets the location against which to resolve relative URLs.
 281:    * @param u the new base URL
 282:    */
 283:   public void setBase(URL u)
 284:   {
 285:     baseURL = u;
 286:     styleSheet.setBase(u);
 287:   }
 288:   
 289:   /**
 290:    * Returns whether or not the parser preserves unknown HTML tags.
 291:    * @return true if the parser preserves unknown tags
 292:    */
 293:   public boolean getPreservesUnknownTags()
 294:   {
 295:     return preservesUnknownTags;
 296:   }
 297:   
 298:   /**
 299:    * Sets the behaviour of the parser when it encounters unknown HTML tags.
 300:    * @param preservesTags true if the parser should preserve unknown tags.
 301:    */
 302:   public void setPreservesUnknownTags(boolean preservesTags)
 303:   {
 304:     preservesUnknownTags = preservesTags;
 305:   }
 306:   
 307:   /**
 308:    * An iterator to iterate through LeafElements in the document.
 309:    */
 310:   class LeafIterator extends Iterator
 311:   {
 312:     HTML.Tag tag;
 313:     HTMLDocument doc;
 314:     ElementIterator it;
 315: 
 316:     public LeafIterator (HTML.Tag t, HTMLDocument d)
 317:     {
 318:       doc = d;
 319:       tag = t;
 320:       it = new ElementIterator(doc);
 321:     }
 322:     
 323:     /**
 324:      * Return the attributes for the tag associated with this iteartor
 325:      * @return the AttributeSet
 326:      */
 327:     public AttributeSet getAttributes()
 328:     {
 329:       if (it.current() != null)
 330:         return it.current().getAttributes();
 331:       return null;
 332:     }
 333: 
 334:     /**
 335:      * Get the end of the range for the current occurrence of the tag
 336:      * being defined and having the same attributes.
 337:      * @return the end of the range
 338:      */
 339:     public int getEndOffset()
 340:     {
 341:       if (it.current() != null)
 342:         return it.current().getEndOffset();
 343:       return -1;
 344:     }
 345: 
 346:     /**
 347:      * Get the start of the range for the current occurrence of the tag
 348:      * being defined and having the same attributes.
 349:      * @return the start of the range (-1 if it can't be found).
 350:      */
 351: 
 352:     public int getStartOffset()
 353:     {
 354:       if (it.current() != null)
 355:         return it.current().getStartOffset();
 356:       return -1;
 357:     }
 358: 
 359:     /**
 360:      * Advance the iterator to the next LeafElement .
 361:      */
 362:     public void next()
 363:     {
 364:       it.next();
 365:       while (it.current()!= null && !it.current().isLeaf())
 366:         it.next();
 367:     }
 368: 
 369:     /**
 370:      * Indicates whether or not the iterator currently represents an occurrence
 371:      * of the tag.
 372:      * @return true if the iterator currently represents an occurrence of the
 373:      * tag.
 374:      */
 375:     public boolean isValid()
 376:     {
 377:       return it.current() != null;
 378:     }
 379: 
 380:     /**
 381:      * Type of tag for this iterator.
 382:      */
 383:     public Tag getTag()
 384:     {
 385:       return tag;
 386:     }
 387: 
 388:   }
 389: 
 390:   public void processHTMLFrameHyperlinkEvent(HTMLFrameHyperlinkEvent event)
 391:   {
 392:     // TODO: Implement this properly.
 393:   }
 394:   
 395:   /**
 396:    * Gets an iterator for the given HTML.Tag.
 397:    * @param t the requested HTML.Tag
 398:    * @return the Iterator
 399:    */
 400:   public HTMLDocument.Iterator getIterator (HTML.Tag t)
 401:   {
 402:     return new HTMLDocument.LeafIterator(t, this);
 403:   }
 404:   
 405:   /**
 406:    * An iterator over a particular type of tag.
 407:    */
 408:   public abstract static class Iterator
 409:   {
 410:     /**
 411:      * Return the attribute set for this tag.
 412:      * @return the <code>AttributeSet</code> (null if none found).
 413:      */
 414:     public abstract AttributeSet getAttributes();
 415:     
 416:     /**
 417:      * Get the end of the range for the current occurrence of the tag
 418:      * being defined and having the same attributes.
 419:      * @return the end of the range
 420:      */
 421:     public abstract int getEndOffset();
 422:     
 423:     /**
 424:      * Get the start of the range for the current occurrence of the tag
 425:      * being defined and having the same attributes.
 426:      * @return the start of the range (-1 if it can't be found).
 427:      */
 428:     public abstract int getStartOffset();
 429:     
 430:     /**
 431:      * Move the iterator forward.
 432:      */
 433:     public abstract void next();
 434:     
 435:     /**
 436:      * Indicates whether or not the iterator currently represents an occurrence
 437:      * of the tag.
 438:      * @return true if the iterator currently represents an occurrence of the
 439:      * tag.
 440:      */
 441:     public abstract boolean isValid();
 442:     
 443:     /**
 444:      * Type of tag this iterator represents.
 445:      * @return the tag.
 446:      */
 447:     public abstract HTML.Tag getTag();
 448:   }
 449:   
 450:   public class BlockElement extends AbstractDocument.BranchElement
 451:   {
 452:     public BlockElement (Element parent, AttributeSet a)
 453:     {
 454:       super (parent, a);
 455:     }
 456:     
 457:     /**
 458:      * Gets the resolving parent.  Since HTML attributes are not 
 459:      * inherited at the model level, this returns null.
 460:      */
 461:     public AttributeSet getResolveParent()
 462:     {
 463:       return null;
 464:     }
 465:     
 466:     /**
 467:      * Gets the name of the element.
 468:      * 
 469:      * @return the name of the element if it exists, null otherwise.
 470:      */
 471:     public String getName()
 472:     {
 473:       return (String) getAttribute(StyleConstants.NameAttribute); 
 474:     }
 475:   }
 476:   
 477:   /**
 478:    * RunElement represents a section of text that has a set of 
 479:    * HTML character level attributes assigned to it.
 480:    */
 481:   public class RunElement extends AbstractDocument.LeafElement
 482:   {
 483:     
 484:     /**
 485:      * Constructs an element that has no children. It represents content
 486:      * within the document.
 487:      * 
 488:      * @param parent - parent of this
 489:      * @param a - elements attributes
 490:      * @param start - the start offset >= 0
 491:      * @param end - the end offset 
 492:      */
 493:     public RunElement(Element parent, AttributeSet a, int start, int end)
 494:     {
 495:       super(parent, a, start, end);
 496:     }
 497:     
 498:     /**
 499:      * Gets the name of the element.
 500:      * 
 501:      * @return the name of the element if it exists, null otherwise.
 502:      */
 503:     public String getName()
 504:     {
 505:       return (String) getAttribute(StyleConstants.NameAttribute);      
 506:     }
 507:     
 508:     /**
 509:      * Gets the resolving parent. HTML attributes do not inherit at the
 510:      * model level, so this method returns null.
 511:      * 
 512:      * @return null
 513:      */
 514:     public AttributeSet getResolveParent()
 515:     {
 516:       return null;
 517:     }
 518:   }
 519:   
 520:   /**
 521:    * A reader to load an HTMLDocument with HTML structure.
 522:    * 
 523:    * @author Anthony Balkissoon abalkiss at redhat dot com
 524:    */
 525:   public class HTMLReader extends HTMLEditorKit.ParserCallback
 526:   {    
 527:     /** Holds the current character attribute set **/
 528:     protected MutableAttributeSet charAttr = new SimpleAttributeSet();
 529:     
 530:     protected Vector parseBuffer = new Vector();
 531:     
 532:     /** A stack for character attribute sets **/
 533:     Stack charAttrStack = new Stack();
 534:     
 535:     /** A mapping between HTML.Tag objects and the actions that handle them **/
 536:     HashMap tagToAction;
 537:     
 538:     /** Tells us whether we've received the '</html>' tag yet **/
 539:     boolean endHTMLEncountered = false;
 540:     
 541:     /** Variables related to the constructor with explicit insertTag **/
 542:     int popDepth, pushDepth, offset;
 543:     HTML.Tag insertTag;
 544:     boolean insertTagEncountered = false;
 545:     
 546:     /** A temporary variable that helps with the printing out of debug information **/
 547:     boolean debug = false;
 548:     
 549:     void print (String line)
 550:     {
 551:       if (debug)
 552:         System.out.println (line);
 553:     }
 554:     
 555:     public class TagAction
 556:     {
 557:       /**
 558:        * This method is called when a start tag is seen for one of the types
 559:        * of tags associated with this Action.  By default this does nothing.
 560:        */
 561:       public void start(HTML.Tag t, MutableAttributeSet a)
 562:       {
 563:         // Nothing to do here.
 564:       }
 565:       
 566:       /**
 567:        * Called when an end tag is seen for one of the types of tags associated
 568:        * with this Action.  By default does nothing.
 569:        */
 570:       public void end(HTML.Tag t)
 571:       {
 572:         // Nothing to do here.
 573:       }
 574:     }
 575: 
 576:     public class BlockAction extends TagAction
 577:     {      
 578:       /**
 579:        * This method is called when a start tag is seen for one of the types
 580:        * of tags associated with this Action.
 581:        */
 582:       public void start(HTML.Tag t, MutableAttributeSet a)
 583:       {
 584:         // Tell the parse buffer to open a new block for this tag.
 585:         blockOpen(t, a);
 586:       }
 587:       
 588:       /**
 589:        * Called when an end tag is seen for one of the types of tags associated
 590:        * with this Action.
 591:        */
 592:       public void end(HTML.Tag t)
 593:       {
 594:         // Tell the parse buffer to close this block.
 595:         blockClose(t);
 596:       }
 597:     }
 598:     
 599:     public class CharacterAction extends TagAction
 600:     {
 601:       /**
 602:        * This method is called when a start tag is seen for one of the types
 603:        * of tags associated with this Action.
 604:        */
 605:       public void start(HTML.Tag t, MutableAttributeSet a)
 606:       {
 607:         // Put the old attribute set on the stack.
 608:         pushCharacterStyle();
 609:         
 610:         // And create the new one by adding the attributes in <code>a</code>.
 611:         if (a != null)
 612:           charAttr.addAttribute(t, a.copyAttributes());          
 613:       }
 614:       
 615:       /**
 616:        * Called when an end tag is seen for one of the types of tags associated
 617:        * with this Action.
 618:        */
 619:       public void end(HTML.Tag t)
 620:       {
 621:         popCharacterStyle();
 622:       } 
 623:     }
 624:     
 625:     public class FormAction extends SpecialAction
 626:     {
 627:       /**
 628:        * This method is called when a start tag is seen for one of the types
 629:        * of tags associated with this Action.
 630:        */
 631:       public void start(HTML.Tag t, MutableAttributeSet a)
 632:       {
 633:         // FIXME: Implement.
 634:         print ("FormAction.start not implemented");
 635:       }
 636:       
 637:       /**
 638:        * Called when an end tag is seen for one of the types of tags associated
 639:        * with this Action.
 640:        */
 641:       public void end(HTML.Tag t)
 642:       {
 643:         // FIXME: Implement.
 644:         print ("FormAction.end not implemented");
 645:       } 
 646:     }
 647:     
 648:     public class HiddenAction extends TagAction
 649:     {
 650:       /**
 651:        * This method is called when a start tag is seen for one of the types
 652:        * of tags associated with this Action.
 653:        */
 654:       public void start(HTML.Tag t, MutableAttributeSet a)
 655:       {
 656:         // FIXME: Implement.
 657:         print ("HiddenAction.start not implemented");
 658:       }
 659:       
 660:       /**
 661:        * Called when an end tag is seen for one of the types of tags associated
 662:        * with this Action.
 663:        */
 664:       public void end(HTML.Tag t)
 665:       {
 666:         // FIXME: Implement.
 667:         print ("HiddenAction.end not implemented");
 668:       } 
 669:     }
 670:     
 671:     public class IsindexAction extends TagAction
 672:     {
 673:       /**
 674:        * This method is called when a start tag is seen for one of the types
 675:        * of tags associated with this Action.
 676:        */
 677:       public void start(HTML.Tag t, MutableAttributeSet a)
 678:       {
 679:         // FIXME: Implement.
 680:         print ("IsindexAction.start not implemented");
 681:       }
 682:       
 683:       /**
 684:        * Called when an end tag is seen for one of the types of tags associated
 685:        * with this Action.
 686:        */
 687:       public void end(HTML.Tag t)
 688:       {
 689:         // FIXME: Implement.
 690:         print ("IsindexAction.end not implemented");
 691:       } 
 692:     }
 693:     
 694:     public class ParagraphAction extends BlockAction
 695:     {
 696:       /**
 697:        * This method is called when a start tag is seen for one of the types
 698:        * of tags associated with this Action.
 699:        */
 700:       public void start(HTML.Tag t, MutableAttributeSet a)
 701:       {
 702:         // FIXME: Implement.
 703:         print ("ParagraphAction.start not implemented");
 704:       }
 705:       
 706:       /**
 707:        * Called when an end tag is seen for one of the types of tags associated
 708:        * with this Action.
 709:        */
 710:       public void end(HTML.Tag t)
 711:       {
 712:         // FIXME: Implement.
 713:         print ("ParagraphAction.end not implemented");
 714:       } 
 715:     }
 716:     
 717:     public class PreAction extends BlockAction
 718:     {
 719:       /**
 720:        * This method is called when a start tag is seen for one of the types
 721:        * of tags associated with this Action.
 722:        */
 723:       public void start(HTML.Tag t, MutableAttributeSet a)
 724:       {
 725:         // FIXME: Implement.
 726:         print ("PreAction.start not implemented");
 727:       }
 728:       
 729:       /**
 730:        * Called when an end tag is seen for one of the types of tags associated
 731:        * with this Action.
 732:        */
 733:       public void end(HTML.Tag t)
 734:       {
 735:         // FIXME: Implement.
 736:         print ("PreAction.end not implemented");
 737:       } 
 738:     }
 739:     
 740:     public class SpecialAction extends TagAction
 741:     {
 742:       /**
 743:        * This method is called when a start tag is seen for one of the types
 744:        * of tags associated with this Action.
 745:        */
 746:       public void start(HTML.Tag t, MutableAttributeSet a)
 747:       {
 748:         // FIXME: Implement.
 749:         print ("SpecialAction.start not implemented");
 750:       }
 751:       
 752:       /**
 753:        * Called when an end tag is seen for one of the types of tags associated
 754:        * with this Action.
 755:        */
 756:       public void end(HTML.Tag t)
 757:       {
 758:         // FIXME: Implement.
 759:         print ("SpecialAction.end not implemented");
 760:       }                
 761:     }
 762:     
 763:     class AreaAction extends TagAction
 764:     {
 765:       /**
 766:        * This method is called when a start tag is seen for one of the types
 767:        * of tags associated with this Action.
 768:        */
 769:       public void start(HTML.Tag t, MutableAttributeSet a)
 770:       {
 771:         // FIXME: Implement.
 772:         print ("AreaAction.start not implemented");
 773:       }
 774:       
 775:       /**
 776:        * Called when an end tag is seen for one of the types of tags associated
 777:        * with this Action.
 778:        */
 779:       public void end(HTML.Tag t)
 780:       {
 781:         // FIXME: Implement.
 782:         print ("AreaAction.end not implemented");
 783:       } 
 784:     }
 785:     
 786:     class BaseAction extends TagAction
 787:     {
 788:       /**
 789:        * This method is called when a start tag is seen for one of the types
 790:        * of tags associated with this Action.
 791:        */
 792:       public void start(HTML.Tag t, MutableAttributeSet a)
 793:       {
 794:         // FIXME: Implement.
 795:         print ("BaseAction.start not implemented");
 796:       }
 797:       
 798:       /**
 799:        * Called when an end tag is seen for one of the types of tags associated
 800:        * with this Action.
 801:        */
 802:       public void end(HTML.Tag t)
 803:       {
 804:         // FIXME: Implement.
 805:         print ("BaseAction.end not implemented");
 806:       } 
 807:     }
 808:     
 809:     class HeadAction extends BlockAction
 810:     {
 811:       /**
 812:        * This method is called when a start tag is seen for one of the types
 813:        * of tags associated with this Action.
 814:        */
 815:       public void start(HTML.Tag t, MutableAttributeSet a)
 816:       {
 817:         // FIXME: Implement.
 818:         print ("HeadAction.start not implemented: "+t);
 819:         super.start(t, a);
 820:       }
 821:       
 822:       /**
 823:        * Called when an end tag is seen for one of the types of tags associated
 824:        * with this Action.
 825:        */
 826:       public void end(HTML.Tag t)
 827:       {
 828:         // FIXME: Implement.
 829:         print ("HeadAction.end not implemented: "+t);
 830:         super.end(t);
 831:       } 
 832:     }
 833:     
 834:     class LinkAction extends TagAction
 835:     {
 836:       /**
 837:        * This method is called when a start tag is seen for one of the types
 838:        * of tags associated with this Action.
 839:        */
 840:       public void start(HTML.Tag t, MutableAttributeSet a)
 841:       {
 842:         // FIXME: Implement.
 843:         print ("LinkAction.start not implemented");
 844:       }
 845:       
 846:       /**
 847:        * Called when an end tag is seen for one of the types of tags associated
 848:        * with this Action.
 849:        */
 850:       public void end(HTML.Tag t)
 851:       {
 852:         // FIXME: Implement.
 853:         print ("LinkAction.end not implemented");
 854:       } 
 855:     }
 856:     
 857:     class MapAction extends TagAction
 858:     {
 859:       /**
 860:        * This method is called when a start tag is seen for one of the types
 861:        * of tags associated with this Action.
 862:        */
 863:       public void start(HTML.Tag t, MutableAttributeSet a)
 864:       {
 865:         // FIXME: Implement.
 866:         print ("MapAction.start not implemented");
 867:       }
 868:       
 869:       /**
 870:        * Called when an end tag is seen for one of the types of tags associated
 871:        * with this Action.
 872:        */
 873:       public void end(HTML.Tag t)
 874:       {
 875:         // FIXME: Implement.
 876:         print ("MapAction.end not implemented");
 877:       } 
 878:     }
 879:     
 880:     class MetaAction extends TagAction
 881:     {
 882:       /**
 883:        * This method is called when a start tag is seen for one of the types
 884:        * of tags associated with this Action.
 885:        */
 886:       public void start(HTML.Tag t, MutableAttributeSet a)
 887:       {
 888:         // FIXME: Implement.
 889:         print ("MetaAction.start not implemented");
 890:       }
 891:       
 892:       /**
 893:        * Called when an end tag is seen for one of the types of tags associated
 894:        * with this Action.
 895:        */
 896:       public void end(HTML.Tag t)
 897:       {
 898:         // FIXME: Implement.
 899:         print ("MetaAction.end not implemented");
 900:       } 
 901:     }
 902:     
 903:     class StyleAction extends TagAction
 904:     {
 905:       /**
 906:        * This method is called when a start tag is seen for one of the types
 907:        * of tags associated with this Action.
 908:        */
 909:       public void start(HTML.Tag t, MutableAttributeSet a)
 910:       {
 911:         // FIXME: Implement.
 912:         print ("StyleAction.start not implemented");
 913:       }
 914:       
 915:       /**
 916:        * Called when an end tag is seen for one of the types of tags associated
 917:        * with this Action.
 918:        */
 919:       public void end(HTML.Tag t)
 920:       {
 921:         // FIXME: Implement.
 922:         print ("StyleAction.end not implemented");
 923:       } 
 924:     }
 925:     
 926:     class TitleAction extends TagAction
 927:     {
 928:       /**
 929:        * This method is called when a start tag is seen for one of the types
 930:        * of tags associated with this Action.
 931:        */
 932:       public void start(HTML.Tag t, MutableAttributeSet a)
 933:       {
 934:         // FIXME: Implement.
 935:         print ("TitleAction.start not implemented");
 936:       }
 937:       
 938:       /**
 939:        * Called when an end tag is seen for one of the types of tags associated
 940:        * with this Action.
 941:        */
 942:       public void end(HTML.Tag t)
 943:       {
 944:         // FIXME: Implement.
 945:         print ("TitleAction.end not implemented");
 946:       } 
 947:     }    
 948:     
 949:     public HTMLReader(int offset)
 950:     {
 951:       this (offset, 0, 0, null);
 952:     }
 953:     
 954:     public HTMLReader(int offset, int popDepth, int pushDepth,
 955:                       HTML.Tag insertTag)
 956:     {
 957:       print ("HTMLReader created with pop: "+popDepth
 958:                           + " push: "+pushDepth + " offset: "+offset
 959:                           + " tag: "+insertTag);
 960:       this.insertTag = insertTag;
 961:       this.offset = offset;
 962:       this.popDepth = popDepth;
 963:       this.pushDepth = pushDepth;
 964:       initTags();
 965:     }
 966:     
 967:     void initTags()
 968:     {
 969:       tagToAction = new HashMap(72);
 970:       CharacterAction characterAction = new CharacterAction();
 971:       HiddenAction hiddenAction = new HiddenAction();
 972:       AreaAction areaAction = new AreaAction();
 973:       BaseAction baseAction = new BaseAction();
 974:       BlockAction blockAction = new BlockAction();
 975:       SpecialAction specialAction = new SpecialAction();
 976:       ParagraphAction paragraphAction = new ParagraphAction();
 977:       HeadAction headAction = new HeadAction();
 978:       FormAction formAction = new FormAction();
 979:       IsindexAction isindexAction = new IsindexAction();
 980:       LinkAction linkAction = new LinkAction();
 981:       MapAction mapAction = new MapAction();
 982:       PreAction preAction = new PreAction();
 983:       MetaAction metaAction = new MetaAction();
 984:       StyleAction styleAction = new StyleAction();
 985:       TitleAction titleAction = new TitleAction();
 986:       
 987:       
 988:       tagToAction.put(HTML.Tag.A, characterAction);
 989:       tagToAction.put(HTML.Tag.ADDRESS, characterAction);
 990:       tagToAction.put(HTML.Tag.APPLET, hiddenAction);
 991:       tagToAction.put(HTML.Tag.AREA, areaAction);
 992:       tagToAction.put(HTML.Tag.B, characterAction);
 993:       tagToAction.put(HTML.Tag.BASE, baseAction);
 994:       tagToAction.put(HTML.Tag.BASEFONT, characterAction);
 995:       tagToAction.put(HTML.Tag.BIG, characterAction);
 996:       tagToAction.put(HTML.Tag.BLOCKQUOTE, blockAction);
 997:       tagToAction.put(HTML.Tag.BODY, blockAction);
 998:       tagToAction.put(HTML.Tag.BR, specialAction);
 999:       tagToAction.put(HTML.Tag.CAPTION, blockAction);
1000:       tagToAction.put(HTML.Tag.CENTER, blockAction);
1001:       tagToAction.put(HTML.Tag.CITE, characterAction);
1002:       tagToAction.put(HTML.Tag.CODE, characterAction);
1003:       tagToAction.put(HTML.Tag.DD, blockAction);
1004:       tagToAction.put(HTML.Tag.DFN, characterAction);
1005:       tagToAction.put(HTML.Tag.DIR, blockAction);
1006:       tagToAction.put(HTML.Tag.DIV, blockAction);
1007:       tagToAction.put(HTML.Tag.DL, blockAction);
1008:       tagToAction.put(HTML.Tag.DT, paragraphAction);
1009:       tagToAction.put(HTML.Tag.EM, characterAction);
1010:       tagToAction.put(HTML.Tag.FONT, characterAction);
1011:       tagToAction.put(HTML.Tag.FORM, blockAction);
1012:       tagToAction.put(HTML.Tag.FRAME, specialAction);
1013:       tagToAction.put(HTML.Tag.FRAMESET, blockAction);
1014:       tagToAction.put(HTML.Tag.H1, paragraphAction);
1015:       tagToAction.put(HTML.Tag.H2, paragraphAction);
1016:       tagToAction.put(HTML.Tag.H3, paragraphAction);
1017:       tagToAction.put(HTML.Tag.H4, paragraphAction);
1018:       tagToAction.put(HTML.Tag.H5, paragraphAction);
1019:       tagToAction.put(HTML.Tag.H6, paragraphAction);
1020:       tagToAction.put(HTML.Tag.HEAD, headAction);
1021:       tagToAction.put(HTML.Tag.HR, specialAction);
1022:       tagToAction.put(HTML.Tag.HTML, blockAction);
1023:       tagToAction.put(HTML.Tag.I, characterAction);
1024:       tagToAction.put(HTML.Tag.IMG, specialAction);
1025:       tagToAction.put(HTML.Tag.INPUT, formAction);
1026:       tagToAction.put(HTML.Tag.ISINDEX, isindexAction);
1027:       tagToAction.put(HTML.Tag.KBD, characterAction);
1028:       tagToAction.put(HTML.Tag.LI, blockAction);
1029:       tagToAction.put(HTML.Tag.LINK, linkAction);
1030:       tagToAction.put(HTML.Tag.MAP, mapAction);
1031:       tagToAction.put(HTML.Tag.MENU, blockAction);
1032:       tagToAction.put(HTML.Tag.META, metaAction);
1033:       tagToAction.put(HTML.Tag.NOFRAMES, blockAction);
1034:       tagToAction.put(HTML.Tag.OBJECT, specialAction);
1035:       tagToAction.put(HTML.Tag.OL, blockAction);
1036:       tagToAction.put(HTML.Tag.OPTION, formAction);
1037:       tagToAction.put(HTML.Tag.P, paragraphAction);
1038:       tagToAction.put(HTML.Tag.PARAM, hiddenAction);
1039:       tagToAction.put(HTML.Tag.PRE, preAction);
1040:       tagToAction.put(HTML.Tag.SAMP, characterAction);
1041:       tagToAction.put(HTML.Tag.SCRIPT, hiddenAction);
1042:       tagToAction.put(HTML.Tag.SELECT, formAction);
1043:       tagToAction.put(HTML.Tag.SMALL, characterAction);
1044:       tagToAction.put(HTML.Tag.STRIKE, characterAction);
1045:       tagToAction.put(HTML.Tag.S, characterAction);      
1046:       tagToAction.put(HTML.Tag.STRONG, characterAction);
1047:       tagToAction.put(HTML.Tag.STYLE, styleAction);
1048:       tagToAction.put(HTML.Tag.SUB, characterAction);
1049:       tagToAction.put(HTML.Tag.SUP, characterAction);
1050:       tagToAction.put(HTML.Tag.TABLE, blockAction);
1051:       tagToAction.put(HTML.Tag.TD, blockAction);
1052:       tagToAction.put(HTML.Tag.TEXTAREA, formAction);
1053:       tagToAction.put(HTML.Tag.TH, blockAction);
1054:       tagToAction.put(HTML.Tag.TITLE, titleAction);
1055:       tagToAction.put(HTML.Tag.TR, blockAction);
1056:       tagToAction.put(HTML.Tag.TT, characterAction);
1057:       tagToAction.put(HTML.Tag.U, characterAction);
1058:       tagToAction.put(HTML.Tag.UL, blockAction);
1059:       tagToAction.put(HTML.Tag.VAR, characterAction);
1060:     }
1061:     
1062:     /**
1063:      * Pushes the current character style onto the stack.
1064:      *
1065:      */
1066:     protected void pushCharacterStyle()
1067:     {
1068:       charAttrStack.push(charAttr);
1069:     }
1070:     
1071:     /**
1072:      * Pops a character style off of the stack and uses it as the 
1073:      * current character style.
1074:      *
1075:      */
1076:     protected void popCharacterStyle()
1077:     {
1078:       if (!charAttrStack.isEmpty())
1079:         charAttr = (MutableAttributeSet) charAttrStack.pop();
1080:     }
1081:     
1082:     /**
1083:      * Registers a given tag with a given Action.  All of the well-known tags
1084:      * are registered by default, but this method can change their behaviour
1085:      * or add support for custom or currently unsupported tags.
1086:      * 
1087:      * @param t the Tag to register
1088:      * @param a the Action for the Tag
1089:      */
1090:     protected void registerTag(HTML.Tag t, HTMLDocument.HTMLReader.TagAction a)
1091:     {
1092:       tagToAction.put (t, a);
1093:     }
1094:     
1095:     /**
1096:      * This is the last method called on the HTMLReader, allowing any pending
1097:      * changes to be flushed to the HTMLDocument.
1098:      */
1099:     public void flush() throws BadLocationException
1100:     {
1101:       DefaultStyledDocument.ElementSpec[] elements;
1102:       elements = new DefaultStyledDocument.ElementSpec[parseBuffer.size()];
1103:       parseBuffer.copyInto(elements);
1104:       parseBuffer.removeAllElements();
1105:       insert(offset, elements);
1106:       offset += HTMLDocument.this.getLength() - offset;
1107:     }
1108:     
1109:     /**
1110:      * This method is called by the parser to indicate a block of 
1111:      * text was encountered.  Should insert the text appropriately.
1112:      * 
1113:      * @param data the text that was inserted
1114:      * @param pos the position at which the text was inserted
1115:      */
1116:     public void handleText(char[] data, int pos)
1117:     {
1118:       if (data != null && data.length > 0)
1119:         addContent(data, 0, data.length);
1120:     }
1121:     
1122:     /**
1123:      * This method is called by the parser and should route the call to 
1124:      * the proper handler for the tag.
1125:      * 
1126:      * @param t the HTML.Tag
1127:      * @param a the attribute set
1128:      * @param pos the position at which the tag was encountered
1129:      */
1130:     public void handleStartTag(HTML.Tag t, MutableAttributeSet a, int pos)
1131:     {
1132:       // Don't call the Action if we've already seen </html>.
1133:       if (endHTMLEncountered)
1134:         return;
1135:         
1136:       TagAction action = (TagAction) tagToAction.get(t);
1137:       if (action != null)
1138:         action.start(t, a);      
1139:     }
1140:     
1141:     /**
1142:      * This method called by parser to handle a comment block.
1143:      * 
1144:      * @param data the comment
1145:      * @param pos the position at which the comment was encountered
1146:      */
1147:     public void handleComment(char[] data, int pos)
1148:     {
1149:       // Don't call the Action if we've already seen </html>.
1150:       if (endHTMLEncountered)
1151:         return;
1152:       
1153:       TagAction action = (TagAction) tagToAction.get(HTML.Tag.COMMENT);
1154:       if (action != null)
1155:         {
1156:           action.start(HTML.Tag.COMMENT, new SimpleAttributeSet());
1157:           action.end (HTML.Tag.COMMENT);
1158:         }
1159:     }
1160:     
1161:     /**
1162:      * This method is called by the parser and should route the call to 
1163:      * the proper handler for the tag.
1164:      * 
1165:      * @param t the HTML.Tag
1166:      * @param pos the position at which the tag was encountered
1167:      */
1168:     public void handleEndTag(HTML.Tag t, int pos)
1169:     {
1170:       // Don't call the Action if we've already seen </html>.
1171:       if (endHTMLEncountered)
1172:         return;
1173:       
1174:       // If this is the </html> tag we need to stop calling the Actions
1175:       if (t == HTML.Tag.HTML)
1176:         endHTMLEncountered = true;
1177:       
1178:       TagAction action = (TagAction) tagToAction.get(t);
1179:       if (action != null)
1180:         action.end(t);
1181:     }
1182:     
1183:     /**
1184:      * This is a callback from the parser that should be routed to the 
1185:      * appropriate handler for the tag.
1186:      * 
1187:      * @param t the HTML.Tag that was encountered
1188:      * @param a the attribute set
1189:      * @param pos the position at which the tag was encountered
1190:      */
1191:     public void handleSimpleTag(HTML.Tag t, MutableAttributeSet a, int pos)
1192:     {
1193:       // Don't call the Action if we've already seen </html>.
1194:       if (endHTMLEncountered)
1195:         return;
1196:       
1197:       TagAction action = (TagAction) tagToAction.get (t);
1198:       if (action != null)
1199:         {
1200:           action.start(t, a);
1201:           action.end(t);
1202:         }
1203:     }
1204:     
1205:     /**
1206:      * This is invoked after the stream has been parsed but before it has been
1207:      * flushed.
1208:      * 
1209:      * @param eol one of \n, \r, or \r\n, whichever was encountered the most in 
1210:      * parsing the stream
1211:      * @since 1.3
1212:      */
1213:     public void handleEndOfLineString(String eol)
1214:     {
1215:       // FIXME: Implement.
1216:       print ("HTMLReader.handleEndOfLineString not implemented yet");
1217:     }
1218:     
1219:     /**
1220:      * Adds the given text to the textarea document.  Called only when we are
1221:      * within a textarea.  
1222:      * 
1223:      * @param data the text to add to the textarea
1224:      */
1225:     protected void textAreaContent(char[] data)
1226:     {
1227:       // FIXME: Implement.
1228:       print ("HTMLReader.textAreaContent not implemented yet");
1229:     }
1230:     
1231:     /**
1232:      * Adds the given text that was encountered in a <PRE> element.
1233:      * 
1234:      * @param data the text
1235:      */
1236:     protected void preContent(char[] data)
1237:     {
1238:       // FIXME: Implement
1239:       print ("HTMLReader.preContent not implemented yet");
1240:     }
1241:     
1242:     /**
1243:      * Instructs the parse buffer to create a block element with the given 
1244:      * attributes.
1245:      * 
1246:      * @param t the tag that requires opening a new block
1247:      * @param attr the attribute set for the new block
1248:      */
1249:     protected void blockOpen(HTML.Tag t, MutableAttributeSet attr)
1250:     {
1251:       printBuffer();
1252:       DefaultStyledDocument.ElementSpec element;
1253:       element = new DefaultStyledDocument.ElementSpec(attr.copyAttributes(),
1254:             DefaultStyledDocument.ElementSpec.StartTagType);
1255:       parseBuffer.addElement(element);
1256:       printBuffer();
1257:     }
1258:     
1259:     /**
1260:      * Instructs the parse buffer to close the block element associated with 
1261:      * the given HTML.Tag
1262:      * 
1263:      * @param t the HTML.Tag that is closing its block
1264:      */
1265:     protected void blockClose(HTML.Tag t)
1266:     {
1267:       printBuffer();
1268:       DefaultStyledDocument.ElementSpec element;
1269:       element = new DefaultStyledDocument.ElementSpec(null,
1270:                 DefaultStyledDocument.ElementSpec.EndTagType);
1271:       parseBuffer.addElement(element);
1272:       printBuffer();
1273:     }
1274:     
1275:     /**
1276:      * Adds text to the appropriate context using the current character
1277:      * attribute set.
1278:      * 
1279:      * @param data the text to add
1280:      * @param offs the offset at which to add it
1281:      * @param length the length of the text to add
1282:      */
1283:     protected void addContent(char[] data, int offs, int length)
1284:     {
1285:       addContent(data, offs, length, true);
1286:     }
1287:     
1288:     /**
1289:      * Adds text to the appropriate context using the current character
1290:      * attribute set, and possibly generating an IMPLIED Tag if necessary.
1291:      * 
1292:      * @param data the text to add
1293:      * @param offs the offset at which to add it
1294:      * @param length the length of the text to add
1295:      * @param generateImpliedPIfNecessary whether or not we should generate
1296:      * an HTML.Tag.IMPLIED tag if necessary
1297:      */
1298:     protected void addContent(char[] data, int offs, int length,
1299:                               boolean generateImpliedPIfNecessary)
1300:     {
1301:       // Copy the attribute set, don't use the same object because 
1302:       // it may change
1303:       AttributeSet attributes = null;
1304:       if (charAttr != null)
1305:         attributes = charAttr.copyAttributes();
1306: 
1307:       DefaultStyledDocument.ElementSpec element;
1308:       element = new DefaultStyledDocument.ElementSpec(attributes,
1309:                   DefaultStyledDocument.ElementSpec.ContentType,
1310:                               data, offs, length);
1311:       
1312:       printBuffer();
1313:       // Add the element to the buffer
1314:       parseBuffer.addElement(element);
1315:       printBuffer();
1316: 
1317:       if (parseBuffer.size() > HTMLDocument.this.getTokenThreshold())
1318:         {
1319:           try
1320:             {
1321:               flush();
1322:             }
1323:           catch (BadLocationException ble)
1324:             {
1325:               // TODO: what to do here?
1326:             }
1327:         }
1328:     }
1329:     
1330:     /**
1331:      * Adds content that is specified in the attribute set.
1332:      * 
1333:      * @param t the HTML.Tag
1334:      * @param a the attribute set specifying the special content
1335:      */
1336:     protected void addSpecialElement(HTML.Tag t, MutableAttributeSet a)
1337:     {
1338:       // FIXME: Implement
1339:       print ("HTMLReader.addSpecialElement not implemented yet");
1340:     }
1341:     
1342:     void printBuffer()
1343:     {      
1344:       print ("\n*********BUFFER**********");
1345:       for (int i = 0; i < parseBuffer.size(); i ++)
1346:         print ("  "+parseBuffer.get(i));
1347:       print ("***************************");
1348:     }
1349:   }
1350:   
1351:   /**
1352:    * Gets the reader for the parser to use when loading the document with HTML. 
1353:    * 
1354:    * @param pos - the starting position
1355:    * @return - the reader
1356:    */
1357:   public HTMLEditorKit.ParserCallback getReader(int pos)
1358:   {
1359:     return new HTMLReader(pos);
1360:   }  
1361:   
1362:   /**
1363:    * Gets the reader for the parser to use when loading the document with HTML. 
1364:    * 
1365:    * @param pos - the starting position
1366:    * @param popDepth - the number of EndTagTypes to generate before inserting
1367:    * @param pushDepth - the number of StartTagTypes with a direction 
1368:    * of JoinNextDirection that should be generated before inserting, 
1369:    * but after the end tags have been generated.
1370:    * @param insertTag - the first tag to start inserting into document
1371:    * @return - the reader
1372:    */
1373:   public HTMLEditorKit.ParserCallback getReader(int pos,
1374:                                                 int popDepth,
1375:                                                 int pushDepth,
1376:                                                 HTML.Tag insertTag)
1377:   {
1378:     return new HTMLReader(pos, popDepth, pushDepth, insertTag);
1379:   }  
1380:   
1381:   /**
1382:    * Gets the child element that contains the attribute with the value or null.
1383:    * Not thread-safe.
1384:    * 
1385:    * @param e - the element to begin search at
1386:    * @param attribute - the desired attribute
1387:    * @param value - the desired value
1388:    * @return the element found with the attribute and value specified or null
1389:    * if it is not found.
1390:    */
1391:   public Element getElement(Element e, Object attribute, Object value)
1392:   {
1393:     if (e != null)
1394:       {
1395:         if (e.getAttributes().containsAttribute(attribute, value))
1396:           return e;
1397:         
1398:         int count = e.getElementCount();
1399:         for (int j = 0; j < count; j++)
1400:           {
1401:             Element child = e.getElement(j);
1402:             if (child.getAttributes().containsAttribute(attribute, value))
1403:               return child;
1404:             
1405:             Element grandChild = getElement(child, attribute, value);
1406:             if (grandChild != null)
1407:               return grandChild;
1408:           }
1409:       }
1410:     return null;
1411:   }
1412:   
1413:   /**
1414:    * Returns the element that has the given id Attribute. If it is not found, 
1415:    * null is returned. This method works on an Attribute, not a character tag.
1416:    * This is not thread-safe.
1417:    * 
1418:    * @param attrId - the Attribute id to look for
1419:    * @return the element that has the given id.
1420:    */
1421:   public Element getElement(String attrId)
1422:   {
1423:     Element root = getDefaultRootElement();
1424:     return getElement(root, HTML.getAttributeKey(attrId) , attrId);
1425:   }
1426:   
1427:   /**
1428:    * Replaces the children of the given element with the contents of
1429:    * the string. The document must have an HTMLEditorKit.Parser set.
1430:    * This will be seen as at least two events, n inserts followed by a remove.
1431:    * 
1432:    * @param elem - the brance element whose children will be replaced
1433:    * @param htmlText - the string to be parsed and assigned to element.
1434:    * @throws BadLocationException
1435:    * @throws IOException
1436:    * @throws IllegalArgumentException - if elem is a leaf 
1437:    * @throws IllegalStateException - if an HTMLEditorKit.Parser has not been set
1438:    */
1439:   public void setInnerHTML(Element elem, String htmlText) 
1440:     throws BadLocationException, IOException
1441:   {
1442:     if (elem.isLeaf())
1443:       throw new IllegalArgumentException("Element is a leaf");
1444:     if (parser == null)
1445:       throw new IllegalStateException("Parser has not been set");
1446:     // FIXME: Not implemented fully, use InsertHTML* in HTMLEditorKit?
1447:     System.out.println("setInnerHTML not implemented");
1448:   }
1449:   
1450:   /**
1451:    * Replaces the given element in the parent with the string. When replacing
1452:    * a leaf, this will attempt to make sure there is a newline present if one is
1453:    * needed. This may result in an additional element being inserted.
1454:    * This will be seen as at least two events, n inserts followed by a remove.
1455:    * The HTMLEditorKit.Parser must be set.
1456:    * 
1457:    * @param elem - the branch element whose parent will be replaced
1458:    * @param htmlText - the string to be parsed and assigned to elem
1459:    * @throws BadLocationException
1460:    * @throws IOException
1461:    * @throws IllegalStateException - if parser is not set
1462:    */
1463:   public void setOuterHTML(Element elem, String htmlText) 
1464:     throws BadLocationException, IOException
1465:     {
1466:       if (parser == null)
1467:         throw new IllegalStateException("Parser has not been set");
1468:       // FIXME: Not implemented fully, use InsertHTML* in HTMLEditorKit?
1469:       System.out.println("setOuterHTML not implemented");
1470:     }
1471:   
1472:   /**
1473:    * Inserts the string before the start of the given element.
1474:    * The parser must be set.
1475:    * 
1476:    * @param elem - the element to be the root for the new text.
1477:    * @param htmlText - the string to be parsed and assigned to elem
1478:    * @throws BadLocationException
1479:    * @throws IOException
1480:    * @throws IllegalStateException - if parser has not been set
1481:    */
1482:   public void insertBeforeStart(Element elem, String htmlText)
1483:       throws BadLocationException, IOException
1484:   {
1485:     if (parser == null)
1486:       throw new IllegalStateException("Parser has not been set");
1487:     //  FIXME: Not implemented fully, use InsertHTML* in HTMLEditorKit?
1488:     System.out.println("insertBeforeStart not implemented");
1489:   }
1490:   
1491:   /**
1492:    * Inserts the string at the end of the element. If elem's children
1493:    * are leaves, and the character at elem.getEndOffset() - 1 is a newline, 
1494:    * then it will be inserted before the newline. The parser must be set.
1495:    * 
1496:    * @param elem - the element to be the root for the new text
1497:    * @param htmlText - the text to insert
1498:    * @throws BadLocationException
1499:    * @throws IOException
1500:    * @throws IllegalStateException - if parser is not set
1501:    */
1502:   public void insertBeforeEnd(Element elem, String htmlText)
1503:       throws BadLocationException, IOException
1504:   {
1505:     if (parser == null)
1506:       throw new IllegalStateException("Parser has not been set");
1507:     //  FIXME: Not implemented fully, use InsertHTML* in HTMLEditorKit?
1508:     System.out.println("insertBeforeEnd not implemented");
1509:   }
1510:   
1511:   /**
1512:    * Inserts the string after the end of the given element.
1513:    * The parser must be set.
1514:    * 
1515:    * @param elem - the element to be the root for the new text
1516:    * @param htmlText - the text to insert
1517:    * @throws BadLocationException
1518:    * @throws IOException
1519:    * @throws IllegalStateException - if parser is not set
1520:    */
1521:   public void insertAfterEnd(Element elem, String htmlText)
1522:       throws BadLocationException, IOException
1523:   {
1524:     if (parser == null)
1525:       throw new IllegalStateException("Parser has not been set");
1526:     //  FIXME: Not implemented fully, use InsertHTML* in HTMLEditorKit?
1527:     System.out.println("insertAfterEnd not implemented");
1528:   }
1529:   
1530:   /**
1531:    * Inserts the string at the start of the element.
1532:    * The parser must be set.
1533:    * 
1534:    * @param elem - the element to be the root for the new text
1535:    * @param htmlText - the text to insert
1536:    * @throws BadLocationException
1537:    * @throws IOException
1538:    * @throws IllegalStateException - if parser is not set
1539:    */
1540:   public void insertAfterStart(Element elem, String htmlText)
1541:       throws BadLocationException, IOException
1542:   {
1543:     if (parser == null)
1544:       throw new IllegalStateException("Parser has not been set");
1545:     //  FIXME: Not implemented fully, use InsertHTML* in HTMLEditorKit?
1546:     System.out.println("insertAfterStart not implemented");
1547:   }
1548:   
1549:   /**
1550:    * This method sets the attributes associated with the paragraph containing
1551:    * offset. If replace is false, s is merged with existing attributes. The
1552:    * length argument determines how many characters are affected by the new
1553:    * attributes. This is often the entire paragraph.
1554:    * 
1555:    * @param offset -
1556:    *          the offset into the paragraph (must be at least 0)
1557:    * @param length -
1558:    *          the number of characters affected (must be at least 0)
1559:    * @param s -
1560:    *          the attributes
1561:    * @param replace -
1562:    *          whether to replace existing attributes, or merge them
1563:    */
1564:   public void setParagraphAttributes(int offset, int length, AttributeSet s,
1565:                                      boolean replace)
1566:   {
1567:     //  FIXME: Not implemented.
1568:     System.out.println("setParagraphAttributes not implemented");
1569:     super.setParagraphAttributes(offset, length, s, replace);
1570:   }
1571:   
1572:   /**
1573:    * This method flags a change in the document.
1574:    * 
1575:    *  @param e - the Document event
1576:    */
1577:   protected void fireChangedUpdate(DocumentEvent e)
1578:   {
1579:     //  FIXME: Not implemented.
1580:     System.out.println("fireChangedUpdate not implemented");
1581:     super.fireChangedUpdate(e);    
1582:   }
1583: 
1584:   /**
1585:    * This method fires an event intended to be caught by Undo listeners. It
1586:    * simply calls the super version inherited from DefaultStyledDocument. With
1587:    * this method, an HTML editor could easily provide undo support.
1588:    * 
1589:    * @param e - the UndoableEditEvent
1590:    */
1591:   protected void fireUndoableEditUpdate(UndoableEditEvent e)
1592:   {
1593:     super.fireUndoableEditUpdate(e);
1594:   }
1595: }