function tableEditor(oDoc) 
{
    this.doc = oDoc; 
    this.document = element.document;
    this.tableRow = null;
    this.tableCell = null; 
    this.tableElem = null; 
    this.tMatrix = null;
    this.cellIdx = null;
    if (typeof(_tableEditor_prototype_called) == 'undefined') 
    {
        _tableEditor_prototype_called = true;
        tableEditor.prototype.alignTop = alignTop;
        tableEditor.prototype.alignMiddle = alignMiddle;
        tableEditor.prototype.alignBottom = alignBottom;
        tableEditor.prototype.mergeDown = mergeDown;
        tableEditor.prototype.unMergeDown = unMergeDown;
        tableEditor.prototype.mergeRight = mergeRight;
        tableEditor.prototype.unMergeRight = unMergeRight;
        tableEditor.prototype.processRow = processRow;
        tableEditor.prototype.processColumn = processColumn;
        tableEditor.prototype.setTableElements = setTableElements;
        tableEditor.prototype.unSetTableElements = unSetTableElements;
        tableEditor.prototype.__getCell = __getCell;
        tableEditor.prototype.__getRow = __getRow;
        tableEditor.prototype.__getTable= __getTable;
        tableEditor.prototype.__formCellMatrix= __formCellMatrix;
    }

    function __getCell()
    {
        if (this.document.selection.type != "Control")
        {
            var tControl = this.document.selection.createRange();
            tControl = tControl.parentElement();
            while ((tControl.tagName != 'TD') && (tControl.tagName != 'TH') && (tControl.tagName != 'TABLE') && (tControl != doc) && (tControl.tagName != 'BODY'))
                tControl = tControl.parentElement;
            if ((tControl.tagName == 'TD') || (tControl.tagName == 'TH'))
                this.tableCell = tControl;
        }
    }

    function __getRow()
    {
        if (this.document.selection.type != "Control")
        {
            var tControl = this.document.selection.createRange();
            tControl = tControl.parentElement();
            while ((tControl.tagName != 'TR') && (tControl.tagName != 'TABLE') && (tControl != doc) && (tControl.tagName != 'BODY'))
                tControl = tControl.parentElement;
            if (tControl.tagName == 'TR')
                this.tableRow = tControl;
        }
    }

    function __getTable()
    {
        if (this.document.selection.type == "Control")
        { 
            var tControl = this.document.selection.createRange();
            if (tControl(0).tagName == 'TABLE')
                this.tableElem = tControl(0);
        }
        else
        {
            var tControl = this.document.selection.createRange();
            tControl = tControl.parentElement();
            while ((tControl.tagName != 'TABLE') && (tControl != doc) && (tControl.tagName != 'BODY'))
                tControl = tControl.parentElement;
            if (tControl.tagName == 'TABLE')
                this.tableElem = tControl;
        }
    }

    function setTableElements()
    {
        this.tableRow = null;
        this.tableCell = null;
        this.tableElem = null;

        this.__getTable();
        if (this.tableElem == null)
        {
            showTableBar(false);
            return;
        }
        this.__getRow();
        this.__getCell();
        showTableBar(true);
        if (this.docTop == null)
        {
            this.docTop = doc.offsetTop;
            var par = doc.offsetParent;
            while (par) 
            {
                this.docTop += par.offsetTop;
                par = par.offsetParent;
            }
        }
    }

    function unSetTableElements()
    {
        showTableBar(false);
        this.tableRow = null;
        this.tableCell = null;
        this.tableElem = null;
    }

    function alignTop() 
    {
        if (this.tableCell)
            this.tableCell.vAlign = "top";
    }

    function alignMiddle() 
    {
        if (this.tableCell)
            this.tableCell.vAlign = "middle";
    }

    function alignBottom() 
    {
        if (this.tableCell)
            this.tableCell.vAlign = "bottom";
    }

    function mergeDown() 
    {
        var ct = this.tableElem;
        var cr = this.tableRow; 
        var cd = this.tableCell; 
       
        if (cd && cr && ct)
        {
            var tm = this.__formCellMatrix();
            for (j=0; j<tm[cr.rowIndex].length; j++)
            {
                if (tm[cr.rowIndex][j] == cd.cellIndex)
                {
                    crealIndex=j;
                    break;
                }
            }
            ccrs = cd.rowSpan?cd.rowSpan:1;
            cccs = cd.colSpan?cd.colSpan:1;

            if (cr.rowIndex+ccrs<ct.rows.length)
            {
                ncellIndex = tm[cr.rowIndex+ccrs][crealIndex];
                if (ncellIndex != -1 && (crealIndex==0 || (crealIndex>0 && (tm[cr.rowIndex+ccrs][crealIndex-1]!=tm[cr.rowIndex+ccrs][crealIndex]))))
                {
                    ncrs = ct.rows(cr.rowIndex+ccrs).cells(ncellIndex).rowSpan?ct.rows(cr.rowIndex+ccrs).cells(ncellIndex).rowSpan:1;
                    nccs = ct.rows(cr.rowIndex+ccrs).cells(ncellIndex).colSpan?ct.rows(cr.rowIndex+ccrs).cells(ncellIndex).colSpan:1;
                    if (cccs == nccs)
                    {
                        cd.innerHTML += ct.rows(cr.rowIndex+ccrs).cells(ncellIndex).innerHTML;
                        ct.rows(cr.rowIndex+ccrs).deleteCell(ncellIndex);
                        cd.rowSpan = ccrs+ncrs;
                    }
                }
            }
        }
    }

    function unMergeRight() 
    {
        var ct = this.tableElem;
        var cr = this.tableRow; 
        var cd = this.tableCell;
        if (cd && cr && ct)
        {
            var tm = this.__formCellMatrix();
    
            for (j=0; j<tm[cr.rowIndex].length; j++)
            {
                if (tm[cr.rowIndex][j] == cd.cellIndex)
                {
                    realIndex=j;
                    break;
                }
            }

            if (cd.colSpan>1) 
            {
                var newc = ct.rows(cr.rowIndex).insertCell(cd.cellIndex+1);
                cd.colSpan--;
                var nc = cd.cloneNode();
                newc.replaceNode(nc);
                cd.colSpan = 1;
            }
            else
            {
                var newc = ct.rows(cr.rowIndex).insertCell(cd.cellIndex+1);
                var nc = cd.cloneNode();
                newc.replaceNode(nc);

                for (i=0; i<tm.length; i++)
                {
                    if (i!=cr.rowIndex && tm[i][realIndex] != -1)
                    {
                        cs = ct.rows(i).cells(tm[i][realIndex]).colSpan>1?ct.rows(i).cells(tm[i][realIndex]).colSpan:1;
                        ct.rows(i).cells(tm[i][realIndex]).colSpan = cs+1;
                    }
                }
            }
        }
    }

    function mergeRight() 
    {
        var ct = this.tableElem;
        var cr = this.tableRow; 
        var cd = this.tableCell; 

        if (cd && cr && ct)
        {
            var tm = this.__formCellMatrix();

            for (j=0; j<tm[cr.rowIndex].length; j++)
            {
                if (tm[cr.rowIndex][j] == cd.cellIndex)
                {
                    realIndex=j;
                    break;
                }
            }

            if (cd.cellIndex+1<cr.cells.length)
            {
                ccrs = cd.rowSpan?cd.rowSpan:1;
                cccs = cd.colSpan?cd.colSpan:1;
                ncrs = cr.cells(cd.cellIndex+1).rowSpan?cr.cells(cd.cellIndex+1).rowSpan:1;
                nccs = cr.cells(cd.cellIndex+1).colSpan?cr.cells(cd.cellIndex+1).colSpan:1;

                j=realIndex;
                while(tm[cr.rowIndex][j] == cd.cellIndex) j++;
                    if (tm[cr.rowIndex][j] == cd.cellIndex+1)
                    {
                        if (ccrs == ncrs)
                        {
                            cd.colSpan = cccs+nccs;
                            cd.innerHTML += cr.cells(cd.cellIndex+1).innerHTML;
                            cr.deleteCell(cd.cellIndex+1);
                        }
                    }
             }
        }
    }

    function unMergeDown() 
    {
        var ct = this.tableElem;
        var cr = this.tableRow; 
        var cd = this.tableCell; 
        if (cd && cr && ct)
        {
            var tm = this.__formCellMatrix();

            for (j=0; j<tm[cr.rowIndex].length; j++)
            {
                if (tm[cr.rowIndex][j] == cd.cellIndex)
                {
                    realIndex=j;
                    break;
                }
            }
    
            if (cd.rowSpan>1) 
            {
                i = realIndex;
                while (tm[cr.rowIndex+1][i] == -1) i++;
                    if (i == tm[cr.rowIndex+1].length) 
                        ni = ct.rows(cr.rowIndex+1).cells.length;
                    else
                        ni = tm[cr.rowIndex+1][i];

                var newc = ct.rows(cr.rowIndex+1).insertCell(ni);
                cd.rowSpan--;
                var nc = cd.cloneNode();
                newc.replaceNode(nc);
                cd.rowSpan = 1;
            }
            else
            {
                ct.insertRow(cr.rowIndex+1);
                for (i=0; i<cr.cells.length; i++)
                {
                    if (i != cd.cellIndex)
                    {
                        rs = cr.cells(i).rowSpan>1?cr.cells(i).rowSpan:1;
                        cr.cells(i).rowSpan = rs+1;
                    }
                }

                for (i=0; i<cr.rowIndex; i++)
                {
                    var tempr = ct.rows(i);
                    for (j=0; j<tempr.cells.length; j++)
                    {
                        if (tempr.cells(j).rowSpan > (cr.rowIndex - i))
                        tempr.cells(j).rowSpan++;
                    }
                }

                var newc = ct.rows(cr.rowIndex+1).insertCell(0);
                var nc = cd.cloneNode();
                newc.replaceNode(nc);
            }
        }
    }

    function processRow(action, insPoint) 
    {
        var ct = this.tableElem; 
        var cr = this.tableRow; 
        var cd = this.tableCell; 

        if (cd && cr && ct)
        {
            if (action == "add") 
            {
                var inc = (insPoint != "beforeBegin") ? 1:0;
                var newr = ct.insertRow(cr.rowIndex+inc);
                var i = 0;
                while (i < cr.cells.length)
                {
                    if (cr.cells(i).rowSpan > 1)
                    {
                        if (insPoint == "beforeBegin")
                        {
                            var newc = cr.cells(i).cloneNode();
                            newr.appendChild(newc);
                            cr.deleteCell(i);
                            i--;
                        }
                        else
                            cr.cells(i).rowSpan++;
                    }
                    else
                    {
                        var newc = cr.cells(i).cloneNode();
                        newr.appendChild(newc);
                    }
                    i++;
                }
                for (i=0; i<cr.rowIndex; i++)
                {
                    var tempr = ct.rows(i);
                    for (j=0; j<tempr.cells.length; j++)
                    {
                        if (tempr.cells(j).rowSpan > (cr.rowIndex - i))
                            tempr.cells(j).rowSpan++;
                    }
                }
            }
            else 
            {
                if (ct.rows.length<=1)
                {
                    ct.removeNode(true);
                }
                else
                {
                    var tm = this.__formCellMatrix();
                    for (i=0; i<cr.rowIndex; i++)
                    {
                        var tempr = ct.rows(i);
                        for (j=0; j<tempr.cells.length; j++)
                        {
                            if (tempr.cells(j).rowSpan > (cr.rowIndex - i))
                                tempr.cells(j).rowSpan--;
                        }
                    }
                    curCI = -1;
                    for (i=0; i<tm[cr.rowIndex].length; i++)
                    {
                        prevCI = curCI;
                        curCI = tm[cr.rowIndex][i];
                        if (curCI != -1 && curCI != prevCI && cr.cells(curCI).rowSpan>1 && (cr.rowIndex+1)<ct.rows.length)
                        {
                            var newc = ct.rows(cr.rowIndex+1).insertCell(curCI);
                            ct.rows(cr.rowIndex).cells(curCI).rowSpan--;
                            var nc = ct.rows(cr.rowIndex).cells(curCI).cloneNode();
                            newc.replaceNode(nc);
                            
                            cs = (cr.cells(curCI).colSpan>1)?cr.cells(curCI).colSpan:1;
                            for (j=i; j<(i+cs);j++)
                            {
                                tm[cr.rowIndex+1][j] = curCI;
                                nj = j;
                            }
                            for (j=nj; j<tm[cr.rowIndex+1].length; j++)
                            {
                                if (tm[cr.rowIndex+1][j] != -1)
                                    tm[cr.rowIndex+1][j]++;
                            }
                        }
                    }
                    ct.deleteRow(cr.rowIndex);
                }
                this.setTableElements();
            }
        }
    }
    
    function __formCellMatrix()
    {
        ct = this.tableElem;
        var tm = new Array();
        for (i=0; i<ct.rows.length; i++)
            tm[i]=new Array();

        for (i=0; i<ct.rows.length; i++)
        {
            jr=0;
            for (j=0; j<ct.rows(i).cells.length;j++)
            {
                while (tm[i][jr] != undefined) 
                    jr++;

                for (jh=jr; jh<jr+(ct.rows(i).cells(j).colSpan?ct.rows(i).cells(j).colSpan:1);jh++)
                {
                    for (jv=i; jv<i+(ct.rows(i).cells(j).rowSpan?ct.rows(i).cells(j).rowSpan:1);jv++)
                    {
                        if (jv==i)
                        {
                            tm[jv][jh]=ct.rows(i).cells(j).cellIndex;
                        }
                        else
                        {
                            tm[jv][jh]=-1;
                        }
                    }
                }
            }
        }
        return(tm);
    }
    
    function processColumn(action, insPoint) 
    {
        var ct = this.tableElem; 
        var cr = this.tableRow; 
        var cd = this.tableCell; 
        var tm = this.__formCellMatrix();

        if (cd && cr && ct)
        {
            if (action == 'add')
            {
                var inc1 = (insPoint == "beforeBegin") ? 1:0;
                var inc2 = (insPoint == "beforeBegin") ? 0:1;
                for (j=0; j<tm[cr.rowIndex].length; j++)
                {
                    if (tm[cr.rowIndex][j] == cd.cellIndex)
                    {
                        realIndex=j;
                        break;
                    }
                }

                for (i=0; i<ct.rows.length; i++)
                {
                    if (tm[i][realIndex] != -1)
                    {
                        if (ct.rows(i).cells(tm[i][realIndex]).colSpan > 1)
                        {
                            ct.rows(i).cells(tm[i][realIndex]).colSpan++;
                        }
                        else
                        {
                            var newc = ct.rows(i).insertCell(tm[i][realIndex]+inc2);
                            var nc = ct.rows(i).cells(tm[cr.rowIndex][realIndex+inc1]).cloneNode();
                            nc.innerHTML = '&nbsp;&nbsp;&nbsp;';
                            newc.replaceNode(nc); 
                        }
                    }
                }
            }
            else
            {
                if (tm[0].length <= 1) 
                {
                    ct.removeNode(true);
                }
                else
                {
                    for (j=0; j<tm[cr.rowIndex].length; j++)
                    {
                        if (tm[cr.rowIndex][j] == cd.cellIndex)
                        {
                            realIndex=j;
                            break;
                        }
                    }

                    for (i=0; i<ct.rows.length; i++)
                    {
                        if (tm[i][realIndex] != -1)
                        {
                            if (ct.rows(i).cells(tm[i][realIndex]).colSpan>1)
                                ct.rows(i).cells(tm[i][realIndex]).colSpan--;
                            else
                                ct.rows(i).deleteCell(tm[i][realIndex]);
                        }
                    }
                }
                this.setTableElements();
            }
        }
    }
} 
