diff options
Diffstat (limited to 'binfilter/bf_sw/source/core/doc/sw_gctable.cxx')
-rw-r--r-- | binfilter/bf_sw/source/core/doc/sw_gctable.cxx | 478 |
1 files changed, 478 insertions, 0 deletions
diff --git a/binfilter/bf_sw/source/core/doc/sw_gctable.cxx b/binfilter/bf_sw/source/core/doc/sw_gctable.cxx new file mode 100644 index 000000000000..b9a1b3c57519 --- /dev/null +++ b/binfilter/bf_sw/source/core/doc/sw_gctable.cxx @@ -0,0 +1,478 @@ +/* -*- 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 + +#include <hintids.hxx> + +#include <bf_svx/boxitem.hxx> + +#include <errhdl.hxx> +#include <tblrwcl.hxx> +#include <swtblfmt.hxx> +namespace binfilter { + + + inline const SvxBorderLine* GetLineTB( const SvxBoxItem* pBox, BOOL bTop ) + { + return bTop ? pBox->GetTop() : pBox->GetBottom(); + } + + +BOOL _SwGCBorder_BoxBrd::CheckLeftBorderOfFormat( const SwFrmFmt& rFmt ) +{ + const SvxBorderLine* pBrd; + const SfxPoolItem* pItem; + if( SFX_ITEM_SET == rFmt.GetItemState( RES_BOX, TRUE, &pItem ) && + 0 != ( pBrd = ((SvxBoxItem*)pItem)->GetLeft() ) ) + { + if( *pBrdLn == *pBrd ) + bAnyBorderFnd = TRUE; + return TRUE; + } + return FALSE; +} + + + +BOOL lcl_GCBorder_ChkBoxBrd_L( const SwTableLine*& rpLine, void* pPara ) +{ + const SwTableBox* pBox = rpLine->GetTabBoxes()[ 0 ]; + return lcl_GCBorder_ChkBoxBrd_B( pBox, pPara ); +} + +BOOL lcl_GCBorder_ChkBoxBrd_B( const SwTableBox*& rpBox, void* pPara ) +{ + BOOL bRet = TRUE; + if( rpBox->GetTabLines().Count() ) + { + for( USHORT n = 0, nLines = rpBox->GetTabLines().Count(); + n < nLines && bRet; ++n ) + { + const SwTableLine* pLine = rpBox->GetTabLines()[ n ]; + bRet = lcl_GCBorder_ChkBoxBrd_L( pLine, pPara ); + } + } + else + { + _SwGCBorder_BoxBrd* pBPara = (_SwGCBorder_BoxBrd*)pPara; + bRet = pBPara->CheckLeftBorderOfFormat( *rpBox->GetFrmFmt() ); + } + return bRet; +} + +BOOL lcl_GCBorder_GetLastBox_L( const SwTableLine*& rpLine, void* pPara ) +{ + const SwTableBoxes& rBoxes = rpLine->GetTabBoxes(); + const SwTableBox* pBox = rBoxes[ rBoxes.Count()-1 ]; + lcl_GCBorder_GetLastBox_B( pBox, pPara ); + return TRUE; +} + +BOOL lcl_GCBorder_GetLastBox_B( const SwTableBox*& rpBox, void* pPara ) +{ + SwTableLines& rLines = (SwTableLines&)rpBox->GetTabLines(); + if( rLines.Count() ) + rLines.ForEach( &lcl_GCBorder_GetLastBox_L, pPara ); + else + ((SwTableBoxes*)pPara)->Insert( rpBox, ((SwTableBoxes*)pPara)->Count() ); + return TRUE; +} + +// suche das "Ende" der vorgegebene BorderLine. Returnt wird die "Layout"Pos! +USHORT lcl_FindEndPosOfBorder( const SwCollectTblLineBoxes& rCollTLB, + const SvxBorderLine& rBrdLn, USHORT& rStt, BOOL bTop ) +{ + USHORT nPos, nLastPos = 0; + for( USHORT nEnd = rCollTLB.Count(); rStt < nEnd; ++rStt ) + { + const SfxPoolItem* pItem; + const SvxBorderLine* pBrd; + const SwTableBox& rBox = rCollTLB.GetBox( rStt, &nPos ); + + if( SFX_ITEM_SET != rBox.GetFrmFmt()->GetItemState(RES_BOX,TRUE, &pItem ) + || 0 == ( pBrd = ::binfilter::GetLineTB( (SvxBoxItem*)pItem, bTop )) + || !( *pBrd == rBrdLn )) + break; + nLastPos = nPos; + } + return nLastPos; +} + + inline const SvxBorderLine* lcl_GCBorder_GetBorder( const SwTableBox& rBox, + BOOL bTop, + const SfxPoolItem** ppItem ) + { + return SFX_ITEM_SET == rBox.GetFrmFmt()->GetItemState( RES_BOX, TRUE, ppItem ) + ? ::binfilter::GetLineTB( (SvxBoxItem*)*ppItem, bTop ) + : 0; + } + +void lcl_GCBorder_DelBorder( const SwCollectTblLineBoxes& rCollTLB, + USHORT& rStt, BOOL bTop, + const SvxBorderLine& rLine, + const SfxPoolItem* pItem, + USHORT nEndPos, + SwShareBoxFmts* pShareFmts ) +{ + SwTableBox* pBox = (SwTableBox*)&rCollTLB.GetBox( rStt ); + USHORT nNextPos; + const SvxBorderLine* pLn = &rLine; + + do { + if( pLn && *pLn == rLine ) + { + SvxBoxItem aBox( *(SvxBoxItem*)pItem ); + if( bTop ) + aBox.SetLine( 0, BOX_LINE_TOP ); + else + aBox.SetLine( 0, BOX_LINE_BOTTOM ); + + if( pShareFmts ) + pShareFmts->SetAttr( *pBox, aBox ); + else + pBox->ClaimFrmFmt()->SetAttr( aBox ); + } + + if( ++rStt >= rCollTLB.Count() ) + break; + + pBox = (SwTableBox*)&rCollTLB.GetBox( rStt, &nNextPos ); + if( nNextPos > nEndPos ) + break; + + pLn = ::binfilter::lcl_GCBorder_GetBorder( *pBox, bTop, &pItem ); + + } while( TRUE ); +} + + +BOOL lcl_GC_Line_Border( const SwTableLine*& rpLine, void* pPara ) +{ + _SwGCLineBorder* pGCPara = (_SwGCLineBorder*)pPara; + + // zuerst die rechte Kante mit der linken Kante der naechsten Box + // innerhalb dieser Line + { + _SwGCBorder_BoxBrd aBPara; + const SvxBorderLine* pBrd; + const SfxPoolItem* pItem; + const SwTableBoxes& rBoxes = rpLine->GetTabBoxes(); + for( USHORT n = 0, nBoxes = rBoxes.Count() - 1; n < nBoxes; ++n ) + { + SwTableBoxes aBoxes; + { + const SwTableBox* pBox = rBoxes[ n ]; + if( pBox->GetSttNd() ) + aBoxes.Insert( pBox, 0 ); + else + ::binfilter::lcl_GCBorder_GetLastBox_B( pBox, &aBoxes ); + } + + SwTableBox* pBox; + for( USHORT i = aBoxes.Count(); i; ) + if( SFX_ITEM_SET == (pBox = aBoxes[ --i ])->GetFrmFmt()-> + GetItemState( RES_BOX, TRUE, &pItem ) && + 0 != ( pBrd = ((SvxBoxItem*)pItem)->GetRight() ) ) + { + aBPara.SetBorder( *pBrd ); + const SwTableBox* pNextBox = rBoxes[n+1]; + if( lcl_GCBorder_ChkBoxBrd_B( pNextBox, &aBPara ) && + aBPara.IsAnyBorderFound() ) + { + SvxBoxItem aBox( *(SvxBoxItem*)pItem ); + aBox.SetLine( 0, BOX_LINE_RIGHT ); + if( pGCPara->pShareFmts ) + pGCPara->pShareFmts->SetAttr( *pBox, aBox ); + else + pBox->ClaimFrmFmt()->SetAttr( aBox ); + } + } + + aBoxes.Remove( 0, aBoxes.Count() ); + } + } + + // und jetzt die eigene untere Kante mit der nachfolgenden oberen Kante + if( !pGCPara->IsLastLine() ) + { + SwCollectTblLineBoxes aBottom( FALSE ); + SwCollectTblLineBoxes aTop( TRUE ); + + ::binfilter::lcl_Line_CollectBox( rpLine, &aBottom ); + + const SwTableLine* pNextLine = (*pGCPara->pLines)[ pGCPara->nLinePos+1 ]; + ::binfilter::lcl_Line_CollectBox( pNextLine, &aTop ); + + // dann entferne mal alle "doppelten" gleichen Lines + USHORT nBtmPos, nTopPos, + nSttBtm = 0, nSttTop = 0, + nEndBtm = aBottom.Count(), nEndTop = aTop.Count(); + + const SwTableBox *pBtmBox = &aBottom.GetBox( nSttBtm++, &nBtmPos ), + *pTopBox = &aTop.GetBox( nSttTop++, &nTopPos ); + const SfxPoolItem *pBtmItem, *pTopItem; + const SvxBorderLine *pBtmLine, *pTopLine; + BOOL bGetTopItem = TRUE, bGetBtmItem = TRUE; + + do { + if( bGetBtmItem ) + pBtmLine = ::binfilter::lcl_GCBorder_GetBorder( *pBtmBox, FALSE, &pBtmItem ); + if( bGetTopItem ) + pTopLine = ::binfilter::lcl_GCBorder_GetBorder( *pTopBox, TRUE, &pTopItem ); + + if( pTopLine && pBtmLine && *pTopLine == *pBtmLine ) + { + // dann kann einer entfernt werden, aber welche? + USHORT nSavSttBtm = nSttBtm, nSavSttTop = nSttTop; + USHORT nBtmEndPos = ::binfilter::lcl_FindEndPosOfBorder( aBottom, + *pTopLine, nSttBtm, FALSE ); + if( !nBtmEndPos ) nBtmEndPos = nBtmPos; + USHORT nTopEndPos = ::binfilter::lcl_FindEndPosOfBorder( aTop, + *pTopLine, nSttTop, TRUE ); + if( !nTopEndPos ) nTopEndPos = nTopPos; + + + if( nTopEndPos <= nBtmEndPos ) + { + // dann die TopBorder bis zur BottomEndPos loeschen + nSttTop = nSavSttTop; + if( nTopPos <= nBtmEndPos ) + ::binfilter::lcl_GCBorder_DelBorder( aTop, --nSttTop, TRUE, + *pBtmLine, pTopItem, nBtmEndPos, + pGCPara->pShareFmts ); + else + nSttBtm = nSavSttBtm; + } + else + { + // sonst die BottomBorder bis zur TopEndPos loeschen + nSttBtm = nSavSttBtm; + if( nBtmPos <= nTopEndPos ) + ::binfilter::lcl_GCBorder_DelBorder( aBottom, --nSttBtm, FALSE, + *pTopLine, pBtmItem, nTopEndPos, + pGCPara->pShareFmts ); + else + nSttTop = nSavSttTop; + } + nTopPos = nBtmPos; + } + + if( nTopPos == nBtmPos ) + { + if( nSttBtm >= nEndBtm || nSttTop >= nEndTop ) + break; + + pBtmBox = &aBottom.GetBox( nSttBtm++, &nBtmPos ); + pTopBox = &aTop.GetBox( nSttTop++, &nTopPos ); + bGetTopItem = bGetBtmItem = TRUE; + } + else if( nTopPos < nBtmPos ) + { + if( nSttTop >= nEndTop ) + break; + pTopBox = &aTop.GetBox( nSttTop++, &nTopPos ); + bGetTopItem = TRUE; + bGetBtmItem = FALSE; + } + else + { + if( nSttBtm >= nEndBtm ) + break; + pBtmBox = &aBottom.GetBox( nSttBtm++, &nBtmPos ); + bGetTopItem = FALSE; + bGetBtmItem = TRUE; + } + + } while( TRUE ); + } + + ((SwTableLine*)rpLine)->GetTabBoxes().ForEach( &lcl_GC_Box_Border, pPara ); + + ++pGCPara->nLinePos; + + return TRUE; +} + + +BOOL lcl_GC_Box_Border( const SwTableBox*& rpBox, void* pPara ) +{ + if( rpBox->GetTabLines().Count() ) + { + _SwGCLineBorder aPara( *rpBox ); + aPara.pShareFmts = ((_SwGCLineBorder*)pPara)->pShareFmts; + ((SwTableBox*)rpBox)->GetTabLines().ForEach( &lcl_GC_Line_Border, &aPara ); + } + return TRUE; +} + + +void SwTable::GCBorderLines() +{ + // alle doppleten Borderlines benachbarter Tabellen-Content-Boxen + // entfernen. Und zwar wird versucht, die Struktur unserer default + // Border wiederherzustellen, die wie folgt aussieht: + // + // +-- +--+ + // | | | + // +-- +--+ + // + // | | | + // +-- +--+ + + SwShareBoxFmts aShareFmts; + _SwGCLineBorder aPara( *this ); + aPara.pShareFmts = &aShareFmts; + GetTabLines().ForEach( &::binfilter::lcl_GC_Line_Border, &aPara ); +} + +/* */ + +struct _GCLinePara +{ + SwTableLines* pLns; + SwShareBoxFmts* pShareFmts; + + _GCLinePara( SwTableLines& rLns, _GCLinePara* pPara = 0 ) + : pLns( &rLns ), pShareFmts( pPara ? pPara->pShareFmts : 0 ) + {} +}; + +/*N*/ BOOL lcl_MergeGCBox( const SwTableBox*& rpTblBox, void* pPara ) +/*N*/ { +/*N*/ SwTableBox*& rpBox = (SwTableBox*&)rpTblBox; +/*N*/ USHORT n, nLen = rpBox->GetTabLines().Count(); +/*N*/ if( nLen ) +/*N*/ { +/*N*/ // ACHTUNG: die Anzahl der Lines kann sich aendern! +/*N*/ _GCLinePara aPara( rpBox->GetTabLines(), (_GCLinePara*)pPara ); +/*N*/ for( n = 0; n < rpBox->GetTabLines().Count() && +/*N*/ lcl_MergeGCLine( *(rpBox->GetTabLines().GetData() + n), &aPara ); +/*N*/ ++n ) +/*N*/ ; +/*N*/ +/*N*/ if( 1 == rpBox->GetTabLines().Count() ) +/*N*/ { +/*N*/ // Box mit einer Line, dann verschiebe alle Boxen der Line +/*N*/ // hinter diese Box in der Parent-Line und loesche diese Box +/*?*/ SwTableLine* pInsLine = rpBox->GetUpper(); +/*?*/ SwTableLine* pCpyLine = rpBox->GetTabLines()[0]; +/*?*/ USHORT nInsPos = pInsLine->GetTabBoxes().C40_GETPOS( SwTableBox, rpBox ); +/*?*/ for( n = 0; n < pCpyLine->GetTabBoxes().Count(); ++n ) +/*?*/ pCpyLine->GetTabBoxes()[n]->SetUpper( pInsLine ); +/*?*/ +/*?*/ pInsLine->GetTabBoxes().Insert( &pCpyLine->GetTabBoxes(), nInsPos+1 ); +/*?*/ pCpyLine->GetTabBoxes().Remove( 0, n ); +/*?*/ // loesche alte die Box mit der Line +/*?*/ pInsLine->GetTabBoxes().DeleteAndDestroy( nInsPos ); +/*?*/ +/*?*/ return FALSE; // neu aufsetzen +/*N*/ } +/*N*/ } +/*N*/ return TRUE; +/*N*/ } + +/*N*/ BOOL lcl_MergeGCLine( const SwTableLine*& rpLine, void* pPara ) +/*N*/ { +/*N*/ SwTableLine* pLn = (SwTableLine*)rpLine; +/*N*/ USHORT nLen = pLn->GetTabBoxes().Count(); +/*N*/ if( nLen ) +/*N*/ { +/*N*/ _GCLinePara* pGCPara = (_GCLinePara*)pPara; +/*N*/ while( 1 == nLen ) +/*N*/ { +/*N*/ // es gibt eine Box mit Lines +/*N*/ SwTableBox* pBox = pLn->GetTabBoxes()[0]; +/*N*/ if( !pBox->GetTabLines().Count() ) +/*N*/ break; +/*N*/ +/*N*/ SwTableLine* pLine = pBox->GetTabLines()[0]; +/*N*/ +/*N*/ // pLine wird zu der aktuellen, also der rpLine, +/*N*/ // die restlichen werden ins LinesArray hinter der akt. +/*N*/ // verschoben. +/*N*/ // Das LinesArray ist im pPara! +/*N*/ nLen = pBox->GetTabLines().Count(); +/*N*/ +/*N*/ SwTableLines& rLns = *pGCPara->pLns; +/*N*/ const SwTableLine* pTmp = pLn; +/*N*/ USHORT nInsPos = rLns.GetPos( pTmp ); +/*N*/ ASSERT( USHRT_MAX != nInsPos, "Line nicht gefunden!" ); +/*N*/ +/*N*/ SwTableBox* pUpper = pLn->GetUpper(); +/*N*/ +/*N*/ rLns.Remove( nInsPos, 1 ); // die Line dem aus Array loeschen +/*N*/ rLns.Insert( &pBox->GetTabLines(), nInsPos ); +/*N*/ +/*N*/ // JP 31.03.99: Bug 60000 - die Attribute der zu loeschenden +/*N*/ // Line an die "eingefuegten" uebertragen +/*N*/ const SfxPoolItem* pItem; +/*N*/ if( SFX_ITEM_SET == pLn->GetFrmFmt()->GetItemState( +/*N*/ RES_BACKGROUND, TRUE, &pItem )) +/*N*/ {DBG_BF_ASSERT(0, "STRIP"); //STRIP001 +/*N*/ } +/*N*/ +/*N*/ pBox->GetTabLines().Remove( 0, nLen ); // Lines aus Array loeschen +/*N*/ +/*N*/ delete pLn; +/*N*/ +/*N*/ // Abhaengigkeit neu setzen +/*N*/ while( nLen-- ) +/*N*/ rLns[ nInsPos++ ]->SetUpper( pUpper ); +/*N*/ +/*N*/ pLn = pLine; // und neu setzen +/*N*/ nLen = pLn->GetTabBoxes().Count(); +/*N*/ } +/*N*/ +/*N*/ // ACHTUNG: die Anzahl der Boxen kann sich aendern! +/*N*/ for( nLen = 0; nLen < pLn->GetTabBoxes().Count(); ++nLen ) +/*N*/ if( !lcl_MergeGCBox( *(pLn->GetTabBoxes().GetData() + nLen ), pPara )) +/*N*/ --nLen; +/*N*/ } +/*N*/ return TRUE; +/*N*/ } + + // Struktur ein wenig aufraeumen +/*N*/ void SwTable::GCLines() +/*N*/ { +/*N*/ // ACHTUNG: die Anzahl der Lines kann sich aendern! +/*N*/ _GCLinePara aPara( GetTabLines() ); +/*N*/ SwShareBoxFmts aShareFmts; +/*N*/ aPara.pShareFmts = &aShareFmts; +/*N*/ for( USHORT n = 0; n < GetTabLines().Count() && +/*N*/ lcl_MergeGCLine( *(GetTabLines().GetData() + n ), &aPara ); ++n ) +/*N*/ ; +/*N*/ } + + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |