mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			454 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Java
		
	
	
	
			
		
		
	
	
			454 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Java
		
	
	
	
/* MinimalHTMLWriter.java --
 | 
						|
   Copyright (C) 2006 Free Software Foundation, Inc.
 | 
						|
 | 
						|
This file is part of GNU Classpath.
 | 
						|
 | 
						|
GNU Classpath is free software; you can redistribute it and/or modify
 | 
						|
it under the terms of the GNU General Public License as published by
 | 
						|
the Free Software Foundation; either version 2, or (at your option)
 | 
						|
any later version.
 | 
						|
 | 
						|
GNU Classpath is distributed in the hope that it will be useful, but
 | 
						|
WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
						|
General Public License for more details.
 | 
						|
 | 
						|
You should have received a copy of the GNU General Public License
 | 
						|
along with GNU Classpath; see the file COPYING.  If not, write to the
 | 
						|
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 | 
						|
02110-1301 USA.
 | 
						|
 | 
						|
Linking this library statically or dynamically with other modules is
 | 
						|
making a combined work based on this library.  Thus, the terms and
 | 
						|
conditions of the GNU General Public License cover the whole
 | 
						|
combination.
 | 
						|
 | 
						|
As a special exception, the copyright holders of this library give you
 | 
						|
permission to link this library with independent modules to produce an
 | 
						|
executable, regardless of the license terms of these independent
 | 
						|
modules, and to copy and distribute the resulting executable under
 | 
						|
terms of your choice, provided that you also meet, for each linked
 | 
						|
independent module, the terms and conditions of the license of that
 | 
						|
module.  An independent module is a module which is not derived from
 | 
						|
or based on this library.  If you modify this library, you may extend
 | 
						|
this exception to your version of the library, but you are not
 | 
						|
obligated to do so.  If you do not wish to do so, delete this
 | 
						|
exception statement from your version. */
 | 
						|
 | 
						|
package javax.swing.text.html;
 | 
						|
 | 
						|
import javax.swing.text.AttributeSet;
 | 
						|
import javax.swing.text.AbstractWriter;
 | 
						|
import javax.swing.text.BadLocationException;
 | 
						|
import javax.swing.text.DefaultStyledDocument;
 | 
						|
import javax.swing.text.Element;
 | 
						|
import javax.swing.text.ElementIterator;
 | 
						|
import javax.swing.text.StyleConstants;
 | 
						|
import javax.swing.text.Style;
 | 
						|
import javax.swing.text.StyledDocument;
 | 
						|
import java.io.Writer;
 | 
						|
import java.io.IOException;
 | 
						|
import java.util.ArrayDeque;
 | 
						|
import java.util.Deque;
 | 
						|
import java.util.Enumeration;
 | 
						|
import java.awt.Color;
 | 
						|
 | 
						|
/**
 | 
						|
 * MinimalHTMLWriter,
 | 
						|
 * A minimal AbstractWriter implementation for HTML.
 | 
						|
 *
 | 
						|
 * @author Sven de Marothy
 | 
						|
 */
 | 
						|
