/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/


#ifdef _MSC_VER
#pragma hdrstop
#endif

#define ITEMID_BOXINFO      SID_ATTR_BORDER_INNER

#include <hintids.hxx>


#include <bf_svx/lrspitem.hxx>

#include <fmtfsize.hxx>

#include <horiornt.hxx>

#include <fmtornt.hxx>
#include <fmtfordr.hxx>
#include <fmtlsplt.hxx>

#include <doc.hxx>
#include <cntfrm.hxx>
#include <hints.hxx>
#include <poolfmt.hxx>
#include <tabfrm.hxx>
#include <tblafmt.hxx>
#include <cellatr.hxx>
#include <swtblfmt.hxx>
#include <docary.hxx>
#include <redline.hxx>
#include <tblrwcl.hxx>

#include <node2lay.hxx>

#include <comcore.hrc>

#include "docsh.hxx"

#include <ndtxt.hxx>
namespace binfilter {

const sal_Unicode T2T_PARA = 0x0a;


// steht im gctable.cxx


/*N*/ void lcl_SetDfltBoxAttr( SwFrmFmt& rFmt, BYTE nId )
/*N*/ {
/*N*/   BOOL bTop = FALSE, bBottom = FALSE, bLeft = FALSE, bRight = FALSE;
/*N*/   switch ( nId )
/*N*/   {
/*?*/   case 0: bTop = bBottom = bLeft = TRUE;          break;
/*N*/   case 1: bTop = bBottom = bLeft = bRight = TRUE; break;
/*?*/   case 2: bBottom = bLeft = TRUE;                 break;
/*?*/   case 3: bBottom = bLeft = bRight = TRUE;        break;
/*N*/   }
/*N*/
/*N*/   const BOOL bHTML = rFmt.GetDoc()->IsHTMLMode();
/*N*/   Color aCol( bHTML ? COL_GRAY : COL_BLACK );
/*N*/   SvxBorderLine aLine( &aCol, DEF_LINE_WIDTH_0 );
/*N*/   if ( bHTML )
/*N*/   {
/*?*/       aLine.SetOutWidth( DEF_DOUBLE_LINE7_OUT );
/*?*/       aLine.SetInWidth ( DEF_DOUBLE_LINE7_IN  );
/*?*/       aLine.SetDistance( DEF_DOUBLE_LINE7_DIST);
/*N*/   }
/*N*/   SvxBoxItem aBox; aBox.SetDistance( 55 );
/*N*/   if ( bTop )
/*N*/       aBox.SetLine( &aLine, BOX_LINE_TOP );
/*N*/   if ( bBottom )
/*N*/       aBox.SetLine( &aLine, BOX_LINE_BOTTOM );
/*N*/   if ( bLeft )
/*N*/       aBox.SetLine( &aLine, BOX_LINE_LEFT );
/*N*/   if ( bRight )
/*N*/       aBox.SetLine( &aLine, BOX_LINE_RIGHT );
/*N*/   rFmt.SetAttr( aBox );
/*N*/ }


/* --> #109161# */
static bool lcl_IsItemSet(const SwCntntNode & rNode, USHORT which)
{
    bool bResult = false;

    if (SFX_ITEM_SET == rNode.GetSwAttrSet().GetItemState(which))
        bResult = true;

    return bResult;
}

/* <-- #109161# */

/*N*/ SwTableBoxFmt *lcl_CreateDfltBoxFmt( SwDoc &rDoc, SvPtrarr &rBoxFmtArr,
/*N*/                                   USHORT nCols, BYTE nId )
/*N*/ {
/*N*/   if ( !rBoxFmtArr[nId] )
/*N*/   {
/*N*/       SwTableBoxFmt* pBoxFmt = rDoc.MakeTableBoxFmt();
/*N*/       if( USHRT_MAX != nCols )
/*N*/           pBoxFmt->SetAttr( SwFmtFrmSize( ATT_VAR_SIZE,
/*N*/                                           USHRT_MAX / nCols, 0 ));
/*N*/       ::binfilter::lcl_SetDfltBoxAttr( *pBoxFmt, nId );
/*N*/       rBoxFmtArr.Replace( pBoxFmt, nId );
/*N*/   }
/*N*/   return (SwTableBoxFmt*)rBoxFmtArr[nId];
/*N*/ }


/*N*/ SwTableNode* SwDoc::IsIdxInTbl(const SwNodeIndex& rIdx)
/*N*/ {
/*N*/   SwTableNode* pTableNd = 0;
/*N*/   ULONG nIndex = rIdx.GetIndex();
/*N*/   do {
/*N*/       SwNode* pNd = (SwNode*)GetNodes()[ nIndex ]->StartOfSectionNode();
/*N*/       if( 0 != ( pTableNd = pNd->GetTableNode() ) )
/*?*/           break;
/*N*/
/*N*/       nIndex = pNd->GetIndex();
/*N*/   } while ( nIndex );
/*N*/   return pTableNd;
/*N*/ }

// --------------- einfuegen einer neuen Tabelle --------------

/*N*/ const SwTable* SwDoc::InsertTable( const SwPosition& rPos, USHORT nRows,
/*N*/                                   USHORT nCols, SwHoriOrient eAdjust,
/*N*/                                   USHORT nInsTblFlags,
/*N*/                                   const SwTableAutoFmt* pTAFmt,
/*N*/                                    const SvUShorts* pColArr,
/*N*/                                    BOOL bCalledFromShell )
/*N*/ {
/*N*/   OSL_ENSURE( nRows, "Tabelle ohne Zeile?" );
/*N*/   OSL_ENSURE( nCols, "Tabelle ohne Spalten?" );
/*N*/
/*N*/   {
/*N*/       // nicht in Fussnoten kopieren !!
/*N*/       if( rPos.nNode < GetNodes().GetEndOfInserts().GetIndex() &&
/*N*/           rPos.nNode >= GetNodes().GetEndOfInserts().StartOfSectionIndex() )
/*?*/           return 0;
/*N*/
/*N*/       // sollte das ColumnArray die falsche Anzahl haben wird es ignoriert!
/*N*/       if( pColArr &&
/*N*/           (nCols + ( HORI_NONE == eAdjust ? 2 : 1 )) != pColArr->Count() )
/*?*/           pColArr = 0;
/*N*/   }
/*N*/
/*N*/   // fuege erstmal die Nodes ein
/*N*/   // hole das Auto-Format fuer die Tabelle
/*N*/   SwTxtFmtColl *pBodyColl = GetTxtCollFromPool( RES_POOLCOLL_TABLE ),
/*N*/                *pHeadColl = pBodyColl;
/*N*/
/*N*/   BOOL bDfltBorders = nInsTblFlags & DEFAULT_BORDER;
/*N*/
/*N*/   if( (nInsTblFlags & HEADLINE) && (1 != nRows || !bDfltBorders) )
/*?*/       pHeadColl = GetTxtCollFromPool( RES_POOLCOLL_TABLE_HDLN );
/*N*/
/*N*/   /* #106283# Save content node to extract FRAMEDIR from. */
/*N*/   const SwCntntNode * pCntntNd = rPos.nNode.GetNode().GetCntntNode();
/*N*/
    /* #109161# If we are called from a shell pass the attrset from
        pCntntNd (aka the node the table is inserted at) thus causing
        SwNodes::InsertTable to propagate an adjust item if
        necessary. */
/*N*/   SwTableNode *pTblNd = GetNodes().InsertTable
/*N*/         ( rPos.nNode, nCols, pBodyColl, nRows, pHeadColl,
/*N*/           bCalledFromShell ? &pCntntNd->GetSwAttrSet() : 0 );
/*N*/
/*N*/   // dann erstelle die Box/Line/Table-Struktur
/*N*/   SwTableLineFmt* pLineFmt = MakeTableLineFmt();
/*N*/   SwTableFmt* pTableFmt = MakeTblFrmFmt( GetUniqueTblName(), GetDfltFrmFmt() );
/*N*/
    /* #106283# If the node to insert the table at is a context node and has a
       non-default FRAMEDIR propagate it to the table. */
/*N*/   if (pCntntNd)
/*N*/   {
/*N*/       const SwAttrSet & aNdSet = pCntntNd->GetSwAttrSet();
/*N*/       const SfxPoolItem *pItem = NULL;
/*N*/
/*N*/       if (SFX_ITEM_SET == aNdSet.GetItemState( RES_FRAMEDIR, TRUE, &pItem )
/*N*/           && pItem != NULL)
/*N*/       {
/*N*/           pTableFmt->SetAttr( *pItem );
/*N*/       }
/*N*/   }
/*N*/
/*N*/   //Orientation am Fmt der Table setzen
/*N*/   pTableFmt->SetAttr( SwFmtHoriOrient( 0, eAdjust ) );
/*N*/   // alle Zeilen haben die Fill-Order von links nach rechts !
/*N*/   pLineFmt->SetAttr( SwFmtFillOrder( ATT_LEFT_TO_RIGHT ));
/*N*/
/*N*/   // die Tabelle bekommt USHRT_MAX als default SSize
/*N*/   SwTwips nWidth = USHRT_MAX;
/*N*/   if( pColArr )
/*N*/   {
/*?*/       USHORT nSttPos = (*pColArr)[ 0 ];
/*?*/       USHORT nLastPos = (*pColArr)[ USHORT(pColArr->Count()-1)];
/*?*/       if( HORI_NONE == eAdjust )
/*?*/       {
/*?*/           USHORT nFrmWidth = nLastPos;
/*?*/           nLastPos = (*pColArr)[ USHORT(pColArr->Count()-2)];
/*?*/           pTableFmt->SetAttr( SvxLRSpaceItem( nSttPos, nFrmWidth - nLastPos ) );
/*?*/       }
/*?*/       nWidth = nLastPos - nSttPos;
/*N*/   }
/*N*/   pTableFmt->SetAttr( SwFmtFrmSize( ATT_VAR_SIZE, nWidth ));
/*N*/   if( !(nInsTblFlags & SPLIT_LAYOUT) )
/*?*/       pTableFmt->SetAttr( SwFmtLayoutSplit( FALSE ));
/*N*/
/*N*/   // verschiebe ggfs. die harten PageDesc/PageBreak Attribute:
/*N*/   SwCntntNode* pNextNd = GetNodes()[ pTblNd->EndOfSectionIndex()+1 ]
/*N*/                           ->GetCntntNode();
/*N*/   if( pNextNd && pNextNd->GetpSwAttrSet() )
/*N*/   {
/*?*/       SwAttrSet* pNdSet = pNextNd->GetpSwAttrSet();
/*?*/       const SfxPoolItem *pItem;
/*?*/       if( SFX_ITEM_SET == pNdSet->GetItemState( RES_PAGEDESC, FALSE,
/*?*/           &pItem ) )
/*?*/       {
/*?*/           pTableFmt->SetAttr( *pItem );
/*?*/           pNextNd->ResetAttr( RES_PAGEDESC );
/*?*/           pNdSet = pNextNd->GetpSwAttrSet();
/*?*/       }
/*?*/       if( pNdSet && SFX_ITEM_SET == pNdSet->GetItemState( RES_BREAK, FALSE,
/*?*/            &pItem ) )
/*?*/       {
/*?*/           pTableFmt->SetAttr( *pItem );
/*?*/           pNextNd->ResetAttr( RES_BREAK );
/*?*/       }
/*N*/   }
/*N*/
/*N*/   SwTable * pNdTbl = &pTblNd->GetTable();
/*N*/   pTableFmt->Add( pNdTbl );       // das Frame-Format setzen
/*N*/
/*N*/   pNdTbl->SetHeadlineRepeat( HEADLINE_REPEAT == (nInsTblFlags & HEADLINE_REPEAT) );
/*N*/
/*N*/   SvPtrarr aBoxFmtArr( 0, 16 );
/*N*/   SwTableBoxFmt* pBoxFmt = 0;
/*N*/   if( !bDfltBorders && !pTAFmt )
/*N*/   {
/*?*/       pBoxFmt = MakeTableBoxFmt();
/*?*/       pBoxFmt->SetAttr( SwFmtFrmSize( ATT_VAR_SIZE, USHRT_MAX / nCols, 0 ));
/*N*/   }
/*N*/   else
/*N*/   {
/*N*/       const USHORT nBoxArrLen = pTAFmt ? 16 : 4;
/*N*/       for( USHORT i = 0; i < nBoxArrLen; ++i )
/*N*/           aBoxFmtArr.Insert( (void*)0, i );
/*N*/   }
/*N*/   SfxItemSet aCharSet( GetAttrPool(), RES_CHRATR_BEGIN, RES_PARATR_END-1 );
/*N*/
/*N*/   SwNodeIndex aNdIdx( *pTblNd, 1 );   // auf den ersten Box-StartNode
/*N*/   SwTableLines& rLines = pNdTbl->GetTabLines();
/*N*/   for( USHORT n = 0; n < nRows; ++n )
/*N*/   {
/*N*/       SwTableLine* pLine = new SwTableLine( pLineFmt, nCols, 0 );
/*N*/       rLines.C40_INSERT( SwTableLine, pLine, n );
/*N*/       SwTableBoxes& rBoxes = pLine->GetTabBoxes();
/*N*/       for( USHORT i = 0; i < nCols; ++i )
/*N*/       {
/*N*/           SwTableBoxFmt *pBoxF(0);
/*N*/           if( !pTAFmt )
                {
                    if( bDfltBorders )
                    {
                        BYTE nBoxId = (i < nCols - 1 ? 0 : 1) + (n ? 2 : 0 );
                        pBoxF = ::binfilter::lcl_CreateDfltBoxFmt( *this, aBoxFmtArr, nCols, nBoxId);
                    }
                    else
                        pBoxF = pBoxFmt;
                }
/*N*/
/*N*/           // fuer AutoFormat bei der Eingabe: beim Einfuegen der Tabelle
/*N*/           // werden gleich die Spalten gesetzt. Im Array stehen die
/*N*/           // Positionen der Spalten!! (nicht deren Breite!)
/*N*/           if( pColArr )
/*N*/           {
/*?*/               nWidth = (*pColArr)[ USHORT(i + 1) ] - (*pColArr)[ i ];
/*?*/               if( pBoxF->GetFrmSize().GetWidth() != nWidth )
/*?*/               {
/*?*/                   if( pBoxF->GetDepends() )       // neues Format erzeugen!
/*?*/                   {
/*?*/                       SwTableBoxFmt *pNewFmt = MakeTableBoxFmt();
/*?*/                       *pNewFmt = *pBoxF;
/*?*/                       pBoxF = pNewFmt;
/*?*/                   }
/*?*/                   pBoxF->SetAttr( SwFmtFrmSize( ATT_VAR_SIZE, nWidth ));
/*?*/               }
/*N*/           }
/*N*/
/*N*/           SwTableBox *pBox = new SwTableBox( pBoxF, aNdIdx, pLine);
/*N*/           rBoxes.C40_INSERT( SwTableBox, pBox, i );
/*N*/           aNdIdx += 3;        // StartNode, TextNode, EndNode  == 3 Nodes
/*N*/       }
/*N*/   }
/*N*/   // und Frms einfuegen.
/*N*/   GetNodes().GoNext( &aNdIdx );      // zum naechsten ContentNode
/*N*/   pTblNd->MakeFrms( &aNdIdx );
/*N*/
/*N*/   SetModified();
/*N*/   return pNdTbl;
/*N*/ }

/*N*/ SwTableNode* SwNodes::InsertTable( const SwNodeIndex& rNdIdx,
/*N*/                                   USHORT nBoxes,
/*N*/                                   SwTxtFmtColl* pCntntTxtColl,
/*N*/                                   USHORT nLines,
/*N*/                                  SwTxtFmtColl* pHeadlineTxtColl,
/*N*/                                    const SwAttrSet * pAttrSet)
/*N*/ {
/*N*/   if( !nBoxes )
/*?*/       return 0;
/*N*/
/*N*/   // wenn Lines angegeben, erzeuge die Matrix aus Lines & Boxen
/*N*/   if( !pHeadlineTxtColl || !nLines )
/*N*/       pHeadlineTxtColl = pCntntTxtColl;
/*N*/
/*N*/   SwTableNode * pTblNd = new SwTableNode( rNdIdx );
/*N*/   SwEndNode* pEndNd = new SwEndNode( rNdIdx, *pTblNd );
/*N*/
/*N*/   if( !nLines )       // fuer die FOR-Schleife
/*N*/       ++nLines;
/*N*/
/*N*/   SwNodeIndex aIdx( *pEndNd );
/*N*/   register SwTxtFmtColl* pTxtColl = pHeadlineTxtColl;
/*N*/   for( register USHORT nL = 0; nL < nLines; ++nL )
/*N*/   {
/*N*/       for( register USHORT nB = 0; nB < nBoxes; ++nB )
/*N*/       {
/*N*/           SwStartNode* pSttNd = new SwStartNode( aIdx, ND_STARTNODE,
/*N*/                                                   SwTableBoxStartNode );
/*N*/           pSttNd->pStartOfSection = pTblNd;

            /** #109161# If there is no adjust item in pTxtColl
                 propagate any existing adjust item in pAttrSet to the
                 newly created context node in the new cell.
             */
/*N*/           SwTxtNode * pTmpNd = new SwTxtNode( aIdx, pTxtColl );
/*N*/
/*N*/             const SfxPoolItem * pItem = NULL;
/*N*/
/*N*/             if (! lcl_IsItemSet(*pTmpNd, RES_PARATR_ADJUST) &&
/*N*/                 pAttrSet != NULL &&
/*N*/                 SFX_ITEM_SET == pAttrSet->GetItemState( RES_PARATR_ADJUST, TRUE,
/*N*/                                                         &pItem)
/*N*/                 )
/*N*/             {
/*N*/                 static_cast<SwCntntNode *>(pTmpNd)->SetAttr(*pItem);
/*N*/             }
/*N*/
/*N*/           new SwEndNode( aIdx, *pSttNd );
/*N*/       }
/*N*/       pTxtColl = pCntntTxtColl;
/*N*/   }
/*N*/   return pTblNd;
/*N*/ }


// -------------------------------------------------------

//---------
// SwTableNode
//---------

/*N*/ SwTableNode::SwTableNode( const SwNodeIndex& rIdx )
/*N*/   : SwStartNode( rIdx, ND_TABLENODE )
/*N*/ {
/*N*/   pTable = new SwTable( 0 );
/*N*/ }

/*M*/ SwTableNode::~SwTableNode()
/*M*/ {
/*M*/   //don't forget to notify uno wrappers
/*M*/   SwFrmFmt* pTblFmt = GetTable().GetFrmFmt();
/*M*/   SwPtrMsgPoolItem aMsgHint( RES_REMOVE_UNO_OBJECT,
/*M*/                               pTblFmt );
/*M*/   pTblFmt->Modify( &aMsgHint, &aMsgHint );
/*M*/   DelFrms();
/*M*/   delete pTable;
/*M*/ }

/*N*/ SwTabFrm *SwTableNode::MakeFrm()
/*N*/ {
/*N*/   return new SwTabFrm( *pTable );
/*N*/ }

//Fuer jede Shell einen TblFrm anlegen und vor den entsprechenden
//CntntFrm pasten.

/*N*/ void SwTableNode::MakeFrms( SwNodeIndex* pIdxBehind )
/*N*/ {
/*N*/   OSL_ENSURE( pIdxBehind, "kein Index" );
/*N*/   *pIdxBehind = *this;
/*N*/ }

/*N*/ void SwTableNode::DelFrms()
/*N*/ {
/*N*/   //Erstmal die TabFrms ausschneiden und deleten, die Columns und Rows
/*N*/   //nehmen sie mit in's Grab.
/*N*/   //Die TabFrms haengen am FrmFmt des SwTable.
/*N*/   //Sie muessen etwas umstaendlich zerstort werden, damit die Master
/*N*/   //die Follows mit in's Grab nehmen.
/*N*/
/*N*/   SwClientIter aIter( *(pTable->GetFrmFmt()) );
/*N*/   SwClient *pLast = aIter.GoStart();
/*N*/   while ( pLast )
/*N*/   {
/*N*/       BOOL bAgain = FALSE;
/*N*/       if ( pLast->IsA( TYPE(SwFrm) ) )
/*N*/       {
/*N*/           SwTabFrm *pFrm = (SwTabFrm*)pLast;
/*N*/           if ( !pFrm->IsFollow() )
/*N*/           {
/*N*/               while ( pFrm->HasFollow() ) { DBG_BF_ASSERT(0, "STRIP"); }
/*N*/               pFrm->Cut();
/*N*/               delete pFrm;
/*N*/               bAgain = TRUE;
/*N*/           }
/*N*/       }
/*N*/       pLast = bAgain ? aIter.GoStart() : aIter++;
/*N*/   }
/*N*/ }


/* --------------------------------------------------
 *  Direktzugriff fuer UNO
 * --------------------------------------------------*/

void SwCollectTblLineBoxes::AddBox( const SwTableBox& rBox )
{
    aPosArr.Insert( nWidth, aPosArr.Count() );
    SwTableBox* p = (SwTableBox*)&rBox;
    aBoxes.Insert( p, aBoxes.Count() );
    nWidth += (USHORT)rBox.GetFrmFmt()->GetFrmSize().GetWidth();
}

const SwTableBox* SwCollectTblLineBoxes::GetBoxOfPos( const SwTableBox& rBox )
{
    const SwTableBox* pRet = 0;
    if( aPosArr.Count() )
    {
        USHORT n;
        for( n = 0; n < aPosArr.Count(); ++n )
            if( aPosArr[ n ] == nWidth )
                break;
            else if( aPosArr[ n ] > nWidth )
            {
                if( n )
                    --n;
                break;
            }

        if( n >= aPosArr.Count() )
            --n;

        nWidth += (USHORT)rBox.GetFrmFmt()->GetFrmSize().GetWidth();
        pRet = aBoxes[ n ];
    }
    return pRet;
}

BOOL lcl_Line_CollectBox( const SwTableLine*& rpLine, void* pPara )
{
    SwCollectTblLineBoxes* pSplPara = (SwCollectTblLineBoxes*)pPara;
    if( pSplPara->IsGetValues() )
        ((SwTableLine*)rpLine)->GetTabBoxes().ForEach( &::binfilter::lcl_Box_CollectBox, pPara );
    else
        ((SwTableLine*)rpLine)->GetTabBoxes().ForEach( &::binfilter::lcl_BoxSetSplitBoxFmts, pPara );
    return TRUE;
}

BOOL lcl_Box_CollectBox( const SwTableBox*& rpBox, void* pPara )
{
    SwCollectTblLineBoxes* pSplPara = (SwCollectTblLineBoxes*)pPara;
    USHORT nLen = rpBox->GetTabLines().Count();
    if( nLen )
    {
        // dann mit der richtigen Line weitermachen
        if( pSplPara->IsGetFromTop() )
            nLen = 0;
        else
            --nLen;

        const SwTableLine* pLn = rpBox->GetTabLines()[ nLen ];
        lcl_Line_CollectBox( pLn, pPara );
    }
    else
        pSplPara->AddBox( *rpBox );
    return TRUE;
}

BOOL lcl_BoxSetSplitBoxFmts( const SwTableBox*& rpBox, void* pPara )
{
    SwCollectTblLineBoxes* pSplPara = (SwCollectTblLineBoxes*)pPara;
    USHORT nLen = rpBox->GetTabLines().Count();
    if( nLen )
    {
        // dann mit der richtigen Line weitermachen
        if( pSplPara->IsGetFromTop() )
            nLen = 0;
        else
            --nLen;

        const SwTableLine* pLn = rpBox->GetTabLines()[ nLen ];
        lcl_Line_CollectBox( pLn, pPara );
    }
    else
    {
        const SwTableBox* pSrcBox = pSplPara->GetBoxOfPos( *rpBox );
        SwFrmFmt* pFmt = pSrcBox->GetFrmFmt();
        SwTableBox* pBox = (SwTableBox*)rpBox;

        if( HEADLINE_BORDERCOPY == pSplPara->GetMode() )
        {
            const SvxBoxItem& rBoxItem = pBox->GetFrmFmt()->GetBox();
            if( !rBoxItem.GetTop() )
            {
                SvxBoxItem aNew( rBoxItem );
                aNew.SetLine( pFmt->GetBox().GetBottom(), BOX_LINE_TOP );
                if( aNew != rBoxItem )
                    pBox->ClaimFrmFmt()->SetAttr( aNew );
            }
        }
        else
        {
USHORT aTableSplitBoxSetRange[] = {
    RES_LR_SPACE,       RES_UL_SPACE,
    RES_BACKGROUND,     RES_SHADOW,
    RES_PROTECT,        RES_PROTECT,
    RES_VERT_ORIENT,    RES_VERT_ORIENT,
    0 };
            SfxItemSet aTmpSet( pFmt->GetDoc()->GetAttrPool(),
                                aTableSplitBoxSetRange );
            aTmpSet.Put( pFmt->GetAttrSet() );
            if( aTmpSet.Count() )
                pBox->ClaimFrmFmt()->SetAttr( aTmpSet );

            if( HEADLINE_BOXATRCOLLCOPY == pSplPara->GetMode() )
            {
                SwNodeIndex aIdx( *pSrcBox->GetSttNd(), 1 );
                SwCntntNode* pCNd = aIdx.GetNode().GetCntntNode();
                if( !pCNd )
                    pCNd = aIdx.GetNodes().GoNext( &aIdx );
                aIdx = *pBox->GetSttNd();
                SwCntntNode* pDNd = aIdx.GetNodes().GoNext( &aIdx );

                // nur wenn der Node alleine in der Section steht
                if( 2 == pDNd->EndOfSectionIndex() -
                        pDNd->StartOfSectionIndex() )
                {
                    pDNd->ChgFmtColl( pCNd->GetFmtColl() );
                }
            }

            // bedingte Vorlage beachten
            pBox->GetSttNd()->CheckSectionCondColl();
        }
    }
    return TRUE;
}



// und die Umkehrung davon. rPos muss in der Tabelle stehen, die bestehen
// bleibt. Das Flag besagt ob die aktuelle mit der davor oder dahinter
// stehenden vereint wird.


// -------------------------------------------------------------------


// -- benutze die ForEach Methode vom PtrArray

// forward deklarieren damit sich die Lines und Boxen rekursiv aufrufen
// koennen.




