#include "Table.h"

#include "AlphaField.h"
#include "Border.h"
#include "Image.h"
#include "KeyboardEvent.h"
#include "MouseEvent.h"
#include "Scroll.h"
#include "Text.h"
#include "ToolTip.h"

using namespace Framework;

// Contents of the ObjTable class from Table.h
// Constructor
ObjTable::ObjTable()
    : DrawableBackground(),
      members(new RCArray<RCArray<Drawable>>()),
      spaltenNamen(new RCArray<Text>()),
      zeilenNamen(new RCArray<Text>()),
      columnWidth(new Array<int>()),
      zeilenHeight(new Array<int>()),
      minSpaltenWidth(new Array<int>()),
      maxSpaltenWidth(new Array<int>()),
      minZeilenHeight(new Array<int>()),
      maxZeilenHeight(new Array<int>()),
      spaltenAnzahl(0),
      zeilenAnzahl(0),
      klickSpalte(-1),
      klickZeile(-1),
      mSpalte(-1),
      mZeile(-1),
      mx(0),
      my(0),
      selected(-1, -1),
      rasterColor(0xFF000000),
      gridWidth(1),
      aRam(0),
      aAf(0),
      msaRam(new RCArray<RCArray<Border>>()),
      msaAf(new RCArray<RCArray<AlphaField>>()),
      styles(new RCArray<Array<__int64>>())
{
    style = Style::MEIgnoreInside | Style::MEIgnoreParentInside
          | Style::MEIgnoreVisible | Style::MEIgnoreProcessed;
}

// Destructor
ObjTable::~ObjTable()
{
    if (members) members->release();
    if (spaltenNamen) spaltenNamen->release();
    if (zeilenNamen) zeilenNamen->release();
    if (columnWidth) columnWidth->release();
    if (zeilenHeight) zeilenHeight->release();
    if (minSpaltenWidth) minSpaltenWidth->release();
    if (maxSpaltenWidth) maxSpaltenWidth->release();
    if (minZeilenHeight) minZeilenHeight->release();
    if (maxZeilenHeight) maxZeilenHeight->release();
    if (aRam) aRam->release();
    if (aAf) aAf->release();
    if (msaRam) msaRam->release();
    if (msaAf) msaAf->release();
    if (styles) styles->release();
}

void ObjTable::doMouseEvent(
    MouseEvent& me, bool userRet) // processes mouse events
{
    if (!hasStyle(Style::Visible) || !me.insideParent || me.processed
        || me.mx < 0 || me.my < 0 || me.mx >= gr.x || me.my >= gr.y || !userRet)
    {
        if (me.id == ME_PLeft)
        {
            klickSpalte = -1;
            klickZeile = -1;
        }
        bool processed = me.processed;
        me.processed |= hasStyleNot(Style::Visible);
        bool insideParent = me.insideParent;
        me.insideParent = 0;
        int rbr = 0;
        if (hasStyle(Style::Border) && border) rbr = border->getRWidth();
        me.mx -= rbr;
        me.my -= rbr;
        if (hasStyle(Style::VScroll) && vertikalScrollBar)
            me.my += vertikalScrollBar->getScroll();
        if (hasStyle(Style::HScroll) && horizontalScrollBar)
            me.mx += horizontalScrollBar->getScroll();
        if (me.id != ME_Enter && me.id != ME_Leaves)
        {
            for (int i = 0; i < zeilenAnzahl; ++i)
            {
                for (int j = 0; j < spaltenAnzahl; ++j)
                {
                    Drawable* obj = zDrawable(j, i);
                    if (obj) obj->doPublicMouseEvent(me);
                }
            }
        }
        me.mx += rbr;
        me.my += rbr;
        if (hasStyle(Style::VScroll) && vertikalScrollBar)
            me.my -= vertikalScrollBar->getScroll();
        if (hasStyle(Style::HScroll) && horizontalScrollBar)
            me.mx -= horizontalScrollBar->getScroll();
        me.insideParent = insideParent;
        if (hasStyleNot(Style::Visible)) me.processed = processed;
        return;
    }
    int tmx = me.mx;
    int tmy = me.my;
    bool aufScroll = 0;
    if (vertikalScrollBar && hasStyle(Style::VScroll)
        && me.mx > pos.x + gr.x - 15)
        aufScroll = 1;
    if (horizontalScrollBar && hasStyle(Style::HScroll)
        && me.my > pos.y + gr.y - 15)
        aufScroll = 1;
    me.mx -= ((horizontalScrollBar && hasStyle(Style::HScroll))
                  ? horizontalScrollBar->getScroll()
                  : 0);
    me.my -= ((vertikalScrollBar && hasStyle(Style::VScroll))
                  ? vertikalScrollBar->getScroll()
                  : 0);
    rwLock.lockRead();
    if (!me.processed && !aufScroll)
    {
        double ox = getMouseColumn(
            me.mx
            + ((horizontalScrollBar && hasStyle(Style::HScroll))
                    ? horizontalScrollBar->getScroll()
                    : 0));
        double oy
            = getMouseRow(me.my
                          + ((vertikalScrollBar && hasStyle(Style::VScroll))
                                  ? vertikalScrollBar->getScroll()
                                  : 0));
        if (me.id == ME_RLeft)
        {
            klickSpalte = -1;
            klickZeile = -1;
            mSpalte = -1, mZeile = -1;
        }
        if ((hasStyle(Style::ColumnWidthChangeable)
                || hasStyle(Style::RowHeightChangeable))
            && klickSpalte < 0 && klickZeile < 0)
        {
            if (hasStyle(Style::ColumnWidthChangeable))
            {
                if (me.id == ME_PLeft && ox != (int)ox)
                {
                    mSpalte = ox;
                    mx = me.mx;
                    rend = 1;
                }
                if (mSpalte > -1)
                {
                    int br = getColumnWidth((int)mSpalte) + (me.mx - mx);
                    if (hasStyle(Style::ColumnWidthMax)
                        && br > getMaxColumnWidth((int)mSpalte))
                        br = getMaxColumnWidth((int)mSpalte);
                    if (hasStyle(Style::ColumnWidthMin)
                        && br < getMinColumnWidth((int)mSpalte))
                        br = getMinColumnWidth((int)mSpalte);
                    setColumnWidth((int)mSpalte, br);
                    mx = me.mx;
                    rend = 1;
                }
            }
            if (hasStyle(Style::RowHeightChangeable))
            {
                if (me.id == ME_PLeft && oy != (int)oy)
                {
                    mZeile = oy;
                    my = me.my;
                    rend = 1;
                }
                if (mZeile > -1)
                {
                    int hi = getRowHeight((int)mZeile) + (me.my - my);
                    if (hasStyle(Style::RowHeightMax)
                        && hi > getMaxRowHeight((int)mZeile))
                        hi = getMaxRowHeight((int)mZeile);
                    if (hasStyle(Style::RowHeightMin)
                        && hi < getMinRowHeight((int)mZeile))
                        hi = getMinRowHeight((int)mZeile);
                    setRowHeight((int)mZeile, hi);
                    my = me.my;
                    rend = 1;
                }
            }
        }
        if (hasStyle(Style::ColumnsMovable) && ox == (int)ox && mSpalte == -1
            && mZeile == -1)
        {
            if (klickSpalte >= 0 && klickSpalte < spaltenAnzahl
                && klickSpalte != ox && !oy && ox >= 0)
            {
                setColumnPosition(klickSpalte, (int)ox);
                klickSpalte = (int)ox;
                rend = 1;
            }
            if (me.id == ME_PLeft)
            {
                if (!oy && klickSpalte < 0)
                {
                    klickSpalte = (int)ox;
                    rend = 1;
                }
            }
        }
        if (hasStyle(Style::RowsMovable) && oy == (int)oy && mSpalte == -1
            && mZeile == -1)
        {
            if (klickZeile >= 0 && klickZeile < zeilenAnzahl && klickZeile != oy
                && !ox && oy >= 0)
            {
                setRowPosition(klickZeile, (int)oy);
                klickZeile = (int)oy;
                rend = 1;
            }
            if (me.id == ME_PLeft)
            {
                if (!ox && klickZeile < 0)
                {
                    klickZeile = (int)oy;
                    rend = 1;
                }
            }
        }
    }
    me.mx += (horizontalScrollBar && hasStyle(Style::HScroll))
               ? horizontalScrollBar->getScroll()
               : 0;
    me.my += (vertikalScrollBar && hasStyle(Style::VScroll))
               ? vertikalScrollBar->getScroll()
               : 0;
    bool vs = hasStyle(Style::VScroll) && vertikalScrollBar;
    bool hs = hasStyle(Style::HScroll) && horizontalScrollBar;
    int rbr = border ? border->getRWidth() : 0;
    if (vs)
    {
        if (hs)
            horizontalScrollBar->doMouseMessage(
                rbr, gr.y - 15 - rbr, gr.x - 15 - rbr * 2, 15, me);
        vertikalScrollBar->doMouseMessage(
            gr.x - 15 - rbr, rbr, 15, gr.y - rbr * 2, me);
    }
    else if (hs)
        horizontalScrollBar->doMouseMessage(
            rbr, gr.y - 15 - rbr, gr.x - rbr * 2, 15, me);
    if (aufScroll) me.processed = 1;
    if (me.id != ME_Enter && me.id != ME_Leaves)
    {
        for (int i = 0; i < zeilenAnzahl; ++i)
        {
            for (int j = 0; j < spaltenAnzahl; ++j)
            {
                bool b = me.processed;
                Drawable* obj = zDrawable(j, i);
                if (obj) obj->doPublicMouseEvent(me);
                if (!b && me.processed && me.id == ME_PLeft)
                    selected = Point(j, i);
            }
        }
    }
    rwLock.unlockRead();
    me.processed = 1;
    me.mx = tmx;
    me.my = tmy;
}

// non-constant
void ObjTable::addColumn(const char* name) // add column
{
    addColumn(spaltenAnzahl, name);
}

void ObjTable::addColumn(Text* name)
{
    addColumn(spaltenAnzahl, name);
}

void ObjTable::addColumn(int sNum, const char* name) // insert column at sNum
{
    if (sNum > spaltenAnzahl) return;
    rwLock.lockWrite();
    members->add(new RCArray<Drawable>(), sNum);
    spaltenNamen->add(new Text(name), sNum);
    columnWidth->add(100, sNum);
    minSpaltenWidth->add(0, sNum);
    maxSpaltenWidth->add(300, sNum);
    msaRam->add(new RCArray<Border>(), sNum);
    msaAf->add(new RCArray<AlphaField>(), sNum);
    styles->add(new Array<__int64>(), sNum);
    for (int i = 0; i < zeilenAnzahl; i++)
    {
        members->z(sNum)->add(0);
        msaRam->z(sNum)->add(0);
        msaAf->z(sNum)->add(0);
        styles->z(sNum)->add(0);
    }
    ++spaltenAnzahl;
    rend = 1;
    rwLock.unlockWrite();
}

void ObjTable::addColumn(int sNum, Text* name)
{
    addColumn(sNum, name->getText());
    name->release();
}

void ObjTable::addRow(const char* name) // add row
{
    addRow(zeilenAnzahl, name);
}

void ObjTable::addRow(Text* name)
{
    addRow(zeilenAnzahl, name);
}

void ObjTable::addRow(int zNum, const char* name) // insert row at zNum
{
    if (zNum > zeilenAnzahl) return;
    rwLock.lockWrite();
    zeilenNamen->add(new Text(name), zNum);
    zeilenHeight->add(20, zNum);
    minZeilenHeight->add(0, zNum);
    maxZeilenHeight->add(100, zNum);
    for (int i = 0; i < spaltenAnzahl; ++i)
    {
        if (members->z(i)) members->z(i)->add(0, zNum);
        if (msaRam->z(i)) msaRam->z(i)->add(0, zNum);
        if (msaAf->z(i)) msaAf->z(i)->add(0, zNum);
        if (styles->z(i)) styles->z(i)->add(0, zNum);
    }
    ++zeilenAnzahl;
    rend = 1;
    rwLock.unlockWrite();
}

void ObjTable::addRow(int zNum, Text* name)
{
    addRow(zNum, name->getText());
    name->release();
}

void ObjTable::removeColumn(int sNum) // delete column
{
    if (sNum >= spaltenAnzahl) return;
    rwLock.lockWrite();
    members->remove(sNum);
    spaltenNamen->remove(sNum);
    columnWidth->remove(sNum);
    minSpaltenWidth->remove(sNum);
    maxSpaltenWidth->remove(sNum);
    if (msaRam->z(sNum)) msaRam->z(sNum)->release();
    msaRam->remove(sNum);
    if (msaAf->z(sNum)) msaAf->z(sNum)->release();
    msaAf->remove(sNum);
    styles->remove(sNum);
    --spaltenAnzahl;
    rend = 1;
    rwLock.unlockWrite();
}

void ObjTable::removeColumn(const char* name)
{
    removeColumn(getColumnNumber(name));
}

void ObjTable::removeColumn(Text* name)
{
    removeColumn(getColumnNumber(name));
}

void ObjTable::removeRow(int zNum) // delete row
{
    if (zNum >= zeilenAnzahl) return;
    rwLock.lockWrite();
    zeilenNamen->remove(zNum);
    zeilenHeight->remove(zNum);
    minZeilenHeight->remove(zNum);
    maxZeilenHeight->remove(zNum);
    for (int i = 0; i < spaltenAnzahl; ++i)
    {
        if (members->z(i)) members->z(i)->remove(zNum);
        if (msaRam->z(i)) msaRam->z(i)->remove(zNum);
        if (msaAf->z(i)) msaAf->z(i)->remove(zNum);
        if (styles->z(i)) styles->z(i)->remove(zNum);
    }
    --zeilenAnzahl;
    rend = 1;
    rwLock.unlockWrite();
}

void ObjTable::removeRow(const char* name)
{
    removeRow(getRowNumber(name));
}

void ObjTable::removeRow(Text* name)
{
    removeRow(getRowNumber(name));
}

void ObjTable::setColumnPosition(
    const char* name, int pos) // sets the position of a column
{
    setColumnPosition(getColumnNumber(name), pos);
}

void ObjTable::setColumnPosition(Text* name, int pos)
{
    setColumnPosition(getColumnNumber(name), pos);
}

void ObjTable::setColumnPosition(int sNum, int pos)
{
    if (sNum >= spaltenAnzahl || pos >= spaltenAnzahl || sNum == pos) return;
    int delPos = sNum;
    int insertPos = pos;
    if (pos < sNum)
        ++delPos;
    else
        ++insertPos;
    rwLock.lockWrite();
    members->add(members->get(sNum), insertPos);
    members->remove(delPos);
    spaltenNamen->add(spaltenNamen->get(sNum), insertPos);
    spaltenNamen->remove(delPos);
    columnWidth->add(
        columnWidth->has(sNum) ? columnWidth->get(sNum) : 0, insertPos);
    columnWidth->remove(delPos);
    minSpaltenWidth->add(
        minSpaltenWidth->has(sNum) ? minSpaltenWidth->get(sNum) : 0, insertPos);
    minSpaltenWidth->remove(delPos);
    msaRam->add(msaRam->z(sNum), insertPos);
    msaRam->remove(delPos);
    msaAf->add(msaAf->z(sNum), insertPos);
    msaAf->remove(delPos);
    styles->add(styles->get(sNum), insertPos);
    styles->remove(delPos);
    rend = 1;
    rwLock.unlockWrite();
}

void ObjTable::setRowPosition(
    const char* name, int pos) // sets the row position
{
    setRowPosition(getRowNumber(name), pos);
}

void ObjTable::setRowPosition(Text* name, int pos)
{
    setRowPosition(getRowNumber(name), pos);
}

void ObjTable::setRowPosition(int zNum, int pos)
{
    if (zNum >= zeilenAnzahl || pos >= zeilenAnzahl || pos == zNum) return;
    int delPos = zNum;
    int insertPos = pos;
    if (pos < zNum)
        ++delPos;
    else
        ++insertPos;
    rwLock.lockWrite();
    zeilenNamen->add(zeilenNamen->get(zNum), insertPos);
    zeilenNamen->remove(delPos);
    zeilenHeight->add(
        zeilenHeight->has(zNum) ? zeilenHeight->get(zNum) : 0, insertPos);
    zeilenHeight->remove(delPos);
    minZeilenHeight->add(
        minZeilenHeight->has(zNum) ? minZeilenHeight->get(zNum) : 0, insertPos);
    minZeilenHeight->remove(delPos);
    maxZeilenHeight->add(
        maxZeilenHeight->has(zNum) ? maxZeilenHeight->get(zNum) : 0, insertPos);
    maxZeilenHeight->remove(delPos);
    for (int i = 0; i < spaltenAnzahl; ++i)
    {
        if (members->z(i))
        {
            members->z(i)->add(
                members->z(i)->has(zNum) ? members->z(i)->get(zNum) : 0,
                insertPos);
            members->z(i)->remove(delPos);
        }
        if (msaRam->z(i))
        {
            msaRam->z(i)->add(
                msaRam->z(i)->z(zNum) ? msaRam->z(i)->get(zNum) : 0, insertPos);
            msaRam->z(i)->remove(delPos);
        }
        if (msaAf->z(i))
        {
            msaAf->z(i)->add(
                msaAf->z(i)->z(zNum) ? msaAf->z(i)->get(zNum) : 0, insertPos);
            msaAf->z(i)->remove(delPos);
        }
        if (styles->z(i))
        {
            styles->z(i)->add(
                styles->z(i)->has(zNum) ? styles->z(i)->get(zNum) : 0,
                insertPos);
            styles->z(i)->remove(delPos);
        }
    }
    rend = 1;
    rwLock.unlockWrite();
}

void ObjTable::setDrawableZ(int sNum, int zNum, Drawable* obj) // sets a drawing
{
    if (sNum >= spaltenAnzahl || zNum >= zeilenAnzahl) return;
    rwLock.lockWrite();
    if (!members->z(sNum)) members->set(new RCArray<Drawable>(), sNum);
    while (members->z(sNum)->getEntryCount() <= zNum)
        members->z(sNum)->add(0);
    members->z(sNum)->set(obj, zNum);
    if (columnWidth->has(sNum))
    {
        obj->setWidth(columnWidth->get(sNum));
    }
    if (zeilenHeight->has(zNum))
    {
        obj->setHeight(zeilenHeight->get(zNum));
    }
    rend = 1;
    rwLock.unlockWrite();
}

void ObjTable::setDrawableZ(
    const char* spaltenName, const char* zeilenName, Drawable* zDrawable)
{
    setDrawableZ(
        getColumnNumber(spaltenName), getRowNumber(zeilenName), zDrawable);
}

void ObjTable::setDrawableZ(
    Text* spaltenName, Text* zeilenName, Drawable* zDrawable)
{
    setDrawableZ(
        getColumnNumber(spaltenName), getRowNumber(zeilenName), zDrawable);
}

void ObjTable::setColumnWidth(int sNum, int br) // sets the column width
{
    if (sNum >= spaltenAnzahl) return;
    rwLock.lockWrite();
    columnWidth->set(br, sNum);
    rend = 1;
    rwLock.unlockWrite();
}

void ObjTable::setColumnWidth(const char* name, int br)
{
    setColumnWidth(getColumnNumber(name), br);
}

void ObjTable::setColumnWidth(Text* name, int br)
{
    setColumnWidth(getColumnNumber(name), br);
}

void ObjTable::setRowHeight(int zNum, int hi) // sets the row height
{
    if (zNum >= zeilenAnzahl) return;
    rwLock.lockWrite();
    zeilenHeight->set(hi, zNum);
    rend = 1;
    rwLock.unlockWrite();
}

void ObjTable::setRowHeight(const char* name, int hi)
{
    setRowHeight(getRowNumber(name), hi);
}