public class MinimalHTMLWriter extends AbstractWriter
 | 
						|
{
 | 
						|
  private StyledDocument doc;
 | 
						|
  private Deque<String> tagStack;
 | 
						|
  private boolean inFontTag = false;
 | 
						|
 | 
						|
  /**
 | 
						|
   * Constructs a MinimalHTMLWriter.
 | 
						|
   * @param w - a Writer, for output.
 | 
						|
   * @param doc - the document
 | 
						|
   */
 | 
						|
  public MinimalHTMLWriter(Writer w, StyledDocument doc)
 | 
						|
  {
 | 
						|
    super(w, doc);
 | 
						|
    this.doc = doc;
 | 
						|
    tagStack = new ArrayDeque<String>();
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Constructs a MinimalHTMLWriter.
 | 
						|
   * @param w - a Writer, for output.
 | 
						|
   * @param doc - the document
 | 
						|
   * @param pos - start position
 | 
						|
   * @param len - length
 | 
						|
   */
 | 
						|
  public MinimalHTMLWriter(Writer w, StyledDocument doc, int pos, int len)
 | 
						|
  {
 | 
						|
    super(w, doc, pos, len);
 | 
						|
    this.doc = doc;
 | 
						|
    tagStack = new ArrayDeque<String>();
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Starts a span tag.
 | 
						|
   */
 | 
						|
  protected void startFontTag(String style) throws IOException
 | 
						|
  {
 | 
						|
    if( inFontTag() )
 | 
						|
      endOpenTags();
 | 
						|
    writeStartTag("<span style=\""+style+"\">");
 | 
						|
    inFontTag = true;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Returns whether the writer is within two span tags.
 | 
						|
   */
 | 
						|
  protected boolean inFontTag()
 | 
						|
  {
 | 
						|
    return inFontTag;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Ends a span tag.
 | 
						|
   */
 | 
						|
  protected void endFontTag() throws IOException
 | 
						|
  {
 | 
						|
    writeEndTag("</span>");
 | 
						|
    inFontTag = false;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Write the entire HTML document.
 | 
						|
   */
 | 
						|
  public synchronized void write() throws IOException, BadLocationException
 | 
						|
  {
 | 
						|
    writeStartTag("<html>");
 | 
						|
    writeHeader();
 | 
						|
    writeBody();
 | 
						|
    writeEndTag("</html>");
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Write a start tag and increment the indent.
 | 
						|
   */
 | 
						|
  protected void writeStartTag(String tag) throws IOException
 | 
						|
  {
 | 
						|
    indent();
 | 
						|
    write(tag+NEWLINE);
 | 
						|
    incrIndent();
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Write an ending tag and decrement the indent.
 | 
						|
   */
 | 
						|
  protected void writeEndTag(String endTag) throws IOException
 | 
						|
  {
 | 
						|
    decrIndent();
 | 
						|
    indent();
 | 
						|
    write(endTag+NEWLINE);
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Write the HTML header.
 | 
						|
   */
 | 
						|
  protected void writeHeader() throws IOException
 | 
						|
  {
 | 
						|
    writeStartTag("<head>");
 | 
						|
    writeStartTag("<style>");
 | 
						|
    writeStartTag("<!--");
 | 
						|
    writeStyles();
 | 
						|
    writeEndTag("-->");
 | 
						|
    writeEndTag("</style>");
 | 
						|
    writeEndTag("</head>");
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Write a paragraph start tag.
 | 
						|
   */
 | 
						|
  protected void writeStartParagraph(Element elem) throws IOException
 | 
						|
  {
 | 
						|
    indent();
 | 
						|
    write("<p class=default>"+NEWLINE); // FIXME: Class value = ?
 | 
						|
    incrIndent();
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Write a paragraph end tag, closes any other open tags.
 | 
						|
   */
 | 
						|
  protected void writeEndParagraph() throws IOException
 | 
						|
  {
 | 
						|
    endOpenTags();
 | 
						|
    writeEndTag("</p>");
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Writes the body of the HTML document.
 | 
						|
   */
 | 
						|
  protected void writeBody() throws IOException, BadLocationException
 | 
						|
  {
 | 
						|
    writeStartTag("<body>");
 | 
						|
 | 
						|
    ElementIterator ei = getElementIterator();
 | 
						|
    Element e = ei.first();
 | 
						|
    boolean inParagraph = false;
 | 
						|
    do
 | 
						|
      {
 | 
						|
        if( e.isLeaf() )
 | 
						|
          {
 | 
						|
            boolean hasNL = (getText(e).indexOf(NEWLINE) != -1);
 | 
						|
            if( !inParagraph && hasText( e ) )
 | 
						|
              {
 | 
						|
                writeStartParagraph(e);
 | 
						|
                inParagraph = true;
 | 
						|
              }
 | 
						|
 | 
						|
            if( hasText( e ) )
 | 
						|
              writeContent(e, true);
 | 
						|
 | 
						|
            if( hasNL && inParagraph )
 | 
						|
              {
 | 
						|
                writeEndParagraph();
 | 
						|
                inParagraph = false;
 | 
						|
              }
 | 
						|
            else
 | 
						|
              endOpenTags();
 | 
						|
          }
 | 
						|
      }
 | 
						|
    while((e = ei.next()) != null);
 | 
						|
 | 
						|
    writeEndTag("</body>");
 | 
						|
  }
 | 
						|
 | 
						|
  protected void text(Element elem) throws IOException, BadLocationException
 | 
						|
  {
 | 
						|
    write( getText(elem).trim() );
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Write bold, indent and underline tags.
 | 
						|
   */
 | 
						|
  protected void writeHTMLTags(AttributeSet attr) throws IOException
 | 
						|
  {
 | 
						|
    if(attr.getAttribute(StyleConstants.Bold) != null)
 | 
						|
      if(((Boolean)attr.getAttribute(StyleConstants.Bold)).booleanValue())
 | 
						|
        {
 | 
						|
          write("<b>");
 | 
						|
          tagStack.push("</b>");
 | 
						|
        }
 | 
						|
    if(attr.getAttribute(StyleConstants.Italic) != null)
 | 
						|
      if(((Boolean)attr.getAttribute(StyleConstants.Italic)).booleanValue())
 | 
						|
        {
 | 
						|
          write("<i>");
 | 
						|
          tagStack.push("</i>");
 | 
						|
        }
 | 
						|
    if(attr.getAttribute(StyleConstants.Underline) != null)
 | 
						|
      if(((Boolean)attr.getAttribute(StyleConstants.Underline)).booleanValue())
 | 
						|
        {
 | 
						|
          write("<u>");
 | 
						|
          tagStack.push("</u>");
 | 
						|
        }
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Returns whether the element contains text or not.
 | 
						|
   */
 | 
						|
  protected boolean isText(Element elem)
 | 
						|
  {
 | 
						|
    return (elem.getEndOffset() != elem.getStartOffset());
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Writes the content of an element.
 | 
						|
   */
 | 
						|
  protected void writeContent(Element elem, boolean needsIndenting)
 | 
						|
    throws IOException, BadLocationException
 | 
						|
  {
 | 
						|
    writeNonHTMLAttributes(elem.getAttributes());
 | 
						|
    if(needsIndenting)
 | 
						|
      indent();
 | 
						|
    writeHTMLTags(elem.getAttributes());
 | 
						|
    if( isText(elem) )
 | 
						|
      text(elem);
 | 
						|
    else
 | 
						|
      writeLeaf(elem);
 | 
						|
 | 
						|
    endOpenTags();
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Writes a non-text leaf element.
 | 
						|
   */
 | 
						|
  protected void writeLeaf(Element e) throws IOException
 | 
						|
  {
 | 
						|
    // NOTE: Haven't tested if this is correct.
 | 
						|
    if(e.getName().equals(StyleConstants.IconElementName))
 | 
						|
      writeImage(e);
 | 
						|
    else
 | 
						|
      writeComponent(e);
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Write the HTML attributes which do not have tag equivalents,
 | 
						|
   * e.g. attributes other than bold/italic/underlined.
 | 
						|
   */
 | 
						|
  protected void writeNonHTMLAttributes(AttributeSet attr) throws IOException
 | 
						|
  {
 | 
						|
    String style = "";
 | 
						|
 | 
						|
    // Alignment? Background?
 | 
						|
 | 
						|
    if( StyleConstants.getForeground(attr) != null )
 | 
						|
      style = style + "color: " +
 | 
						|
        getColor(StyleConstants.getForeground(attr)) + "; ";
 | 
						|
 | 
						|
    style = style + "font-size: "+StyleConstants.getFontSize(attr)+"pt; ";
 | 
						|
    style = style + "font-family: "+StyleConstants.getFontFamily(attr);
 | 
						|
 | 
						|
    startFontTag(style);
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Write the styles used.
 | 
						|
   */
 | 
						|
  protected void writeStyles() throws IOException
 | 
						|
  {
 | 
						|
    if(doc instanceof DefaultStyledDocument)
 | 
						|
      {
 | 
						|
        Enumeration<?> styles = ((DefaultStyledDocument)doc).getStyleNames();
 | 
						|
        while(styles.hasMoreElements())
 | 
						|
          writeStyle(doc.getStyle((String)styles.nextElement()));
 | 
						|
      }
 | 
						|
    else
 | 
						|
      { // What else to do here?
 | 
						|
        Style s = doc.getStyle("default");
 | 
						|
        if(s != null)
 | 
						|
          writeStyle( s );
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Write a set of attributes.
 | 
						|
   */
 | 
						|
  protected void writeAttributes(AttributeSet attr) throws IOException
 | 
						|
  {
 | 
						|
    Enumeration<?> attribs = attr.getAttributeNames();
 | 
						|
    while(attribs.hasMoreElements())
 | 
						|
      {
 | 
						|
        Object attribName = attribs.nextElement();
 | 
						|
        String name = attribName.toString();
 | 
						|
        String output = getAttribute(name, attr.getAttribute(attribName));
 | 
						|
        if( output != null )
 | 
						|
          {
 | 
						|
            indent();
 | 
						|
            write( output + NEWLINE );
 | 
						|
          }
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Deliberately unimplemented, handles component elements.
 | 
						|
   */
 | 
						|
  protected void writeComponent(Element elem) throws IOException
 | 
						|
  {
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Deliberately unimplemented.
 | 
						|
   * Writes StyleConstants.IconElementName elements.
 | 
						|
   */
 | 
						|
  protected void writeImage(Element elem) throws IOException
 | 
						|
  {
 | 
						|
  }
 | 
						|
 | 
						|
  // -------------------- Private methods. --------------------------------
 | 
						|
 | 
						|
  /**
 | 
						|
   * Write a single style attribute
 | 
						|
   */
 | 
						|
  private String getAttribute(String name, Object a) throws IOException
 | 
						|
  {
 | 
						|
    if(name.equals("foreground"))
 | 
						|
      return "foreground:"+getColor((Color)a)+";";
 | 
						|
    if(name.equals("background"))
 | 
						|
      return "background:"+getColor((Color)a)+";";
 | 
						|
    if(name.equals("italic"))
 | 
						|
      return "italic:"+(((Boolean)a).booleanValue() ? "italic;" : ";");
 | 
						|
    if(name.equals("bold"))
 | 
						|
      return "bold:"+(((Boolean)a).booleanValue() ? "bold;" : "normal;");
 | 
						|
    if(name.equals("family"))
 | 
						|
      return "family:" + a + ";";
 | 
						|
    if(name.equals("size"))
 | 
						|
      {
 | 
						|
        int size = ((Integer)a).intValue();
 | 
						|
        int htmlSize;
 | 
						|
        if( size > 24 )
 | 
						|
          htmlSize = 7;
 | 
						|
        else if( size > 18 )
 | 
						|
          htmlSize = 6;
 | 
						|
        else if( size > 14 )
 | 
						|
          htmlSize = 5;
 | 
						|
        else if( size > 12 )
 | 
						|
          htmlSize = 4;
 | 
						|
        else if( size > 10 )
 | 
						|
          htmlSize = 3;
 | 
						|
        else if( size > 8 )
 | 
						|
          htmlSize = 2;
 | 
						|
        else
 | 
						|
          htmlSize = 1;
 | 
						|
 | 
						|
        return "size:" + htmlSize + ";";
 | 
						|
      }
 | 
						|
 | 
						|
    return null;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Stupid that Color doesn't have a method for this.
 | 
						|
   */
 | 
						|
  private String getColor(Color c)
 | 
						|
  {
 | 
						|
    String r = "00" + Integer.toHexString(c.getRed());
 | 
						|
    r = r.substring(r.length() - 2);
 | 
						|
    String g = "00" + Integer.toHexString(c.getGreen());
 | 
						|
    g = g.substring(g.length() - 2);
 | 
						|
    String b = "00" + Integer.toHexString(c.getBlue());
 | 
						|
    b = b.substring(b.length() - 2);
 | 
						|
    return "#" + r + g + b;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Empty the stack of open tags
 | 
						|
   */
 | 
						|
  private void endOpenTags() throws IOException
 | 
						|
  {
 | 
						|
    while(tagStack.size() > 0)
 | 
						|
      write(tagStack.pop());
 | 
						|
 | 
						|
    if( inFontTag() )
 | 
						|
      {
 | 
						|
        write(""+NEWLINE);
 | 
						|
        endFontTag();
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Output a single style
 | 
						|
   */
 | 
						|
  private void writeStyle(Style s) throws IOException
 | 
						|
  {
 | 
						|
    if( s == null )
 | 
						|
      return;
 | 
						|
 | 
						|
    writeStartTag("p."+s.getName()+" {");
 | 
						|
    writeAttributes(s);
 | 
						|
    writeEndTag("}");
 | 
						|
  }
 | 
						|
 | 
						|
  private boolean hasText(Element e) throws BadLocationException
 | 
						|
  {
 | 
						|
    return (getText(e).trim().length() > 0);
 | 
						|
  }
 | 
						|
}
 |