package org.stfm.texdoclet; import javax.swing.text.MutableAttributeSet; import javax.swing.text.html.HTML; /** * This class provides support for converting HTML tables into <TEX * txt="\LaTeX{}">LaTeX</TEX> tables. Some of the things <b>NOT</b> implemented * include the following: * <ul> * <li>valign attributes are not processed, but align= is. * <li>rowspan attributes are not processed, but colspan= is. * <li>the argument to border= in the table tag is not used to control line size * </ul> * <br> * Here is an example table. * <p> * <table border bgcolor="#DDDDDD"> * <tr> * <th>Column 1 Heading * <th>Column two heading * <th>Column three heading * <tr> * <td>data * <td colspan=2>Span two columns * <tr> * <td><i>more data</i> * <td align=right>right * <td align=left>left * <tr> * <td colspan=3> * <table border=5 bgcolor="#EEEEEE"> * <tr> * <th colspan=3>A nested table example * <tr> * <th>Column one Heading</th> * <th>Column two heading</th> * <th>Column three heading</th> * <tr> * <td>data</td> * <td colspan=2>Span two columns</td> * <tr> * <td><i>more data</i></td> * <td align=right>right</td> * <td align=left>left</td> * <tr> * <td> * * <pre> * 1 * 2 * 3 * 4 * </pre> * * </td> * <td> * * <pre> * first line * second line * third line * fourth line * </pre> * * </td> * </table> * </table> * * @version $Revision: 1.2 $ * @author Gregg Wonderly - C2 Technologies Inc. */ public class TableInfo { private StringBuffer originalBuffer; private StringBuffer ret; private int colcnt = 0; private int rowcnt = 0; private int totalcolcnt = 0; private boolean border = false; private int bordwid; private boolean parboxed; private double red = -1.0; private double blue = -1.0; private double green = -1.0; private static int tblcnt; private int tblno; private String tc; int hasNumAttr(HTML.Attribute attr, MutableAttributeSet attrSet) { String val = (String) attrSet.getAttribute(attr); if (val == null) { return -1; } try { return Integer.parseInt(val); } catch (Exception ex) { return -1; } } /** * Constructs a new table object and starts processing of the table by * scanning the <code><table></code> passed to count columns. * * //@param p // properties found on the <code><table></code> tag * //@param ret // the result buffer that will contain the output //@param * table // the input string that has the entire table definition in it. * //@param off // the offset into <code><table></code> where scanning * // should start */ public StringBuffer startTable(StringBuffer org, MutableAttributeSet attrSet) { originalBuffer = org; ret = new StringBuffer(); tblno = tblcnt++; tc = "" + (char) ('a' + (tblno / (26 * 26))) + (char) ((tblno / 26) + 'a') + (char) ((tblno % 26) + 'a'); String val = (String) attrSet.getAttribute(HTML.Attribute.BORDER); border = false; if (val != null) { border = true; bordwid = 2; if (val.equals("") == false) { try { bordwid = Integer.parseInt(val); } catch (Exception ex) { } if (bordwid == 0) { border = false; } } } String bgcolor = (String) attrSet.getAttribute(HTML.Attribute.BGCOLOR); if (bgcolor != null) { try { if (bgcolor.length() != 7 && bgcolor.charAt(0) == '#') { throw new NumberFormatException(); } red = Integer.decode("#" + bgcolor.substring(1, 3)) .doubleValue(); blue = Integer.decode("#" + bgcolor.substring(3, 5)) .doubleValue(); green = Integer.decode("#" + bgcolor.substring(5, 7)) .doubleValue(); red /= 255.0; blue /= 255.0; green /= 255.0; } catch (NumberFormatException e) { red = 1.0; blue = 1.0; green = 1.0; } } return ret; } /** * Ends the table, closing the last row as needed * */ public StringBuffer endTable() { originalBuffer.append("\n% Table #" + tblno + "\n\\begin{center}\n"); int col = totalcolcnt; if (col == 0) { col = 1; } for (int i = 0; i < col; ++i) { String cc = "" + (char) ('a' + (i / (26 * 26))) + (char) ((i / 26) + 'a') + (char) ((i % 26) + 'a'); originalBuffer.append("\\newlength{\\tbl" + tc + "c" + cc + "w}\n"); // originalBuffer.append("\\setlength{\\tbl"+tc+"c"+cc+"w}{"+(1.0/col)+"\\hsize}\n"); originalBuffer.append("\\setlength{\\tbl" + tc + "c" + cc + "w}{" + (TeXDoclet.tableWidthScale / col) + "\\linewidth}\n"); } if (red != -1.0 && green != -1.0 && blue != -1.0) { originalBuffer.append("\\colorbox[rgb]{" + Double.toString(red) + "," + Double.toString(blue) + "," + Double.toString(green) + "}{"); } originalBuffer.append("\\begin{tabular}{"); if (border) { originalBuffer.append("|"); } for (int i = 0; i < col; ++i) { String cc = "" + (char) ('a' + (i / (26 * 26))) + (char) ((i / 26) + 'a') + (char) ((i % 26) + 'a'); originalBuffer.append("p{\\tbl" + tc + "c" + cc + "w}"); if (border) { originalBuffer.append("|"); } } originalBuffer.append("}\n"); // Append the cached table originalBuffer.append(ret); originalBuffer.append("\\end{tabular}\n"); if (red != -1.0 && green != -1.0 && blue != -1.0) { originalBuffer.append("}\n"); } originalBuffer.append("\\end{center}\n"); return originalBuffer; } /** * Starts a new column, possibly closing the current column if needed * * //@param ret The output buffer to put <TEX txt="\LaTeXe{}">LaTeX2e</TEX> * into. //@param p the properties from the <code><td></code> tag */ public void startCol(MutableAttributeSet attrSet) { int span = hasNumAttr(HTML.Attribute.COLSPAN, attrSet); if (colcnt > 0) { ret.append(" & "); } String align = (String) attrSet.getAttribute(HTML.Attribute.ALIGN); if (align != null && span < 0) { span = 1; } if (span > 0) { ret.append("\\multicolumn{" + span + "}{"); if (border && colcnt == 0) { ret.append("|"); } String cc = "" + (char) ('a' + (colcnt / (26 * 26))) + (char) ((colcnt / 26) + 'a') + (char) ((colcnt % 26) + 'a'); if (align != null) { String h = align.substring(0, 1); if ("rR".indexOf(h) >= 0) { ret.append("r"); } else if ("lL".indexOf(h) >= 0) { ret.append("p{\\tbl" + tc + "c" + cc + "w}"); } else if ("cC".indexOf(h) >= 0) { ret.append("p{\\tbl" + tc + "c" + cc + "w}"); } } else { ret.append("p{\\tbl" + tc + "c" + cc + "w}"); } if (border) { ret.append("|"); } ret.append("}"); } String wid = (String) attrSet.getAttribute("texwidth"); ret.append("{"); if (wid != null) { ret.append("\\parbox{" + wid + "}{\\vskip 1ex "); parboxed = true; } colcnt++; totalcolcnt = totalcolcnt > colcnt ? totalcolcnt : colcnt; } /** * Starts a new Heading column, possibly closing the current column if * needed. A Heading column has a Bold Face font directive around it. * * //@param ret The output buffer to put <TEX txt="\LaTeXe{}">LaTeX2e</TEX> * into. //@param p The properties from the <code><th></code> tag */ public void startHeadCol(MutableAttributeSet attrSet) { startCol(attrSet); ret.append("\\bf "); } /** * Ends the current column. * * //@param ret The output buffer to put <TEX txt="\LaTeXe{}">LaTeX2e</TEX> * into. */ public void endCol() { if (parboxed) { ret.append("\\vskip 1ex}"); } parboxed = false; ret.append("}"); } /** * Starts a new row, possibly closing the current row if needed * * //@param ret The output buffer to put <TEX txt="\LaTeX{}">LaTeX</TEX> * into. //@param p The properties from the <code><tr></code> tag */ public void startRow(MutableAttributeSet attrSet) { if (rowcnt == 0) { if (border) { ret.append(" \\hline "); } } colcnt = 0; ++rowcnt; } /** * Ends the current row. * * // @param ret The output buffer to put <TEX txt="\LaTeXe{}">LaTeX2e</TEX> * into. */ public void endRow() { ret.append(" \\\\"); if (border) { ret.append(" \\hline"); } ret.append("\n"); } }