void ObjTable::setRowHeight(Text* name, int hi)
{
    setRowHeight(getRowNumber(name), hi);
}

void ObjTable::setMinColumnWidth(
    int sNum, int minBr) // sets the minimum column width
{
    if (sNum >= spaltenAnzahl) return;
    rwLock.lockWrite();
    minSpaltenWidth->set(minBr, sNum);
    rend = 1;
    rwLock.unlockWrite();
}

void ObjTable::setMinColumnWidth(const char* name, int minBr)
{
    setMinColumnWidth(getColumnNumber(name), minBr);
}

void ObjTable::setMinColumnWidth(Text* name, int minBr)
{
    setMinColumnWidth(getColumnNumber(name), minBr);
}

void ObjTable::setMaxColumnWidth(
    int sNum, int maxBr) // sets the maximum column width
{
    if (sNum >= spaltenAnzahl) return;
    rwLock.lockWrite();
    maxSpaltenWidth->set(maxBr, sNum);
    rend = 1;
    rwLock.unlockWrite();
}

void ObjTable::setMaxColumnWidth(const char* name, int maxBr)
{
    setMaxColumnWidth(getColumnNumber(name), maxBr);
}

void ObjTable::setMaxColumnWidth(Text* name, int maxBr)
{
    setMaxColumnWidth(getColumnNumber(name), maxBr);
}

void ObjTable::setMinRowHeight(
    int zNum, int minHi) // sets the minimum row height
{
    if (zNum >= zeilenAnzahl) return;
    rwLock.lockWrite();
    minZeilenHeight->set(minHi, zNum);
    rend = 1;
    rwLock.unlockWrite();
}

void ObjTable::setMinRowHeight(const char* name, int minHi)
{
    setMinRowHeight(getRowNumber(name), minHi);
}

void ObjTable::setMinRowHeight(Text* name, int minHi)
{
    setMinRowHeight(getRowNumber(name), minHi);
}

void ObjTable::setMaxRowHeight(
    int zNum, int maxHi) // sets the maximum row height
{
    if (zNum >= zeilenAnzahl) return;
    rwLock.lockWrite();
    maxZeilenHeight->set(maxHi, zNum);
    rend = 1;
    rwLock.unlockWrite();
}

void ObjTable::setMaxRowHeight(const char* name, int maxHi)
{
    setMaxRowHeight(getRowHeight(name), maxHi);
}

void ObjTable::setMaxRowHeight(Text* name, int maxHi)
{
    setMaxRowHeight(getRowHeight(name), maxHi);
}

void ObjTable::setSelection(
    int sNum, int zNum) // selects the corresponding field
{
    if (sNum >= spaltenAnzahl || zNum >= zeilenAnzahl) return;
    rwLock.lockWrite();
    selected.x = sNum;
    selected.y = zNum;
    rend = 1;
    rwLock.unlockWrite();
}

void ObjTable::setSelection(const char* spaltenName, const char* zeilenName)
{
    setSelection(getColumnNumber(spaltenName), getRowNumber(zeilenName));
}

void ObjTable::setSelection(Text* spaltenName, Text* zeilenName)
{
    setSelection(getColumnNumber(spaltenName), getRowNumber(zeilenName));
}

void ObjTable::setGridColor(int f) // sets the grid color
{
    rasterColor = f;
    rend = 1;
}

void ObjTable::setGridWidth(int br) // sets the width of the grid
{
    gridWidth = br;
    rend = 1;
}

void ObjTable::setABorderZ(Border* ram) // sets the selection border
{
    if (aRam) aRam->release();
    aRam = ram;
    rend = 1;
}

void ObjTable::setARColor(int f) // sets the selection border color
{
    if (!aRam) aRam = new LBorder();
    aRam->setColor(f);
    rend = 1;
}

void ObjTable::setARWidth(int br) // sets the selection border width
{
    if (!aRam) aRam = new LBorder();
    aRam->setBorderWidth(br);
    rend = 1;
}

void ObjTable::setAAlphaFieldZ(AlphaField* af) // sets the selection AlphaField
{
    if (aAf) aAf->release();
    aAf = af;
    rend = 1;
}

void ObjTable::setAAfColor(int f) // sets the color of the selection AlphaField
{
    if (!aAf) aAf = new AlphaField();
    aAf->setColor(f);
    rend = 1;
}

void ObjTable::setAAfStrength(
    int st) // sets the strength of the selection AlphaField
{
    if (!aAf) aAf = new AlphaField();
    aAf->setStrength(st);
    rend = 1;
}

void ObjTable::setABorderZ(
    int sNum, int zNum, Border* ram) // sets the selection border
{
    if (msaRam->z(sNum)) msaRam->z(sNum)->set(ram, zNum);
    rend = 1;
}

void ObjTable::setABorderZ(
    const char* spaltenName, const char* zeilenName, Border* ram)
{
    setABorderZ(getColumnNumber(spaltenName), getRowNumber(zeilenName), ram);
}

void ObjTable::setABorderZ(Text* spaltenName, Text* zeilenName, Border* ram)
{
    setABorderZ(getColumnNumber(spaltenName), getRowNumber(zeilenName), ram);
}

void ObjTable::setARColor(
    int sNum, int zNum, int f) // sets the selection border color
{
    if (msaRam->z(sNum))
    {
        Border* tmp = msaRam->z(sNum)->z(zNum);
        if (!tmp)
        {
            tmp = new LBorder();
            msaRam->z(sNum)->set(tmp, zNum);
        }
        tmp->setColor(f);
        rend = 1;
    }
}

void ObjTable::setARColor(
    const char* spaltenName, const char* zeilenName, int f)
{
    setARColor(getColumnNumber(spaltenName), getRowNumber(zeilenName), f);
}

void ObjTable::setARColor(Text* spaltenName, Text* zeilenName, int f)
{
    setARColor(getColumnNumber(spaltenName), getRowNumber(zeilenName), f);
}

void ObjTable::setARWidth(
    int sNum, int zNum, int br) // sets the selection border width
{
    if (msaRam->z(sNum))
    {
        Border* tmp = msaRam->z(sNum)->z(zNum);
        if (!tmp)
        {
            tmp = new LBorder();
            msaRam->z(sNum)->set(tmp, zNum);
        }
        tmp->setBorderWidth(br);
        rend = 1;
    }
}

void ObjTable::setARWidth(
    const char* spaltenName, const char* zeilenName, int br)
{
    setARWidth(getColumnNumber(spaltenName), getRowNumber(zeilenName), br);
}

void ObjTable::setARWidth(Text* spaltenName, Text* zeilenName, int br)
{
    setARWidth(getColumnNumber(spaltenName), getRowNumber(zeilenName), br);
}

