// Decompiled by DJ v3.0.0.63 Copyright 2002 Atanas Neshkov  Date: 6/22/2007 12:59:51 PM
// Home Page : http://members.fortunecity.com/neshkov/dj.html  - Check often for new version!
// Decompiler options: packimports(3) 
// Source File Name:   Table.java

package com.opdm.text;

import com.opdm.text.markup.MarkupParser;
import java.awt.*;
import java.io.PrintStream;
import java.util.*;

// Referenced classes of package com.opdm.text:
//            Rectangle, Element, MarkupAttributes, BadElementException, 
//            Cell, Row, ElementListener, DocumentException, 
//            Phrase, ExceptionConverter

public class Table extends Rectangle
    implements Element, MarkupAttributes
{

    public Table(int columns)
        throws BadElementException
    {
        this(columns, 1);
    }

    public Table(int columns, int rows)
        throws BadElementException
    {
        super(0.0F, 0.0F, 0.0F, 0.0F);
        curPosition = new Point(0, 0);
        this.rows = new ArrayList();
        defaultLayout = new Cell(true);
        lastHeaderRow = -1;
        alignment = 1;
        widthPercentage = 80F;
        absWidth = "";
        mDebug = false;
        mTableInserted = false;
        mAutoFillEmptyCells = false;
        tableFitsPage = false;
        cellsFitPage = false;
        offset = (0.0F / 0.0F);
        alternatingRowAttributes = null;
        setBorder(15);
        setBorderWidth(1.0F);
        defaultLayout.setBorder(15);
        if(columns <= 0)
            throw new BadElementException("A table should have at least 1 column.");
        this.columns = columns;
        for(int i = 0; i < rows; i++)
            this.rows.add(new Row(columns));

        curPosition = new Point(0, 0);
        widths = new float[columns];
        float width = 100F / (float)columns;
        for(int i = 0; i < columns; i++)
            widths[i] = width;

    }

    public Table(Properties attributes)
    {
        super(0.0F, 0.0F, 0.0F, 0.0F);
        curPosition = new Point(0, 0);
        rows = new ArrayList();
        defaultLayout = new Cell(true);
        lastHeaderRow = -1;
        alignment = 1;
        widthPercentage = 80F;
        absWidth = "";
        mDebug = false;
        mTableInserted = false;
        mAutoFillEmptyCells = false;
        tableFitsPage = false;
        cellsFitPage = false;
        offset = (0.0F / 0.0F);
        alternatingRowAttributes = null;
        setBorder(15);
        setBorderWidth(1.0F);
        defaultLayout.setBorder(15);
        String value = (String)attributes.remove("columns");
        if(value == null)
        {
            columns = 1;
        } else
        {
            columns = Integer.parseInt(value);
            if(columns <= 0)
                columns = 1;
        }
        rows.add(new Row(columns));
        curPosition.setLocation(0, curPosition.y);
        if((value = (String)attributes.remove("lastHeaderRow")) != null)
            setLastHeaderRow(Integer.parseInt(value));
        if((value = (String)attributes.remove("align")) != null)
            setAlignment(value);
        if((value = (String)attributes.remove("cellspacing")) != null)
            setSpacing(Float.valueOf(value + "f").floatValue());
        if((value = (String)attributes.remove("cellpadding")) != null)
            setPadding(Float.valueOf(value + "f").floatValue());
        if((value = (String)attributes.remove("offset")) != null)
            setOffset(Float.valueOf(value + "f").floatValue());
        if((value = (String)attributes.remove("width")) != null)
            if(value.endsWith("%"))
                setWidth(Float.valueOf(value.substring(0, value.length() - 1) + "f").floatValue());
            else
                setAbsWidth(value);
        widths = new float[columns];
        for(int i = 0; i < columns; i++)
            widths[i] = 0.0F;

        if((value = (String)attributes.remove("widths")) != null)
        {
            StringTokenizer widthTokens = new StringTokenizer(value, ";");
            int i;
            for(i = 0; widthTokens.hasMoreTokens(); i++)
            {
                value = widthTokens.nextToken();
                widths[i] = Float.valueOf(value + "f").floatValue();
            }

            columns = i;
        }
        if((value = (String)attributes.remove("tablefitspage")) != null)
            tableFitsPage = (new Boolean(value)).booleanValue();
        if((value = (String)attributes.remove("cellsfitpage")) != null)
            cellsFitPage = (new Boolean(value)).booleanValue();
        if((value = (String)attributes.remove("borderwidth")) != null)
            setBorderWidth(Float.valueOf(value + "f").floatValue());
        int border = 0;
        if((value = (String)attributes.remove("left")) != null && (new Boolean(value)).booleanValue())
            border |= 4;
        if((value = (String)attributes.remove("right")) != null && (new Boolean(value)).booleanValue())
            border |= 8;
        if((value = (String)attributes.remove("top")) != null && (new Boolean(value)).booleanValue())
            border |= 1;
        if((value = (String)attributes.remove("bottom")) != null && (new Boolean(value)).booleanValue())
            border |= 2;
        setBorder(border);
        String r = (String)attributes.remove("red");
        String g = (String)attributes.remove("green");
        String b = (String)attributes.remove("blue");
        if(r != null || g != null || b != null)
        {
            int red = 0;
            int green = 0;
            int blue = 0;
            if(r != null)
                red = Integer.parseInt(r);
            if(g != null)
                green = Integer.parseInt(g);
            if(b != null)
                blue = Integer.parseInt(b);
            setBorderColor(new Color(red, green, blue));
        } else
        if((value = attributes.getProperty("bordercolor")) != null)
            setBorderColor(MarkupParser.decodeColor(value));
        r = (String)attributes.remove("bgred");
        g = (String)attributes.remove("bggreen");
        b = (String)attributes.remove("bgblue");
        if(r != null || g != null || b != null)
        {
            int red = 0;
            int green = 0;
            int blue = 0;
            if(r != null)
                red = Integer.parseInt(r);
            if(g != null)
                green = Integer.parseInt(g);
            if(b != null)
                blue = Integer.parseInt(b);
            setBackgroundColor(new Color(red, green, blue));
        } else
        if((value = (String)attributes.remove("backgroundcolor")) != null)
            setBackgroundColor(MarkupParser.decodeColor(value));
        if((value = (String)attributes.remove("grayfill")) != null)
            setGrayFill(Float.valueOf(value + "f").floatValue());
        if(attributes.size() > 0)
            setMarkupAttributes(attributes);
    }

    public boolean process(ElementListener listener)
    {
        try
        {
            return listener.add(this);
        }
        catch(DocumentException de)
        {
            return false;
        }
    }

    public void setDebug(boolean aDebug)
    {
        mDebug = aDebug;
    }

    public void setAutoFillEmptyCells(boolean aDoAutoFill)
    {
        mAutoFillEmptyCells = aDoAutoFill;
    }

    public void setTableFitsPage(boolean fitPage)
    {
        tableFitsPage = fitPage;
        if(fitPage)
            setCellsFitPage(true);
    }

    public void setCellsFitPage(boolean fitPage)
    {
        cellsFitPage = fitPage;
    }

    public boolean hasToFitPageTable()
    {
        return tableFitsPage;
    }

    public boolean hasToFitPageCells()
    {
        return cellsFitPage;
    }

    public void setOffset(float offset)
    {
        this.offset = offset;
    }

    public float getOffset()
    {
        return offset;
    }

    public int type()
    {
        return 22;
    }

    public ArrayList getChunks()
    {
        return new ArrayList();
    }

    public void addCell(Cell aCell, int row, int column)
        throws BadElementException
    {
        addCell(aCell, new Point(row, column));
    }

    public void addCell(Cell aCell, Point aLocation)
        throws BadElementException
    {
        if(aCell == null)
            throw new NullPointerException("addCell - cell has null-value");
        if(aLocation == null)
            throw new NullPointerException("addCell - point has null-value");
        if(aCell.isTable())
            insertTable((Table)aCell.getElements().next(), aLocation);
        if(mDebug)
        {
            if(aLocation.x < 0)
                throw new BadElementException("row coordinate of location must be >= 0");
            if(aLocation.y <= 0 && aLocation.y > columns)
                throw new BadElementException("column coordinate of location must be >= 0 and < nr of columns");
            if(!isValidLocation(aCell, aLocation))
                throw new BadElementException("Adding a cell at the location (" + aLocation.x + "," + aLocation.y + ") with a colspan of " + aCell.colspan() + " and a rowspan of " + aCell.rowspan() + " is illegal (beyond boundaries/overlapping).");
        }
        if(aCell.border() == -1)
            aCell.setBorder(defaultLayout.border());
        aCell.fill();
        placeCell(rows, aCell, aLocation);
        setCurrentLocationToNextValidPosition(aLocation);
    }

    public void addCell(Cell cell)
    {
        try
        {
            addCell(cell, curPosition);
        }
        catch(BadElementException badelementexception) { }
    }

    public void addCell(Phrase content)
        throws BadElementException
    {
        addCell(content, curPosition);
    }

    public void addCell(Phrase content, Point location)
        throws BadElementException
    {
        Cell cell = new Cell(content);
        cell.setBorder(defaultLayout.border());
        cell.setBorderWidth(defaultLayout.borderWidth());
        cell.setBorderColor(defaultLayout.borderColor());
        cell.setBackgroundColor(defaultLayout.backgroundColor());
        cell.setGrayFill(defaultLayout.grayFill());
        cell.setHorizontalAlignment(defaultLayout.horizontalAlignment());
        cell.setVerticalAlignment(defaultLayout.verticalAlignment());
        cell.setColspan(defaultLayout.colspan());
        cell.setRowspan(defaultLayout.rowspan());
        addCell(cell, location);
    }

    public void addCell(String content)
        throws BadElementException
    {
        addCell(new Phrase(content), curPosition);
    }

    public void addCell(String content, Point location)
        throws BadElementException
    {
        addCell(new Phrase(content), location);
    }

    public void insertTable(Table aTable)
    {
        if(aTable == null)
        {
            throw new NullPointerException("insertTable - table has null-value");
        } else
        {
            insertTable(aTable, curPosition);
            return;
        }
    }

    public void insertTable(Table aTable, int row, int column)
    {
        if(aTable == null)
        {
            throw new NullPointerException("insertTable - table has null-value");
        } else
        {
            insertTable(aTable, new Point(row, column));
            return;
        }
    }

    public void insertTable(Table aTable, Point aLocation)
    {
        if(aTable == null)
            throw new NullPointerException("insertTable - table has null-value");
        if(aLocation == null)
            throw new NullPointerException("insertTable - point has null-value");
        mTableInserted = true;
        aTable.complete();
        if(mDebug && aLocation.y > columns)
            System.err.println("insertTable -- wrong columnposition(" + aLocation.y + ") of location; max =" + columns);
        int rowCount = (aLocation.x + 1) - rows.size();
        int i = 0;
        if(rowCount > 0)
            for(; i < rowCount; i++)
                rows.add(new Row(columns));

        ((Row)rows.get(aLocation.x)).setElement(aTable, aLocation.y);
        setCurrentLocationToNextValidPosition(aLocation);
    }

    public void complete()
    {
        if(mTableInserted)
        {
            mergeInsertedTables();
            mTableInserted = false;
        }
        if(mAutoFillEmptyCells)
            fillEmptyMatrixCells();
        if(alternatingRowAttributes != null)
        {
            Properties even = new Properties();
            Properties odd = new Properties();
            String name;
            String value[];
            for(Iterator iterator = alternatingRowAttributes.keySet().iterator(); iterator.hasNext(); odd.setProperty(name, value[1]))
            {
                name = String.valueOf(iterator.next());
                value = (String[])alternatingRowAttributes.get(name);
                even.setProperty(name, value[0]);
            }

            for(int i = lastHeaderRow + 1; i < rows.size(); i++)
            {
                Row row = (Row)rows.get(i);
                row.setMarkupAttributes(i % 2 != 0 ? odd : even);
            }

        }
    }

    public void setDefaultCellBorder(int value)
    {
        defaultLayout.setBorder(value);
    }

    public void setDefaultCellBorderWidth(float value)
    {
        defaultLayout.setBorderWidth(value);
    }

    public void setDefaultCellBorderColor(Color color)
    {
        defaultLayout.setBorderColor(color);
    }

    public void setDefaultCellBackgroundColor(Color color)
    {
        defaultLayout.setBackgroundColor(color);
    }

    public void setDefaultCellGrayFill(float value)
    {
        if(value >= 0.0F && value <= 1.0F)
            defaultLayout.setGrayFill(value);
    }

    public void setDefaultHorizontalAlignment(int value)
    {
        defaultLayout.setHorizontalAlignment(value);
    }

    public void setDefaultVerticalAlignment(int value)
    {
        defaultLayout.setVerticalAlignment(value);
    }

    public void setDefaultRowspan(int value)
    {
        defaultLayout.setRowspan(value);
    }

    public void setDefaultColspan(int value)
    {
        defaultLayout.setColspan(value);
    }

    private void assumeTableDefaults(Cell aCell)
    {
        if(aCell.border() == -1)
            aCell.setBorder(defaultLayout.border());
        if(aCell.borderWidth() == -1F)
            aCell.setBorderWidth(defaultLayout.borderWidth());
        if(aCell.borderColor() == null)
            aCell.setBorderColor(defaultLayout.borderColor());
        if(aCell.backgroundColor() == null)
            aCell.setBackgroundColor(defaultLayout.backgroundColor());
        if(aCell.grayFill() == -1F)
            aCell.setGrayFill(defaultLayout.grayFill());
        if(aCell.horizontalAlignment() == -1)
            aCell.setHorizontalAlignment(defaultLayout.horizontalAlignment());
        if(aCell.verticalAlignment() == -1)
            aCell.setVerticalAlignment(defaultLayout.verticalAlignment());
    }

    public void deleteColumn(int column)
        throws BadElementException
    {
        float newWidths[] = new float[--columns];
        for(int i = 0; i < column; i++)
            newWidths[i] = widths[i];

        for(int i = column; i < columns; i++)
            newWidths[i] = widths[i + 1];

        setWidths(newWidths);
        for(int i = 0; i < columns; i++)
            newWidths[i] = widths[i];

        widths = newWidths;
        int size = rows.size();
        for(int i = 0; i < size; i++)
        {
            Row row = (Row)rows.get(i);
            row.deleteColumn(column);
            rows.set(i, row);
        }

        if(column == columns)
            curPosition.setLocation(curPosition.x + 1, 0);
    }

    public boolean deleteRow(int row)
    {
        if(row < 0 || row >= rows.size())
        {
            return false;
        } else
        {
            rows.remove(row);
            curPosition.setLocation(curPosition.x - 1, curPosition.y);
            return true;
        }
    }

    public boolean deleteLastRow()
    {
        return deleteRow(rows.size() - 1);
    }

    public int endHeaders()
    {
        lastHeaderRow = curPosition.x - 1;
        return lastHeaderRow;
    }

    public void setLastHeaderRow(int value)
    {
        lastHeaderRow = value;
    }

    public void setAlignment(int value)
    {
        alignment = value;
    }

    public void setAlignment(String alignment)
    {
        if("Left".equalsIgnoreCase(alignment))
        {
            this.alignment = 0;
            return;
        }
        if("right".equalsIgnoreCase(alignment))
        {
            this.alignment = 2;
            return;
        } else
        {
            this.alignment = 1;
            return;
        }
    }

    public void setSpaceInsideCell(float value)
    {
        cellpadding = value;
    }

    public void setSpaceBetweenCells(float value)
    {
        cellspacing = value;
    }

    public void setPadding(float value)
    {
        cellpadding = value;
    }

    public void setSpacing(float value)
    {
        cellspacing = value;
    }

    /**
     * @deprecated Method setCellpadding is deprecated
     */

    public void setCellpadding(float value)
    {
        cellspacing = value;
    }

    /**
     * @deprecated Method setCellspacing is deprecated
     */

    public void setCellspacing(float value)
    {
        cellpadding = value;
    }

    public void setWidth(float width)
    {
        widthPercentage = width;
    }

    public void setAbsWidth(String width)
    {
        absWidth = width;
    }

    public void setWidths(float widths[])
        throws BadElementException
    {
        if(widths.length != columns)
            throw new BadElementException("Wrong number of columns.");
        float hundredPercent = 0.0F;
        for(int i = 0; i < columns; i++)
            hundredPercent += widths[i];

        this.widths[columns - 1] = 100F;
        for(int i = 0; i < columns - 1; i++)
        {
            float width = (100F * widths[i]) / hundredPercent;
            this.widths[i] = width;
            this.widths[columns - 1] -= width;
        }

    }

    public void setWidths(int widths[])
        throws DocumentException
    {
        float tb[] = new float[widths.length];
        for(int k = 0; k < widths.length; k++)
            tb[k] = widths[k];

        setWidths(tb);
    }

    public int columns()
    {
        return columns;
    }

    public int size()
    {
        return rows.size();
    }

    public float[] getProportionalWidths()
    {
        return widths;
    }

    public Iterator iterator()
    {
        return rows.iterator();
    }

    public int alignment()
    {
        return alignment;
    }

    public float cellpadding()
    {
        return cellpadding;
    }

    public float cellspacing()
    {
        return cellspacing;
    }

    public float widthPercentage()
    {
        return widthPercentage;
    }

    public String absWidth()
    {
        return absWidth;
    }

    public int firstDataRow()
    {
        return lastHeaderRow + 1;
    }

    public Dimension getDimension()
    {
        return new Dimension(columns, rows.size());
    }

    public Object getElement(int row, int column)
    {
        return ((Row)rows.get(row)).getCell(column);
    }

    private void mergeInsertedTables()
    {
        int i = 0;
        int j = 0;
        float lNewWidths[] = (float[])null;
        int lDummyWidths[] = new int[columns];
        float lDummyColumnWidths[][] = new float[columns][];
        int lDummyHeights[] = new int[rows.size()];
        ArrayList newRows = null;
        boolean isTable = false;
        int lTotalRows = 0;
        int lTotalColumns = 0;
        int lNewMaxRows = 0;
        int lNewMaxColumns = 0;
        Table lDummyTable = null;
        for(j = 0; j < columns; j++)
        {
            lNewMaxColumns = 1;
            for(i = 0; i < rows.size(); i++)
                if(com.opdm.text.Table.class.isInstance(((Row)rows.get(i)).getCell(j)))
                {
                    isTable = true;
                    lDummyTable = (Table)((Row)rows.get(i)).getCell(j);
                    if(lDummyTable.getDimension().width > lNewMaxColumns)
                    {
                        lNewMaxColumns = lDummyTable.getDimension().width;
                        lDummyColumnWidths[j] = lDummyTable.widths;
                    }
                }

            lTotalColumns += lNewMaxColumns;
            lDummyWidths[j] = lNewMaxColumns;
        }

        for(i = 0; i < rows.size(); i++)
        {
            lNewMaxRows = 1;
            for(j = 0; j < columns; j++)
                if(com.opdm.text.Table.class.isInstance(((Row)rows.get(i)).getCell(j)))
                {
                    isTable = true;
                    lDummyTable = (Table)((Row)rows.get(i)).getCell(j);
                    if(lDummyTable.getDimension().height > lNewMaxRows)
                        lNewMaxRows = lDummyTable.getDimension().height;
                }

            lTotalRows += lNewMaxRows;
            lDummyHeights[i] = lNewMaxRows;
        }

        if(lTotalColumns != columns || lTotalRows != rows.size() || isTable)
        {
            lNewWidths = new float[lTotalColumns];
            int lDummy = 0;
            for(int tel = 0; tel < widths.length; tel++)
                if(lDummyWidths[tel] != 1)
                {
                    for(int tel2 = 0; tel2 < lDummyWidths[tel]; tel2++)
                    {
                        lNewWidths[lDummy] = (widths[tel] * lDummyColumnWidths[tel][tel2]) / 100F;
                        lDummy++;
                    }

                } else
                {
                    lNewWidths[lDummy] = widths[tel];
                    lDummy++;
                }

            newRows = new ArrayList(lTotalRows);
            for(i = 0; i < lTotalRows; i++)
                newRows.add(new Row(lTotalColumns));

            int lDummyRow = 0;
            int lDummyColumn = 0;
            Object lDummyElement = null;
            for(i = 0; i < rows.size(); i++)
            {
                lDummyColumn = 0;
                lNewMaxRows = 1;
                for(j = 0; j < columns; j++)
                {
                    if(com.opdm.text.Table.class.isInstance(((Row)rows.get(i)).getCell(j)))
                    {
                        lDummyTable = (Table)((Row)rows.get(i)).getCell(j);
                        for(int k = 0; k < lDummyTable.getDimension().height; k++)
                        {
                            for(int l = 0; l < lDummyTable.getDimension().width; l++)
                            {
                                lDummyElement = lDummyTable.getElement(k, l);
                                if(lDummyElement != null)
                                    ((Row)newRows.get(k + lDummyRow)).addElement(lDummyElement, l + lDummyColumn);
                            }

                        }

                    } else
                    {
                        Object aElement = getElement(i, j);
                        if(com.opdm.text.Cell.class.isInstance(aElement))
                        {
                            ((Cell)aElement).setRowspan((((Cell)((Row)rows.get(i)).getCell(j)).rowspan() + lDummyHeights[i]) - 1);
                            ((Cell)aElement).setColspan((((Cell)((Row)rows.get(i)).getCell(j)).colspan() + lDummyWidths[j]) - 1);
                            placeCell(newRows, (Cell)aElement, new Point(lDummyRow, lDummyColumn));
                        }
                    }
                    lDummyColumn += lDummyWidths[j];
                }

                lDummyRow += lDummyHeights[i];
            }

            columns = lTotalColumns;
            rows = newRows;
            widths = lNewWidths;
        }
    }

    private void fillEmptyMatrixCells()
    {
        try
        {
            for(int i = 0; i < rows.size(); i++)
            {
                for(int j = 0; j < columns; j++)
                    if(!((Row)rows.get(i)).isReserved(j))
                        addCell(defaultLayout, new Point(i, j));

            }

        }
        catch(BadElementException bee)
        {
            throw new ExceptionConverter(bee);
        }
    }

    private boolean isValidLocation(Cell aCell, Point aLocation)
    {
        if(aLocation.x < rows.size())
        {
            if(aLocation.y + aCell.colspan() > columns)
                return false;
            int difx = rows.size() - aLocation.x <= aCell.rowspan() ? rows.size() - aLocation.x : aCell.rowspan();
            int dify = columns - aLocation.y <= aCell.colspan() ? columns - aLocation.y : aCell.colspan();
            for(int i = aLocation.x; i < aLocation.x + difx; i++)
            {
                for(int j = aLocation.y; j < aLocation.y + dify; j++)
                    if(((Row)rows.get(i)).isReserved(j))
                        return false;

            }

        } else
        if(aLocation.y + aCell.colspan() > columns)
            return false;
        return true;
    }

    private void placeCell(ArrayList someRows, Cell aCell, Point aPosition)
    {
        Row row = null;
        int lColumns = ((Row)someRows.get(0)).columns();
        int rowCount = (aPosition.x + aCell.rowspan()) - someRows.size();
        assumeTableDefaults(aCell);
        if(aPosition.x + aCell.rowspan() > someRows.size())
        {
            for(int i = 0; i < rowCount; i++)
            {
                row = new Row(lColumns);
                someRows.add(row);
            }

        }
        for(int i = aPosition.x + 1; i < aPosition.x + aCell.rowspan(); i++)
            if(!((Row)someRows.get(i)).reserve(aPosition.y, aCell.colspan()))
                throw new RuntimeException("addCell - error in reserve");

        row = (Row)someRows.get(aPosition.x);
        row.addElement(aCell, aPosition.y);
    }

    public void addColumns(int aColumns)
    {
        ArrayList newRows = new ArrayList(rows.size());
        int newColumns = columns + aColumns;
        for(int i = 0; i < rows.size(); i++)
        {
            Row row = new Row(newColumns);
            for(int j = 0; j < columns; j++)
                row.setElement(((Row)rows.get(i)).getCell(j), j);

            for(int j = columns; j < newColumns && i < curPosition.x; j++)
                row.setElement(defaultLayout, j);

            newRows.add(row);
        }

        float newWidths[] = new float[newColumns];
        for(int j = 0; j < columns; j++)
            newWidths[j] = widths[j];

        for(int j = columns; j < newColumns; j++)
            newWidths[j] = 0.0F;

        columns = newColumns;
        widths = newWidths;
        rows = newRows;
    }

    public float[] getWidths(float left, float totalWidth)
    {
        float w[] = new float[columns + 1];
        switch(alignment)
        {
        case 0: // '\0'
            w[0] = left;
            break;

        case 2: // '\002'
            w[0] = left + (totalWidth * (100F - widthPercentage)) / 100F;
            break;

        case 1: // '\001'
        default:
            w[0] = left + (totalWidth * (100F - widthPercentage)) / 200F;
            break;
        }
        totalWidth = (totalWidth * widthPercentage) / 100F;
        for(int i = 1; i < columns; i++)
            w[i] = w[i - 1] + (widths[i - 1] * totalWidth) / 100F;

        w[columns] = w[0] + totalWidth;
        return w;
    }

    private void setCurrentLocationToNextValidPosition(Point aLocation)
    {
        int i = aLocation.x;
        int j = aLocation.y;
        do
            if(j + 1 == columns)
            {
                i++;
                j = 0;
            } else
            {
                j++;
            }
        while(i < rows.size() && j < columns && ((Row)rows.get(i)).isReserved(j));
        curPosition = new Point(i, j);
    }

    public static boolean isTag(String tag)
    {
        return "table".equals(tag);
    }

    public void setAlternatingRowAttribute(String name, String value0, String value1)
    {
        if(value0 == null || value1 == null)
        {
            throw new NullPointerException("MarkupTable#setAlternatingRowAttribute(): null values are not permitted.");
        } else
        {
            alternatingRowAttributes = alternatingRowAttributes != null ? alternatingRowAttributes : new Hashtable();
            String value[] = (String[])alternatingRowAttributes.get(name);
            value = value != null ? value : new String[2];
            value[0] = value0;
            value[1] = value1;
            alternatingRowAttributes.put(name, value);
            return;
        }
    }

    public float top()
    {
        throw new UnsupportedOperationException("Dimensions of a Table can't be calculated. See the FAQ.");
    }

    public float bottom()
    {
        throw new UnsupportedOperationException("Dimensions of a Table can't be calculated. See the FAQ.");
    }

    public float left()
    {
        throw new UnsupportedOperationException("Dimensions of a Table can't be calculated. See the FAQ.");
    }

    public float right()
    {
        throw new UnsupportedOperationException("Dimensions of a Table can't be calculated. See the FAQ.");
    }

    public float top(int margin)
    {
        throw new UnsupportedOperationException("Dimensions of a Table can't be calculated. See the FAQ.");
    }

    public float bottom(int margin)
    {
        throw new UnsupportedOperationException("Dimensions of a Table can't be calculated. See the FAQ.");
    }

    public float left(int margin)
    {
        throw new UnsupportedOperationException("Dimensions of a Table can't be calculated. See the FAQ.");
    }

    public float right(int margin)
    {
        throw new UnsupportedOperationException("Dimensions of a Table can't be calculated. See the FAQ.");
    }

    public void setTop(int value)
    {
        throw new UnsupportedOperationException("Dimensions of a Table are attributed automagically. See the FAQ.");
    }

    public void setBottom(int value)
    {
        throw new UnsupportedOperationException("Dimensions of a Table are attributed automagically. See the FAQ.");
    }

    public void setLeft(int value)
    {
        throw new UnsupportedOperationException("Dimensions of a Table are attributed automagically. See the FAQ.");
    }

    public void setRight(int value)
    {
        throw new UnsupportedOperationException("Dimensions of a Table are attributed automagically. See the FAQ.");
    }

    private int columns;
    private Point curPosition;
    private ArrayList rows;
    private Cell defaultLayout;
    private int lastHeaderRow;
    private int alignment;
    private float cellpadding;
    private float cellspacing;
    private float widthPercentage;
    private String absWidth;
    private float widths[];
    boolean mDebug;
    boolean mTableInserted;
    boolean mAutoFillEmptyCells;
    boolean tableFitsPage;
    boolean cellsFitPage;
    float offset;
    protected Hashtable alternatingRowAttributes;
}