package weblogic.taglib.quote;

import java.io.*;
import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;

/**
 * This class defines a custom JSP tag that enumerates through
 * the contents of the current session. 
 */

public class CodeTag extends BodyTagSupport {
  
  String commentColor = "red";
  String quoteColor = "green";
  String defaultFont = "face=\"Courier New\" color=navy";
  
  public void setCommentColor(String col) { commentColor = col; }
  public String getCommentColor() { return commentColor; }
  
  public void setQuoteColor(String col) { quoteColor = col; }
  public String getQuoteColor() { return quoteColor; }
  
  public void setDefaultFont(String col) { defaultFont = col; }
  public String getDefaultFont() { return defaultFont; }
  
  public int doStartTag() throws javax.servlet.jsp.JspException {
      return BodyTag.EVAL_BODY_TAG;
  }
  
  public int doAfterBody() throws javax.servlet.jsp.JspException {
    // Get the processed body content of the tag
    String body = getBodyContent().getString();
         
    // Reformat the body
    String output = processCode(body);
    
    // Write contents of 'output' to the parent's out stream. 
    try {
      getPreviousOut().print("<pre><font "+defaultFont+" >"+
                             output+"</font></pre>");
    } catch (IOException ioe) {}
    
    return(SKIP_BODY);
  }
  
  
  /**
   * Processes the given String to produce formatted and highlighted output for HTML. 
   */
  private String processCode(String body) {
    ByteArrayOutputStream buffer = new ByteArrayOutputStream();
    PrintWriter out = new PrintWriter(buffer);
    int index = 0;
    // The following booleans are used to keep state when parsing the body
    boolean line_comment = false;
    boolean reg_comment = false;
    boolean in_quotes = false;
    boolean in_single_quote = false;
    
    int len = body.length();
    // Process the body contents, adding high-lighting
    while(index < len)
    {
      switch(body.charAt(index)) {
    case '<':
        out.write("&lt;");
        break;
    case '>':
        out.write("&gt;");
        break;
    case '&':
        out.write("&amp;");
        break;
    case '/':
        if (!in_single_quote && !in_quotes && !line_comment && !reg_comment) {
          if (body.charAt(index+1) == '/') {
            out.write("<font color=\""+commentColor+"\">//");
            line_comment = true;
            index++;
          } else if (body.charAt(index+1) == '*') {
            out.write("<font color=\""+commentColor+"\">/*");
            reg_comment = true;
            index++;
          } else {
            out.write('/');
          }
        } else {
          out.write('/');
        }
        break;
    case '\n':
        if (line_comment) {
          out.write("</font>");
          line_comment = false;
        }
        out.write('\n');
        break;
    case '*':
        if (!line_comment && reg_comment &&
            (body.charAt(index+1) == '/'))
        {
          out.write("*/</font>");
          index++;
          reg_comment = false;
        } else {
          out.write('*');
        }
        break;
    case '\'':
        if (!in_quotes  && !line_comment && !reg_comment) {
          if (!in_single_quote) {
            out.write("<font color=\""+quoteColor+"\">'");
            in_single_quote = true;
          } else {
            out.write("'");
            // Make sure this is not an escaped single quote
            // Make sure this is not an escaped quote
            if ( (index==1) || (body.charAt(index-1)!='\\') || 
                 // and that this escape character isn't escaped !
                 ((index > 1) && (body.charAt(index-2)=='\\')))
            {
              out.write("</font>");
              in_single_quote = false;
            }
          }
        } else {
          out.write('\'');
        }
        break;
    case '"':
        if (!in_single_quote && !line_comment && !reg_comment) {
          if (!in_quotes) {
            out.write("<font color=\""+quoteColor+"\">\"");
            in_quotes = true;
          } else {
            out.write('"');
            // Make sure this is not an escaped quote
            if ( (index==1) || (body.charAt(index-1)!='\\') || 
                 // and that this escape character isn't escaped !
                 ((index > 1) && (body.charAt(index-2)=='\\')) )
            {
              out.write("</font>");
              in_quotes = false;
            }
          }
        } else {
          out.write('"');
        }
        break;
    default:
        out.write(body.charAt(index));
      }
      index++;
    }
    
    out.flush();
    out.close();
    
    return(buffer.toString());
  }
  
}