void ObjTable::setAAlphaFieldZ(
    int sNum, int zNum, AlphaField* af) // sets the selection AlphaField
{
    if (msaAf->z(sNum)) msaAf->z(sNum)->set(af, zNum);
    rend = 1;
}

void ObjTable::setAAlphaFieldZ(
    const char* spaltenName, const char* zeilenName, AlphaField* af)
{
    setAAlphaFieldZ(getColumnNumber(spaltenName), getRowNumber(zeilenName), af);
}

void ObjTable::setAAlphaFieldZ(
    Text* spaltenName, Text* zeilenName, AlphaField* af)
{
    setAAlphaFieldZ(getColumnNumber(spaltenName), getRowNumber(zeilenName), af);
}

void ObjTable::setAAfColor(
    int sNum, int zNum, int f) // sets the color of the selection AlphaField
{
    if (msaAf->z(sNum))
    {
        AlphaField* tmp = msaAf->z(sNum)->z(zNum);
        if (!tmp)
        {
            tmp = new AlphaField();
            msaAf->z(sNum)->set(tmp, zNum);
        }
        tmp->setColor(f);
        rend = 1;
    }
}

void ObjTable::setAAfColor(
    const char* spaltenName, const char* zeilenName, int f)
{
    setAAfColor(getColumnNumber(spaltenName), getRowNumber(zeilenName), f);
}

void ObjTable::setAAfColor(Text* spaltenName, Text* zeilenName, int f)
{
    setAAfColor(getColumnNumber(spaltenName), getRowNumber(zeilenName), f);
}

void ObjTable::setAAfStrength(
    int sNum, int zNum, int st) // sets the strength of the selection AlphaField
{
    if (msaAf->z(sNum))
    {
        AlphaField* tmp = msaAf->z(sNum)->z(zNum);
        if (!tmp)
        {
            tmp = new AlphaField();
            msaAf->z(sNum)->set(tmp, zNum);
        }
        tmp->setStrength(st);
        rend = 1;
    }
}

void ObjTable::setAAfStrength(
    const char* spaltenName, const char* zeilenName, int st)
{
    setAAfStrength(getColumnNumber(spaltenName), getRowNumber(zeilenName), st);
}

void ObjTable::setAAfStrength(Text* spaltenName, Text* zeilenName, int st)
{
    setAAfStrength(getColumnNumber(spaltenName), getRowNumber(zeilenName), st);
}

void ObjTable::addMsStyle(
    int sNum, int zNum, __int64 style) // sets the style when Multistyled
{
    if (sNum >= spaltenAnzahl || zNum >= zeilenAnzahl) return;
    if (styles->z(sNum))
        styles->z(sNum)->set(
            (styles->z(sNum)->has(zNum) ? styles->z(sNum)->get(zNum) : 0)
                | style,
            zNum);
    rend = 1;
}

void ObjTable::addMsStyle(
    const char* spaltenName, const char* zeilenName, __int64 style)
{
    addMsStyle(getColumnNumber(spaltenName), getRowNumber(zeilenName), style);
}

void ObjTable::addMsStyle(Text* spaltenName, Text* zeilenName, __int64 style)
{
    addMsStyle(getColumnNumber(spaltenName), getRowNumber(zeilenName), style);
}

void ObjTable::setMsStyle(int sNum, int zNum, __int64 style)
{
    if (sNum >= spaltenAnzahl || zNum >= zeilenAnzahl) return;
    if (styles->z(sNum)) styles->z(sNum)->set(style, zNum);
    rend = 1;
}

void ObjTable::setMsStyle(
    const char* spaltenName, const char* zeilenName, __int64 style)
{
    setMsStyle(getColumnNumber(spaltenName), getRowNumber(zeilenName), style);
}

void ObjTable::setMsStyle(Text* spaltenName, Text* zeilenName, __int64 style)
{
    setMsStyle(getColumnNumber(spaltenName), getRowNumber(zeilenName), style);
}

void ObjTable::setMsStyle(int sNum, int zNum, __int64 style, bool add_remove)
{
    if (sNum >= spaltenAnzahl || zNum >= zeilenAnzahl) return;
    if (styles->z(sNum))
    {
        if (add_remove)
            styles->z(sNum)->set(
                (styles->z(sNum)->has(zNum) ? styles->z(sNum)->get(zNum) : 0)
                    | style,
                zNum);
        else
            styles->z(sNum)->set(
                (styles->z(sNum)->has(zNum) ? styles->z(sNum)->get(zNum) : 0)
                    & (~style),
                zNum);
        rend = 1;
    }
}

void ObjTable::setMsStyle(const char* spaltenName,
    const char* zeilenName,
    __int64 style,
    bool add_remove)
{
    setMsStyle(getColumnNumber(spaltenName),
        getRowNumber(zeilenName),
        style,
        add_remove);
}

void ObjTable::setMsStyle(
    Text* spaltenName, Text* zeilenName, __int64 style, bool add_remove)
{
    setMsStyle(getColumnNumber(spaltenName),
        getRowNumber(zeilenName),
        style,
        add_remove);
}

void ObjTable::removeMsStyle(int sNum, int zNum, __int64 style)
{
    if (sNum >= spaltenAnzahl || zNum >= zeilenAnzahl) return;
    if (styles->z(sNum))
        styles->z(sNum)->set(
            (styles->z(sNum)->has(zNum) ? styles->z(sNum)->get(zNum) : 0)
                & (~style),
            zNum);
    rend = 1;
}

void ObjTable::removeMsStyle(
    const char* spaltenName, const char* zeilenName, __int64 style)
{
    removeMsStyle(
        getColumnNumber(spaltenName), getRowNumber(zeilenName), style);
}

void ObjTable::removeMsStyle(Text* spaltenName, Text* zeilenName, __int64 style)
{
    removeMsStyle(
        getColumnNumber(spaltenName), getRowNumber(zeilenName), style);
}

bool ObjTable::tick(double tickVal) // tick Message
{
    rwLock.lockRead();
    for (int i = 0; i < zeilenAnzahl; ++i)
    {
        for (int j = 0; j < spaltenAnzahl; ++j)
        {
            Drawable* obj = zDrawable(j, i);
            if (obj) rend |= obj->tick(tickVal);
        }
    }
    rwLock.unlockRead();
    return DrawableBackground::tick(tickVal);
}

