package com.mindprod.pal;

/**
 * prepares  ASCII table in HTML
 */

import java.io.FileWriter;
import java.io.IOException;

/**
 * Generate an ASCII code table showing decimal, hex, octal and HTML
 */
public class Asciitab
   {

   /**
    * Non displayed copyright message
    */
   private static final String EmbeddedCopyright =
   "copyright (c) 2001-2008 Roedy Green, Canadian Mind Products, http://mindprod.com";

   /**
    * generates table C:\temp\ascii.html
    *
    * @param args   not used
    */
   public static void main(String[] args)
      {
      generateAsciitab("C:/temp/ascii.html");

      } // end main

   /**
    * Generate ascii table
    *
    * @param fileName filename where to put the generated table
    */
   public static void generateAsciitab( String fileName)
      {
      try
         {
         FileWriter p = new FileWriter(fileName);
         p.write( "<table class=\"standard\">\n");
         p.write( "<tr><th colspan=\"6\">ASCII and Latin-1 Character Table</th></tr>");
         p.write( "<tr><th>Char</th><th>Dec</th><th>Hex</th><th>Octal</th><th>HTML</th><th>Notes</th></tr>");
         for ( char c=0; c<=0xff; c++ )
            {

            p.write("<tr>");

            /* displayable char */
            p.write("<td align=\"center\"><b>");
            p.write(asHTML(c));
            p.write("</b></td>");

            /* decimal */
            p.write("<td align=\"right\">");
            p.write(Integer.toString(c));
            p.write("</td>");

            /* hex */
            p.write("<td>");
            p.write("0x"+toLZ(c,2,16));
            p.write("</td>");

            /* octal */
            p.write("<td>");
            p.write(toLZ(c,4,8));
            p.write("</td>");

            /* HTML code */
            p.write("<td align=\"center\">");
            p.write(asQuotedHTML(c));
            p.write("</td>");

            /* notes */
            p.write("<td>");
            p.write(descs(c));
            p.write("</td>");

            p.write("</tr>\n");

            } // end for
         p.write("</table>");
         p.close();
         }
      catch ( IOException e )
         {

         }
      } // end generateAsciitab

   /**
    * Get description of a character
    *
    * @param c      character to describe
    *
    * @return string destribing character, or &nbsp; if none available.
    */
   static String descs( char c )
      {
      if ( 'A' <= c && c <= 'Z' )
         {
         return "upper case " + String.valueOf(c);
         }
      else if ( 'a' <= c && c <= 'z' )
         {
         return "lower case " + String.valueOf(c);
         }
      else if ( '0' <= c && c <= '9' )
         {
         return "digit " + String.valueOf(c);
         }
      else switch ( c )
            {
            case 0: return "NUL <b>nul</b>";
            case 1: return "SOH <b>s</b>tart <b>o</b>f <b>h</b>eader";
            case 2: return "STX <b>s</b>tart of <b>t</b>e<b>x</b>t";
            case 3: return "ETX <b>e</b>nd of <b>t</b>e<b>x</b>t";
            case 4: return "EOT <b>e</b>nd <b>o</b>f <b>t</b>ransmission";
            case 5: return "ENQ <b>e</b><b>nq</b>uiry";
            case 6: return "ACK <b>ack</b>nowledege";
            case 7: return "BEL <b>bel</b>l";
            case 8: return "BS <b>b</b>ack<b>s</b>pace [\\b]";
            case 9: return "HT <b>h</b>orizonal <b>t</b>ab [\\t]";
            case 10: return "LF <b>l</b>ine <b>f</b>eed [\\n]";
            case 11: return "VT <b>v</b>ertical <b>t</b>ab";
            case 12: return "FF <b>f</b>orm <b>f</b>eed [\\f]";
            case 13: return "CR <b>c</b>arriage <b>r</b>eturn [\\r]";
            case 14: return "SO <b>s</b>hift <b>o</b>ut";
            case 15: return "SI <b>s</b>hift <b>i</b>n";
            case 16: return "DLE <b>d</b>ata <b>l</b>ink <b>e</b>scape";
            case 17: return "DC1 <b>d</b>evice <b>c</b>ontrol <b>1</b>,"
               +" XON resume transmission";
            case 18: return "DC2 <b>d</b>evice <b>c</b>ontrol <b>2</b>";
            case 19: return "DC3 <b>d</b>evice <b>c</b>ontrol <b>3</b>,"
               + " XOFF pause transmission";
            case 20: return "DC4 <b>d</b>evice <b>c</b>ontrol <b>4</b>";
            case 21: return "NAK <b>n</b>egative <b>a</b>c<b>k</b>nowledge";
            case 22: return "SYN <b>syn</b>chronise";
            case 23: return "ETB <b>e</b>nd <b>t</b>ext <b>b</b>lock";
            case 24: return "CAN <b>can</b>cel";
            case 25: return "EM <b>e</b>nd <b>m</b>essage";
            case 26: return "SUB <b>sub</b>stitute";
            case 27: return "ESC <b>esc</b>ape";
            case 28: return "FS <b>f</b>ile <b>s</b>eparator";
            case 29: return "GS <b>g</b>roup <b>s</b>eparator";
            case 30: return "RS <b>r</b>ecord <b>s</b>eparator";
            case 31: return "US <b>u</b>nit <b>s</b>eparator";
            case 32: return "space";
            case 33: return "bang, exclamation";
            case 34: return "quote";
            case 35: return "sharp, number sign";
            case 36: return "dollar sign";
            case 37: return "percent";
            case 38: return "ampersand";
            case 39: return "apostrophe";
            case 40: return "left parenthesis";
            case 41: return "right parenthesis";
            case 42: return "star, asterisk";
            case 43: return "plus";
            case 44: return "comma";
            case 45: return "minus";
            case 46: return "period";
            case 47: return "slash, <b>not backslash!</b>";
            case 58: return "colon";
            case 59: return "semicolon";
            case 60: return "less than";
            case 61: return "equals";
            case 62: return "greater than";
            case 63: return "question mark";
            case 64: return "at sign";
            case 91: return "left square bracket";
            case 92: return "backslash, <b>not slash!</b>";
            case 93: return "right square bracket";
            case 94: return "hat, circumflex";
            case 95: return "underscore";
            case 96: return "grave, rhymes with have";
            case 123: return "left curly brace";
            case 124: return "vertical bar";
            case 125: return "right curly brace";
            case 126: return "tilde";
            case 127: return "DEL <b>del</b>ete";

               // the following are OCTAL because that'show PostScript specifies them
               // &xxx; codes are for Latin-1
            case 0241: return "PostScript " + "(&iexcl;) exclamdown";
            case 0242: return "PostScript " + "(&cent;) cent";
            case 0243: return "PostScript " + "(&pound;) sterling";
            case 0244: return "PostScript " + "(/) fraction";
            case 0245: return "PostScript " + "(&yen;) yen";
            case 0246: return "PostScript " + "(&#131;) florin";
            case 0247: return "PostScript " + "(&sect;) section";
            case 0250: return "PostScript " + "(&curren;) currency";
            case 0251: return "PostScript " + "(') quotesingle";
            case 0252: return "PostScript " + "(&#147;) quotedblleft";
            case 0253: return "PostScript " + "(&laquo;) guillemotleft";
            case 0254: return "PostScript " + "(&lt;) guilsinglleft";
            case 0255: return "PostScript " + "(&gt;) guilsinglright";
            case 0256: return "PostScript " + "fi ligature";
            case 0257: return "PostScript " + "fl ligature;";
            case 0261: return "PostScript " + "(&#150;) endash";
            case 0262: return "PostScript " + "(&#134;) dagger";
            case 0263: return "PostScript " + "(&middot;) periodcentered";
            case 0266: return "PostScript " + "(&para;) paragraph";
            case 0267: return "PostScript " + "(&#149;) bullet";
            case 0270: return "PostScript " + "(,) quotesinglbase";
            case 0271: return "PostScript " + "(&#132;) quotedblbase";
            case 0272: return "PostScript " + "(&#148;) quotedblright";
            case 0273: return "PostScript " + "(&raquo;) guillemotright";
            case 0274: return "PostScript " + "(&#133;) ellipsis";
            case 0275: return "PostScript " + "(&#137;) perthousand";
            case 0277: return "PostScript " + "(&iquest;) questiondown";
            case 0301: return "PostScript " + "(`) grave";
            case 0302: return "PostScript " + "(&acute;) acute";
            case 0303: return "PostScript " + "(^) circumflex";
            case 0304: return "PostScript " + "(~) tilde";
            case 0305: return "PostScript " + "(&macr;) macron, overbar accent";
            case 0306: return "PostScript " + "(<sup>u</sup>) breve, flattened u-shaped accent";
            case 0307: return "PostScript " + "(&#183;) dotaccent";
            case 0310: return "PostScript " + "(&uml;) dieresis";
            case 0312: return "PostScript " + "(&#176;) ring";
            case 0313: return "PostScript " + "(&cedil;) cedilla";
            case 0315: return "PostScript " + "(&#148;) hungarumlaut";
            case 0316: return "PostScript " + "(,) ogonek, reverse comma";
            case 0317: return "PostScript " + "(<sup>v</sup>) caron, flattened v-shaped accent";
            case 0320: return "PostScript " + "(&#151;) emdash";
            case 0341: return "PostScript " + "(&AElig;) AE";
            case 0343: return "PostScript " + "(&ordf;) ordfeminine";
            case 0350: return "PostScript " + "(L/) Lslash, L with / overstrike";
            case 0351: return "PostScript " + "(&Oslash;) Oslash";
            case 0352: return "PostScript " + "(&#140;) OE";
            case 0353: return "PostScript " + "(&ordm;) ordmasculine";
            case 0361: return "PostScript " + "(&aelig;) ae";
            case 0365: return "PostScript " + "(1) dotlessi, i without dot";
            case 0370: return "PostScript " + "(l/) l with / overstrike";
            case 0371: return "PostScript " + "(&oslash;) oslash";
            case 0372: return "PostScript " + "(&#156;) oe";
            case 0373: return "PostScript " + "(&szlig;) germandbls";
            default: return "&nbsp;";
            }
      }
   /**
    * how you display this character in HTML
    *
    * @param c      the character you want to render
    *
    * @return html for rendering the character
    */
   static String asHTML ( char c )
      {
      if ( c < 32 )
         {
         /* control char */
         return "^" + (char)(c+64);
         }
      else if ( c > 126 )
         {
         /* high ascii */
         return "&#" + Integer.toString(c) + ";";
         }
      else
         {
         switch ( c )
            {
            case 32: return "&nbsp;";
            case 38: return "&amp;";
            case 34: return "&quot;";
            case 60: return "&lt;";
            case 62: return "&gt;";
               /* ordinary char */
            default: return String.valueOf(c);
            }
         }
      }

   /**
   * how you display this character in HTML, quoted so you can see the code
   *
   * @param c      the character you want to render
   *
   * @return html for rendering the character
   */
   static String asQuotedHTML (char c )
      {
      String result = asHTML(c);
      if ( result.charAt(0) == '&' )
         {
         return "&amp;" + result.substring(1);
         }
      else
         {
         return result;
         }

      }

   /**
   * Convert an integer to a String, with left zeroes.
   *
   * @param i      the integer to be converted
   *
   * @param len    len the length of the resulting string
   *
   * @param base   base 10=decimal 16=hex 8=octal
   *
   * @return String representation of the int e.g. 007
   */
   public final static String toLZ( int i, int len, int base)
      {
      // Since String is final, we could not add this method there.
      String s = Integer.toString(i, base);
      if ( s.length() > len ) return s.substring(0,len);
      else if ( s.length() < len )
         // pad on left with zeros
         return "000000000000000000000000000".substring(0,len  - s.length()) + s;
      else return s;
      } // end toLZ

   }