        // AutoFormat fuer die Tabelle/TabellenSelection


        // Erfrage wie attributiert ist

/*N*/ String SwDoc::GetUniqueTblName() const
/*N*/ {
/*N*/   ResId aId( STR_TABLE_DEFNAME, *pSwResMgr );
/*N*/   String aName( aId.toString() );
/*N*/   xub_StrLen nNmLen = aName.Len();
/*N*/
/*N*/   USHORT nNum, nTmp, nFlagSize = ( pTblFrmFmtTbl->Count() / 8 ) +2;
/*N*/   BYTE* pSetFlags = new BYTE[ nFlagSize ];
/*N*/   memset( pSetFlags, 0, nFlagSize );
/*N*/
        USHORT n=0;
/*N*/   for( n = 0; n < pTblFrmFmtTbl->Count(); ++n )
/*N*/   {
/*N*/       const SwFrmFmt* pFmt = (*pTblFrmFmtTbl)[ n ];
/*N*/       if( !pFmt->IsDefault() && IsUsed( *pFmt )  &&
/*N*/           pFmt->GetName().Match( aName ) == nNmLen )
/*N*/       {
/*N*/           // Nummer bestimmen und das Flag setzen
/*N*/           nNum = pFmt->GetName().Copy( nNmLen ).ToInt32();
/*N*/           if( nNum-- && nNum < pTblFrmFmtTbl->Count() )
/*N*/               pSetFlags[ nNum / 8 ] |= (0x01 << ( nNum & 0x07 ));
/*N*/       }
/*N*/   }
/*N*/
/*N*/   // alle Nummern entsprechend geflag, also bestimme die richtige Nummer
/*N*/   nNum = pTblFrmFmtTbl->Count();
/*N*/   for( n = 0; n < nFlagSize; ++n )
/*N*/       if( 0xff != ( nTmp = pSetFlags[ n ] ))
/*N*/       {
/*N*/           // also die Nummer bestimmen
/*N*/           nNum = n * 8;
/*N*/           while( nTmp & 1 )
/*N*/               ++nNum, nTmp >>= 1;
/*N*/           break;
/*N*/       }
/*N*/
/*N*/   delete [] pSetFlags;
/*N*/   return aName += String::CreateFromInt32( ++nNum );
/*N*/ }

/*N*/ SwTableFmt* SwDoc::FindTblFmtByName( const String& rName, BOOL bAll ) const
/*N*/ {
/*N*/   const SwFmt* pRet = 0;
/*N*/   if( bAll )
/*?*/       pRet = FindFmtByName( (SvPtrarr&)*pTblFrmFmtTbl, rName );
/*N*/   else
/*N*/   {
/*N*/       // dann nur die, die im Doc gesetzt sind
/*N*/       for( USHORT n = 0; n < pTblFrmFmtTbl->Count(); ++n )
/*N*/       {
/*N*/           const SwFrmFmt* pFmt = (*pTblFrmFmtTbl)[ n ];
/*N*/           if( !pFmt->IsDefault() && IsUsed( *pFmt ) &&
/*N*/               pFmt->GetName() == rName )
/*N*/           {
/*?*/               pRet = pFmt;
/*?*/               break;
/*N*/           }
/*N*/       }
/*N*/   }
/*N*/   return (SwTableFmt*)pRet;
/*N*/ }





/*N*/ void SwDoc::ClearBoxNumAttrs( const SwNodeIndex& rNode )
/*N*/ {
/*N*/   SwStartNode* pSttNd;
/*N*/   if( 0 != ( pSttNd = GetNodes()[ rNode ]->
/*N*/                               FindSttNodeByType( SwTableBoxStartNode )) &&
/*N*/       2 == pSttNd->EndOfSectionIndex() - pSttNd->GetIndex() )
/*N*/   {
/*N*/       SwTableBox* pBox = pSttNd->FindTableNode()->GetTable().
/*N*/                           GetTblBox( pSttNd->GetIndex() );
/*N*/
/*N*/       const SfxPoolItem* pFmtItem = 0;
/*N*/       const SfxItemSet& rSet = pBox->GetFrmFmt()->GetAttrSet();
/*N*/       if( SFX_ITEM_SET == rSet.GetItemState( RES_BOXATR_FORMAT, FALSE, &pFmtItem ) ||
/*N*/           SFX_ITEM_SET == rSet.GetItemState( RES_BOXATR_FORMULA, FALSE ) ||
/*N*/           SFX_ITEM_SET == rSet.GetItemState( RES_BOXATR_VALUE, FALSE ))
/*N*/       {
/*?*/           SwFrmFmt* pBoxFmt = pBox->ClaimFrmFmt();
/*?*/
/*?*/           //JP 01.09.97: TextFormate bleiben erhalten!
/*?*/           USHORT nWhich1 = RES_BOXATR_FORMAT;
/*?*/           if( pFmtItem && GetNumberFormatter()->IsTextFormat(
/*?*/                   ((SwTblBoxNumFormat*)pFmtItem)->GetValue() ))
/*?*/               nWhich1 = RES_BOXATR_FORMULA;
/*?*/           else
/*?*/               // JP 15.01.99: Nur Attribute zuruecksetzen reicht nicht.
/*?*/               //              Sorge dafuer, das der Text auch entsprechend
/*?*/               //              formatiert wird!
/*?*/               pBoxFmt->SetAttr( *GetDfltAttr( RES_BOXATR_FORMAT ));
/*?*/
/*?*/           pBoxFmt->ResetAttr( nWhich1, RES_BOXATR_VALUE );
/*?*/           SetModified();
/*N*/       }
/*N*/   }
/*N*/ }



// kopiert eine Tabelle aus dem selben oder einem anderen Doc in sich
// selbst. Dabei wird eine neue Tabelle angelegt oder eine bestehende
// mit dem Inhalt gefuellt; wobei entweder der Inhalt ab einer Box oder
// in eine bestehende TblSelektion gefuellt wird.
// Gerufen wird es von: edglss.cxx/fecopy.cxx













}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