void ObjTable::doKeyboardEvent(KeyboardEvent& te)
{
    bool ntakc = !te.processed;
    if (hasStyleNot(Style::Focus) || hasStyleNot(Style::Allowed)
        || hasStyleNot(Style::Visible))
        return;
    if (tak && (te.processed || tak(takParam, this, te)))
    {
        rwLock.lockRead();
        if (zDrawable(selected.x, selected.y))
        {
            zDrawable(selected.x, selected.y)->doKeyboardEvent(te);
            if (!te.processed && te.id == TE_Press)
            {
                if (te.virtualKey == T_Oben)
                {
                    --(selected.y);
                    rend = 1;
                }
                if (te.virtualKey == T_Unten)
                {
                    ++(selected.y);
                    rend = 1;
                }
                if (te.virtualKey == T_Links)
                {
                    --(selected.x);
                    rend = 1;
                }
                if (te.virtualKey == T_Rechts)
                {
                    ++(selected.x);
                    rend = 1;
                }
            }
        }
        rwLock.unlockRead();
    }
    te.processed = 1;
    if (ntakc && te.processed && nTak) te.processed = nTak(ntakParam, this, te);
}

void ObjTable::render(Image& zRObj) // renders the table into zRObj
{
    if (hasStyleNot(Style::Visible)) return;
    DrawableBackground::render(zRObj);
    rwLock.lockRead();
    if (!zRObj.setDrawOptions(innenPosition, innenSize))
    {
        rwLock.unlockRead();
        return;
    }
    int xPos = 0;
    if (horizontalScrollBar && hasStyle(Style::HScroll))
        xPos -= horizontalScrollBar->getScroll();
    for (int s = 0; s < spaltenAnzahl; ++s)
    {
        int sBr = columnWidth->has(s) ? columnWidth->get(s) : 0;
        int yPos = 0;
        if (vertikalScrollBar && hasStyle(Style::VScroll))
            yPos -= vertikalScrollBar->getScroll();
        RCArray<Drawable>* tmp_zDrawables = members->z(s);
        if (!tmp_zDrawables) continue;
        for (int z = 0; z < zeilenAnzahl && tmp_zDrawables; ++z)
        {
            int zHi = zeilenHeight->has(z) ? zeilenHeight->get(z) : 0;
            if (hasStyle(Style::Raster)) yPos += gridWidth;
            yPos += zHi;
            if (z == zeilenAnzahl - 1 && vertikalScrollBar
                && hasStyle(Style::VScroll))
                vertikalScrollBar->getScrollData()->max
                    = yPos + vertikalScrollBar->getScroll();
        }
        for (int z = zeilenAnzahl - 1; z >= 0 && tmp_zDrawables; z--)
        {
            int zHi = zeilenHeight->has(z) ? zeilenHeight->get(z) : 0;
            yPos -= zHi;
            if (hasStyle(Style::Raster))
            {
                yPos -= gridWidth;
                for (int i = 0; i < gridWidth; i++)
                    zRObj.drawLineHAlpha(
                        xPos, yPos + zHi + i, sBr, rasterColor);
            }
            Drawable* obj = tmp_zDrawables->has(z) ? tmp_zDrawables->z(z) : 0;
            if (obj)
            {
                obj->setPosition(xPos, yPos);
                obj->setSize(sBr, zHi);
                obj->render(zRObj);
                if (selected.x == s && selected.y == z)
                {
                    Border* tmp_aRam = aRam;
                    AlphaField* tmp_aAf = aAf;
                    bool aRamB = hasStyle(Style::SelectionBorder) && tmp_aRam;
                    bool aAfB = hasStyle(Style::SelectionBuffer) && tmp_aAf;
                    if (hasStyle(Style::SelectionMultistyled))
                    {
                        tmp_aRam = getABorder(s, z);
                        tmp_aAf = getAAlphaField(s, z);
                        aRamB = hasMsStyle(s, z, Style::SelectionBorder)
                             && tmp_aRam;
                        aAfB = hasMsStyle(s, z, Style::SelectionBuffer)
                            && tmp_aAf;
                    }
                    int aRbr = 0;
                    if (aRamB)
                    {
                        tmp_aRam->setPosition(xPos, yPos);
                        tmp_aRam->setSize(sBr, zHi);
                        tmp_aRam->render(zRObj);
                        aRbr = tmp_aRam->getRWidth();
                    }
                    if (aAfB)
                    {
                        tmp_aAf->setPosition(aRbr + xPos, aRbr + yPos);
                        tmp_aAf->setSize(sBr - aRbr * 2, zHi - aRbr * 2);
                        tmp_aAf->render(zRObj);
                    }
                }
            }
        }
        if (hasStyle(Style::Raster))
        {
            for (int i = 0; i < gridWidth; i++)
                zRObj.drawLineVAlpha(
                    xPos + sBr + i, 0, innenSize.y, rasterColor);
            xPos += gridWidth;
        }
        xPos += sBr;
    }
    if (horizontalScrollBar && hasStyle(Style::HScroll))
        horizontalScrollBar->getScrollData()->max
            = xPos + horizontalScrollBar->getScroll();
    zRObj.releaseDrawOptions();
    rwLock.unlockRead();
}

// constant
int ObjTable::getColumnCount() const // returns the number of columns
{
    return spaltenAnzahl;
}

int ObjTable::getRowCount() const // returns the number of rows
{
    return zeilenAnzahl;
}

int ObjTable::getColumnNumber(
    const char* name) const // returns the index of the column with the name
{
    for (int i = 0; i < spaltenAnzahl; ++i)
    {
        if (spaltenNamen->z(i)->isEqual(name)) return i;
    }
    return -1;
}

int ObjTable::getColumnNumber(Text* name) const
{
    int ret = getColumnNumber(name->getText());
    name->release();
    return ret;
}

Text* ObjTable::getColumnName(
    int num) const // returns the name of the column with index num
{
    return spaltenNamen->get(num);
}

Text* ObjTable::zColumnName(int num) const
{
    return spaltenNamen->z(num);
}

int ObjTable::getRowNumber(
    const char* name) const // returns the index of the row with the name
{
    for (int i = 0; i < zeilenAnzahl; ++i)
    {
        if (zeilenNamen->z(i)->isEqual(name)) return i;
    }
    return -1;
}

int ObjTable::getRowNumber(Text* name) const
{
    int ret = getRowNumber(name->getText());
    name->release();
    return ret;
}

Text* ObjTable::getRowName(
    int num) const // returns the name of the row with index num
{
    return zeilenNamen->get(num);
}

Text* ObjTable::zRowName(int num) const
{
    return zeilenNamen->z(num);
}

Point ObjTable::getDrawablePosition(
    Drawable* zObj) const // returns the position of a drawing
{
    for (int x = 0; x < spaltenAnzahl; ++x)
    {
        for (int y = 0; y < zeilenAnzahl; ++y)
        {
            if (zDrawable(x, y) == zObj) return Point(x, y);
        }
    }
    return Point(-1, -1);
}

Drawable* ObjTable::zDrawable(
    int sNum, int zNum) const // returns the drawing at the position
{
    if (sNum < 0 || zNum < 0 || sNum >= spaltenAnzahl || zNum >= zeilenAnzahl)
        return 0;
    if (!members->z(sNum)) return 0;
    RCArray<Drawable>* tmp = members->z(sNum);
    if (!tmp->has(zNum)) return 0;
    return tmp ? tmp->z(zNum) : 0;
}

Drawable* ObjTable::zDrawable(
    const char* spaltenName, const char* zeilenName) const
{
    return zDrawable(getColumnNumber(spaltenName), getRowNumber(zeilenName));
}

Drawable* ObjTable::zDrawable(Text* spaltenName, Text* zeilenName) const
{
    return zDrawable(getColumnNumber(spaltenName), getRowNumber(zeilenName));
}

Drawable* ObjTable::getDrawable(
    int sNum, int zNum) const // returns the drawing at the position
{
    if (!members->z(sNum)) return 0;
    RCArray<Drawable>* tmp = members->z(sNum);
    if (!tmp->has(zNum)) return 0;
    return tmp ? tmp->get(zNum) : 0;
}

Drawable* ObjTable::getDrawable(
    const char* spaltenName, const char* zeilenName) const
{
    return getDrawable(getColumnNumber(spaltenName), getRowNumber(zeilenName));
}

Drawable* ObjTable::getDrawable(Text* spaltenName, Text* zeilenName) const
{
    return getDrawable(getColumnNumber(spaltenName), getRowNumber(zeilenName));
}

int ObjTable::getColumnWidth(int num) const // returns the width of the column
{
    return columnWidth->get(num);
}

int ObjTable::getColumnWidth(const char* name) const
{
    return getColumnWidth(getColumnNumber(name));
}

int ObjTable::getColumnWidth(Text* name) const
{
    return getColumnWidth(getColumnNumber(name));
}

int ObjTable::getRowHeight(int num) const // returns the height of the row
{
    return zeilenHeight->get(num);
}

int ObjTable::getRowHeight(const char* name) const
{
    return getRowHeight(getRowNumber(name));
}

int ObjTable::getRowHeight(Text* name) const
{
    return getRowHeight(getRowNumber(name));
}

int ObjTable::getMinColumnWidth(
    int num) const // returns the minimum column width
{
    return minSpaltenWidth->get(num);
}

int ObjTable::getMinColumnWidth(const char* name) const
{
    return getMinColumnWidth(getColumnNumber(name));
}

int ObjTable::getMinColumnWidth(Text* name) const
{
    return getMinColumnWidth(getColumnNumber(name));
}

int ObjTable::getMaxColumnWidth(
    int num) const // returns the maximum column width
{
    return maxSpaltenWidth->get(num);
}

int ObjTable::getMaxColumnWidth(const char* name) const
{
    return getMaxColumnWidth(getColumnNumber(name));
}

int ObjTable::getMaxColumnWidth(Text* name) const
{
    return getMaxColumnWidth(getColumnNumber(name));
}

int ObjTable::getMinRowHeight(int num) const // returns the minimum row height
{
    return minZeilenHeight->get(num);
}

int ObjTable::getMinRowHeight(const char* name) const
{
    return getMinRowHeight(getRowNumber(name));
}

int ObjTable::getMinRowHeight(Text* name) const
{
    return getMinRowHeight(getRowNumber(name));
}

int ObjTable::getMaxRowHeight(int num) const // returns the maximum row height
{
    return maxZeilenHeight->get(num);
}

int ObjTable::getMaxRowHeight(const char* name) const
{
    return getMaxRowHeight(getRowNumber(name));
}

int ObjTable::getMaxRowHeight(Text* name) const
{
    return getMaxRowHeight(getRowNumber(name));
}

double ObjTable::getMouseColumn(
    int mx) const // determines the column under the mouse
{
    if (mx >= gr.x) return -1;
    int hsBeg = (horizontalScrollBar && hasStyle(Style::HScroll))
                  ? horizontalScrollBar->getScroll()
                  : 0;
    mx += hsBeg;
    if (mx < 0) return -1;
    int xx = border ? border->getRWidth() : 0;
    for (int i = 0; i < spaltenAnzahl; ++i)
    {
        xx += columnWidth->get(i);
        if (mx < xx - 5) return i;
        if (mx < xx + 5) return i + 0.5;
        xx += gridWidth;
    }
    return -1;
}

Text* ObjTable::getMouseColumnnName(int mx) const
{
    double tmp = getMouseColumn(mx);
    if (tmp != (int)tmp) return 0;
    return getColumnName((int)tmp);
}

Text* ObjTable::zMouseColumnName(int mx) const
{
    double tmp = getMouseColumn(mx);
    if (tmp != (int)tmp) return 0;
    return zColumnName((int)tmp);
}

double ObjTable::getMouseRow(int my) const // calculates the row under the mouse
{
    if (my >= gr.y) return -1;
    if (my < 0) return -1;
    int vsBeg = vertikalScrollBar && hasStyle(Style::VScroll)
                  ? vertikalScrollBar->getScroll()
                  : 0;
    my += vsBeg;
    int yy = border ? border->getRWidth() : 0;
    for (int i = 0; i < zeilenAnzahl; ++i)
    {
        yy += zeilenHeight->get(i);
        if (my < yy - 5) return i;
        if (my < yy + 5) return i + 0.5;
        yy += gridWidth;
    }
    return -1;
}

Text* ObjTable::getMouseRownName(int my) const
{
    double tmp = getMouseRow(my);
    if (tmp != (int)tmp) return 0;
    return getRowName((int)tmp);
}

Text* ObjTable::zMouseRowName(int my) const
{
    double tmp = getMouseRow(my);
    if (tmp != (int)tmp) return 0;
    return zRowName((int)tmp);
}

const Point&
ObjTable::getSelahlPosition() const // returns the selection position
{
    return selected;
}

int ObjTable::getGridColor() const // returns the color of the grid
{
    return rasterColor;
}

int ObjTable::getGridWidth() const // returns the width of the grid
{
    return gridWidth;
}

Border* ObjTable::getABorder() const // returns the selection border
{
    return aRam ? dynamic_cast<Border*>(aRam->getThis()) : 0;
}

Border* ObjTable::zABorder() const
{
    return aRam;
}

AlphaField* ObjTable::getAAlphaField() const // returns the selection AlphaField
{
    return aAf ? dynamic_cast<AlphaField*>(aAf->getThis()) : 0;
}

AlphaField* ObjTable::zAAlphaField() const
{
    return aAf;
}

Border* ObjTable::getABorder(
    int sNum, int zNum) const // returns the selection border
{
    RCArray<Border>* tmp = msaRam->z(sNum);
    return tmp ? tmp->get(zNum) : 0;
}

Border* ObjTable::zABorder(int sNum, int zNum) const
{
    RCArray<Border>* tmp = msaRam->z(sNum);
    return tmp ? tmp->z(zNum) : 0;
}

AlphaField* ObjTable::getAAlphaField(
    int sNum, int zNum) const // returns the selection AlphaField
{
    RCArray<AlphaField>* tmp = msaAf->z(sNum);
    return tmp ? tmp->get(zNum) : 0;
}

AlphaField* ObjTable::zAAlphaField(int sNum, int zNum) const
{
    return msaAf->z(sNum) ? msaAf->z(sNum)->z(zNum) : 0;
}

Border* ObjTable::getABorder(const char* spaltenName,
    const char* zeilenName) const // returns the selection border
{
    return getABorder(getColumnNumber(spaltenName), getRowNumber(zeilenName));
}

Border* ObjTable::zABorder(
    const char* spaltenName, const char* zeilenName) const
{
    return zABorder(getColumnNumber(spaltenName), getRowNumber(zeilenName));
}

AlphaField* ObjTable::getAAlphaField(const char* spaltenName,
    const char* zeilenName) const // returns the selection AlphaField
{
    return getAAlphaField(
        getColumnNumber(spaltenName), getRowNumber(zeilenName));
}

AlphaField* ObjTable::zAAlphaField(
    const char* spaltenName, const char* zeilenName) const
{
    return zAAlphaField(getColumnNumber(spaltenName), getRowNumber(zeilenName));
}

Border* ObjTable::getABorder(
    Text* spaltenName, Text* zeilenName) const // returns the selection border
{
    return getABorder(getColumnNumber(spaltenName), getRowNumber(zeilenName));
}

Border* ObjTable::zABorder(Text* spaltenName, Text* zeilenName) const
{
    return zABorder(getColumnNumber(spaltenName), getRowNumber(zeilenName));
}

AlphaField* ObjTable::getAAlphaField(Text* spaltenName,
    Text* zeilenName) const // returns the selection AlphaField
{
    return getAAlphaField(
        getColumnNumber(spaltenName), getRowNumber(zeilenName));
}

AlphaField* ObjTable::zAAlphaField(Text* spaltenName, Text* zeilenName) const
{
    return zAAlphaField(getColumnNumber(spaltenName), getRowNumber(zeilenName));
}

bool ObjTable::hasMsStyle(
    int sNum, int zNum, __int64 style) const // checks if style is present
{
    __int64 s = styles->z(sNum) && styles->z(sNum)->has(zNum)
                  ? styles->z(sNum)->get(zNum)
                  : 0;
    return (s | style) == s;
}

bool ObjTable::hasMsStyleNot(int sNum,
    int zNum,
    __int64 style) const // checks if style is not present
{
    __int64 s = styles->z(sNum) && styles->z(sNum)->has(zNum)
                  ? styles->z(sNum)->get(zNum)
                  : 0;
    return (s | style) != s;
}

bool ObjTable::hasMsStyle(const char* spaltenName,
    const char* zeilenName,
    __int64 style) const // checks if style is present
{
    return hasMsStyle(
        getColumnNumber(spaltenName), getRowNumber(zeilenName), style);
}

bool ObjTable::hasMsStyleNot(const char* spaltenName,
    const char* zeilenName,
    __int64 style) const // checks if style is not present
{
    return hasMsStyleNot(
        getColumnNumber(spaltenName), getRowNumber(zeilenName), style);
}

bool ObjTable::hasMsStyle(Text* spaltenName,
    Text* zeilenName,
    __int64 style) const // checks if style is present
{
    return hasMsStyle(
        getColumnNumber(spaltenName), getRowNumber(zeilenName), style);
}

bool ObjTable::hasMsStyleNot(Text* spaltenName,
    Text* zeilenName,
    __int64 style) const // checks if style is not present
{
    return hasMsStyleNot(
        getColumnNumber(spaltenName), getRowNumber(zeilenName), style);
}

Drawable* ObjTable::duplicate() const // Creates a copy of the table
{
    ObjTable* obj = new ObjTable();
    obj->setPosition(pos);
    obj->setSize(gr);
    obj->setMouseEventParameter(makParam);
    obj->setKeyboardEventParameter(takParam);
    obj->setMouseEvent(mak);
    obj->setKeyboardEvent(tak);
    if (toolTip) obj->setToolTipZ((ToolTip*)toolTip->duplicate());
    obj->setStyle(style);
    if (border) obj->setBorderZ((Border*)border->duplicate());
    obj->setBackgroundColor(backgroundColor);
    if (backgroundImage)
        obj->setBackgroundImage(
            dynamic_cast<Image*>(backgroundImage->getThis()));
    if (backgroundFeld)
        obj->setAlphaFieldZ((AlphaField*)backgroundFeld->duplicate());
    obj->setGridColor(rasterColor);
    obj->setGridWidth(gridWidth);
    if (aRam) obj->setABorderZ((Border*)aRam->duplicate());
    if (aAf) obj->setAAlphaFieldZ((AlphaField*)aAf->duplicate());
    for (int s = 0; s < spaltenAnzahl; ++s)
    {
        obj->addColumn(spaltenNamen->get(s));
        if (columnWidth->has(s)) obj->setColumnWidth(s, columnWidth->get(s));
        if (minSpaltenWidth->has(s))
            obj->setMinColumnWidth(s, minSpaltenWidth->get(s));
        if (maxSpaltenWidth->has(s))
            obj->setMaxColumnWidth(s, maxSpaltenWidth->get(s));
        for (int z = 0; z < zeilenAnzahl; ++z)
        {
            if (!s)
            {
                obj->addRow(zeilenNamen->get(z));
                if (zeilenHeight->has(z))
                    obj->setRowHeight(z, zeilenHeight->get(z));
                if (minZeilenHeight->has(z))
                    obj->setMinRowHeight(z, minZeilenHeight->get(z));
                if (maxZeilenHeight->has(z))
                    obj->setMaxRowHeight(z, maxZeilenHeight->get(z));
            }
            if (members->z(s) && members->z(s)->has(z))
                obj->setDrawableZ(s, z, members->z(s)->get(z));
            if (styles->z(s) && styles->z(s)->has(z))
                obj->setMsStyle(s, z, styles->z(s)->get(z));
            if (msaRam->z(s) && msaRam->z(s)->z(z))
                obj->setABorderZ(
                    s, z, (Border*)msaRam->z(s)->z(z)->duplicate());
            if (msaAf->z(s) && msaAf->z(s)->z(z))
                obj->setAAlphaFieldZ(
                    s, z, (AlphaField*)msaAf->z(s)->z(z)->duplicate());
        }
    }
    obj->setSelection(selected.x, selected.y);
    return obj;
}