| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_sw.hxx" |
| |
| #include <com/sun/star/chart2/XChartDocument.hpp> |
| #include <hintids.hxx> |
| #include <editeng/lrspitem.hxx> |
| #include <editeng/brkitem.hxx> |
| #include <editeng/protitem.hxx> |
| #include <editeng/boxitem.hxx> |
| #include <editeng/shaditem.hxx> |
| #include <fmtfsize.hxx> |
| #include <fmtornt.hxx> |
| #include <fmtfordr.hxx> |
| #include <fmtpdsc.hxx> |
| #include <fmtanchr.hxx> |
| #include <fmtlsplt.hxx> |
| #include <frmatr.hxx> |
| #include <charatr.hxx> |
| #include <cellfrm.hxx> |
| #include <pagefrm.hxx> |
| #include <tabcol.hxx> |
| #include <doc.hxx> |
| #include <IDocumentUndoRedo.hxx> |
| #include <UndoManager.hxx> |
| #include <cntfrm.hxx> |
| #include <pam.hxx> |
| #include <swcrsr.hxx> |
| #include <viscrs.hxx> |
| #include <swtable.hxx> |
| #include <ndtxt.hxx> |
| #include <swundo.hxx> |
| #include <tblsel.hxx> |
| #include <fldbas.hxx> |
| #include <poolfmt.hxx> |
| #include <tabfrm.hxx> |
| #include <UndoCore.hxx> |
| #include <UndoRedline.hxx> |
| #include <UndoDelete.hxx> |
| #include <UndoTable.hxx> |
| #include <hints.hxx> |
| #include <tblafmt.hxx> |
| #include <swcache.hxx> |
| #include <ddefld.hxx> |
| #include <frminf.hxx> |
| #include <cellatr.hxx> |
| #include <swtblfmt.hxx> |
| #include <swddetbl.hxx> |
| #include <mvsave.hxx> |
| #include <docary.hxx> |
| #include <redline.hxx> |
| #include <rolbck.hxx> |
| #include <tblrwcl.hxx> |
| #include <editsh.hxx> |
| #include <txtfrm.hxx> |
| #include <ftnfrm.hxx> |
| #include <section.hxx> |
| #include <frmtool.hxx> |
| #include <node2lay.hxx> |
| #include <comcore.hrc> |
| #include "docsh.hxx" |
| #include <tabcol.hxx> |
| #include <unochart.hxx> |
| #include <node.hxx> |
| #include <ndtxt.hxx> |
| #include <map> |
| #include <algorithm> |
| #include <rootfrm.hxx> |
| #include <fldupde.hxx> |
| #include <switerator.hxx> |
| |
| #ifndef DBG_UTIL |
| #define CHECK_TABLE(t) |
| #else |
| #ifdef DEBUG |
| #define CHECK_TABLE(t) (t).CheckConsistency(); |
| #else |
| #define CHECK_TABLE(t) |
| #endif |
| #endif |
| |
| |
| using namespace ::com::sun::star; |
| |
| // #i17764# delete table redlines when modifying the table structure? |
| // #define DEL_TABLE_REDLINES 1 |
| |
| const sal_Unicode T2T_PARA = 0x0a; |
| |
| extern void ClearFEShellTabCols(); |
| |
| // steht im gctable.cxx |
| extern sal_Bool lcl_GC_Line_Border( const SwTableLine*& , void* pPara ); |
| |
| #ifdef DEL_TABLE_REDLINES |
| class lcl_DelRedlines |
| { |
| SwDoc* pDoc; |
| public: |
| lcl_DelRedlines( const SwTableNode& rNd, sal_Bool bCheckForOwnRedline ); |
| lcl_DelRedlines( SwPaM& rPam ); |
| |
| ~lcl_DelRedlines() { pDoc->EndUndo(UNDO_EMPTY, NULL); } |
| }; |
| |
| lcl_DelRedlines::lcl_DelRedlines( SwPaM & rPam) : pDoc( rPam.GetDoc() ) |
| { |
| pDoc->GetIDocumentUndoRedo().StartUndo(UNDO_EMPTY, NULL); |
| if( !pDoc->IsIgnoreRedline() && pDoc->GetRedlineTbl().Count() ) |
| pDoc->AcceptRedline( rPam, true ); |
| } |
| #endif |
| |
| void lcl_SetDfltBoxAttr( SwFrmFmt& rFmt, sal_uInt8 nId ) |
| { |
| sal_Bool bTop = sal_False, bBottom = sal_False, bLeft = sal_False, bRight = sal_False; |
| switch ( nId ) |
| { |
| case 0: bTop = bBottom = bLeft = sal_True; break; |
| case 1: bTop = bBottom = bLeft = bRight = sal_True; break; |
| case 2: bBottom = bLeft = sal_True; break; |
| case 3: bBottom = bLeft = bRight = sal_True; break; |
| } |
| |
| const sal_Bool bHTML = rFmt.getIDocumentSettingAccess()->get(IDocumentSettingAccess::HTML_MODE); |
| Color aCol( bHTML ? COL_GRAY : COL_BLACK ); |
| SvxBorderLine aLine( &aCol, DEF_LINE_WIDTH_0 ); |
| if ( bHTML ) |
| { |
| aLine.SetOutWidth( DEF_DOUBLE_LINE7_OUT ); |
| aLine.SetInWidth ( DEF_DOUBLE_LINE7_IN ); |
| aLine.SetDistance( DEF_DOUBLE_LINE7_DIST); |
| } |
| SvxBoxItem aBox(RES_BOX); aBox.SetDistance( 55 ); |
| if ( bTop ) |
| aBox.SetLine( &aLine, BOX_LINE_TOP ); |
| if ( bBottom ) |
| aBox.SetLine( &aLine, BOX_LINE_BOTTOM ); |
| if ( bLeft ) |
| aBox.SetLine( &aLine, BOX_LINE_LEFT ); |
| if ( bRight ) |
| aBox.SetLine( &aLine, BOX_LINE_RIGHT ); |
| rFmt.SetFmtAttr( aBox ); |
| } |
| |
| void lcl_SetDfltBoxAttr( SwTableBox& rBox, SvPtrarr &rBoxFmtArr, sal_uInt8 nId, |
| const SwTableAutoFmt* pAutoFmt = 0 ) |
| { |
| SvPtrarr* pArr = (SvPtrarr*)rBoxFmtArr[ nId ]; |
| if( !pArr ) |
| { |
| pArr = new SvPtrarr; |
| rBoxFmtArr.Replace( pArr, nId ); |
| } |
| |
| SwTableBoxFmt* pNewBoxFmt = 0; |
| SwFrmFmt* pBoxFmt = rBox.GetFrmFmt(); |
| for( sal_uInt16 n = 0; n < pArr->Count(); n += 2 ) |
| if( pArr->GetObject( n ) == pBoxFmt ) |
| { |
| pNewBoxFmt = (SwTableBoxFmt*)pArr->GetObject( n + 1 ); |
| break; |
| } |
| |
| if( !pNewBoxFmt ) |
| { |
| SwDoc* pDoc = pBoxFmt->GetDoc(); |
| // das Format ist also nicht vorhanden, also neu erzeugen |
| pNewBoxFmt = pDoc->MakeTableBoxFmt(); |
| pNewBoxFmt->SetFmtAttr( pBoxFmt->GetAttrSet().Get( RES_FRM_SIZE ) ); |
| |
| if( pAutoFmt ) |
| pAutoFmt->UpdateToSet( nId, (SfxItemSet&)pNewBoxFmt->GetAttrSet(), |
| SwTableAutoFmt::UPDATE_BOX, |
| pDoc->GetNumberFormatter( sal_True ) ); |
| else |
| ::lcl_SetDfltBoxAttr( *pNewBoxFmt, nId ); |
| |
| void* p = pBoxFmt; |
| pArr->Insert( p, pArr->Count() ); |
| p = pNewBoxFmt; |
| pArr->Insert( p, pArr->Count() ); |
| } |
| rBox.ChgFrmFmt( pNewBoxFmt ); |
| } |
| |
| SwTableBoxFmt *lcl_CreateDfltBoxFmt( SwDoc &rDoc, SvPtrarr &rBoxFmtArr, |
| sal_uInt16 nCols, sal_uInt8 nId ) |
| { |
| if ( !rBoxFmtArr[nId] ) |
| { |
| SwTableBoxFmt* pBoxFmt = rDoc.MakeTableBoxFmt(); |
| if( USHRT_MAX != nCols ) |
| pBoxFmt->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE, |
| USHRT_MAX / nCols, 0 )); |
| ::lcl_SetDfltBoxAttr( *pBoxFmt, nId ); |
| rBoxFmtArr.Replace( pBoxFmt, nId ); |
| } |
| return (SwTableBoxFmt*)rBoxFmtArr[nId]; |
| } |
| |
| SwTableBoxFmt *lcl_CreateAFmtBoxFmt( SwDoc &rDoc, SvPtrarr &rBoxFmtArr, |
| const SwTableAutoFmt& rAutoFmt, |
| sal_uInt16 nCols, sal_uInt8 nId ) |
| { |
| if( !rBoxFmtArr[nId] ) |
| { |
| SwTableBoxFmt* pBoxFmt = rDoc.MakeTableBoxFmt(); |
| rAutoFmt.UpdateToSet( nId, (SfxItemSet&)pBoxFmt->GetAttrSet(), |
| SwTableAutoFmt::UPDATE_BOX, |
| rDoc.GetNumberFormatter( sal_True ) ); |
| if( USHRT_MAX != nCols ) |
| pBoxFmt->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE, |
| USHRT_MAX / nCols, 0 )); |
| rBoxFmtArr.Replace( pBoxFmt, nId ); |
| } |
| return (SwTableBoxFmt*)rBoxFmtArr[nId]; |
| } |
| |
| SwTableNode* SwDoc::IsIdxInTbl(const SwNodeIndex& rIdx) |
| { |
| SwTableNode* pTableNd = 0; |
| sal_uLong nIndex = rIdx.GetIndex(); |
| do { |
| SwNode* pNd = (SwNode*)GetNodes()[ nIndex ]->StartOfSectionNode(); |
| if( 0 != ( pTableNd = pNd->GetTableNode() ) ) |
| break; |
| |
| nIndex = pNd->GetIndex(); |
| } while ( nIndex ); |
| return pTableNd; |
| } |
| |
| |
| // --------------- einfuegen einer neuen Box -------------- |
| |
| // fuege in der Line, vor der InsPos eine neue Box ein. |
| |
| sal_Bool SwNodes::InsBoxen( SwTableNode* pTblNd, |
| SwTableLine* pLine, |
| SwTableBoxFmt* pBoxFmt, |
| SwTxtFmtColl* pTxtColl, |
| const SfxItemSet* pAutoAttr, |
| sal_uInt16 nInsPos, |
| sal_uInt16 nCnt ) |
| { |
| if( !nCnt ) |
| return sal_False; |
| ASSERT( pLine, "keine gueltige Zeile" ); |
| |
| // Index hinter die letzte Box der Line |
| sal_uLong nIdxPos = 0; |
| SwTableBox *pPrvBox = 0, *pNxtBox = 0; |
| if( pLine->GetTabBoxes().Count() ) |
| { |
| if( nInsPos < pLine->GetTabBoxes().Count() ) |
| { |
| if( 0 == (pPrvBox = pLine->FindPreviousBox( pTblNd->GetTable(), |
| pLine->GetTabBoxes()[ nInsPos ] ))) |
| pPrvBox = pLine->FindPreviousBox( pTblNd->GetTable() ); |
| } |
| else if( 0 == ( pNxtBox = pLine->FindNextBox( pTblNd->GetTable(), |
| pLine->GetTabBoxes()[ nInsPos-1 ] ))) |
| pNxtBox = pLine->FindNextBox( pTblNd->GetTable() ); |
| } |
| else if( 0 == ( pNxtBox = pLine->FindNextBox( pTblNd->GetTable() ))) |
| pPrvBox = pLine->FindPreviousBox( pTblNd->GetTable() ); |
| |
| if( !pPrvBox && !pNxtBox ) |
| { |
| sal_Bool bSetIdxPos = sal_True; |
| if( pTblNd->GetTable().GetTabLines().Count() && !nInsPos ) |
| { |
| const SwTableLine* pTblLn = pLine; |
| while( pTblLn->GetUpper() ) |
| pTblLn = pTblLn->GetUpper()->GetUpper(); |
| |
| if( pTblNd->GetTable().GetTabLines()[ 0 ] == pTblLn ) |
| { |
| // also vor die erste Box der Tabelle |
| while( ( pNxtBox = pLine->GetTabBoxes()[0])->GetTabLines().Count() ) |
| pLine = pNxtBox->GetTabLines()[0]; |
| nIdxPos = pNxtBox->GetSttIdx(); |
| bSetIdxPos = sal_False; |
| } |
| } |
| if( bSetIdxPos ) |
| // Tabelle ohne irgendeinen Inhalt oder am Ende, also vors Ende |
| nIdxPos = pTblNd->EndOfSectionIndex(); |
| } |
| else if( pNxtBox ) // es gibt einen Nachfolger |
| nIdxPos = pNxtBox->GetSttIdx(); |
| else // es gibt einen Vorgaenger |
| nIdxPos = pPrvBox->GetSttNd()->EndOfSectionIndex() + 1; |
| |
| SwNodeIndex aEndIdx( *this, nIdxPos ); |
| for( sal_uInt16 n = 0; n < nCnt; ++n ) |
| { |
| SwStartNode* pSttNd = new SwStartNode( aEndIdx, ND_STARTNODE, |
| SwTableBoxStartNode ); |
| pSttNd->pStartOfSection = pTblNd; |
| new SwEndNode( aEndIdx, *pSttNd ); |
| |
| pPrvBox = new SwTableBox( pBoxFmt, *pSttNd, pLine ); |
| |
| SwTableBoxes & rTabBoxes = pLine->GetTabBoxes(); |
| sal_uInt16 nRealInsPos = nInsPos + n; |
| if (nRealInsPos > rTabBoxes.Count()) |
| nRealInsPos = rTabBoxes.Count(); |
| |
| rTabBoxes.C40_INSERT( SwTableBox, pPrvBox, nRealInsPos ); |
| |
| //if( NO_NUMBERING == pTxtColl->GetOutlineLevel()//#outline level,zhaojianwei |
| if( ! pTxtColl->IsAssignedToListLevelOfOutlineStyle()//<-end,zhaojianwei |
| //FEATURE::CONDCOLL |
| && RES_CONDTXTFMTCOLL != pTxtColl->Which() |
| //FEATURE::CONDCOLL |
| ) |
| new SwTxtNode( SwNodeIndex( *pSttNd->EndOfSectionNode() ), |
| pTxtColl, pAutoAttr ); |
| else |
| { |
| // Outline-Numerierung richtig behandeln !!! |
| SwTxtNode* pTNd = new SwTxtNode( |
| SwNodeIndex( *pSttNd->EndOfSectionNode() ), |
| (SwTxtFmtColl*)GetDoc()->GetDfltTxtFmtColl(), |
| pAutoAttr ); |
| pTNd->ChgFmtColl( pTxtColl ); |
| } |
| } |
| return sal_True; |
| } |
| |
| // --------------- einfuegen einer neuen Tabelle -------------- |
| |
| const SwTable* SwDoc::InsertTable( const SwInsertTableOptions& rInsTblOpts, |
| const SwPosition& rPos, sal_uInt16 nRows, |
| sal_uInt16 nCols, sal_Int16 eAdjust, |
| const SwTableAutoFmt* pTAFmt, |
| const SvUShorts* pColArr, |
| sal_Bool bCalledFromShell, |
| sal_Bool bNewModel ) |
| { |
| ASSERT( nRows, "Tabelle ohne Zeile?" ); |
| ASSERT( nCols, "Tabelle ohne Spalten?" ); |
| |
| { |
| // nicht in Fussnoten kopieren !! |
| if( rPos.nNode < GetNodes().GetEndOfInserts().GetIndex() && |
| rPos.nNode >= GetNodes().GetEndOfInserts().StartOfSectionIndex() ) |
| return 0; |
| |
| // sollte das ColumnArray die falsche Anzahl haben wird es ignoriert! |
| if( pColArr && |
| (nCols + ( text::HoriOrientation::NONE == eAdjust ? 2 : 1 )) != pColArr->Count() ) |
| pColArr = 0; |
| } |
| |
| String aTblName = GetUniqueTblName(); |
| |
| if( GetIDocumentUndoRedo().DoesUndo() ) |
| { |
| GetIDocumentUndoRedo().AppendUndo( |
| new SwUndoInsTbl( rPos, nCols, nRows, static_cast<sal_uInt16>(eAdjust), |
| rInsTblOpts, pTAFmt, pColArr, |
| aTblName)); |
| } |
| |
| // fuege erstmal die Nodes ein |
| // hole das Auto-Format fuer die Tabelle |
| SwTxtFmtColl *pBodyColl = GetTxtCollFromPool( RES_POOLCOLL_TABLE ), |
| *pHeadColl = pBodyColl; |
| |
| sal_Bool bDfltBorders = 0 != ( rInsTblOpts.mnInsMode & tabopts::DEFAULT_BORDER ); |
| |
| if( (rInsTblOpts.mnInsMode & tabopts::HEADLINE) && (1 != nRows || !bDfltBorders) ) |
| pHeadColl = GetTxtCollFromPool( RES_POOLCOLL_TABLE_HDLN ); |
| |
| const sal_uInt16 nRowsToRepeat = |
| tabopts::HEADLINE == (rInsTblOpts.mnInsMode & tabopts::HEADLINE) ? |
| rInsTblOpts.mnRowsToRepeat : |
| 0; |
| |
| /* #106283# Save content node to extract FRAMEDIR from. */ |
| const SwCntntNode * pCntntNd = rPos.nNode.GetNode().GetCntntNode(); |
| |
| /* #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. */ |
| SwTableNode *pTblNd = GetNodes().InsertTable( |
| rPos.nNode, |
| nCols, |
| pBodyColl, |
| nRows, |
| nRowsToRepeat, |
| pHeadColl, |
| bCalledFromShell ? &pCntntNd->GetSwAttrSet() : 0 ); |
| |
| // dann erstelle die Box/Line/Table-Struktur |
| SwTableLineFmt* pLineFmt = MakeTableLineFmt(); |
| SwTableFmt* pTableFmt = MakeTblFrmFmt( aTblName, GetDfltFrmFmt() ); |
| |
| /* #106283# If the node to insert the table at is a context node and has a |
| non-default FRAMEDIR propagate it to the table. */ |
| if (pCntntNd) |
| { |
| const SwAttrSet & aNdSet = pCntntNd->GetSwAttrSet(); |
| const SfxPoolItem *pItem = NULL; |
| |
| if (SFX_ITEM_SET == aNdSet.GetItemState( RES_FRAMEDIR, sal_True, &pItem ) |
| && pItem != NULL) |
| { |
| pTableFmt->SetFmtAttr( *pItem ); |
| } |
| } |
| |
| //Orientation am Fmt der Table setzen |
| pTableFmt->SetFmtAttr( SwFmtHoriOrient( 0, eAdjust ) ); |
| // alle Zeilen haben die Fill-Order von links nach rechts ! |
| pLineFmt->SetFmtAttr( SwFmtFillOrder( ATT_LEFT_TO_RIGHT )); |
| |
| // die Tabelle bekommt USHRT_MAX als default SSize |
| SwTwips nWidth = USHRT_MAX; |
| if( pColArr ) |
| { |
| sal_uInt16 nSttPos = (*pColArr)[ 0 ]; |
| sal_uInt16 nLastPos = (*pColArr)[ sal_uInt16(pColArr->Count()-1)]; |
| if( text::HoriOrientation::NONE == eAdjust ) |
| { |
| sal_uInt16 nFrmWidth = nLastPos; |
| nLastPos = (*pColArr)[ sal_uInt16(pColArr->Count()-2)]; |
| pTableFmt->SetFmtAttr( SvxLRSpaceItem( nSttPos, nFrmWidth - nLastPos, 0, 0, RES_LR_SPACE ) ); |
| } |
| nWidth = nLastPos - nSttPos; |
| } |
| else if( nCols ) |
| { |
| nWidth /= nCols; |
| nWidth *= nCols; // to avoid rounding problems |
| } |
| pTableFmt->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE, nWidth )); |
| if( !(rInsTblOpts.mnInsMode & tabopts::SPLIT_LAYOUT) ) |
| pTableFmt->SetFmtAttr( SwFmtLayoutSplit( sal_False )); |
| |
| // verschiebe ggfs. die harten PageDesc/PageBreak Attribute: |
| SwCntntNode* pNextNd = GetNodes()[ pTblNd->EndOfSectionIndex()+1 ] |
| ->GetCntntNode(); |
| if( pNextNd && pNextNd->HasSwAttrSet() ) |
| { |
| const SfxItemSet* pNdSet = pNextNd->GetpSwAttrSet(); |
| const SfxPoolItem *pItem; |
| if( SFX_ITEM_SET == pNdSet->GetItemState( RES_PAGEDESC, sal_False, |
| &pItem ) ) |
| { |
| pTableFmt->SetFmtAttr( *pItem ); |
| pNextNd->ResetAttr( RES_PAGEDESC ); |
| pNdSet = pNextNd->GetpSwAttrSet(); |
| } |
| if( pNdSet && SFX_ITEM_SET == pNdSet->GetItemState( RES_BREAK, sal_False, |
| &pItem ) ) |
| { |
| pTableFmt->SetFmtAttr( *pItem ); |
| pNextNd->ResetAttr( RES_BREAK ); |
| } |
| } |
| |
| SwTable * pNdTbl = &pTblNd->GetTable(); |
| pNdTbl->RegisterToFormat( *pTableFmt ); |
| |
| pNdTbl->SetRowsToRepeat( nRowsToRepeat ); |
| pNdTbl->SetTableModel( bNewModel ); |
| |
| SvPtrarr aBoxFmtArr( 0, 16 ); |
| SwTableBoxFmt* pBoxFmt = 0; |
| if( !bDfltBorders && !pTAFmt ) |
| { |
| pBoxFmt = MakeTableBoxFmt(); |
| pBoxFmt->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE, USHRT_MAX / nCols, 0 )); |
| } |
| else |
| { |
| const sal_uInt16 nBoxArrLen = pTAFmt ? 16 : 4; |
| for( sal_uInt16 i = 0; i < nBoxArrLen; ++i ) |
| aBoxFmtArr.Insert( (void*)0, i ); |
| } |
| // --> OD 2008-02-25 #refactorlists# |
| // SfxItemSet aCharSet( GetAttrPool(), RES_CHRATR_BEGIN, RES_PARATR_END-1 ); |
| SfxItemSet aCharSet( GetAttrPool(), RES_CHRATR_BEGIN, RES_PARATR_LIST_END-1 ); |
| // <-- |
| |
| SwNodeIndex aNdIdx( *pTblNd, 1 ); // auf den ersten Box-StartNode |
| SwTableLines& rLines = pNdTbl->GetTabLines(); |
| for( sal_uInt16 n = 0; n < nRows; ++n ) |
| { |
| SwTableLine* pLine = new SwTableLine( pLineFmt, nCols, 0 ); |
| rLines.C40_INSERT( SwTableLine, pLine, n ); |
| SwTableBoxes& rBoxes = pLine->GetTabBoxes(); |
| for( sal_uInt16 i = 0; i < nCols; ++i ) |
| { |
| SwTableBoxFmt *pBoxF; |
| if( pTAFmt ) |
| { |
| sal_uInt8 nId = static_cast<sal_uInt8>(!n ? 0 : (( n+1 == nRows ) |
| ? 12 : (4 * (1 + ((n-1) & 1 ))))); |
| nId = nId + static_cast<sal_uInt8>( !i ? 0 : |
| ( i+1 == nCols ? 3 : (1 + ((i-1) & 1)))); |
| pBoxF = ::lcl_CreateAFmtBoxFmt( *this, aBoxFmtArr, *pTAFmt, |
| nCols, nId ); |
| |
| // ggfs. noch die Absatz/ZeichenAttribute setzen |
| if( pTAFmt->IsFont() || pTAFmt->IsJustify() ) |
| { |
| aCharSet.ClearItem(); |
| pTAFmt->UpdateToSet( nId, aCharSet, |
| SwTableAutoFmt::UPDATE_CHAR, 0 ); |
| if( aCharSet.Count() ) |
| GetNodes()[ aNdIdx.GetIndex()+1 ]->GetCntntNode()-> |
| SetAttr( aCharSet ); |
| } |
| } |
| else if( bDfltBorders ) |
| { |
| sal_uInt8 nBoxId = (i < nCols - 1 ? 0 : 1) + (n ? 2 : 0 ); |
| pBoxF = ::lcl_CreateDfltBoxFmt( *this, aBoxFmtArr, nCols, nBoxId); |
| } |
| else |
| pBoxF = pBoxFmt; |
| |
| // fuer AutoFormat bei der Eingabe: beim Einfuegen der Tabelle |
| // werden gleich die Spalten gesetzt. Im Array stehen die |
| // Positionen der Spalten!! (nicht deren Breite!) |
| if( pColArr ) |
| { |
| nWidth = (*pColArr)[ sal_uInt16(i + 1) ] - (*pColArr)[ i ]; |
| if( pBoxF->GetFrmSize().GetWidth() != nWidth ) |
| { |
| if( pBoxF->GetDepends() ) // neues Format erzeugen! |
| { |
| SwTableBoxFmt *pNewFmt = MakeTableBoxFmt(); |
| *pNewFmt = *pBoxF; |
| pBoxF = pNewFmt; |
| } |
| pBoxF->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE, nWidth )); |
| } |
| } |
| |
| SwTableBox *pBox = new SwTableBox( pBoxF, aNdIdx, pLine); |
| rBoxes.C40_INSERT( SwTableBox, pBox, i ); |
| aNdIdx += 3; // StartNode, TextNode, EndNode == 3 Nodes |
| } |
| } |
| // und Frms einfuegen. |
| GetNodes().GoNext( &aNdIdx ); // zum naechsten ContentNode |
| pTblNd->MakeFrms( &aNdIdx ); |
| |
| if( IsRedlineOn() || (!IsIgnoreRedline() && pRedlineTbl->Count() )) |
| { |
| SwPaM aPam( *pTblNd->EndOfSectionNode(), *pTblNd, 1 ); |
| if( IsRedlineOn() ) |
| AppendRedline( new SwRedline( nsRedlineType_t::REDLINE_INSERT, aPam ), true); |
| else |
| SplitRedline( aPam ); |
| } |
| |
| SetModified(); |
| CHECK_TABLE( *pNdTbl ); |
| return pNdTbl; |
| } |
| |
| SwTableNode* SwNodes::InsertTable( const SwNodeIndex& rNdIdx, |
| sal_uInt16 nBoxes, |
| SwTxtFmtColl* pCntntTxtColl, |
| sal_uInt16 nLines, |
| sal_uInt16 nRepeat, |
| SwTxtFmtColl* pHeadlineTxtColl, |
| const SwAttrSet * pAttrSet) |
| { |
| if( !nBoxes ) |
| return 0; |
| |
| // wenn Lines angegeben, erzeuge die Matrix aus Lines & Boxen |
| if( !pHeadlineTxtColl || !nLines ) |
| pHeadlineTxtColl = pCntntTxtColl; |
| |
| SwTableNode * pTblNd = new SwTableNode( rNdIdx ); |
| SwEndNode* pEndNd = new SwEndNode( rNdIdx, *pTblNd ); |
| |
| if( !nLines ) // fuer die FOR-Schleife |
| ++nLines; |
| |
| SwNodeIndex aIdx( *pEndNd ); |
| SwTxtFmtColl* pTxtColl = pHeadlineTxtColl; |
| for( sal_uInt16 nL = 0; nL < nLines; ++nL ) |
| { |
| for( sal_uInt16 nB = 0; nB < nBoxes; ++nB ) |
| { |
| SwStartNode* pSttNd = new SwStartNode( aIdx, ND_STARTNODE, |
| SwTableBoxStartNode ); |
| pSttNd->pStartOfSection = pTblNd; |
| |
| SwTxtNode * pTmpNd = new SwTxtNode( aIdx, pTxtColl ); |
| |
| // --> FME 2006-04-13 #i60422# Propagate some more attributes. |
| // Adjustment was done for #109161# |
| const SfxPoolItem* pItem = NULL; |
| if ( NULL != pAttrSet ) |
| { |
| static const sal_uInt16 aPropagateItems[] = { |
| RES_PARATR_ADJUST, |
| RES_CHRATR_FONT, RES_CHRATR_FONTSIZE, |
| RES_CHRATR_CJK_FONT, RES_CHRATR_CJK_FONTSIZE, |
| RES_CHRATR_CTL_FONT, RES_CHRATR_CTL_FONTSIZE, 0 }; |
| |
| const sal_uInt16* pIdx = aPropagateItems; |
| while ( *pIdx != 0 ) |
| { |
| if ( SFX_ITEM_SET != pTmpNd->GetSwAttrSet().GetItemState( *pIdx ) && |
| SFX_ITEM_SET == pAttrSet->GetItemState( *pIdx, sal_True, &pItem ) ) |
| static_cast<SwCntntNode *>(pTmpNd)->SetAttr(*pItem); |
| ++pIdx; |
| } |
| } |
| // <-- |
| |
| new SwEndNode( aIdx, *pSttNd ); |
| } |
| if ( nL + 1 >= nRepeat ) |
| pTxtColl = pCntntTxtColl; |
| } |
| return pTblNd; |
| } |
| |
| |
| //---------------- Text -> Tabelle ----------------------- |
| |
| const SwTable* SwDoc::TextToTable( const SwInsertTableOptions& rInsTblOpts, |
| const SwPaM& rRange, sal_Unicode cCh, |
| sal_Int16 eAdjust, |
| const SwTableAutoFmt* pTAFmt ) |
| { |
| // pruefe ob in der Selection eine Tabelle liegt |
| const SwPosition *pStt = rRange.Start(), *pEnd = rRange.End(); |
| { |
| sal_uLong nCnt = pStt->nNode.GetIndex(); |
| for( ; nCnt <= pEnd->nNode.GetIndex(); ++nCnt ) |
| if( !GetNodes()[ nCnt ]->IsTxtNode() ) |
| return 0; |
| } |
| |
| /* #106283# Save first node in the selection if it is a context node. */ |
| SwCntntNode * pSttCntntNd = pStt->nNode.GetNode().GetCntntNode(); |
| |
| SwPaM aOriginal( *pStt, *pEnd ); |
| pStt = aOriginal.GetMark(); |
| pEnd = aOriginal.GetPoint(); |
| |
| #ifdef DEL_TABLE_REDLINES |
| lcl_DelRedlines aDelRedl( aOriginal ); |
| #endif |
| |
| SwUndoTxtToTbl* pUndo = 0; |
| if( GetIDocumentUndoRedo().DoesUndo() ) |
| { |
| GetIDocumentUndoRedo().StartUndo( UNDO_TEXTTOTABLE, NULL ); |
| pUndo = new SwUndoTxtToTbl( aOriginal, rInsTblOpts, cCh, |
| static_cast<sal_uInt16>(eAdjust), pTAFmt ); |
| GetIDocumentUndoRedo().AppendUndo( pUndo ); |
| |
| // das Splitten vom TextNode nicht in die Undohistory aufnehmen |
| GetIDocumentUndoRedo().DoUndo( false ); |
| } |
| |
| ::PaMCorrAbs( aOriginal, *pEnd ); |
| |
| // sorge dafuer, das der Bereich auf Node-Grenzen liegt |
| SwNodeRange aRg( pStt->nNode, pEnd->nNode ); |
| if( pStt->nContent.GetIndex() ) |
| SplitNode( *pStt, false ); |
| |
| sal_Bool bEndCntnt = 0 != pEnd->nContent.GetIndex(); |
| // nicht splitten am Ende der Zeile (aber am Ende vom Doc!!) |
| if( bEndCntnt ) |
| { |
| if( pEnd->nNode.GetNode().GetCntntNode()->Len() != pEnd->nContent.GetIndex() |
| || pEnd->nNode.GetIndex() >= GetNodes().GetEndOfContent().GetIndex()-1 ) |
| { |
| SplitNode( *pEnd, false ); |
| ((SwNodeIndex&)pEnd->nNode)--; |
| ((SwIndex&)pEnd->nContent).Assign( |
| pEnd->nNode.GetNode().GetCntntNode(), 0 ); |
| // ein Node und am Ende ?? |
| if( pStt->nNode.GetIndex() >= pEnd->nNode.GetIndex() ) |
| aRg.aStart--; |
| } |
| else |
| aRg.aEnd++; |
| } |
| |
| |
| if( aRg.aEnd.GetIndex() == aRg.aStart.GetIndex() ) |
| { |
| ASSERT( sal_False, "Kein Bereich" ); |
| aRg.aEnd++; |
| } |
| |
| // Wir gehen jetzt immer ueber die Upper, um die Tabelle einzufuegen: |
| SwNode2Layout aNode2Layout( aRg.aStart.GetNode() ); |
| |
| GetIDocumentUndoRedo().DoUndo( 0 != pUndo ); |
| |
| // dann erstelle die Box/Line/Table-Struktur |
| SwTableBoxFmt* pBoxFmt = MakeTableBoxFmt(); |
| SwTableLineFmt* pLineFmt = MakeTableLineFmt(); |
| SwTableFmt* pTableFmt = MakeTblFrmFmt( GetUniqueTblName(), GetDfltFrmFmt() ); |
| |
| // alle Zeilen haben die Fill-Order von links nach rechts ! |
| pLineFmt->SetFmtAttr( SwFmtFillOrder( ATT_LEFT_TO_RIGHT )); |
| // die Tabelle bekommt USHRT_MAX als default SSize |
| pTableFmt->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE, USHRT_MAX )); |
| if( !(rInsTblOpts.mnInsMode & tabopts::SPLIT_LAYOUT) ) |
| pTableFmt->SetFmtAttr( SwFmtLayoutSplit( sal_False )); |
| |
| /* #106283# If the first node in the selection is a context node and if it |
| has an item FRAMEDIR set (no default) propagate the item to the |
| replacing table. */ |
| if (pSttCntntNd) |
| { |
| const SwAttrSet & aNdSet = pSttCntntNd->GetSwAttrSet(); |
| const SfxPoolItem *pItem = NULL; |
| |
| if (SFX_ITEM_SET == aNdSet.GetItemState( RES_FRAMEDIR, sal_True, &pItem ) |
| && pItem != NULL) |
| { |
| pTableFmt->SetFmtAttr( *pItem ); |
| } |
| } |
| |
| SwTableNode* pTblNd = GetNodes().TextToTable( |
| aRg, cCh, pTableFmt, pLineFmt, pBoxFmt, |
| GetTxtCollFromPool( RES_POOLCOLL_STANDARD ), pUndo ); |
| |
| SwTable * pNdTbl = &pTblNd->GetTable(); |
| ASSERT( pNdTbl, "kein Tabellen-Node angelegt." ) |
| |
| const sal_uInt16 nRowsToRepeat = |
| tabopts::HEADLINE == (rInsTblOpts.mnInsMode & tabopts::HEADLINE) ? |
| rInsTblOpts.mnRowsToRepeat : |
| 0; |
| pNdTbl->SetRowsToRepeat( nRowsToRepeat ); |
| |
| sal_Bool bUseBoxFmt = sal_False; |
| if( !pBoxFmt->GetDepends() ) |
| { |
| // die Formate an den Boxen haben schon die richtige Size, es darf |
| // also nur noch die richtige Umrandung/AutoFmt gesetzt werden. |
| bUseBoxFmt = sal_True; |
| pTableFmt->SetFmtAttr( pBoxFmt->GetFrmSize() ); |
| delete pBoxFmt; |
| eAdjust = text::HoriOrientation::NONE; |
| } |
| |
| //Orientation am Fmt der Table setzen |
| pTableFmt->SetFmtAttr( SwFmtHoriOrient( 0, eAdjust ) ); |
| pNdTbl->RegisterToFormat( *pTableFmt ); |
| |
| if( pTAFmt || ( rInsTblOpts.mnInsMode & tabopts::DEFAULT_BORDER) ) |
| { |
| sal_uInt8 nBoxArrLen = pTAFmt ? 16 : 4; |
| SvPtrarr aBoxFmtArr( nBoxArrLen, 0 ); |
| { |
| for( sal_uInt8 i = 0; i < nBoxArrLen; ++i ) |
| aBoxFmtArr.Insert( (void*)0, i ); |
| } |
| |
| // --> OD 2008-02-25 #refactorlists# |
| // SfxItemSet aCharSet( GetAttrPool(), RES_CHRATR_BEGIN, RES_PARATR_END-1 ); |
| SfxItemSet aCharSet( GetAttrPool(), RES_CHRATR_BEGIN, RES_PARATR_LIST_END-1 ); |
| // <-- |
| SwHistory* pHistory = pUndo ? &pUndo->GetHistory() : 0; |
| |
| SwTableBoxFmt *pBoxF = 0; |
| SwTableLines& rLines = pNdTbl->GetTabLines(); |
| sal_uInt16 nRows = rLines.Count(); |
| for( sal_uInt16 n = 0; n < nRows; ++n ) |
| { |
| SwTableBoxes& rBoxes = rLines[ n ]->GetTabBoxes(); |
| sal_uInt16 nCols = rBoxes.Count(); |
| for( sal_uInt16 i = 0; i < nCols; ++i ) |
| { |
| SwTableBox* pBox = rBoxes[ i ]; |
| sal_Bool bChgSz = sal_False; |
| |
| if( pTAFmt ) |
| { |
| sal_uInt8 nId = static_cast<sal_uInt8>(!n ? 0 : (( n+1 == nRows ) |
| ? 12 : (4 * (1 + ((n-1) & 1 ))))); |
| nId = nId + static_cast<sal_uInt8>(!i ? 0 : |
| ( i+1 == nCols ? 3 : (1 + ((i-1) & 1)))); |
| if( bUseBoxFmt ) |
| ::lcl_SetDfltBoxAttr( *pBox, aBoxFmtArr, nId, pTAFmt ); |
| else |
| { |
| bChgSz = 0 == aBoxFmtArr[ nId ]; |
| pBoxF = ::lcl_CreateAFmtBoxFmt( *this, aBoxFmtArr, |
| *pTAFmt, USHRT_MAX, nId ); |
| } |
| |
| // ggfs. noch die Absatz/ZeichenAttribute setzen |
| if( pTAFmt->IsFont() || pTAFmt->IsJustify() ) |
| { |
| aCharSet.ClearItem(); |
| pTAFmt->UpdateToSet( nId, aCharSet, |
| SwTableAutoFmt::UPDATE_CHAR, 0 ); |
| if( aCharSet.Count() ) |
| { |
| sal_uLong nSttNd = pBox->GetSttIdx()+1; |
| sal_uLong nEndNd = pBox->GetSttNd()->EndOfSectionIndex(); |
| for( ; nSttNd < nEndNd; ++nSttNd ) |
| { |
| SwCntntNode* pNd = GetNodes()[ nSttNd ]->GetCntntNode(); |
| if( pNd ) |
| { |
| if( pHistory ) |
| { |
| SwRegHistory aReg( pNd, *pNd, pHistory ); |
| pNd->SetAttr( aCharSet ); |
| } |
| else |
| pNd->SetAttr( aCharSet ); |
| } |
| } |
| } |
| } |
| } |
| else |
| { |
| sal_uInt8 nId = (i < nCols - 1 ? 0 : 1) + (n ? 2 : 0 ); |
| if( bUseBoxFmt ) |
| ::lcl_SetDfltBoxAttr( *pBox, aBoxFmtArr, nId ); |
| else |
| { |
| bChgSz = 0 == aBoxFmtArr[ nId ]; |
| pBoxF = ::lcl_CreateDfltBoxFmt( *this, aBoxFmtArr, |
| USHRT_MAX, nId ); |
| } |
| } |
| |
| if( !bUseBoxFmt ) |
| { |
| if( bChgSz ) |
| pBoxF->SetFmtAttr( pBox->GetFrmFmt()->GetFrmSize() ); |
| pBox->ChgFrmFmt( pBoxF ); |
| } |
| } |
| } |
| |
| if( bUseBoxFmt ) |
| { |
| for( sal_uInt8 i = 0; i < nBoxArrLen; ++i ) |
| { |
| SvPtrarr* pArr = (SvPtrarr*)aBoxFmtArr[ i ]; |
| delete pArr; |
| } |
| } |
| } |
| |
| // JP 03.04.97: Inhalt der Boxen auf Zahlen abpruefen |
| if( IsInsTblFormatNum() ) |
| { |
| for( sal_uInt16 nBoxes = pNdTbl->GetTabSortBoxes().Count(); nBoxes; ) |
| ChkBoxNumFmt( *pNdTbl->GetTabSortBoxes()[ --nBoxes ], sal_False ); |
| } |
| |
| sal_uLong nIdx = pTblNd->GetIndex(); |
| aNode2Layout.RestoreUpperFrms( GetNodes(), nIdx, nIdx + 1 ); |
| |
| { |
| SwPaM& rTmp = (SwPaM&)rRange; // Point immer an den Anfang |
| rTmp.DeleteMark(); |
| rTmp.GetPoint()->nNode = *pTblNd; |
| SwCntntNode* pCNd = GetNodes().GoNext( &rTmp.GetPoint()->nNode ); |
| rTmp.GetPoint()->nContent.Assign( pCNd, 0 ); |
| } |
| |
| if( pUndo ) |
| { |
| GetIDocumentUndoRedo().EndUndo( UNDO_TEXTTOTABLE, NULL ); |
| } |
| |
| SetModified(); |
| SetFieldsDirty(true, NULL, 0); |
| return pNdTbl; |
| } |
| |
| SwTableNode* SwNodes::TextToTable( const SwNodeRange& rRange, sal_Unicode cCh, |
| SwTableFmt* pTblFmt, |
| SwTableLineFmt* pLineFmt, |
| SwTableBoxFmt* pBoxFmt, |
| SwTxtFmtColl* pTxtColl, |
| SwUndoTxtToTbl* pUndo ) |
| { |
| if( rRange.aStart >= rRange.aEnd ) |
| return 0; |
| |
| SwTableNode * pTblNd = new SwTableNode( rRange.aStart ); |
| new SwEndNode( rRange.aEnd, *pTblNd ); |
| |
| SwDoc* pDoc = GetDoc(); |
| SvUShorts aPosArr( 0, 16 ); |
| SwTable * pTable = &pTblNd->GetTable(); |
| SwTableLine* pLine; |
| SwTableBox* pBox; |
| sal_uInt16 nBoxes, nLines, nMaxBoxes = 0; |
| |
| SwNodeIndex aSttIdx( *pTblNd, 1 ); |
| SwNodeIndex aEndIdx( rRange.aEnd, -1 ); |
| for( nLines = 0, nBoxes = 0; |
| aSttIdx.GetIndex() < aEndIdx.GetIndex(); |
| aSttIdx += 2, nLines++, nBoxes = 0 ) |
| { |
| SwTxtNode* pTxtNd = aSttIdx.GetNode().GetTxtNode(); |
| ASSERT( pTxtNd, "nur TextNodes in der Tabelle aufnehmen" ); |
| |
| if( !nLines && 0x0b == cCh ) |
| { |
| cCh = 0x09; |
| |
| // JP 28.10.96: vom 1. Node die Positionen des Trenners besorgen, |
| // damit die Boxen entsprechend eingestellt werden |
| SwTxtFrmInfo aFInfo( (SwTxtFrm*)pTxtNd->getLayoutFrm( pTxtNd->GetDoc()->GetCurrentLayout() ) ); |
| if( aFInfo.IsOneLine() ) // nur dann sinnvoll! |
| { |
| const sal_Unicode* pTxt = pTxtNd->GetTxt().GetBuffer(); |
| for( xub_StrLen nChPos = 0; *pTxt; ++nChPos, ++pTxt ) |
| { |
| if( *pTxt == cCh ) |
| { |
| aPosArr.Insert( static_cast<sal_uInt16>( |
| aFInfo.GetCharPos( nChPos+1, sal_False )), |
| aPosArr.Count() ); |
| } |
| } |
| |
| aPosArr.Insert( /*aFInfo.GetFrm()->Frm().Left() +*/ |
| static_cast<sal_uInt16>(aFInfo.GetFrm()->IsVertical() ? |
| aFInfo.GetFrm()->Prt().Bottom() : |
| aFInfo.GetFrm()->Prt().Right()), |
| aPosArr.Count() ); |
| } |
| } |
| |
| // die alten Frames loeschen, es werden neue erzeugt |
| pTxtNd->DelFrms(); |
| |
| // PageBreaks/PageDesc/ColBreak rausschmeissen. |
| const SfxItemSet* pSet = pTxtNd->GetpSwAttrSet(); |
| if( pSet ) |
| { |
| // das entfernen der PageBreaks erst nach dem erzeugen der Tabelle |
| // erfolgen, denn sonst stehen sie falsch in der History !!! |
| // SwRegHistory aRegH( pTxtNd, *pTxtNd, pHistory ); |
| const SfxPoolItem* pItem; |
| if( SFX_ITEM_SET == pSet->GetItemState( RES_BREAK, sal_False, &pItem ) ) |
| { |
| if( !nLines ) |
| pTblFmt->SetFmtAttr( *pItem ); |
| pTxtNd->ResetAttr( RES_BREAK ); |
| pSet = pTxtNd->GetpSwAttrSet(); |
| } |
| |
| if( pSet && SFX_ITEM_SET == pSet->GetItemState( |
| RES_PAGEDESC, sal_False, &pItem ) && |
| ((SwFmtPageDesc*)pItem)->GetPageDesc() ) |
| { |
| if( !nLines ) |
| pTblFmt->SetFmtAttr( *pItem ); |
| pTxtNd->ResetAttr( RES_PAGEDESC ); |
| } |
| } |
| |
| // setze den bei allen TextNode in der Tabelle den TableNode |
| // als StartNode |
| pTxtNd->pStartOfSection = pTblNd; |
| |
| pLine = new SwTableLine( pLineFmt, 1, 0 ); |
| pTable->GetTabLines().C40_INSERT( SwTableLine, pLine, nLines ); |
| |
| SwStartNode* pSttNd; |
| SwPosition aCntPos( aSttIdx, SwIndex( pTxtNd )); |
| |
| SvULongs aBkmkArr( 15, 15 ); |
| _SaveCntntIdx( pDoc, aSttIdx.GetIndex(), pTxtNd->GetTxt().Len(), aBkmkArr ); |
| |
| const sal_Unicode* pTxt = pTxtNd->GetTxt().GetBuffer(); |
| |
| if( T2T_PARA != cCh ) |
| for( xub_StrLen nChPos = 0; *pTxt; ++nChPos, ++pTxt ) |
| if( *pTxt == cCh ) |
| { |
| aCntPos.nContent = nChPos; |
| SwCntntNode* pNewNd = pTxtNd->SplitCntntNode( aCntPos ); |
| |
| if( aBkmkArr.Count() ) |
| _RestoreCntntIdx( aBkmkArr, *pNewNd, nChPos, |
| nChPos + 1 ); |
| |
| // Trennzeichen loeschen und SuchString korrigieren |
| pTxtNd->EraseText( aCntPos.nContent, 1 ); |
| pTxt = pTxtNd->GetTxt().GetBuffer(); |
| nChPos = 0; |
| --nChPos, --pTxt; // for the ++ in the for loop !!! |
| |
| // setze bei allen TextNodes in der Tabelle den TableNode |
| // als StartNode |
| const SwNodeIndex aTmpIdx( aCntPos.nNode, -1 ); |
| pSttNd = new SwStartNode( aTmpIdx, ND_STARTNODE, |
| SwTableBoxStartNode ); |
| new SwEndNode( aCntPos.nNode, *pSttNd ); |
| pNewNd->pStartOfSection = pSttNd; |
| |
| // Section der Box zuweisen |
| pBox = new SwTableBox( pBoxFmt, *pSttNd, pLine ); |
| pLine->GetTabBoxes().C40_INSERT( SwTableBox, pBox, nBoxes++ ); |
| } |
| |
| // und jetzt den letzten Teil-String |
| if( aBkmkArr.Count() ) |
| _RestoreCntntIdx( aBkmkArr, *pTxtNd, pTxtNd->GetTxt().Len(), |
| pTxtNd->GetTxt().Len()+1 ); |
| |
| pSttNd = new SwStartNode( aCntPos.nNode, ND_STARTNODE, SwTableBoxStartNode ); |
| const SwNodeIndex aTmpIdx( aCntPos.nNode, 1 ); |
| new SwEndNode( aTmpIdx, *pSttNd ); |
| pTxtNd->pStartOfSection = pSttNd; |
| |
| pBox = new SwTableBox( pBoxFmt, *pSttNd, pLine ); |
| pLine->GetTabBoxes().C40_INSERT( SwTableBox, pBox, nBoxes++ ); |
| if( nMaxBoxes < nBoxes ) |
| nMaxBoxes = nBoxes; |
| } |
| |
| // die Tabelle ausgleichen, leere Sections einfuegen |
| sal_uInt16 n; |
| |
| for( n = 0; n < pTable->GetTabLines().Count(); ++n ) |
| { |
| SwTableLine* pCurrLine = pTable->GetTabLines()[ n ]; |
| if( nMaxBoxes != ( nBoxes = pCurrLine->GetTabBoxes().Count() )) |
| { |
| InsBoxen( pTblNd, pCurrLine, pBoxFmt, pTxtColl, 0, |
| nBoxes, nMaxBoxes - nBoxes ); |
| |
| if( pUndo ) |
| for( sal_uInt16 i = nBoxes; i < nMaxBoxes; ++i ) |
| pUndo->AddFillBox( *pCurrLine->GetTabBoxes()[ i ] ); |
| |
| // fehlen der 1. Line Boxen, dann kann man das Breiten Array |
| // vergessen! |
| if( !n ) |
| aPosArr.Remove( 0, aPosArr.Count() ); |
| } |
| } |
| |
| if( aPosArr.Count() ) |
| { |
| SwTableLines& rLns = pTable->GetTabLines(); |
| sal_uInt16 nLastPos = 0; |
| for( n = 0; n < aPosArr.Count(); ++n ) |
| { |
| SwTableBoxFmt *pNewFmt = pDoc->MakeTableBoxFmt(); |
| pNewFmt->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE, |
| aPosArr[ n ] - nLastPos )); |
| for( sal_uInt16 nTmpLine = 0; nTmpLine < rLns.Count(); ++nTmpLine ) |
| //JP 24.06.98: hier muss ein Add erfolgen, da das BoxFormat |
| // von der rufenden Methode noch gebraucht wird! |
| pNewFmt->Add( rLns[ nTmpLine ]->GetTabBoxes()[ n ] ); |
| |
| nLastPos = aPosArr[ n ]; |
| } |
| |
| // damit die Tabelle die richtige Groesse bekommt, im BoxFormat die |
| // Groesse nach "oben" transportieren. |
| ASSERT( !pBoxFmt->GetDepends(), "wer ist in dem Format noch angemeldet" ); |
| pBoxFmt->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE, nLastPos )); |
| } |
| else |
| pBoxFmt->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE, USHRT_MAX / nMaxBoxes )); |
| |
| // das wars doch wohl ?? |
| return pTblNd; |
| } |
| /*-- 18.05.2006 10:30:29--------------------------------------------------- |
| |
| -----------------------------------------------------------------------*/ |
| const SwTable* SwDoc::TextToTable( const std::vector< std::vector<SwNodeRange> >& rTableNodes ) |
| { |
| /* #106283# Save first node in the selection if it is a content node. */ |
| SwCntntNode * pSttCntntNd = rTableNodes.begin()->begin()->aStart.GetNode().GetCntntNode(); |
| |
| /**debug**/ |
| #if OSL_DEBUG_LEVEL > 1 |
| const SwNodeRange& rStartRange = *rTableNodes.begin()->begin(); |
| const SwNodeRange& rEndRange = *rTableNodes.rbegin()->rbegin(); |
| (void) rStartRange; |
| (void) rEndRange; |
| #endif |
| /**debug**/ |
| |
| //!!! not necessarily TextNodes !!! |
| SwPaM aOriginal( rTableNodes.begin()->begin()->aStart, rTableNodes.rbegin()->rbegin()->aEnd ); |
| const SwPosition *pStt = aOriginal.GetMark(); |
| const SwPosition *pEnd = aOriginal.GetPoint(); |
| |
| #ifdef DEL_TABLE_REDLINES |
| lcl_DelRedlines aDelRedl( aOriginal ); |
| #endif |
| |
| // SwUndoTxtToTbl* pUndo = 0; |
| bool const bUndo(GetIDocumentUndoRedo().DoesUndo()); |
| if (bUndo) |
| { |
| // das Splitten vom TextNode nicht in die Undohistory aufnehmen |
| GetIDocumentUndoRedo().DoUndo(false); |
| } |
| |
| ::PaMCorrAbs( aOriginal, *pEnd ); |
| |
| // sorge dafuer, das der Bereich auf Node-Grenzen liegt |
| SwNodeRange aRg( pStt->nNode, pEnd->nNode ); |
| if( pStt->nContent.GetIndex() ) |
| SplitNode( *pStt, false ); |
| |
| sal_Bool bEndCntnt = 0 != pEnd->nContent.GetIndex(); |
| // nicht splitten am Ende der Zeile (aber am Ende vom Doc!!) |
| if( bEndCntnt ) |
| { |
| if( pEnd->nNode.GetNode().GetCntntNode()->Len() != pEnd->nContent.GetIndex() |
| || pEnd->nNode.GetIndex() >= GetNodes().GetEndOfContent().GetIndex()-1 ) |
| { |
| SplitNode( *pEnd, false ); |
| ((SwNodeIndex&)pEnd->nNode)--; |
| ((SwIndex&)pEnd->nContent).Assign( |
| pEnd->nNode.GetNode().GetCntntNode(), 0 ); |
| // ein Node und am Ende ?? |
| if( pStt->nNode.GetIndex() >= pEnd->nNode.GetIndex() ) |
| aRg.aStart--; |
| } |
| else |
| aRg.aEnd++; |
| } |
| |
| |
| if( aRg.aEnd.GetIndex() == aRg.aStart.GetIndex() ) |
| { |
| ASSERT( sal_False, "Kein Bereich" ); |
| aRg.aEnd++; |
| } |
| |
| // Wir gehen jetzt immer ueber die Upper, um die Tabelle einzufuegen: |
| SwNode2Layout aNode2Layout( aRg.aStart.GetNode() ); |
| |
| GetIDocumentUndoRedo().DoUndo(bUndo); |
| |
| // dann erstelle die Box/Line/Table-Struktur |
| SwTableBoxFmt* pBoxFmt = MakeTableBoxFmt(); |
| SwTableLineFmt* pLineFmt = MakeTableLineFmt(); |
| SwTableFmt* pTableFmt = MakeTblFrmFmt( GetUniqueTblName(), GetDfltFrmFmt() ); |
| |
| // alle Zeilen haben die Fill-Order von links nach rechts ! |
| pLineFmt->SetFmtAttr( SwFmtFillOrder( ATT_LEFT_TO_RIGHT )); |
| // die Tabelle bekommt USHRT_MAX als default SSize |
| pTableFmt->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE, USHRT_MAX )); |
| |
| /* #106283# If the first node in the selection is a context node and if it |
| has an item FRAMEDIR set (no default) propagate the item to the |
| replacing table. */ |
| if (pSttCntntNd) |
| { |
| const SwAttrSet & aNdSet = pSttCntntNd->GetSwAttrSet(); |
| const SfxPoolItem *pItem = NULL; |
| |
| if (SFX_ITEM_SET == aNdSet.GetItemState( RES_FRAMEDIR, sal_True, &pItem ) |
| && pItem != NULL) |
| { |
| pTableFmt->SetFmtAttr( *pItem ); |
| } |
| } |
| |
| SwTableNode* pTblNd = GetNodes().TextToTable( |
| rTableNodes, pTableFmt, pLineFmt, pBoxFmt, |
| GetTxtCollFromPool( RES_POOLCOLL_STANDARD )/*, pUndo*/ ); |
| |
| SwTable * pNdTbl = &pTblNd->GetTable(); |
| ASSERT( pNdTbl, "kein Tabellen-Node angelegt." ) |
| pNdTbl->RegisterToFormat( *pTableFmt ); |
| |
| sal_Bool bUseBoxFmt = sal_False; |
| if( !pBoxFmt->GetDepends() ) |
| { |
| // die Formate an den Boxen haben schon die richtige Size, es darf |
| // also nur noch die richtige Umrandung/AutoFmt gesetzt werden. |
| bUseBoxFmt = sal_True; |
| pTableFmt->SetFmtAttr( pBoxFmt->GetFrmSize() ); |
| delete pBoxFmt; |
| } |
| |
| sal_uLong nIdx = pTblNd->GetIndex(); |
| aNode2Layout.RestoreUpperFrms( GetNodes(), nIdx, nIdx + 1 ); |
| |
| SetModified(); |
| SetFieldsDirty( true, NULL, 0 ); |
| return pNdTbl; |
| } |
| |
| SwNodeRange * SwNodes::ExpandRangeForTableBox(const SwNodeRange & rRange) |
| { |
| SwNodeRange * pResult = NULL; |
| bool bChanged = false; |
| |
| SwNodeIndex aNewStart = rRange.aStart; |
| SwNodeIndex aNewEnd = rRange.aEnd; |
| |
| SwNodeIndex aEndIndex = rRange.aEnd; |
| SwNodeIndex aIndex = rRange.aStart; |
| |
| while (aIndex < aEndIndex) |
| { |
| SwNode& rNode = aIndex.GetNode(); |
| |
| if (rNode.IsStartNode()) |
| { |
| // advance aIndex to the end node of this start node |
| SwNode * pEndNode = rNode.EndOfSectionNode(); |
| aIndex = *pEndNode; |
| |
| if (aIndex > aNewEnd) |
| { |
| aNewEnd = aIndex; |
| bChanged = true; |
| } |
| } |
| else if (rNode.IsEndNode()) |
| { |
| SwNode * pStartNode = rNode.StartOfSectionNode(); |
| SwNodeIndex aStartIndex = *pStartNode; |
| |
| if (aStartIndex < aNewStart) |
| { |
| aNewStart = aStartIndex; |
| bChanged = true; |
| } |
| } |
| |
| if (aIndex < aEndIndex) |
| ++aIndex; |
| } |
| |
| SwNode * pNode = &aIndex.GetNode(); |
| while (pNode->IsEndNode()) |
| { |
| SwNode * pStartNode = pNode->StartOfSectionNode(); |
| SwNodeIndex aStartIndex(*pStartNode); |
| aNewStart = aStartIndex; |
| aNewEnd = aIndex; |
| bChanged = true; |
| |
| ++aIndex; |
| pNode = &aIndex.GetNode(); |
| } |
| |
| if (bChanged) |
| pResult = new SwNodeRange(aNewStart, aNewEnd); |
| |
| return pResult; |
| } |
| |
| /*-- 18.05.2006 08:23:28--------------------------------------------------- |
| |
| -----------------------------------------------------------------------*/ |
| SwTableNode* SwNodes::TextToTable( const SwNodes::TableRanges_t & rTableNodes, |
| SwTableFmt* pTblFmt, |
| SwTableLineFmt* pLineFmt, |
| SwTableBoxFmt* pBoxFmt, |
| SwTxtFmtColl* /*pTxtColl*/ /*, SwUndo... pUndo*/ ) |
| { |
| if( !rTableNodes.size() ) |
| return 0; |
| |
| SwTableNode * pTblNd = new SwTableNode( rTableNodes.begin()->begin()->aStart ); |
| //insert the end node after the last text node |
| SwNodeIndex aInsertIndex( rTableNodes.rbegin()->rbegin()->aEnd ); |
| ++aInsertIndex; |
| |
| //!! owner ship will be transferred in c-tor to SwNodes array. |
| //!! Thus no real problem here... |
| new SwEndNode( aInsertIndex, *pTblNd ); |
| |
| #if OSL_DEBUG_LEVEL > 1 |
| /**debug**/ |
| const SwNodeRange& rStartRange = *rTableNodes.begin()->begin(); |
| const SwNodeRange& rEndRange = *rTableNodes.rbegin()->rbegin(); |
| (void) rStartRange; |
| (void) rEndRange; |
| /**debug**/ |
| #endif |
| |
| SwDoc* pDoc = GetDoc(); |
| SvUShorts aPosArr( 0, 16 ); |
| SwTable * pTable = &pTblNd->GetTable(); |
| SwTableLine* pLine; |
| SwTableBox* pBox; |
| sal_uInt16 nBoxes, nLines, nMaxBoxes = 0; |
| |
| // SwHistory* pHistory = pUndo ? &pUndo->GetHistory() : 0; |
| |
| |
| SwNodeIndex aNodeIndex = rTableNodes.begin()->begin()->aStart; |
| // delete frames of all contained content nodes |
| for( nLines = 0; aNodeIndex <= rTableNodes.rbegin()->rbegin()->aEnd; ++aNodeIndex,++nLines ) |
| { |
| SwNode& rNode = aNodeIndex.GetNode(); |
| if( rNode.IsCntntNode() ) |
| { |
| static_cast<SwCntntNode&>(rNode).DelFrms(); |
| if(rNode.IsTxtNode()) |
| { |
| SwTxtNode& rTxtNode = static_cast<SwTxtNode&>(rNode); |
| // setze den bei allen TextNode in der Tabelle den TableNode |
| // als StartNode |
| // FIXME: this is setting wrong node StartOfSections in nested tables. |
| // rTxtNode.pStartOfSection = pTblNd; |
| // remove PageBreaks/PageDesc/ColBreak |
| const SwAttrSet* pSet = rTxtNode.GetpSwAttrSet(); |
| if( pSet ) |
| { |
| // das entfernen der PageBreaks erst nach dem erzeugen der Tabelle |
| // erfolgen, denn sonst stehen sie falsch in der History !!! |
| // SwRegHistory aRegH( pTxtNd, *pTxtNd, pHistory ); |
| const SfxPoolItem* pItem; |
| if( SFX_ITEM_SET == pSet->GetItemState( RES_BREAK, sal_False, &pItem ) ) |
| { |
| if( !nLines ) |
| pTblFmt->SetFmtAttr( *pItem ); |
| rTxtNode.ResetAttr( RES_BREAK ); |
| pSet = rTxtNode.GetpSwAttrSet(); |
| } |
| |
| if( pSet && SFX_ITEM_SET == pSet->GetItemState( |
| RES_PAGEDESC, sal_False, &pItem ) && |
| ((SwFmtPageDesc*)pItem)->GetPageDesc() ) |
| { |
| if( !nLines ) |
| pTblFmt->SetFmtAttr( *pItem ); |
| rTxtNode.ResetAttr( RES_PAGEDESC ); |
| } |
| } |
| } |
| } |
| } |
| |
| // SwNodeIndex aSttIdx( *pTblNd, 1 ); |
| // SwNodeIndex aEndIdx( rlNodes.rbegin()->aEnd, -1 ); |
| std::vector<std::vector < SwNodeRange > >::const_iterator aRowIter = rTableNodes.begin(); |
| for( nLines = 0, nBoxes = 0; |
| aRowIter != rTableNodes.end(); |
| ++aRowIter, /*aSttIdx += 2, */nLines++, nBoxes = 0 ) |
| { |
| // SwTxtNode* pTxtNd = aSttIdx.GetNode().GetTxtNode(); |
| // ASSERT( pTxtNd, "nur TextNodes in der Tabelle aufnehmen" ); |
| |
| pLine = new SwTableLine( pLineFmt, 1, 0 ); |
| pTable->GetTabLines().C40_INSERT( SwTableLine, pLine, nLines ); |
| |
| // SwStartNode* pSttNd; |
| // SwPosition aCntPos( aSttIdx, SwIndex( pTxtNd )); |
| |
| std::vector< SwNodeRange >::const_iterator aCellIter = aRowIter->begin(); |
| // SvULongs aBkmkArr( 15, 15 ); |
| // _SaveCntntIdx( pDoc, aCellIter->aStart.GetIndex(), pTxtNd->GetTxt().Len(), aBkmkArr ); |
| // const sal_Unicode* pTxt = pTxtNd->GetTxt().GetBuffer(); |
| |
| for( ; aCellIter != aRowIter->end(); ++aCellIter ) |
| { |
| // aCellIter->aStart aCellIter->aEnd |
| // aCntPos.nContent = nChPos; |
| // SwCntntNode* pNewNd = pTxtNd->SplitNode( aCntPos ); |
| |
| // auch f?rs undo? |
| // if( aBkmkArr.Count() ) |
| // _RestoreCntntIdx( aBkmkArr, *pNewNd, nChPos, |
| // nChPos + 1 ); |
| |
| const SwNodeIndex aTmpIdx( aCellIter->aStart, 0 ); |
| |
| SwNodeIndex aCellEndIdx(aCellIter->aEnd); |
| ++aCellEndIdx; |
| SwStartNode* pSttNd = new SwStartNode( aTmpIdx, ND_STARTNODE, |
| SwTableBoxStartNode ); |
| new SwEndNode( aCellEndIdx, *pSttNd ); |
| //set the start node on all node of the current cell |
| SwNodeIndex aCellNodeIdx = aCellIter->aStart; |
| for(;aCellNodeIdx <= aCellIter->aEnd; ++aCellNodeIdx ) |
| { |
| aCellNodeIdx.GetNode().pStartOfSection = pSttNd; |
| //skip start/end node pairs |
| if( aCellNodeIdx.GetNode().IsStartNode() ) |
| aCellNodeIdx = SwNodeIndex( *aCellNodeIdx.GetNode().EndOfSectionNode() ); |
| } |
| |
| // Section der Box zuweisen |
| pBox = new SwTableBox( pBoxFmt, *pSttNd, pLine ); |
| pLine->GetTabBoxes().C40_INSERT( SwTableBox, pBox, nBoxes++ ); |
| } |
| if( nMaxBoxes < nBoxes ) |
| nMaxBoxes = nBoxes; |
| } |
| |
| // die Tabelle ausgleichen, leere Sections einfuegen |
| sal_uInt16 n; |
| |
| if( aPosArr.Count() ) |
| { |
| SwTableLines& rLns = pTable->GetTabLines(); |
| sal_uInt16 nLastPos = 0; |
| for( n = 0; n < aPosArr.Count(); ++n ) |
| { |
| SwTableBoxFmt *pNewFmt = pDoc->MakeTableBoxFmt(); |
| pNewFmt->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE, |
| aPosArr[ n ] - nLastPos )); |
| for( sal_uInt16 nLines2 = 0; nLines2 < rLns.Count(); ++nLines2 ) |
| //JP 24.06.98: hier muss ein Add erfolgen, da das BoxFormat |
| // von der rufenden Methode noch gebraucht wird! |
| pNewFmt->Add( rLns[ nLines2 ]->GetTabBoxes()[ n ] ); |
| |
| nLastPos = aPosArr[ n ]; |
| } |
| |
| // damit die Tabelle die richtige Groesse bekommt, im BoxFormat die |
| // Groesse nach "oben" transportieren. |
| ASSERT( !pBoxFmt->GetDepends(), "wer ist in dem Format noch angemeldet" ); |
| pBoxFmt->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE, nLastPos )); |
| } |
| else |
| pBoxFmt->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE, USHRT_MAX / nMaxBoxes )); |
| |
| // das wars doch wohl ?? |
| return pTblNd; |
| } |
| |
| |
| //---------------- Tabelle -> Text ----------------------- |
| |
| |
| sal_Bool SwDoc::TableToText( const SwTableNode* pTblNd, sal_Unicode cCh ) |
| { |
| if( !pTblNd ) |
| return sal_False; |
| |
| // --> FME 2004-09-28 #i34471# |
| // If this is trigged by SwUndoTblToTxt::Repeat() nobody ever deleted |
| // the table cursor. |
| SwEditShell* pESh = GetEditShell(); |
| if( pESh && pESh->IsTableMode() ) |
| pESh->ClearMark(); |
| // <-- |
| |
| #ifdef DEL_TABLE_REDLINES |
| lcl_DelRedlines aDelRedl( *pTblNd, sal_False ); |
| #endif |
| |
| SwNodeRange aRg( *pTblNd, 0, *pTblNd->EndOfSectionNode() ); |
| SwUndoTblToTxt* pUndo = 0; |
| SwNodeRange* pUndoRg = 0; |
| if (GetIDocumentUndoRedo().DoesUndo()) |
| { |
| GetIDocumentUndoRedo().ClearRedo(); |
| pUndoRg = new SwNodeRange( aRg.aStart, -1, aRg.aEnd, +1 ); |
| pUndo = new SwUndoTblToTxt( pTblNd->GetTable(), cCh ); |
| } |
| |
| SwTableFmlUpdate aMsgHnt( &pTblNd->GetTable() ); |
| aMsgHnt.eFlags = TBL_BOXNAME; |
| UpdateTblFlds( &aMsgHnt ); |
| |
| sal_Bool bRet = GetNodes().TableToText( aRg, cCh, pUndo ); |
| if( pUndoRg ) |
| { |
| pUndoRg->aStart++; |
| pUndoRg->aEnd--; |
| pUndo->SetRange( *pUndoRg ); |
| GetIDocumentUndoRedo().AppendUndo(pUndo); |
| delete pUndoRg; |
| } |
| |
| if( bRet ) |
| SetModified(); |
| |
| return bRet; |
| } |
| |
| // -- benutze die ForEach Methode vom PtrArray um aus einer Tabelle wieder |
| // Text zuerzeugen. (Die Boxen koennen auch noch Lines enthalten !!) |
| struct _DelTabPara |
| { |
| SwTxtNode* pLastNd; |
| SwNodes& rNds; |
| SwUndoTblToTxt* pUndo; |
| sal_Unicode cCh; |
| |
| _DelTabPara( SwNodes& rNodes, sal_Unicode cChar, SwUndoTblToTxt* pU ) : |
| pLastNd(0), rNds( rNodes ), pUndo( pU ), cCh( cChar ) {} |
| _DelTabPara( const _DelTabPara& rPara ) : |
| pLastNd(rPara.pLastNd), rNds( rPara.rNds ), |
| pUndo( rPara.pUndo ), cCh( rPara.cCh ) {} |
| }; |
| |
| // forward deklarieren damit sich die Lines und Boxen rekursiv aufrufen |
| // koennen. |
| sal_Bool lcl_DelBox( const SwTableBox*&, void *pPara ); |
| |
| sal_Bool lcl_DelLine( const SwTableLine*& rpLine, void* pPara ) |
| { |
| ASSERT( pPara, "die Parameter fehlen" ); |
| _DelTabPara aPara( *(_DelTabPara*)pPara ); |
| ((SwTableLine*&)rpLine)->GetTabBoxes().ForEach( &lcl_DelBox, &aPara ); |
| if( rpLine->GetUpper() ) // gibt es noch eine uebergeordnete Box ?? |
| // dann gebe den letzten TextNode zurueck |
| ((_DelTabPara*)pPara)->pLastNd = aPara.pLastNd; |
| return sal_True; |
| } |
| |
| |
| sal_Bool lcl_DelBox( const SwTableBox*& rpBox, void* pPara ) |
| { |
| ASSERT( pPara, "die Parameter fehlen" ); |
| |
| // loesche erstmal die Lines der Box |
| _DelTabPara* pDelPara = (_DelTabPara*)pPara; |
| if( rpBox->GetTabLines().Count() ) |
| ((SwTableBox*&)rpBox)->GetTabLines().ForEach( &lcl_DelLine, pDelPara ); |
| else |
| { |
| SwDoc* pDoc = pDelPara->rNds.GetDoc(); |
| SwNodeRange aDelRg( *rpBox->GetSttNd(), 0, |
| *rpBox->GetSttNd()->EndOfSectionNode() ); |
| // loesche die Section |
| pDelPara->rNds.SectionUp( &aDelRg ); |
| const SwTxtNode* pCurTxtNd; |
| if( T2T_PARA != pDelPara->cCh && pDelPara->pLastNd && |
| 0 != ( pCurTxtNd = aDelRg.aStart.GetNode().GetTxtNode() )) |
| { |
| // Join the current text node with the last from the previous box if possible |
| sal_uLong nNdIdx = aDelRg.aStart.GetIndex(); |
| aDelRg.aStart--; |
| if( pDelPara->pLastNd == &aDelRg.aStart.GetNode() ) |
| { |
| // Inserting the seperator |
| SwIndex aCntIdx( pDelPara->pLastNd, pDelPara->pLastNd->GetTxt().Len()); |
| pDelPara->pLastNd->InsertText( pDelPara->cCh, aCntIdx, |
| IDocumentContentOperations::INS_EMPTYEXPAND ); |
| if( pDelPara->pUndo ) |
| pDelPara->pUndo->AddBoxPos( *pDoc, nNdIdx, aDelRg.aEnd.GetIndex(), |
| aCntIdx.GetIndex() ); |
| |
| SvULongs aBkmkArr( 4, 4 ); |
| xub_StrLen nOldTxtLen = aCntIdx.GetIndex(); |
| _SaveCntntIdx( pDoc, nNdIdx, pCurTxtNd->GetTxt().Len(), |
| aBkmkArr ); |
| |
| pDelPara->pLastNd->JoinNext(); |
| |
| if( aBkmkArr.Count() ) |
| _RestoreCntntIdx( pDoc, aBkmkArr, |
| pDelPara->pLastNd->GetIndex(), |
| nOldTxtLen ); |
| } |
| else if( pDelPara->pUndo ) |
| { |
| aDelRg.aStart++; |
| pDelPara->pUndo->AddBoxPos( *pDoc, nNdIdx, aDelRg.aEnd.GetIndex() ); |
| } |
| } |
| else if( pDelPara->pUndo ) |
| pDelPara->pUndo->AddBoxPos( *pDoc, aDelRg.aStart.GetIndex(), aDelRg.aEnd.GetIndex() ); |
| aDelRg.aEnd--; |
| pDelPara->pLastNd = aDelRg.aEnd.GetNode().GetTxtNode(); |
| |
| //JP 03.04.97: die Ausrichtung der ZahlenFormatierung auf |
| // keinen Fall uebernehmen |
| if( pDelPara->pLastNd && pDelPara->pLastNd->HasSwAttrSet() ) |
| pDelPara->pLastNd->ResetAttr( RES_PARATR_ADJUST ); |
| } |
| return sal_True; |
| } |
| |
| |
| sal_Bool SwNodes::TableToText( const SwNodeRange& rRange, sal_Unicode cCh, |
| SwUndoTblToTxt* pUndo ) |
| { |
| // ist eine Tabelle selektiert ? |
| SwTableNode* pTblNd; |
| if( rRange.aStart.GetIndex() >= rRange.aEnd.GetIndex() || |
| 0 == ( pTblNd = rRange.aStart.GetNode().GetTableNode()) || |
| &rRange.aEnd.GetNode() != pTblNd->EndOfSectionNode() ) |
| return sal_False; |
| |
| // stand die Tabelle ganz alleine in einer Section ? |
| // dann ueber den Upper der Tabelle die Frames anlegen |
| SwNode2Layout* pNode2Layout = 0; |
| SwNodeIndex aFrmIdx( rRange.aStart ); |
| SwNode* pFrmNd = FindPrvNxtFrmNode( aFrmIdx, &rRange.aEnd.GetNode() ); |
| if( !pFrmNd ) |
| // dann sammel mal alle Uppers ein |
| pNode2Layout = new SwNode2Layout( *pTblNd ); |
| |
| // loesche schon mal die Frames |
| pTblNd->DelFrms(); |
| |
| // dann "loeschen" die Tabellen und fasse alle Lines/Boxen zusammen |
| _DelTabPara aDelPara( *this, cCh, pUndo ); |
| pTblNd->pTable->GetTabLines().ForEach( &lcl_DelLine, &aDelPara ); |
| |
| // jetzt ist aus jeder TableLine ein TextNode mit dem entsprechenden |
| // Trenner erzeugt worden. Es braucht nur noch die Table-Section |
| // geloescht und fuer die neuen TextNode die Frames erzeugt werden. |
| SwNodeRange aDelRg( rRange.aStart, rRange.aEnd ); |
| |
| // JP 14.01.97: hat die Tabelle PageDesc-/Break-Attribute? Dann in den |
| // ersten TextNode uebernehmen |
| { |
| // was ist mit UNDO??? |
| const SfxItemSet& rTblSet = pTblNd->pTable->GetFrmFmt()->GetAttrSet(); |
| const SfxPoolItem *pBreak, *pDesc; |
| if( SFX_ITEM_SET != rTblSet.GetItemState( RES_PAGEDESC, sal_False, &pDesc )) |
| pDesc = 0; |
| if( SFX_ITEM_SET != rTblSet.GetItemState( RES_BREAK, sal_False, &pBreak )) |
| pBreak = 0; |
| |
| if( pBreak || pDesc ) |
| { |
| SwNodeIndex aIdx( *pTblNd ); |
| SwCntntNode* pCNd = GoNext( &aIdx ); |
| if( pBreak ) |
| pCNd->SetAttr( *pBreak ); |
| if( pDesc ) |
| pCNd->SetAttr( *pDesc ); |
| } |
| } |
| |
| SectionUp( &aDelRg ); // loesche die Section und damit die Tabelle |
| // #i28006# |
| sal_uLong nStt = aDelRg.aStart.GetIndex(), nEnd = aDelRg.aEnd.GetIndex(); |
| if( !pFrmNd ) |
| { |
| pNode2Layout->RestoreUpperFrms( *this, |
| aDelRg.aStart.GetIndex(), aDelRg.aEnd.GetIndex() ); |
| delete pNode2Layout; |
| } |
| else |
| { |
| SwCntntNode *pCNd; |
| SwSectionNode *pSNd; |
| while( aDelRg.aStart.GetIndex() < nEnd ) |
| { |
| if( 0 != ( pCNd = aDelRg.aStart.GetNode().GetCntntNode())) |
| { |
| if( pFrmNd->IsCntntNode() ) |
| ((SwCntntNode*)pFrmNd)->MakeFrms( *pCNd ); |
| else if( pFrmNd->IsTableNode() ) |
| ((SwTableNode*)pFrmNd)->MakeFrms( aDelRg.aStart ); |
| else if( pFrmNd->IsSectionNode() ) |
| ((SwSectionNode*)pFrmNd)->MakeFrms( aDelRg.aStart ); |
| pFrmNd = pCNd; |
| } |
| else if( 0 != ( pSNd = aDelRg.aStart.GetNode().GetSectionNode())) |
| { |
| if( !pSNd->GetSection().IsHidden() && !pSNd->IsCntntHidden() ) |
| { |
| pSNd->MakeFrms( &aFrmIdx, &aDelRg.aEnd ); |
| pFrmNd = pSNd; |
| break; |
| } |
| aDelRg.aStart = *pSNd->EndOfSectionNode(); |
| } |
| aDelRg.aStart++; |
| } |
| } |
| |
| // #i28006# Fly frames have to be restored even if the table was |
| // #alone in the section |
| const SwSpzFrmFmts& rFlyArr = *GetDoc()->GetSpzFrmFmts(); |
| for( sal_uInt16 n = 0; n < rFlyArr.Count(); ++n ) |
| { |
| SwFrmFmt *const pFmt = (SwFrmFmt*)rFlyArr[n]; |
| const SwFmtAnchor& rAnchor = pFmt->GetAnchor(); |
| SwPosition const*const pAPos = rAnchor.GetCntntAnchor(); |
| if (pAPos && |
| ((FLY_AT_PARA == rAnchor.GetAnchorId()) || |
| (FLY_AT_CHAR == rAnchor.GetAnchorId())) && |
| nStt <= pAPos->nNode.GetIndex() && |
| pAPos->nNode.GetIndex() < nEnd ) |
| { |
| pFmt->MakeFrms(); |
| } |
| } |
| |
| return sal_True; |
| } |
| |
| |
| // ----- einfuegen von Spalten/Zeilen ------------------------ |
| |
| sal_Bool SwDoc::InsertCol( const SwCursor& rCursor, sal_uInt16 nCnt, sal_Bool bBehind ) |
| { |
| if( !::CheckSplitCells( rCursor, nCnt + 1, nsSwTblSearchType::TBLSEARCH_COL ) ) |
| return sal_False; |
| |
| // lasse ueber das Layout die Boxen suchen |
| SwSelBoxes aBoxes; |
| ::GetTblSel( rCursor, aBoxes, nsSwTblSearchType::TBLSEARCH_COL ); |
| |
| sal_Bool bRet = sal_False; |
| if( aBoxes.Count() ) |
| bRet = InsertCol( aBoxes, nCnt, bBehind ); |
| return bRet; |
| } |
| |
| sal_Bool SwDoc::InsertCol( const SwSelBoxes& rBoxes, sal_uInt16 nCnt, sal_Bool bBehind ) |
| { |
| // uebers SwDoc fuer Undo !! |
| ASSERT( rBoxes.Count(), "keine gueltige Box-Liste" ); |
| SwTableNode* pTblNd = (SwTableNode*)rBoxes[0]->GetSttNd()->FindTableNode(); |
| if( !pTblNd ) |
| return sal_False; |
| |
| SwTable& rTbl = pTblNd->GetTable(); |
| if( rTbl.ISA( SwDDETable )) |
| return sal_False; |
| |
| #ifdef DEL_TABLE_REDLINES |
| lcl_DelRedlines aDelRedl( *pTblNd, sal_True ); |
| #endif |
| |
| SwTableSortBoxes aTmpLst( 0, 5 ); |
| SwUndoTblNdsChg* pUndo = 0; |
| if (GetIDocumentUndoRedo().DoesUndo()) |
| { |
| pUndo = new SwUndoTblNdsChg( UNDO_TABLE_INSCOL, rBoxes, *pTblNd, |
| 0, 0, nCnt, bBehind, sal_False ); |
| aTmpLst.Insert( &rTbl.GetTabSortBoxes(), 0, rTbl.GetTabSortBoxes().Count() ); |
| } |
| |
| bool bRet(false); |
| { |
| ::sw::UndoGuard const undoGuard(GetIDocumentUndoRedo()); |
| |
| SwTableFmlUpdate aMsgHnt( &rTbl ); |
| aMsgHnt.eFlags = TBL_BOXPTR; |
| UpdateTblFlds( &aMsgHnt ); |
| |
| bRet = rTbl.InsertCol( this, rBoxes, nCnt, bBehind ); |
| if (bRet) |
| { |
| SetModified(); |
| ::ClearFEShellTabCols(); |
| SetFieldsDirty( true, NULL, 0 ); |
| } |
| } |
| |
| if( pUndo ) |
| { |
| if( bRet ) |
| { |
| pUndo->SaveNewBoxes( *pTblNd, aTmpLst ); |
| GetIDocumentUndoRedo().AppendUndo( pUndo ); |
| } |
| else |
| delete pUndo; |
| } |
| return bRet; |
| } |
| |
| sal_Bool SwDoc::InsertRow( const SwCursor& rCursor, sal_uInt16 nCnt, sal_Bool bBehind ) |
| { |
| // lasse ueber das Layout die Boxen suchen |
| SwSelBoxes aBoxes; |
| GetTblSel( rCursor, aBoxes, nsSwTblSearchType::TBLSEARCH_ROW ); |
| |
| sal_Bool bRet = sal_False; |
| if( aBoxes.Count() ) |
| bRet = InsertRow( aBoxes, nCnt, bBehind ); |
| return bRet; |
| } |
| |
| sal_Bool SwDoc::InsertRow( const SwSelBoxes& rBoxes, sal_uInt16 nCnt, sal_Bool bBehind ) |
| { |
| // uebers SwDoc fuer Undo !! |
| ASSERT( rBoxes.Count(), "keine gueltige Box-Liste" ); |
| SwTableNode* pTblNd = (SwTableNode*)rBoxes[0]->GetSttNd()->FindTableNode(); |
| if( !pTblNd ) |
| return sal_False; |
| |
| SwTable& rTbl = pTblNd->GetTable(); |
| if( rTbl.ISA( SwDDETable )) |
| return sal_False; |
| |
| #ifdef DEL_TABLE_REDLINES |
| lcl_DelRedlines aDelRedl( *pTblNd, sal_True ); |
| #endif |
| |
| SwTableSortBoxes aTmpLst( 0, 5 ); |
| SwUndoTblNdsChg* pUndo = 0; |
| if (GetIDocumentUndoRedo().DoesUndo()) |
| { |
| pUndo = new SwUndoTblNdsChg( UNDO_TABLE_INSROW,rBoxes, *pTblNd, |
| 0, 0, nCnt, bBehind, sal_False ); |
| aTmpLst.Insert( &rTbl.GetTabSortBoxes(), 0, rTbl.GetTabSortBoxes().Count() ); |
| } |
| |
| bool bRet(false); |
| { |
| ::sw::UndoGuard const undoGuard(GetIDocumentUndoRedo()); |
| |
| SwTableFmlUpdate aMsgHnt( &rTbl ); |
| aMsgHnt.eFlags = TBL_BOXPTR; |
| UpdateTblFlds( &aMsgHnt ); |
| |
| bRet = rTbl.InsertRow( this, rBoxes, nCnt, bBehind ); |
| if (bRet) |
| { |
| SetModified(); |
| ::ClearFEShellTabCols(); |
| SetFieldsDirty( true, NULL, 0 ); |
| } |
| } |
| |
| if( pUndo ) |
| { |
| if( bRet ) |
| { |
| pUndo->SaveNewBoxes( *pTblNd, aTmpLst ); |
| GetIDocumentUndoRedo().AppendUndo( pUndo ); |
| } |
| else |
| delete pUndo; |
| } |
| return bRet; |
| |
| } |
| |
| // ----- loeschen von Spalten/Zeilen ------------------------ |
| |
| sal_Bool SwDoc::DeleteRow( const SwCursor& rCursor ) |
| { |
| // lasse ueber das Layout die Boxen suchen |
| SwSelBoxes aBoxes; |
| GetTblSel( rCursor, aBoxes, nsSwTblSearchType::TBLSEARCH_ROW ); |
| if( ::HasProtectedCells( aBoxes )) |
| return sal_False; |
| |
| // die Crsr aus dem Loeschbereich entfernen. |
| // Der Cursor steht danach: |
| // - es folgt noch eine Zeile, in dieser |
| // - vorher steht noch eine Zeile, in dieser |
| // - sonst immer dahinter |
| { |
| SwTableNode* pTblNd = rCursor.GetNode()->FindTableNode(); |
| |
| if( pTblNd->GetTable().ISA( SwDDETable )) |
| return sal_False; |
| |
| // suche alle Boxen / Lines |
| _FndBox aFndBox( 0, 0 ); |
| { |
| _FndPara aPara( aBoxes, &aFndBox ); |
| pTblNd->GetTable().GetTabLines().ForEach( &_FndLineCopyCol, &aPara ); |
| } |
| |
| if( !aFndBox.GetLines().Count() ) |
| return sal_False; |
| |
| SwEditShell* pESh = GetEditShell(); |
| if( pESh ) |
| { |
| pESh->KillPams(); |
| // JP: eigentlich sollte man ueber alle Shells iterieren!! |
| } |
| |
| _FndBox* pFndBox = &aFndBox; |
| while( 1 == pFndBox->GetLines().Count() && |
| 1 == pFndBox->GetLines()[0]->GetBoxes().Count() ) |
| { |
| _FndBox* pTmp = pFndBox->GetLines()[0]->GetBoxes()[0]; |
| if( pTmp->GetBox()->GetSttNd() ) |
| break; // das ist sonst zu weit |
| pFndBox = pTmp; |
| } |
| |
| SwTableLine* pDelLine = pFndBox->GetLines()[ |
| pFndBox->GetLines().Count()-1 ]->GetLine(); |
| SwTableBox* pDelBox = pDelLine->GetTabBoxes()[ |
| pDelLine->GetTabBoxes().Count() - 1 ]; |
| while( !pDelBox->GetSttNd() ) |
| { |
| SwTableLine* pLn = pDelBox->GetTabLines()[ |
| pDelBox->GetTabLines().Count()-1 ]; |
| pDelBox = pLn->GetTabBoxes()[ pLn->GetTabBoxes().Count() - 1 ]; |
| } |
| SwTableBox* pNextBox = pDelLine->FindNextBox( pTblNd->GetTable(), |
| pDelBox, sal_True ); |
| while( pNextBox && |
| pNextBox->GetFrmFmt()->GetProtect().IsCntntProtected() ) |
| pNextBox = pNextBox->FindNextBox( pTblNd->GetTable(), pNextBox ); |
| |
| if( !pNextBox ) // keine nachfolgende? dann die vorhergehende |
| { |
| pDelLine = pFndBox->GetLines()[ 0 ]->GetLine(); |
| pDelBox = pDelLine->GetTabBoxes()[ 0 ]; |
| while( !pDelBox->GetSttNd() ) |
| pDelBox = pDelBox->GetTabLines()[0]->GetTabBoxes()[0]; |
| pNextBox = pDelLine->FindPreviousBox( pTblNd->GetTable(), |
| pDelBox, sal_True ); |
| while( pNextBox && |
| pNextBox->GetFrmFmt()->GetProtect().IsCntntProtected() ) |
| pNextBox = pNextBox->FindPreviousBox( pTblNd->GetTable(), pNextBox ); |
| } |
| |
| sal_uLong nIdx; |
| if( pNextBox ) // dann den Cursor hier hinein |
| nIdx = pNextBox->GetSttIdx() + 1; |
| else // ansonsten hinter die Tabelle |
| nIdx = pTblNd->EndOfSectionIndex() + 1; |
| |
| SwNodeIndex aIdx( GetNodes(), nIdx ); |
| SwCntntNode* pCNd = aIdx.GetNode().GetCntntNode(); |
| if( !pCNd ) |
| pCNd = GetNodes().GoNext( &aIdx ); |
| |
| if( pCNd ) |
| { |
| // die Cursor von der Shell oder den uebergebenen Cursor aendern? |
| SwPaM* pPam = (SwPaM*)&rCursor; |
| pPam->GetPoint()->nNode = aIdx; |
| pPam->GetPoint()->nContent.Assign( pCNd, 0 ); |
| pPam->SetMark(); // beide wollen etwas davon haben |
| pPam->DeleteMark(); |
| } |
| } |
| |
| // dann loesche doch die Zeilen |
| |
| GetIDocumentUndoRedo().StartUndo(UNDO_ROW_DELETE, NULL); |
| sal_Bool bResult = DeleteRowCol( aBoxes ); |
| GetIDocumentUndoRedo().EndUndo(UNDO_ROW_DELETE, NULL); |
| |
| return bResult; |
| } |
| |
| sal_Bool SwDoc::DeleteCol( const SwCursor& rCursor ) |
| { |
| // lasse ueber das Layout die Boxen suchen |
| SwSelBoxes aBoxes; |
| GetTblSel( rCursor, aBoxes, nsSwTblSearchType::TBLSEARCH_COL ); |
| if( ::HasProtectedCells( aBoxes )) |
| return sal_False; |
| |
| // die Crsr muessen noch aus dem Loesch Bereich entfernt |
| // werden. Setze sie immer hinter/auf die Tabelle; ueber die |
| // Dokument-Position werden sie dann immer an die alte Position gesetzt. |
| SwEditShell* pESh = GetEditShell(); |
| if( pESh ) |
| { |
| const SwNode* pNd = rCursor.GetNode()->FindTableBoxStartNode(); |
| pESh->ParkCrsr( SwNodeIndex( *pNd ) ); |
| } |
| |
| // dann loesche doch die Spalten |
| GetIDocumentUndoRedo().StartUndo(UNDO_COL_DELETE, NULL); |
| sal_Bool bResult = DeleteRowCol( aBoxes, true ); |
| GetIDocumentUndoRedo().EndUndo(UNDO_COL_DELETE, NULL); |
| |
| return bResult; |
| } |
| |
| sal_Bool SwDoc::DeleteRowCol( const SwSelBoxes& rBoxes, bool bColumn ) |
| { |
| if( ::HasProtectedCells( rBoxes )) |
| return sal_False; |
| |
| // uebers SwDoc fuer Undo !! |
| ASSERT( rBoxes.Count(), "keine gueltige Box-Liste" ); |
| SwTableNode* pTblNd = (SwTableNode*)rBoxes[0]->GetSttNd()->FindTableNode(); |
| if( !pTblNd ) |
| return sal_False; |
| |
| if( pTblNd->GetTable().ISA( SwDDETable )) |
| return sal_False; |
| |
| ::ClearFEShellTabCols(); |
| SwSelBoxes aSelBoxes; |
| aSelBoxes.Insert(rBoxes.GetData(), rBoxes.Count()); |
| SwTable &rTable = pTblNd->GetTable(); |
| long nMin = 0; |
| long nMax = 0; |
| if( rTable.IsNewModel() ) |
| { |
| if( bColumn ) |
| rTable.ExpandColumnSelection( aSelBoxes, nMin, nMax ); |
| else |
| rTable.FindSuperfluousRows( aSelBoxes ); |
| } |
| |
| #ifdef DEL_TABLE_REDLINES |
| lcl_DelRedlines aDelRedl( *pTblNd, sal_True ); |
| #endif |
| |
| // soll die gesamte Tabelle geloescht werden ?? |
| const sal_uLong nTmpIdx1 = pTblNd->GetIndex(); |
| const sal_uLong nTmpIdx2 = aSelBoxes[ aSelBoxes.Count()-1 ]->GetSttNd()-> |
| EndOfSectionIndex()+1; |
| if( pTblNd->GetTable().GetTabSortBoxes().Count() == aSelBoxes.Count() && |
| aSelBoxes[0]->GetSttIdx()-1 == nTmpIdx1 && |
| nTmpIdx2 == pTblNd->EndOfSectionIndex() ) |
| { |
| sal_Bool bNewTxtNd = sal_False; |
| // steht diese auch noch alleine in einem FlyFrame ? |
| SwNodeIndex aIdx( *pTblNd, -1 ); |
| const SwStartNode* pSttNd = aIdx.GetNode().GetStartNode(); |
| if( pSttNd ) |
| { |
| const sal_uLong nTblEnd = pTblNd->EndOfSectionIndex() + 1; |
| const sal_uLong nSectEnd = pSttNd->EndOfSectionIndex(); |
| if( nTblEnd == nSectEnd ) |
| { |
| if( SwFlyStartNode == pSttNd->GetStartNodeType() ) |
| { |
| SwFrmFmt* pFmt = pSttNd->GetFlyFmt(); |
| if( pFmt ) |
| { |
| // Ok, das ist das gesuchte FlyFormat |
| DelLayoutFmt( pFmt ); |
| return sal_True; |
| } |
| } |
| // kein Fly ?? also Kopf- oder Fusszeile: dann immer einen |
| // TextNode ueberig lassen. |
| // Undo koennen wir dann vergessen !! |
| bNewTxtNd = sal_True; |
| } |
| } |
| |
| // kein Fly ?? also Kopf- oder Fusszeile: dann immer einen |
| // TextNode ueberig lassen. |
| aIdx++; |
| if (GetIDocumentUndoRedo().DoesUndo()) |
| { |
| GetIDocumentUndoRedo().ClearRedo(); |
| SwPaM aPaM( *pTblNd->EndOfSectionNode(), aIdx.GetNode() ); |
| |
| if( bNewTxtNd ) |
| { |
| const SwNodeIndex aTmpIdx( *pTblNd->EndOfSectionNode(), 1 ); |
| GetNodes().MakeTxtNode( aTmpIdx, |
| GetTxtCollFromPool( RES_POOLCOLL_STANDARD ) ); |
| } |
| |
| // save the cursors (UNO and otherwise) |
| SwPaM aSavePaM( SwNodeIndex( *pTblNd->EndOfSectionNode() ) ); |
| if( ! aSavePaM.Move( fnMoveForward, fnGoNode ) ) |
| { |
| *aSavePaM.GetMark() = SwPosition( *pTblNd ); |
| aSavePaM.Move( fnMoveBackward, fnGoNode ); |
| } |
| { |
| SwPaM const tmpPaM(*pTblNd, *pTblNd->EndOfSectionNode()); |
| ::PaMCorrAbs(tmpPaM, *aSavePaM.GetMark()); |
| } |
| |
| // harte SeitenUmbrueche am nachfolgenden Node verschieben |
| sal_Bool bSavePageBreak = sal_False, bSavePageDesc = sal_False; |
| sal_uLong nNextNd = pTblNd->EndOfSectionIndex()+1; |
| SwCntntNode* pNextNd = GetNodes()[ nNextNd ]->GetCntntNode(); |
| if( pNextNd ) |
| { |
| //JP 24.08.98: will man wirklich den PageDesc/Break vom |
| // nachfolgen Absatz ueberbuegeln? |
| // const SwAttrSet& rAttrSet = pNextNd->GetSwAttrSet(); |
| // if( SFX_ITEM_SET != rAttrSet.GetItemState( RES_PAGEDESC ) && |
| // SFX_ITEM_SET != rAttrSet.GetItemState( RES_BREAK )) |
| { |
| SwFrmFmt* pTableFmt = pTblNd->GetTable().GetFrmFmt(); |
| const SfxPoolItem *pItem; |
| if( SFX_ITEM_SET == pTableFmt->GetItemState( RES_PAGEDESC, |
| sal_False, &pItem ) ) |
| { |
| pNextNd->SetAttr( *pItem ); |
| bSavePageDesc = sal_True; |
| } |
| |
| if( SFX_ITEM_SET == pTableFmt->GetItemState( RES_BREAK, |
| sal_False, &pItem ) ) |
| { |
| pNextNd->SetAttr( *pItem ); |
| bSavePageBreak = sal_True; |
| } |
| } |
| } |
| SwUndoDelete* pUndo = new SwUndoDelete( aPaM ); |
| if( bNewTxtNd ) |
| pUndo->SetTblDelLastNd(); |
| pUndo->SetPgBrkFlags( bSavePageBreak, bSavePageDesc ); |
| pUndo->SetTableName(pTblNd->GetTable().GetFrmFmt()->GetName()); |
| GetIDocumentUndoRedo().AppendUndo( pUndo ); |
| } |
| else |
| { |
| if( bNewTxtNd ) |
| { |
| const SwNodeIndex aTmpIdx( *pTblNd->EndOfSectionNode(), 1 ); |
| GetNodes().MakeTxtNode( aTmpIdx, |
| GetTxtCollFromPool( RES_POOLCOLL_STANDARD ) ); |
| } |
| |
| // save the cursors (UNO and otherwise) |
| SwPaM aSavePaM( SwNodeIndex( *pTblNd->EndOfSectionNode() ) ); |
| if( ! aSavePaM.Move( fnMoveForward, fnGoNode ) ) |
| { |
| *aSavePaM.GetMark() = SwPosition( *pTblNd ); |
| aSavePaM.Move( fnMoveBackward, fnGoNode ); |
| } |
| { |
| SwPaM const tmpPaM(*pTblNd, *pTblNd->EndOfSectionNode()); |
| ::PaMCorrAbs(tmpPaM, *aSavePaM.GetMark()); |
| } |
| |
| // harte SeitenUmbrueche am nachfolgenden Node verschieben |
| SwCntntNode* pNextNd = GetNodes()[ pTblNd->EndOfSectionIndex()+1 ]->GetCntntNode(); |
| if( pNextNd ) |
| { |
| SwFrmFmt* pTableFmt = pTblNd->GetTable().GetFrmFmt(); |
| const SfxPoolItem *pItem; |
| if( SFX_ITEM_SET == pTableFmt->GetItemState( RES_PAGEDESC, |
| sal_False, &pItem ) ) |
| pNextNd->SetAttr( *pItem ); |
| |
| if( SFX_ITEM_SET == pTableFmt->GetItemState( RES_BREAK, |
| sal_False, &pItem ) ) |
| pNextNd->SetAttr( *pItem ); |
| } |
| |
| pTblNd->DelFrms(); |
| DeleteSection( pTblNd ); |
| } |
| SetModified(); |
| SetFieldsDirty( true, NULL, 0 ); |
| return sal_True; |
| } |
| |
| SwUndoTblNdsChg* pUndo = 0; |
| if (GetIDocumentUndoRedo().DoesUndo()) |
| { |
| pUndo = new SwUndoTblNdsChg( UNDO_TABLE_DELBOX, aSelBoxes, *pTblNd, |
| nMin, nMax, 0, sal_False, sal_False ); |
| } |
| |
| bool bRet(false); |
| { |
| ::sw::UndoGuard const undoGuard(GetIDocumentUndoRedo()); |
| |
| SwTableFmlUpdate aMsgHnt( &pTblNd->GetTable() ); |
| aMsgHnt.eFlags = TBL_BOXPTR; |
| UpdateTblFlds( &aMsgHnt ); |
| |
| if (rTable.IsNewModel()) |
| { |
| if (bColumn) |
| rTable.PrepareDeleteCol( nMin, nMax ); |
| rTable.FindSuperfluousRows( aSelBoxes ); |
| if (pUndo) |
| pUndo->ReNewBoxes( aSelBoxes ); |
| } |
| bRet = rTable.DeleteSel( this, aSelBoxes, 0, pUndo, sal_True, sal_True ); |
| if (bRet) |
| { |
| SetModified(); |
| SetFieldsDirty( true, NULL, 0 ); |
| } |
| } |
| |
| if( pUndo ) |
| { |
| if( bRet ) |
| { |
| GetIDocumentUndoRedo().AppendUndo( pUndo ); |
| } |
| else |
| delete pUndo; |
| } |
| |
| return bRet; |
| } |
| |
| |
| // ---------- teilen / zusammenfassen von Boxen in der Tabelle -------- |
| |
| sal_Bool SwDoc::SplitTbl( const SwSelBoxes& rBoxes, sal_Bool bVert, sal_uInt16 nCnt, |
| sal_Bool bSameHeight ) |
| { |
| // uebers SwDoc fuer Undo !! |
| ASSERT( rBoxes.Count() && nCnt, "keine gueltige Box-Liste" ); |
| SwTableNode* pTblNd = (SwTableNode*)rBoxes[0]->GetSttNd()->FindTableNode(); |
| if( !pTblNd ) |
| return sal_False; |
| |
| SwTable& rTbl = pTblNd->GetTable(); |
| if( rTbl.ISA( SwDDETable )) |
| return sal_False; |
| |
| #ifdef DEL_TABLE_REDLINES |
| lcl_DelRedlines aDelRedl( *pTblNd, sal_True ); |
| #endif |
| |
| SvULongs aNdsCnts; |
| SwTableSortBoxes aTmpLst( 0, 5 ); |
| SwUndoTblNdsChg* pUndo = 0; |
| if (GetIDocumentUndoRedo().DoesUndo()) |
| { |
| pUndo = new SwUndoTblNdsChg( UNDO_TABLE_SPLIT, rBoxes, *pTblNd, 0, 0, |
| nCnt, bVert, bSameHeight ); |
| |
| aTmpLst.Insert( &rTbl.GetTabSortBoxes(), 0, rTbl.GetTabSortBoxes().Count() ); |
| if( !bVert ) |
| { |
| for( sal_uInt16 n = 0; n < rBoxes.Count(); ++n ) |
| { |
| const SwStartNode* pSttNd = rBoxes[ n ]->GetSttNd(); |
| aNdsCnts.Insert( pSttNd->EndOfSectionIndex() - |
| pSttNd->GetIndex(), n ); |
| } |
| } |
| } |
| |
| bool bRet(false); |
| { |
| ::sw::UndoGuard const undoGuard(GetIDocumentUndoRedo()); |
| |
| SwTableFmlUpdate aMsgHnt( &rTbl ); |
| aMsgHnt.eFlags = TBL_BOXPTR; |
| UpdateTblFlds( &aMsgHnt ); |
| |
| if (bVert) |
| bRet = rTbl.SplitCol( this, rBoxes, nCnt ); |
| else |
| bRet = rTbl.SplitRow( this, rBoxes, nCnt, bSameHeight ); |
| |
| if (bRet) |
| { |
| SetModified(); |
| SetFieldsDirty( true, NULL, 0 ); |
| } |
| } |
| |
| if( pUndo ) |
| { |
| if( bRet ) |
| { |
| if( bVert ) |
| pUndo->SaveNewBoxes( *pTblNd, aTmpLst ); |
| else |
| pUndo->SaveNewBoxes( *pTblNd, aTmpLst, rBoxes, aNdsCnts ); |
| GetIDocumentUndoRedo().AppendUndo( pUndo ); |
| } |
| else |
| delete pUndo; |
| } |
| |
| return bRet; |
| } |
| |
| |
| sal_uInt16 SwDoc::MergeTbl( SwPaM& rPam ) |
| { |
| // pruefe ob vom aktuellen Crsr der SPoint/Mark in einer Tabelle stehen |
| SwTableNode* pTblNd = rPam.GetNode()->FindTableNode(); |
| if( !pTblNd ) |
| return TBLMERGE_NOSELECTION; |
| SwTable& rTable = pTblNd->GetTable(); |
| if( rTable.ISA(SwDDETable) ) |
| return TBLMERGE_NOSELECTION; |
| sal_uInt16 nRet = TBLMERGE_NOSELECTION; |
| if( !rTable.IsNewModel() ) |
| { |
| nRet =::CheckMergeSel( rPam ); |
| if( TBLMERGE_OK != nRet ) |
| return nRet; |
| nRet = TBLMERGE_NOSELECTION; |
| } |
| |
| // --> FME 2004-10-08 #i33394# |
| GetIDocumentUndoRedo().StartUndo( UNDO_TABLE_MERGE, NULL ); |
| // <-- |
| |
| #ifdef DEL_TABLE_REDLINES |
| if( !IsIgnoreRedline() && GetRedlineTbl().Count() ) |
| DeleteRedline( *pTblNd, true, USHRT_MAX ); |
| #endif |
| RedlineMode_t eOld = GetRedlineMode(); |
| SetRedlineMode_intern((RedlineMode_t)(eOld | nsRedlineMode_t::REDLINE_IGNORE)); |
| |
| SwUndoTblMerge *const pUndo( (GetIDocumentUndoRedo().DoesUndo()) |
| ? new SwUndoTblMerge( rPam ) |
| : 0 ); |
| |
| // lasse ueber das Layout die Boxen suchen |
| SwSelBoxes aBoxes; |
| SwSelBoxes aMerged; |
| SwTableBox* pMergeBox; |
| |
| if( !rTable.PrepareMerge( rPam, aBoxes, aMerged, &pMergeBox, pUndo ) ) |
| { // no cells found to merge |
| SetRedlineMode_intern( eOld ); |
| if( pUndo ) |
| { |
| delete pUndo; |
| SwUndoId nLastUndoId(UNDO_EMPTY); |
| if (GetIDocumentUndoRedo().GetLastUndoInfo(0, & nLastUndoId) |
| && (UNDO_REDLINE == nLastUndoId)) |
| { |
| // FIXME: why is this horrible cleanup necessary? |
| SwUndoRedline *const pU = dynamic_cast<SwUndoRedline*>( |
| GetUndoManager().RemoveLastUndo()); |
| if( pU->GetRedlSaveCount() ) |
| { |
| SwEditShell *const pEditShell(GetEditShell(0)); |
| OSL_ASSERT(pEditShell); |
| ::sw::UndoRedoContext context(*this, *pEditShell); |
| static_cast<SfxUndoAction *>(pU)->UndoWithContext(context); |
| } |
| delete pU; |
| } |
| } |
| } |
| else |
| { |
| // die PaMs muessen noch aus dem Loesch Bereich entfernt |
| // werden. Setze sie immer hinter/auf die Tabelle; ueber die |
| // Dokument-Position werden sie dann immer an die alte Position gesetzt. |
| // Erstmal einen Index auf die Parkposition merken, denn nach GetMergeSel |
| // komme ich nicht mehr dran. |
| { |
| rPam.DeleteMark(); |
| rPam.GetPoint()->nNode = *pMergeBox->GetSttNd(); |
| rPam.GetPoint()->nContent.Assign( 0, 0 ); |
| rPam.SetMark(); |
| rPam.DeleteMark(); |
| |
| SwPaM* pTmp = &rPam; |
| while( &rPam != ( pTmp = (SwPaM*)pTmp->GetNext() )) |
| for( int i = 0; i < 2; ++i ) |
| pTmp->GetBound( (sal_Bool)i ) = *rPam.GetPoint(); |
| } |
| |
| // dann fuege sie zusammen |
| SwTableFmlUpdate aMsgHnt( &pTblNd->GetTable() ); |
| aMsgHnt.eFlags = TBL_BOXPTR; |
| UpdateTblFlds( &aMsgHnt ); |
| |
| if( pTblNd->GetTable().Merge( this, aBoxes, aMerged, pMergeBox, pUndo )) |
| { |
| nRet = TBLMERGE_OK; |
| SetModified(); |
| SetFieldsDirty( true, NULL, 0 ); |
| if( pUndo ) |
| { |
| GetIDocumentUndoRedo().AppendUndo( pUndo ); |
| } |
| } |
| else if( pUndo ) |
| delete pUndo; |
| |
| rPam.GetPoint()->nNode = *pMergeBox->GetSttNd(); |
| rPam.Move(); |
| |
| ::ClearFEShellTabCols(); |
| SetRedlineMode_intern( eOld ); |
| } |
| GetIDocumentUndoRedo().EndUndo( UNDO_TABLE_MERGE, NULL ); |
| return nRet; |
| } |
| |
| |
| |
| // ------------------------------------------------------- |
| |
| //--------- |
| // SwTableNode |
| //--------- |
| |
| SwTableNode::SwTableNode( const SwNodeIndex& rIdx ) |
| : SwStartNode( rIdx, ND_TABLENODE ) |
| { |
| pTable = new SwTable( 0 ); |
| } |
| |
| SwTableNode::~SwTableNode() |
| { |
| //don't forget to notify uno wrappers |
| SwFrmFmt* pTblFmt = GetTable().GetFrmFmt(); |
| SwPtrMsgPoolItem aMsgHint( RES_REMOVE_UNO_OBJECT, |
| pTblFmt ); |
| pTblFmt->ModifyNotification( &aMsgHint, &aMsgHint ); |
| DelFrms(); |
| delete pTable; |
| } |
| |
| SwTabFrm *SwTableNode::MakeFrm( SwFrm* pSib ) |
| { |
| return new SwTabFrm( *pTable, pSib ); |
| } |
| |
| //Methode erzeugt fuer den vorhergehenden Node alle Ansichten vom |
| //Dokument. Die erzeugten Contentframes werden in das entsprechende |
| //Layout gehaengt. |
| void SwTableNode::MakeFrms(const SwNodeIndex & rIdx ) |
| { |
| if( !GetTable().GetFrmFmt()->GetDepends())//gibt es ueberhaupt Frames ?? |
| return; |
| |
| SwFrm *pFrm, *pNew; |
| SwCntntNode * pNode = rIdx.GetNode().GetCntntNode(); |
| |
| ASSERT( pNode, "Kein Contentnode oder Copy-Node und neuer Node identisch."); |
| |
| sal_Bool bBefore = rIdx < GetIndex(); |
| |
| SwNode2Layout aNode2Layout( *this, rIdx.GetIndex() ); |
| |
| while( 0 != (pFrm = aNode2Layout.NextFrm()) ) |
| { |
| pNew = pNode->MakeFrm( pFrm ); |
| // wird ein Node vorher oder nachher mit Frames versehen |
| if ( bBefore ) |
| // der neue liegt vor mir |
| pNew->Paste( pFrm->GetUpper(), pFrm ); |
| else |
| // der neue liegt hinter mir |
| pNew->Paste( pFrm->GetUpper(), pFrm->GetNext() ); |
| } |
| } |
| |
| //Fuer jede Shell einen TblFrm anlegen und vor den entsprechenden |
| //CntntFrm pasten. |
| |
| void SwTableNode::MakeFrms( SwNodeIndex* pIdxBehind ) |
| { |
| ASSERT( pIdxBehind, "kein Index" ); |
| *pIdxBehind = *this; |
| SwNode *pNd = GetNodes().FindPrvNxtFrmNode( *pIdxBehind, EndOfSectionNode() ); |
| if( !pNd ) |
| return ; |
| |
| SwFrm *pFrm( 0L ); |
| SwLayoutFrm *pUpper( 0L ); |
| SwNode2Layout aNode2Layout( *pNd, GetIndex() ); |
| while( 0 != (pUpper = aNode2Layout.UpperFrm( pFrm, *this )) ) |
| { |
| SwTabFrm* pNew = MakeFrm( pUpper ); |
| pNew->Paste( pUpper, pFrm ); |
| // --> OD 2005-12-01 #i27138# |
| // notify accessibility paragraphs objects about changed |
| // CONTENT_FLOWS_FROM/_TO relation. |
| // Relation CONTENT_FLOWS_FROM for next paragraph will change |
| // and relation CONTENT_FLOWS_TO for previous paragraph will change. |
| { |
| ViewShell* pViewShell( pNew->getRootFrm()->GetCurrShell() ); |
| if ( pViewShell && pViewShell->GetLayout() && |
| pViewShell->GetLayout()->IsAnyShellAccessible() ) |
| { |
| pViewShell->InvalidateAccessibleParaFlowRelation( |
| dynamic_cast<SwTxtFrm*>(pNew->FindNextCnt( true )), |
| dynamic_cast<SwTxtFrm*>(pNew->FindPrevCnt( true )) ); |
| } |
| } |
| // <-- |
| ((SwTabFrm*)pNew)->RegistFlys(); |
| } |
| } |
| |
| void SwTableNode::DelFrms() |
| { |
| //Erstmal die TabFrms ausschneiden und deleten, die Columns und Rows |
| //nehmen sie mit in's Grab. |
| //Die TabFrms haengen am FrmFmt des SwTable. |
| //Sie muessen etwas umstaendlich zerstort werden, damit die Master |
| //die Follows mit in's Grab nehmen. |
| |
| SwIterator<SwTabFrm,SwFmt> aIter( *(pTable->GetFrmFmt()) ); |
| SwTabFrm *pFrm = aIter.First(); |
| while ( pFrm ) |
| { |
| sal_Bool bAgain = sal_False; |
| { |
| if ( !pFrm->IsFollow() ) |
| { |
| while ( pFrm->HasFollow() ) |
| pFrm->JoinAndDelFollows(); |
| // --> OD 2005-12-01 #i27138# |
| // notify accessibility paragraphs objects about changed |
| // CONTENT_FLOWS_FROM/_TO relation. |
| // Relation CONTENT_FLOWS_FROM for current next paragraph will change |
| // and relation CONTENT_FLOWS_TO for current previous paragraph will change. |
| { |
| ViewShell* pViewShell( pFrm->getRootFrm()->GetCurrShell() ); |
| if ( pViewShell && pViewShell->GetLayout() && |
| pViewShell->GetLayout()->IsAnyShellAccessible() ) |
| { |
| pViewShell->InvalidateAccessibleParaFlowRelation( |
| dynamic_cast<SwTxtFrm*>(pFrm->FindNextCnt( true )), |
| dynamic_cast<SwTxtFrm*>(pFrm->FindPrevCnt( true )) ); |
| } |
| } |
| // <-- |
| pFrm->Cut(); |
| delete pFrm; |
| bAgain = sal_True; |
| } |
| } |
| pFrm = bAgain ? aIter.First() : aIter.Next(); |
| } |
| } |
| |
| |
| void SwTableNode::SetNewTable( SwTable* pNewTable, sal_Bool bNewFrames ) |
| { |
| DelFrms(); |
| delete pTable; |
| pTable = pNewTable; |
| if( bNewFrames ) |
| { |
| SwNodeIndex aIdx( *EndOfSectionNode()); |
| GetNodes().GoNext( &aIdx ); |
| MakeFrms( &aIdx ); |
| } |
| } |
| |
| void SwDoc::GetTabCols( SwTabCols &rFill, const SwCursor* pCrsr, |
| const SwCellFrm* pBoxFrm ) const |
| { |
| const SwTableBox* pBox = 0; |
| SwTabFrm *pTab = 0; |
| |
| if( pBoxFrm ) |
| { |
| pTab = ((SwFrm*)pBoxFrm)->ImplFindTabFrm(); |
| pBox = pBoxFrm->GetTabBox(); |
| } |
| else if( pCrsr ) |
| { |
| const SwCntntNode* pCNd = pCrsr->GetCntntNode(); |
| if( !pCNd ) |
| return ; |
| |
| Point aPt; |
| const SwShellCrsr *pShCrsr = dynamic_cast<const SwShellCrsr*>(pCrsr); |
| if( pShCrsr ) |
| aPt = pShCrsr->GetPtPos(); |
| |
| const SwFrm* pTmpFrm = pCNd->getLayoutFrm( pCNd->GetDoc()->GetCurrentLayout(), &aPt, 0, sal_False ); |
| do { |
| pTmpFrm = pTmpFrm->GetUpper(); |
| } while ( !pTmpFrm->IsCellFrm() ); |
| |
| pBoxFrm = (SwCellFrm*)pTmpFrm; |
| pTab = ((SwFrm*)pBoxFrm)->ImplFindTabFrm(); |
| pBox = pBoxFrm->GetTabBox(); |
| } |
| else if( !pCrsr && !pBoxFrm ) |
| { |
| ASSERT( !this, "einer von beiden muss angegeben werden!" ); |
| return ; |
| } |
| |
| //Fix-Punkte setzen, LeftMin in Dokumentkoordinaten die anderen relativ. |
| SWRECTFN( pTab ) |
| const SwPageFrm* pPage = pTab->FindPageFrm(); |
| const sal_uLong nLeftMin = (pTab->Frm().*fnRect->fnGetLeft)() - |
| (pPage->Frm().*fnRect->fnGetLeft)(); |
| const sal_uLong nRightMax = (pTab->Frm().*fnRect->fnGetRight)() - |
| (pPage->Frm().*fnRect->fnGetLeft)(); |
| |
| rFill.SetLeftMin ( nLeftMin ); |
| rFill.SetLeft ( (pTab->Prt().*fnRect->fnGetLeft)() ); |
| rFill.SetRight ( (pTab->Prt().*fnRect->fnGetRight)()); |
| rFill.SetRightMax( nRightMax - nLeftMin ); |
| |
| pTab->GetTable()->GetTabCols( rFill, pBox ); |
| } |
| |
| // |
| // Here are some little helpers used in SwDoc::GetTabRows |
| // |
| |
| #define ROWFUZZY 25 |
| |
| struct FuzzyCompare |
| { |
| bool operator() ( long s1, long s2 ) const; |
| }; |
| |
| bool FuzzyCompare::operator() ( long s1, long s2 ) const |
| { |
| return ( s1 < s2 && abs( s1 - s2 ) > ROWFUZZY ); |
| } |
| |
| bool lcl_IsFrmInColumn( const SwCellFrm& rFrm, SwSelBoxes& rBoxes ) |
| { |
| for( sal_uInt16 i = 0; i < rBoxes.Count(); ++i ) |
| { |
| if ( rFrm.GetTabBox() == rBoxes[ i ] ) |
| return true; |
| } |
| |
| return false; |
| } |
| |
| // |
| // SwDoc::GetTabRows() |
| // |
| |
| void SwDoc::GetTabRows( SwTabCols &rFill, const SwCursor* , |
| const SwCellFrm* pBoxFrm ) const |
| { |
| ASSERT( pBoxFrm, "GetTabRows called without pBoxFrm" ) |
| |
| // --> FME 2005-09-12 #121591# Make code robust: |
| if ( !pBoxFrm ) |
| return; |
| // <-- |
| |
| // --> FME 2005-01-06 #i39552# Collection of the boxes of the current |
| // column has to be done at the beginning of this function, because |
| // the table may be formatted in ::GetTblSel. |
| SwDeletionChecker aDelCheck( pBoxFrm ); |
| |
| SwSelBoxes aBoxes; |
| const SwCntntFrm* pCntnt = ::GetCellCntnt( *pBoxFrm ); |
| if ( pCntnt && pCntnt->IsTxtFrm() ) |
| { |
| const SwPosition aPos( *((SwTxtFrm*)pCntnt)->GetTxtNode() ); |
| const SwCursor aTmpCrsr( aPos, 0, false ); |
| ::GetTblSel( aTmpCrsr, aBoxes, nsSwTblSearchType::TBLSEARCH_COL ); |
| } |
| // <-- |
| |
| // --> FME 2005-09-12 #121591# Make code robust: |
| if ( aDelCheck.HasBeenDeleted() ) |
| { |
| ASSERT( false, "Current box has been deleted during GetTabRows()" ) |
| return; |
| } |
| // <-- |
| |
| // --> FME 2005-09-12 #121591# Make code robust: |
| const SwTabFrm* pTab = pBoxFrm->FindTabFrm(); |
| ASSERT( pTab, "GetTabRows called without a table" ) |
| if ( !pTab ) |
| return; |
| // <-- |
| |
| const SwFrm* pFrm = pTab->GetNextLayoutLeaf(); |
| |
| //Fix-Punkte setzen, LeftMin in Dokumentkoordinaten die anderen relativ. |
| SWRECTFN( pTab ) |
| const SwPageFrm* pPage = pTab->FindPageFrm(); |
| const long nLeftMin = ( bVert ? |
| pTab->GetPrtLeft() - pPage->Frm().Left() : |
| pTab->GetPrtTop() - pPage->Frm().Top() ); |
| const long nLeft = bVert ? LONG_MAX : 0; |
| const long nRight = (pTab->Prt().*fnRect->fnGetHeight)(); |
| const long nRightMax = bVert ? nRight : LONG_MAX; |
| |
| rFill.SetLeftMin( nLeftMin ); |
| rFill.SetLeft( nLeft ); |
| rFill.SetRight( nRight ); |
| rFill.SetRightMax( nRightMax ); |
| |
| typedef std::map< long, std::pair< long, long >, FuzzyCompare > BoundaryMap; |
| BoundaryMap aBoundaries; |
| BoundaryMap::iterator aIter; |
| std::pair< long, long > aPair; |
| |
| typedef std::map< long, bool > HiddenMap; |
| HiddenMap aHidden; |
| HiddenMap::iterator aHiddenIter; |
| |
| while ( pFrm && pTab->IsAnLower( pFrm ) ) |
| { |
| if ( pFrm->IsCellFrm() && pFrm->FindTabFrm() == pTab ) |
| { |
| // upper and lower borders of current cell frame: |
| long nUpperBorder = (pFrm->Frm().*fnRect->fnGetTop)(); |
| long nLowerBorder = (pFrm->Frm().*fnRect->fnGetBottom)(); |
| |
| // get boundaries for nUpperBorder: |
| aIter = aBoundaries.find( nUpperBorder ); |
| if ( aIter == aBoundaries.end() ) |
| { |
| aPair.first = nUpperBorder; aPair.second = LONG_MAX; |
| aBoundaries[ nUpperBorder ] = aPair; |
| } |
| |
| // get boundaries for nLowerBorder: |
| aIter = aBoundaries.find( nLowerBorder ); |
| if ( aIter == aBoundaries.end() ) |
| { |
| aPair.first = nUpperBorder; aPair.second = LONG_MAX; |
| } |
| else |
| { |
| nLowerBorder = (*aIter).first; |
| long nNewLowerBorderUpperBoundary = Max( (*aIter).second.first, nUpperBorder ); |
| aPair.first = nNewLowerBorderUpperBoundary; aPair.second = LONG_MAX; |
| } |
| aBoundaries[ nLowerBorder ] = aPair; |
| |
| // calculate hidden flags for entry nUpperBorder/nLowerBorder: |
| long nTmpVal = nUpperBorder; |
| for ( sal_uInt8 i = 0; i < 2; ++i ) |
| { |
| aHiddenIter = aHidden.find( nTmpVal ); |
| if ( aHiddenIter == aHidden.end() ) |
| aHidden[ nTmpVal ] = !lcl_IsFrmInColumn( *((SwCellFrm*)pFrm), aBoxes ); |
| else |
| { |
| if ( aHidden[ nTmpVal ] && |
| lcl_IsFrmInColumn( *((SwCellFrm*)pFrm), aBoxes ) ) |
| aHidden[ nTmpVal ] = false; |
| } |
| nTmpVal = nLowerBorder; |
| } |
| } |
| |
| pFrm = pFrm->GetNextLayoutLeaf(); |
| } |
| |
| // transfer calculated values from BoundaryMap and HiddenMap into rFill: |
| sal_uInt16 nIdx = 0; |
| for ( aIter = aBoundaries.begin(); aIter != aBoundaries.end(); ++aIter ) |
| { |
| const long nTabTop = (pTab->*fnRect->fnGetPrtTop)(); |
| const long nKey = (*fnRect->fnYDiff)( (*aIter).first, nTabTop ); |
| const std::pair< long, long > aTmpPair = (*aIter).second; |
| const long nFirst = (*fnRect->fnYDiff)( aTmpPair.first, nTabTop ); |
| const long nSecond = aTmpPair.second; |
| |
| aHiddenIter = aHidden.find( (*aIter).first ); |
| const bool bHidden = aHiddenIter != aHidden.end() && (*aHiddenIter).second; |
| rFill.Insert( nKey, nFirst, nSecond, bHidden, nIdx++ ); |
| } |
| |
| // delete first and last entry |
| ASSERT( rFill.Count(), "Deleting from empty vector. Fasten your seatbelts!" ) |
| // --> FME 2006-01-19 #i60818# There may be only one entry in rFill. Make |
| // code robust by checking count of rFill. |
| if ( rFill.Count() ) rFill.Remove( 0, 1 ); |
| if ( rFill.Count() ) rFill.Remove( rFill.Count() - 1 , 1 ); |
| // <-- |
| rFill.SetLastRowAllowedToChange( !pTab->HasFollowFlowLine() ); |
| } |
| |
| void SwDoc::SetTabCols( const SwTabCols &rNew, sal_Bool bCurRowOnly, |
| const SwCursor* pCrsr, const SwCellFrm* pBoxFrm ) |
| { |
| const SwTableBox* pBox = 0; |
| SwTabFrm *pTab = 0; |
| |
| if( pBoxFrm ) |
| { |
| pTab = ((SwFrm*)pBoxFrm)->ImplFindTabFrm(); |
| pBox = pBoxFrm->GetTabBox(); |
| } |
| else if( pCrsr ) |
| { |
| const SwCntntNode* pCNd = pCrsr->GetCntntNode(); |
| if( !pCNd ) |
| return ; |
| |
| Point aPt; |
| const SwShellCrsr *pShCrsr = dynamic_cast<const SwShellCrsr*>(pCrsr); |
| if( pShCrsr ) |
| aPt = pShCrsr->GetPtPos(); |
| |
| const SwFrm* pTmpFrm = pCNd->getLayoutFrm( pCNd->GetDoc()->GetCurrentLayout(), &aPt, 0, sal_False ); |
| do { |
| pTmpFrm = pTmpFrm->GetUpper(); |
| } while ( !pTmpFrm->IsCellFrm() ); |
| |
| pBoxFrm = (SwCellFrm*)pTmpFrm; |
| pTab = ((SwFrm*)pBoxFrm)->ImplFindTabFrm(); |
| pBox = pBoxFrm->GetTabBox(); |
| } |
| else if( !pCrsr && !pBoxFrm ) |
| { |
| ASSERT( !this, "einer von beiden muss angegeben werden!" ); |
| return ; |
| } |
| |
| // sollte die Tabelle noch auf relativen Werten (USHRT_MAX) stehen |
| // dann muss es jetzt auf absolute umgerechnet werden. |
| SwTable& rTab = *pTab->GetTable(); |
| const SwFmtFrmSize& rTblFrmSz = rTab.GetFrmFmt()->GetFrmSize(); |
| SWRECTFN( pTab ) |
| // OD 06.08.2003 #i17174# - With fix for #i9040# the shadow size is taken |
| // from the table width. Thus, add its left and right size to current table |
| // printing area width in order to get the correct table size attribute. |
| SwTwips nPrtWidth = (pTab->Prt().*fnRect->fnGetWidth)(); |
| { |
| SvxShadowItem aShadow( rTab.GetFrmFmt()->GetShadow() ); |
| nPrtWidth += aShadow.CalcShadowSpace( SHADOW_LEFT ) + |
| aShadow.CalcShadowSpace( SHADOW_RIGHT ); |
| } |
| if( nPrtWidth != rTblFrmSz.GetWidth() ) |
| { |
| SwFmtFrmSize aSz( rTblFrmSz ); |
| aSz.SetWidth( nPrtWidth ); |
| rTab.GetFrmFmt()->SetFmtAttr( aSz ); |
| } |
| |
| SwTabCols aOld( rNew.Count() ); |
| |
| const SwPageFrm* pPage = pTab->FindPageFrm(); |
| const sal_uLong nLeftMin = (pTab->Frm().*fnRect->fnGetLeft)() - |
| (pPage->Frm().*fnRect->fnGetLeft)(); |
| const sal_uLong nRightMax = (pTab->Frm().*fnRect->fnGetRight)() - |
| (pPage->Frm().*fnRect->fnGetLeft)(); |
| |
| //Fix-Punkte setzen, LeftMin in Dokumentkoordinaten die anderen relativ. |
| aOld.SetLeftMin ( nLeftMin ); |
| aOld.SetLeft ( (pTab->Prt().*fnRect->fnGetLeft)() ); |
| aOld.SetRight ( (pTab->Prt().*fnRect->fnGetRight)()); |
| aOld.SetRightMax( nRightMax - nLeftMin ); |
| |
| rTab.GetTabCols( aOld, pBox ); |
| SetTabCols(rTab, rNew, aOld, pBox, bCurRowOnly ); |
| } |
| |
| void SwDoc::SetTabRows( const SwTabCols &rNew, sal_Bool bCurColOnly, const SwCursor*, |
| const SwCellFrm* pBoxFrm ) |
| { |
| const SwTableBox* pBox; |
| SwTabFrm *pTab; |
| |
| ASSERT( pBoxFrm, "SetTabRows called without pBoxFrm" ) |
| |
| pTab = ((SwFrm*)pBoxFrm)->ImplFindTabFrm(); |
| pBox = pBoxFrm->GetTabBox(); |
| |
| // sollte die Tabelle noch auf relativen Werten (USHRT_MAX) stehen |
| // dann muss es jetzt auf absolute umgerechnet werden. |
| SWRECTFN( pTab ) |
| SwTabCols aOld( rNew.Count() ); |
| |
| //Fix-Punkte setzen, LeftMin in Dokumentkoordinaten die anderen relativ. |
| const SwPageFrm* pPage = pTab->FindPageFrm(); |
| |
| aOld.SetRight( (pTab->Prt().*fnRect->fnGetHeight)() ); |
| long nLeftMin; |
| if ( bVert ) |
| { |
| nLeftMin = pTab->GetPrtLeft() - pPage->Frm().Left(); |
| aOld.SetLeft ( LONG_MAX ); |
| aOld.SetRightMax( aOld.GetRight() ); |
| |
| } |
| else |
| { |
| nLeftMin = pTab->GetPrtTop() - pPage->Frm().Top(); |
| aOld.SetLeft ( 0 ); |
| aOld.SetRightMax( LONG_MAX ); |
| } |
| aOld.SetLeftMin ( nLeftMin ); |
| |
| GetTabRows( aOld, 0, pBoxFrm ); |
| |
| GetIDocumentUndoRedo().StartUndo( UNDO_TABLE_ATTR, NULL ); |
| |
| // check for differences between aOld and rNew: |
| const sal_uInt16 nCount = rNew.Count(); |
| const SwTable* pTable = pTab->GetTable(); |
| ASSERT( pTable, "My colleague told me, this couldn't happen" ); |
| |
| for ( sal_uInt16 i = 0; i <= nCount; ++i ) |
| { |
| const sal_uInt16 nIdxStt = bVert ? nCount - i : i - 1; |
| const sal_uInt16 nIdxEnd = bVert ? nCount - i - 1 : i; |
| |
| const long nOldRowStart = i == 0 ? 0 : aOld[ nIdxStt ]; |
| const long nOldRowEnd = i == nCount ? aOld.GetRight() : aOld[ nIdxEnd ]; |
| const long nOldRowHeight = nOldRowEnd - nOldRowStart; |
| |
| const long nNewRowStart = i == 0 ? 0 : rNew[ nIdxStt ]; |
| const long nNewRowEnd = i == nCount ? rNew.GetRight() : rNew[ nIdxEnd ]; |
| const long nNewRowHeight = nNewRowEnd - nNewRowStart; |
| |
| const long nDiff = nNewRowHeight - nOldRowHeight; |
| if ( abs( nDiff ) >= ROWFUZZY ) |
| { |
| // For the old table model pTxtFrm and pLine will be set for every box. |
| // For the new table model pTxtFrm will be set if the box is not covered, |
| // but the pLine will be set if the box is not an overlapping box |
| // In the new table model the row height can be adjusted, |
| // when both variables are set. |
| SwTxtFrm* pTxtFrm = 0; |
| const SwTableLine* pLine = 0; |
| |
| // Iterate over all SwCellFrms with Bottom = nOldPos |
| const SwFrm* pFrm = pTab->GetNextLayoutLeaf(); |
| while ( pFrm && pTab->IsAnLower( pFrm ) ) |
| { |
| if ( pFrm->IsCellFrm() && pFrm->FindTabFrm() == pTab ) |
| { |
| const long nLowerBorder = (pFrm->Frm().*fnRect->fnGetBottom)(); |
| const sal_uLong nTabTop = (pTab->*fnRect->fnGetPrtTop)(); |
| if ( abs( (*fnRect->fnYInc)( nTabTop, nOldRowEnd ) - nLowerBorder ) <= ROWFUZZY ) |
| { |
| if ( !bCurColOnly || pFrm == pBoxFrm ) |
| { |
| const SwFrm* pCntnt = ::GetCellCntnt( static_cast<const SwCellFrm&>(*pFrm) ); |
| |
| if ( pCntnt && pCntnt->IsTxtFrm() ) |
| { |
| pBox = ((SwCellFrm*)pFrm)->GetTabBox(); |
| const long nRowSpan = pBox->getRowSpan(); |
| if( nRowSpan > 0 ) // Not overlapped |
| pTxtFrm = (SwTxtFrm*)pCntnt; |
| if( nRowSpan < 2 ) // Not overlapping for row height |
| pLine = pBox->GetUpper(); |
| if( pLine && pTxtFrm ) // always for old table model |
| { |
| // The new row height must not to be calculated from a overlapping box |
| SwFmtFrmSize aNew( pLine->GetFrmFmt()->GetFrmSize() ); |
| const long nNewSize = (pFrm->Frm().*fnRect->fnGetHeight)() + nDiff; |
| if( nNewSize != aNew.GetHeight() ) |
| { |
| aNew.SetHeight( nNewSize ); |
| if ( ATT_VAR_SIZE == aNew.GetHeightSizeType() ) |
| aNew.SetHeightSizeType( ATT_MIN_SIZE ); |
| // This position must not be in an overlapped box |
| const SwPosition aPos( *((SwTxtFrm*)pCntnt)->GetTxtNode() ); |
| const SwCursor aTmpCrsr( aPos, 0, false ); |
| SetRowHeight( aTmpCrsr, aNew ); |
| // For the new table model we're done, for the old one |
| // there might be another (sub)row to adjust... |
| if( pTable->IsNewModel() ) |
| break; |
| } |
| pLine = 0; |
| } |
| } |
| } |
| } |
| } |
| pFrm = pFrm->GetNextLayoutLeaf(); |
| } |
| } |
| } |
| |
| GetIDocumentUndoRedo().EndUndo( UNDO_TABLE_ATTR, NULL ); |
| |
| ::ClearFEShellTabCols(); |
| } |
| |
| /* -----------------18.07.98 11:45------------------- |
| * Direktzugriff fuer UNO |
| * --------------------------------------------------*/ |
| void SwDoc::SetTabCols(SwTable& rTab, const SwTabCols &rNew, const SwTabCols &rOld, |
| const SwTableBox *pStart, sal_Bool bCurRowOnly ) |
| { |
| if (GetIDocumentUndoRedo().DoesUndo()) |
| { |
| GetIDocumentUndoRedo().AppendUndo( |
| new SwUndoAttrTbl( *rTab.GetTableNode(), sal_True )); |
| } |
| rTab.SetTabCols( rNew, rOld, pStart, bCurRowOnly ); |
| ::ClearFEShellTabCols(); |
| SetModified(); |
| } |
| |
| void SwDoc::SetRowsToRepeat( SwTable &rTable, sal_uInt16 nSet ) |
| { |
| if( nSet == rTable.GetRowsToRepeat() ) |
| return; |
| |
| if (GetIDocumentUndoRedo().DoesUndo()) |
| { |
| GetIDocumentUndoRedo().AppendUndo( |
| new SwUndoTblHeadline(rTable, rTable.GetRowsToRepeat(), nSet) ); |
| } |
| |
| SwMsgPoolItem aChg( RES_TBLHEADLINECHG ); |
| rTable.SetRowsToRepeat( nSet ); |
| rTable.GetFrmFmt()->ModifyNotification( &aChg, &aChg ); |
| SetModified(); |
| } |
| |
| |
| |
| |
| // Splittet eine Tabelle in der Grund-Zeile, in der der Index steht. |
| // Alle GrundZeilen dahinter wandern in eine neue Tabelle/-Node. |
| // Ist das Flag bCalcNewSize auf sal_True, wird fuer beide neuen Tabellen |
| // die neue Size aus dem Max der Boxen errechnet; vorrausgesetzt, |
| // die Size ist "absolut" gesetzt (USHRT_MAX) |
| |
| void SwCollectTblLineBoxes::AddToUndoHistory( const SwCntntNode& rNd ) |
| { |
| if( pHst ) |
| pHst->Add( rNd.GetFmtColl(), rNd.GetIndex(), ND_TEXTNODE ); |
| } |
| |
| void SwCollectTblLineBoxes::AddBox( const SwTableBox& rBox ) |
| { |
| aPosArr.Insert( nWidth, aPosArr.Count() ); |
| SwTableBox* p = (SwTableBox*)&rBox; |
| aBoxes.Insert( p, aBoxes.Count() ); |
| nWidth = nWidth + (sal_uInt16)rBox.GetFrmFmt()->GetFrmSize().GetWidth(); |
| } |
| |
| const SwTableBox* SwCollectTblLineBoxes::GetBoxOfPos( const SwTableBox& rBox ) |
| { |
| const SwTableBox* pRet = 0; |
| sal_uInt16 n; |
| |
| if( aPosArr.Count() ) |
| { |
| 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 = nWidth + (sal_uInt16)rBox.GetFrmFmt()->GetFrmSize().GetWidth(); |
| pRet = aBoxes[ n ]; |
| } |
| return pRet; |
| } |
| |
| sal_Bool SwCollectTblLineBoxes::Resize( sal_uInt16 nOffset, sal_uInt16 nOldWidth ) |
| { |
| sal_uInt16 n; |
| |
| if( aPosArr.Count() ) |
| { |
| for( n = 0; n < aPosArr.Count(); ++n ) |
| if( aPosArr[ n ] == nOffset ) |
| break; |
| else if( aPosArr[ n ] > nOffset ) |
| { |
| if( n ) |
| --n; |
| break; |
| } |
| |
| aPosArr.Remove( 0, n ); |
| aBoxes.Remove( 0, n ); |
| |
| // dann die Positionen der neuen Size anpassen |
| for( n = 0; n < aPosArr.Count(); ++n ) |
| { |
| sal_uLong nSize = nWidth; |
| nSize *= ( aPosArr[ n ] - nOffset ); |
| nSize /= nOldWidth; |
| aPosArr[ n ] = sal_uInt16( nSize ); |
| } |
| } |
| return 0 != aPosArr.Count(); |
| } |
| |
| sal_Bool lcl_Line_CollectBox( const SwTableLine*& rpLine, void* pPara ) |
| { |
| SwCollectTblLineBoxes* pSplPara = (SwCollectTblLineBoxes*)pPara; |
| if( pSplPara->IsGetValues() ) |
| ((SwTableLine*)rpLine)->GetTabBoxes().ForEach( &lcl_Box_CollectBox, pPara ); |
| else |
| ((SwTableLine*)rpLine)->GetTabBoxes().ForEach( &lcl_BoxSetSplitBoxFmts, pPara ); |
| return sal_True; |
| } |
| |
| sal_Bool lcl_Box_CollectBox( const SwTableBox*& rpBox, void* pPara ) |
| { |
| SwCollectTblLineBoxes* pSplPara = (SwCollectTblLineBoxes*)pPara; |
| sal_uInt16 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 sal_True; |
| } |
| |
| sal_Bool lcl_BoxSetSplitBoxFmts( const SwTableBox*& rpBox, void* pPara ) |
| { |
| SwCollectTblLineBoxes* pSplPara = (SwCollectTblLineBoxes*)pPara; |
| sal_uInt16 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()->SetFmtAttr( aNew ); |
| } |
| } |
| else |
| { |
| sal_uInt16 __FAR_DATA 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()->SetFmtAttr( 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() ) |
| { |
| pSplPara->AddToUndoHistory( *pDNd ); |
| pDNd->ChgFmtColl( pCNd->GetFmtColl() ); |
| } |
| } |
| |
| // bedingte Vorlage beachten |
| pBox->GetSttNd()->CheckSectionCondColl(); |
| } |
| } |
| return sal_True; |
| } |
| |
| |
| sal_Bool SwDoc::SplitTable( const SwPosition& rPos, sal_uInt16 eHdlnMode, |
| sal_Bool bCalcNewSize ) |
| { |
| SwNode* pNd = &rPos.nNode.GetNode(); |
| SwTableNode* pTNd = pNd->FindTableNode(); |
| if( !pTNd || pNd->IsTableNode() ) |
| return 0; |
| |
| if( pTNd->GetTable().ISA( SwDDETable )) |
| return sal_False; |
| |
| SwTable& rTbl = pTNd->GetTable(); |
| rTbl.SetHTMLTableLayout( 0 ); // MIB 9.7.97: HTML-Layout loeschen |
| |
| SwTableFmlUpdate aMsgHnt( &rTbl ); |
| |
| SwHistory aHistory; |
| if (GetIDocumentUndoRedo().DoesUndo()) |
| { |
| aMsgHnt.pHistory = &aHistory; |
| } |
| |
| { |
| sal_uLong nSttIdx = pNd->FindTableBoxStartNode()->GetIndex(); |
| |
| // Suche die Grund-Line dieser Box: |
| SwTableBox* pBox = rTbl.GetTblBox( nSttIdx ); |
| if( pBox ) |
| { |
| SwTableLine* pLine = pBox->GetUpper(); |
| while( pLine->GetUpper() ) |
| pLine = pLine->GetUpper()->GetUpper(); |
| |
| // in pLine steht jetzt die GrundLine. |
| aMsgHnt.nSplitLine = rTbl.GetTabLines().C40_GETPOS( SwTableLine, pLine ); |
| } |
| |
| String sNewTblNm( GetUniqueTblName() ); |
| aMsgHnt.DATA.pNewTblNm = &sNewTblNm; |
| aMsgHnt.eFlags = TBL_SPLITTBL; |
| UpdateTblFlds( &aMsgHnt ); |
| } |
| |
| //Lines fuer das Layout-Update heraussuchen. |
| _FndBox aFndBox( 0, 0 ); |
| aFndBox.SetTableLines( rTbl ); |
| aFndBox.DelFrms( rTbl ); |
| |
| // TL_CHART2: need to inform chart of probably changed cell names |
| //pDoc->UpdateCharts( rTbl.GetFrmFmt()->GetName() ); |
| |
| SwTableNode* pNew = GetNodes().SplitTable( rPos.nNode, sal_False, bCalcNewSize ); |
| |
| if( pNew ) |
| { |
| SwSaveRowSpan* pSaveRowSp = pNew->GetTable().CleanUpTopRowSpan( rTbl.GetTabLines().Count() ); |
| SwUndoSplitTbl* pUndo = 0; |
| if (GetIDocumentUndoRedo().DoesUndo()) |
| { |
| pUndo = new SwUndoSplitTbl( |
| *pNew, pSaveRowSp, eHdlnMode, bCalcNewSize); |
| GetIDocumentUndoRedo().AppendUndo(pUndo); |
| if( aHistory.Count() ) |
| pUndo->SaveFormula( aHistory ); |
| } |
| |
| switch( eHdlnMode ) |
| { |
| // setze die untere Border der vorherige Line, |
| // an der aktuellen als obere |
| case HEADLINE_BORDERCOPY: |
| { |
| SwCollectTblLineBoxes aPara( sal_False, eHdlnMode ); |
| SwTableLine* pLn = rTbl.GetTabLines()[ |
| rTbl.GetTabLines().Count() - 1 ]; |
| pLn->GetTabBoxes().ForEach( &lcl_Box_CollectBox, &aPara ); |
| |
| aPara.SetValues( sal_True ); |
| pLn = pNew->GetTable().GetTabLines()[ 0 ]; |
| pLn->GetTabBoxes().ForEach( &lcl_BoxSetSplitBoxFmts, &aPara ); |
| |
| // Kopfzeile wiederholen abschalten |
| pNew->GetTable().SetRowsToRepeat( 0 ); |
| } |
| break; |
| |
| // setze die Attributierung der ersten Line an der neuen ersten |
| case HEADLINE_BOXATTRCOPY: |
| case HEADLINE_BOXATRCOLLCOPY: |
| { |
| SwHistory* pHst = 0; |
| if( HEADLINE_BOXATRCOLLCOPY == eHdlnMode && pUndo ) |
| pHst = pUndo->GetHistory(); |
| |
| SwCollectTblLineBoxes aPara( sal_True, eHdlnMode, pHst ); |
| SwTableLine* pLn = rTbl.GetTabLines()[ 0 ]; |
| pLn->GetTabBoxes().ForEach( &lcl_Box_CollectBox, &aPara ); |
| |
| aPara.SetValues( sal_True ); |
| pLn = pNew->GetTable().GetTabLines()[ 0 ]; |
| pLn->GetTabBoxes().ForEach( &lcl_BoxSetSplitBoxFmts, &aPara ); |
| } |
| break; |
| |
| case HEADLINE_CNTNTCOPY: |
| rTbl.CopyHeadlineIntoTable( *pNew ); |
| if( pUndo ) |
| pUndo->SetTblNodeOffset( pNew->GetIndex() ); |
| break; |
| |
| case HEADLINE_NONE: |
| // Kopfzeile wiederholen abschalten |
| pNew->GetTable().SetRowsToRepeat( 0 ); |
| break; |
| } |
| |
| // und Frms einfuegen. |
| SwNodeIndex aNdIdx( *pNew->EndOfSectionNode() ); |
| GetNodes().GoNext( &aNdIdx ); // zum naechsten ContentNode |
| pNew->MakeFrms( &aNdIdx ); |
| |
| //Zwischen die Tabellen wird ein Absatz geschoben |
| GetNodes().MakeTxtNode( SwNodeIndex( *pNew ), |
| GetTxtCollFromPool( RES_POOLCOLL_TEXT ) ); |
| } |
| |
| //Layout updaten |
| aFndBox.MakeFrms( rTbl ); |
| |
| // TL_CHART2: need to inform chart of probably changed cell names |
| UpdateCharts( rTbl.GetFrmFmt()->GetName() ); |
| |
| SetFieldsDirty( true, NULL, 0 ); |
| |
| return 0 != pNew; |
| } |
| |
| sal_Bool lcl_ChgTblSize( SwTable& rTbl ) |
| { |
| // das Attribut darf nicht ueber das Modify an der |
| // Tabelle gesetzt werden, denn sonst werden alle |
| // Boxen wieder auf 0 zurueck gesetzt. Also locke das Format |
| SwFrmFmt* pFmt = rTbl.GetFrmFmt(); |
| SwFmtFrmSize aTblMaxSz( pFmt->GetFrmSize() ); |
| |
| if( USHRT_MAX == aTblMaxSz.GetWidth() ) |
| return sal_False; |
| |
| sal_Bool bLocked = pFmt->IsModifyLocked(); |
| pFmt->LockModify(); |
| |
| aTblMaxSz.SetWidth( 0 ); |
| |
| SwTableLines& rLns = rTbl.GetTabLines(); |
| for( sal_uInt16 nLns = 0; nLns < rLns.Count(); ++nLns ) |
| { |
| SwTwips nMaxLnWidth = 0; |
| SwTableBoxes& rBoxes = rLns[ nLns ]->GetTabBoxes(); |
| for( sal_uInt16 nBox = 0; nBox < rBoxes.Count(); ++nBox ) |
| nMaxLnWidth += rBoxes[nBox]->GetFrmFmt()->GetFrmSize().GetWidth(); |
| |
| if( nMaxLnWidth > aTblMaxSz.GetWidth() ) |
| aTblMaxSz.SetWidth( nMaxLnWidth ); |
| } |
| pFmt->SetFmtAttr( aTblMaxSz ); |
| if( !bLocked ) // und gegebenenfalls Lock wieder freigeben |
| pFmt->UnlockModify(); |
| |
| return sal_True; |
| } |
| |
| class _SplitTable_Para |
| { |
| SvPtrarr aSrc, aDest; |
| SwTableNode* pNewTblNd; |
| SwTable& rOldTbl; |
| |
| public: |
| _SplitTable_Para( SwTableNode* pNew, SwTable& rOld ) |
| : aSrc( 16, 16 ), aDest( 16, 16 ), pNewTblNd( pNew ), rOldTbl( rOld ) |
| {} |
| sal_uInt16 SrcFmt_GetPos( void* pFmt ) const |
| { return aSrc.GetPos( pFmt ); } |
| |
| void DestFmt_Insert( void* pFmt ) |
| { aDest.Insert( pFmt, aDest.Count() ); } |
| |
| void SrcFmt_Insert( void* pFmt ) |
| { aSrc.Insert( pFmt, aSrc.Count() ); } |
| |
| SwFrmFmt* DestFmt_Get( sal_uInt16 nPos ) const |
| { return (SwFrmFmt*)aDest[ nPos ]; } |
| |
| void ChgBox( SwTableBox* pBox ) |
| { |
| rOldTbl.GetTabSortBoxes().Remove( pBox ); |
| pNewTblNd->GetTable().GetTabSortBoxes().Insert( pBox ); |
| } |
| }; |
| |
| |
| sal_Bool lcl_SplitTable_CpyBox( const SwTableBox*& rpBox, void* pPara ); |
| |
| sal_Bool lcl_SplitTable_CpyLine( const SwTableLine*& rpLine, void* pPara ) |
| { |
| SwTableLine* pLn = (SwTableLine*)rpLine; |
| _SplitTable_Para& rPara = *(_SplitTable_Para*)pPara; |
| |
| SwFrmFmt *pSrcFmt = pLn->GetFrmFmt(); |
| sal_uInt16 nPos = rPara.SrcFmt_GetPos( pSrcFmt ); |
| if( USHRT_MAX == nPos ) |
| { |
| rPara.DestFmt_Insert( pLn->ClaimFrmFmt() ); |
| rPara.SrcFmt_Insert( pSrcFmt ); |
| } |
| else |
| pLn->ChgFrmFmt( (SwTableLineFmt*)rPara.DestFmt_Get( nPos ) ); |
| |
| pLn->GetTabBoxes().ForEach( &lcl_SplitTable_CpyBox, pPara ); |
| return sal_True; |
| } |
| |
| sal_Bool lcl_SplitTable_CpyBox( const SwTableBox*& rpBox, void* pPara ) |
| { |
| SwTableBox* pBox = (SwTableBox*)rpBox; |
| _SplitTable_Para& rPara = *(_SplitTable_Para*)pPara; |
| |
| SwFrmFmt *pSrcFmt = pBox->GetFrmFmt(); |
| sal_uInt16 nPos = rPara.SrcFmt_GetPos( pSrcFmt ); |
| if( USHRT_MAX == nPos ) |
| { |
| rPara.DestFmt_Insert( pBox->ClaimFrmFmt() ); |
| rPara.SrcFmt_Insert( pSrcFmt ); |
| } |
| else |
| pBox->ChgFrmFmt( (SwTableBoxFmt*)rPara.DestFmt_Get( nPos ) ); |
| |
| if( pBox->GetSttNd() ) |
| rPara.ChgBox( pBox ); |
| else |
| pBox->GetTabLines().ForEach( &lcl_SplitTable_CpyLine, pPara ); |
| return sal_True; |
| } |
| |
| SwTableNode* SwNodes::SplitTable( const SwNodeIndex& rPos, sal_Bool bAfter, |
| sal_Bool bCalcNewSize ) |
| { |
| SwNode* pNd = &rPos.GetNode(); |
| SwTableNode* pTNd = pNd->FindTableNode(); |
| if( !pTNd || pNd->IsTableNode() ) |
| return 0; |
| |
| sal_uLong nSttIdx = pNd->FindTableBoxStartNode()->GetIndex(); |
| |
| // Suche die Grund-Line dieser Box: |
| SwTable& rTbl = pTNd->GetTable(); |
| SwTableBox* pBox = rTbl.GetTblBox( nSttIdx ); |
| if( !pBox ) |
| return 0; |
| |
| SwTableLine* pLine = pBox->GetUpper(); |
| while( pLine->GetUpper() ) |
| pLine = pLine->GetUpper()->GetUpper(); |
| |
| // in pLine steht jetzt die GrundLine. |
| sal_uInt16 nLinePos = rTbl.GetTabLines().C40_GETPOS( SwTableLine, pLine ); |
| if( USHRT_MAX == nLinePos || |
| ( bAfter ? ++nLinePos >= rTbl.GetTabLines().Count() : !nLinePos )) |
| return 0; // nicht gefunden oder letze Line !! |
| |
| // Suche jetzt die 1. Box der nachfolgenden Line |
| SwTableLine* pNextLine = rTbl.GetTabLines()[ nLinePos ]; |
| pBox = pNextLine->GetTabBoxes()[0]; |
| while( !pBox->GetSttNd() ) |
| pBox = pBox->GetTabLines()[0]->GetTabBoxes()[0]; |
| |
| // dann fuege mal einen End- und TabelleNode ins Nodes-Array ein. |
| SwTableNode * pNewTblNd; |
| { |
| SwEndNode* pOldTblEndNd = (SwEndNode*)pTNd->EndOfSectionNode()->GetEndNode(); |
| ASSERT( pOldTblEndNd, "wo ist der EndNode?" ) |
| |
| SwNodeIndex aIdx( *pBox->GetSttNd() ); |
| new SwEndNode( aIdx, *pTNd ); |
| pNewTblNd = new SwTableNode( aIdx ); |
| pNewTblNd->GetTable().SetTableModel( rTbl.IsNewModel() ); |
| |
| pOldTblEndNd->pStartOfSection = pNewTblNd; |
| pNewTblNd->pEndOfSection = pOldTblEndNd; |
| |
| SwNode* pBoxNd = aIdx.GetNode().GetStartNode(); |
| do { |
| ASSERT( pBoxNd->IsStartNode(), "das muss ein StartNode sein!" ); |
| pBoxNd->pStartOfSection = pNewTblNd; |
| pBoxNd = (*this)[ pBoxNd->EndOfSectionIndex() + 1 ]; |
| } while( pBoxNd != pOldTblEndNd ); |
| } |
| |
| { |
| // die Lines ruebermoven... |
| SwTable& rNewTbl = pNewTblNd->GetTable(); |
| rNewTbl.GetTabLines().Insert( &rTbl.GetTabLines(), 0, nLinePos ); |
| // |
| // von hinten (unten-rechts) nach vorn (oben-links) alle Boxen |
| // beim chart data provider austragen (das modified event wird dann |
| // in der aufrufenden Funktion getriggert. |
| // TL_CHART2: |
| SwChartDataProvider *pPCD = rTbl.GetFrmFmt()->getIDocumentChartDataProviderAccess()->GetChartDataProvider(); |
| if( pPCD ) |
| { |
| for (sal_uInt16 k = nLinePos; k < rTbl.GetTabLines().Count(); ++k) |
| { |
| sal_uInt16 nLineIdx = (rTbl.GetTabLines().Count() - 1) - k + nLinePos; |
| sal_uInt16 nBoxCnt = rTbl.GetTabLines()[ nLineIdx ]->GetTabBoxes().Count(); |
| for (sal_uInt16 j = 0; j < nBoxCnt; ++j) |
| { |
| sal_uInt16 nIdx = nBoxCnt - 1 - j; |
| pPCD->DeleteBox( &rTbl, *rTbl.GetTabLines()[ nLineIdx ]->GetTabBoxes()[nIdx] ); |
| } |
| } |
| } |
| // |
| // ...und loeschen |
| sal_uInt16 nDeleted = rTbl.GetTabLines().Count() - nLinePos; |
| rTbl.GetTabLines().Remove( nLinePos, nDeleted ); |
| |
| // und die betr. Boxen verschieben. Dabei die Formate eindeutig |
| // machen und die StartNodes korrigieren |
| _SplitTable_Para aPara( pNewTblNd, rTbl ); |
| rNewTbl.GetTabLines().ForEach( &lcl_SplitTable_CpyLine, &aPara ); |
| rTbl.CleanUpBottomRowSpan( nDeleted ); |
| } |
| |
| { |
| // Das Tabellen-FrmFormat kopieren |
| SwFrmFmt* pOldTblFmt = rTbl.GetFrmFmt(); |
| SwFrmFmt* pNewTblFmt = pOldTblFmt->GetDoc()->MakeTblFrmFmt( |
| pOldTblFmt->GetDoc()->GetUniqueTblName(), |
| pOldTblFmt->GetDoc()->GetDfltFrmFmt() ); |
| |
| *pNewTblFmt = *pOldTblFmt; |
| pNewTblNd->GetTable().RegisterToFormat( *pNewTblFmt ); |
| |
| // neue Size errechnen ? (lcl_ChgTblSize nur das 2. aufrufen, wenn es |
| // beim 1. schon geklappt hat; also absolute Groesse hat) |
| if( bCalcNewSize && lcl_ChgTblSize( rTbl ) ) |
| lcl_ChgTblSize( pNewTblNd->GetTable() ); |
| } |
| |
| // TL_CHART2: need to inform chart of probably changed cell names |
| rTbl.UpdateCharts(); |
| |
| return pNewTblNd; // das wars |
| } |
| |
| // 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. |
| sal_Bool SwDoc::MergeTable( const SwPosition& rPos, sal_Bool bWithPrev, sal_uInt16 nMode ) |
| { |
| SwTableNode* pTblNd = rPos.nNode.GetNode().FindTableNode(), *pDelTblNd; |
| if( !pTblNd ) |
| return sal_False; |
| |
| SwNodes& rNds = GetNodes(); |
| if( bWithPrev ) |
| pDelTblNd = rNds[ pTblNd->GetIndex() - 1 ]->FindTableNode(); |
| else |
| pDelTblNd = rNds[ pTblNd->EndOfSectionIndex() + 1 ]->GetTableNode(); |
| if( !pDelTblNd ) |
| return sal_False; |
| |
| if( pTblNd->GetTable().ISA( SwDDETable ) || |
| pDelTblNd->GetTable().ISA( SwDDETable )) |
| return sal_False; |
| |
| // MIB 9.7.97: HTML-Layout loeschen |
| pTblNd->GetTable().SetHTMLTableLayout( 0 ); |
| pDelTblNd->GetTable().SetHTMLTableLayout( 0 ); |
| |
| // beide Tabellen vorhanden, also kanns losgehen |
| SwUndoMergeTbl* pUndo = 0; |
| SwHistory* pHistory = 0; |
| if (GetIDocumentUndoRedo().DoesUndo()) |
| { |
| pUndo = new SwUndoMergeTbl( *pTblNd, *pDelTblNd, bWithPrev, nMode ); |
| GetIDocumentUndoRedo().AppendUndo(pUndo); |
| pHistory = new SwHistory; |
| } |
| |
| // alle "Tabellenformeln" anpassen |
| SwTableFmlUpdate aMsgHnt( &pTblNd->GetTable() ); |
| aMsgHnt.DATA.pDelTbl = &pDelTblNd->GetTable(); |
| aMsgHnt.eFlags = TBL_MERGETBL; |
| aMsgHnt.pHistory = pHistory; |
| UpdateTblFlds( &aMsgHnt ); |
| |
| // das eigentliche Mergen |
| SwNodeIndex aIdx( bWithPrev ? *pTblNd : *pDelTblNd ); |
| sal_Bool bRet = rNds.MergeTable( aIdx, !bWithPrev, nMode, pHistory ); |
| |
| if( pHistory ) |
| { |
| if( pHistory->Count() ) |
| pUndo->SaveFormula( *pHistory ); |
| delete pHistory; |
| } |
| if( bRet ) |
| { |
| SetModified(); |
| SetFieldsDirty( true, NULL, 0 ); |
| } |
| return bRet; |
| } |
| |
| sal_Bool SwNodes::MergeTable( const SwNodeIndex& rPos, sal_Bool bWithPrev, |
| sal_uInt16 nMode, SwHistory* ) |
| { |
| SwTableNode* pDelTblNd = rPos.GetNode().GetTableNode(); |
| ASSERT( pDelTblNd, "wo ist der TableNode geblieben?" ); |
| |
| SwTableNode* pTblNd = (*this)[ rPos.GetIndex() - 1]->FindTableNode(); |
| ASSERT( pTblNd, "wo ist der TableNode geblieben?" ); |
| |
| if( !pDelTblNd || !pTblNd ) |
| return sal_False; |
| |
| pDelTblNd->DelFrms(); |
| |
| SwTable& rDelTbl = pDelTblNd->GetTable(); |
| SwTable& rTbl = pTblNd->GetTable(); |
| |
| //Lines fuer das Layout-Update herausuchen. |
| _FndBox aFndBox( 0, 0 ); |
| aFndBox.SetTableLines( rTbl ); |
| aFndBox.DelFrms( rTbl ); |
| |
| // TL_CHART2: since chart currently does not want to get informed about |
| // additional rows/cols there is no need for a modified event in the |
| // remaining first table. Also, if it is required it should be done |
| // after the merging and not here... |
| // pDoc->UpdateCharts( rTbl.GetFrmFmt()->GetName() ); |
| |
| |
| // TL_CHART2: |
| // tell the charts about the table to be deleted and have them use their own data |
| GetDoc()->CreateChartInternalDataProviders( &rDelTbl ); |
| |
| // die Breite der TabellenFormate abgleichen: |
| { |
| const SwFmtFrmSize& rTblSz = rTbl.GetFrmFmt()->GetFrmSize(); |
| const SwFmtFrmSize& rDelTblSz = rDelTbl.GetFrmFmt()->GetFrmSize(); |
| if( rTblSz != rDelTblSz ) |
| { |
| // dann sollten die mal schleunigst korrigiert werden |
| if( bWithPrev ) |
| rDelTbl.GetFrmFmt()->SetFmtAttr( rTblSz ); |
| else |
| rTbl.GetFrmFmt()->SetFmtAttr( rDelTblSz ); |
| } |
| } |
| |
| if( !bWithPrev ) |
| { |
| // dann mussen alle Attruibute der hinteren Tabelle auf die |
| // vordere uebertragen werden, weil die hintere ueber das loeschen |
| // des Node geloescht wird. |
| rTbl.SetRowsToRepeat( rDelTbl.GetRowsToRepeat() ); |
| rTbl.SetTblChgMode( rDelTbl.GetTblChgMode() ); |
| |
| rTbl.GetFrmFmt()->LockModify(); |
| *rTbl.GetFrmFmt() = *rDelTbl.GetFrmFmt(); |
| // auch den Namen umsetzen! |
| rTbl.GetFrmFmt()->SetName( rDelTbl.GetFrmFmt()->GetName() ); |
| rTbl.GetFrmFmt()->UnlockModify(); |
| } |
| |
| // die Lines und Boxen ruebermoven |
| sal_uInt16 nOldSize = rTbl.GetTabLines().Count(); |
| rTbl.GetTabLines().Insert( &rDelTbl.GetTabLines(), nOldSize ); |
| rDelTbl.GetTabLines().Remove( 0, rDelTbl.GetTabLines().Count() ); |
| |
| rTbl.GetTabSortBoxes().Insert( &rDelTbl.GetTabSortBoxes() ); |
| rDelTbl.GetTabSortBoxes().Remove( (sal_uInt16)0, rDelTbl.GetTabSortBoxes().Count() ); |
| |
| // die vordere Tabelle bleibt immer stehen, die hintere wird geloescht |
| SwEndNode* pTblEndNd = pDelTblNd->EndOfSectionNode(); |
| pTblNd->pEndOfSection = pTblEndNd; |
| |
| SwNodeIndex aIdx( *pDelTblNd, 1 ); |
| |
| SwNode* pBoxNd = aIdx.GetNode().GetStartNode(); |
| do { |
| ASSERT( pBoxNd->IsStartNode(), "das muss ein StartNode sein!" ); |
| pBoxNd->pStartOfSection = pTblNd; |
| pBoxNd = (*this)[ pBoxNd->EndOfSectionIndex() + 1 ]; |
| } while( pBoxNd != pTblEndNd ); |
| pBoxNd->pStartOfSection = pTblNd; |
| |
| aIdx -= 2; |
| DelNodes( aIdx, 2 ); |
| |
| // jetzt an der 1. eingefuegten Line die bedingten Vorlagen umschubsen |
| const SwTableLine* pFirstLn = rTbl.GetTabLines()[ nOldSize ]; |
| if( 1 == nMode ) // |
| { |
| // Header-Vorlagen in der Zeile setzen |
| // und ggfs. in der History speichern fuers Undo!!! |
| } |
| lcl_LineSetHeadCondColl( pFirstLn, 0 ); |
| |
| // und die Borders "aufrauemen" |
| if( nOldSize ) |
| { |
| _SwGCLineBorder aPara( rTbl ); |
| aPara.nLinePos = --nOldSize; |
| pFirstLn = rTbl.GetTabLines()[ nOldSize ]; |
| lcl_GC_Line_Border( pFirstLn, &aPara ); |
| } |
| |
| //Layout updaten |
| aFndBox.MakeFrms( rTbl ); |
| |
| return sal_True; |
| } |
| |
| // ------------------------------------------------------------------- |
| |
| |
| // -- benutze die ForEach Methode vom PtrArray |
| struct _SetAFmtTabPara |
| { |
| SwTableAutoFmt& rTblFmt; |
| SwUndoTblAutoFmt* pUndo; |
| sal_uInt16 nEndBox, nCurBox; |
| sal_uInt8 nAFmtLine, nAFmtBox; |
| |
| _SetAFmtTabPara( const SwTableAutoFmt& rNew ) |
| : rTblFmt( (SwTableAutoFmt&)rNew ), pUndo( 0 ), |
| nEndBox( 0 ), nCurBox( 0 ), nAFmtLine( 0 ), nAFmtBox( 0 ) |
| {} |
| }; |
| |
| // forward deklarieren damit sich die Lines und Boxen rekursiv aufrufen |
| // koennen. |
| sal_Bool lcl_SetAFmtBox( const _FndBox*&, void *pPara ); |
| sal_Bool lcl_SetAFmtLine( const _FndLine*&, void *pPara ); |
| |
| sal_Bool lcl_SetAFmtLine( const _FndLine*& rpLine, void *pPara ) |
| { |
| ((_FndLine*&)rpLine)->GetBoxes().ForEach( &lcl_SetAFmtBox, pPara ); |
| return sal_True; |
| } |
| |
| sal_Bool lcl_SetAFmtBox( const _FndBox*& rpBox, void *pPara ) |
| { |
| _SetAFmtTabPara* pSetPara = (_SetAFmtTabPara*)pPara; |
| |
| if( !rpBox->GetUpper()->GetUpper() ) // Box auf 1. Ebene ? |
| { |
| if( !pSetPara->nCurBox ) |
| pSetPara->nAFmtBox = 0; |
| else if( pSetPara->nCurBox == pSetPara->nEndBox ) |
| pSetPara->nAFmtBox = 3; |
| else |
| pSetPara->nAFmtBox = (sal_uInt8)(1 + ((pSetPara->nCurBox-1) & 1)); |
| } |
| |
| if( rpBox->GetBox()->GetSttNd() ) |
| { |
| SwTableBox* pSetBox = (SwTableBox*)rpBox->GetBox(); |
| SwDoc* pDoc = pSetBox->GetFrmFmt()->GetDoc(); |
| // --> OD 2008-02-25 #refactorlists# |
| // SfxItemSet aCharSet( pDoc->GetAttrPool(), RES_CHRATR_BEGIN, RES_PARATR_END-1 ); |
| SfxItemSet aCharSet( pDoc->GetAttrPool(), RES_CHRATR_BEGIN, RES_PARATR_LIST_END-1 ); |
| // <-- |
| SfxItemSet aBoxSet( pDoc->GetAttrPool(), aTableBoxSetRange ); |
| sal_uInt8 nPos = pSetPara->nAFmtLine * 4 + pSetPara->nAFmtBox; |
| pSetPara->rTblFmt.UpdateToSet( nPos, aCharSet, |
| SwTableAutoFmt::UPDATE_CHAR, 0 ); |
| pSetPara->rTblFmt.UpdateToSet( nPos, aBoxSet, |
| SwTableAutoFmt::UPDATE_BOX, |
| pDoc->GetNumberFormatter( sal_True ) ); |
| if( aCharSet.Count() ) |
| { |
| sal_uLong nSttNd = pSetBox->GetSttIdx()+1; |
| sal_uLong nEndNd = pSetBox->GetSttNd()->EndOfSectionIndex(); |
| for( ; nSttNd < nEndNd; ++nSttNd ) |
| { |
| SwCntntNode* pNd = pDoc->GetNodes()[ nSttNd ]->GetCntntNode(); |
| if( pNd ) |
| pNd->SetAttr( aCharSet ); |
| } |
| } |
| |
| if( aBoxSet.Count() ) |
| { |
| if( pSetPara->pUndo && |
| SFX_ITEM_SET == aBoxSet.GetItemState( RES_BOXATR_FORMAT )) |
| pSetPara->pUndo->SaveBoxCntnt( *pSetBox ); |
| |
| pSetBox->ClaimFrmFmt()->SetFmtAttr( aBoxSet ); |
| } |
| } |
| else |
| ((_FndBox*&)rpBox)->GetLines().ForEach( &lcl_SetAFmtLine, pPara ); |
| |
| if( !rpBox->GetUpper()->GetUpper() ) // eine BaseLine |
| ++pSetPara->nCurBox; |
| return sal_True; |
| } |
| |
| |
| // AutoFormat fuer die Tabelle/TabellenSelection |
| sal_Bool SwDoc::SetTableAutoFmt( const SwSelBoxes& rBoxes, const SwTableAutoFmt& rNew ) |
| { |
| ASSERT( rBoxes.Count(), "keine gueltige Box-Liste" ); |
| SwTableNode* pTblNd = (SwTableNode*)rBoxes[0]->GetSttNd()->FindTableNode(); |
| if( !pTblNd ) |
| return sal_False; |
| |
| // suche alle Boxen / Lines |
| _FndBox aFndBox( 0, 0 ); |
| { |
| _FndPara aPara( rBoxes, &aFndBox ); |
| pTblNd->GetTable().GetTabLines().ForEach( &_FndLineCopyCol, &aPara ); |
| } |
| if( !aFndBox.GetLines().Count() ) |
| return sal_False; |
| |
| pTblNd->GetTable().SetHTMLTableLayout( 0 ); |
| |
| _FndBox* pFndBox = &aFndBox; |
| while( 1 == pFndBox->GetLines().Count() && |
| 1 == pFndBox->GetLines()[0]->GetBoxes().Count() ) |
| pFndBox = pFndBox->GetLines()[0]->GetBoxes()[0]; |
| |
| if( !pFndBox->GetLines().Count() ) // eine zu weit? (nur 1 sel.Box) |
| pFndBox = pFndBox->GetUpper()->GetUpper(); |
| |
| |
| // Undo abschalten, Attribute werden sich vorher gemerkt |
| SwUndoTblAutoFmt* pUndo = 0; |
| bool const bUndo(GetIDocumentUndoRedo().DoesUndo()); |
| if (bUndo) |
| { |
| pUndo = new SwUndoTblAutoFmt( *pTblNd, rNew ); |
| GetIDocumentUndoRedo().AppendUndo(pUndo); |
| GetIDocumentUndoRedo().DoUndo(false); |
| } |
| |
| _SetAFmtTabPara aPara( rNew ); |
| _FndLines& rFLns = pFndBox->GetLines(); |
| _FndLine* pLine; |
| |
| for( sal_uInt16 n = 0; n < rFLns.Count(); ++n ) |
| { |
| pLine = rFLns[n]; |
| |
| // Upper auf 0 setzen (Base-Line simulieren!) |
| _FndBox* pSaveBox = pLine->GetUpper(); |
| pLine->SetUpper( 0 ); |
| |
| if( !n ) |
| aPara.nAFmtLine = 0; |
| else if( n+1 == rFLns.Count() ) |
| aPara.nAFmtLine = 3; |
| else |
| aPara.nAFmtLine = (sal_uInt8)(1 + ((n-1) & 1 )); |
| |
| aPara.nAFmtBox = 0; |
| aPara.nCurBox = 0; |
| aPara.nEndBox = pLine->GetBoxes().Count()-1; |
| aPara.pUndo = pUndo; |
| pLine->GetBoxes().ForEach( &lcl_SetAFmtBox, &aPara ); |
| |
| pLine->SetUpper( pSaveBox ); |
| } |
| |
| if( pUndo ) |
| { |
| GetIDocumentUndoRedo().DoUndo(bUndo); |
| } |
| |
| SetModified(); |
| SetFieldsDirty( true, NULL, 0 ); |
| |
| return sal_True; |
| } |
| |
| |
| // Erfrage wie attributiert ist |
| sal_Bool SwDoc::GetTableAutoFmt( const SwSelBoxes& rBoxes, SwTableAutoFmt& rGet ) |
| { |
| ASSERT( rBoxes.Count(), "keine gueltige Box-Liste" ); |
| SwTableNode* pTblNd = (SwTableNode*)rBoxes[0]->GetSttNd()->FindTableNode(); |
| if( !pTblNd ) |
| return sal_False; |
| |
| // suche alle Boxen / Lines |
| _FndBox aFndBox( 0, 0 ); |
| { |
| _FndPara aPara( rBoxes, &aFndBox ); |
| pTblNd->GetTable().GetTabLines().ForEach( &_FndLineCopyCol, &aPara ); |
| } |
| if( !aFndBox.GetLines().Count() ) |
| return sal_False; |
| |
| _FndBox* pFndBox = &aFndBox; |
| while( 1 == pFndBox->GetLines().Count() && |
| 1 == pFndBox->GetLines()[0]->GetBoxes().Count() ) |
| pFndBox = pFndBox->GetLines()[0]->GetBoxes()[0]; |
| |
| if( !pFndBox->GetLines().Count() ) // eine zu weit? (nur 1 sel.Box) |
| pFndBox = pFndBox->GetUpper()->GetUpper(); |
| |
| _FndLines& rFLns = pFndBox->GetLines(); |
| |
| sal_uInt16 aLnArr[4]; |
| aLnArr[0] = 0; |
| aLnArr[1] = 1 < rFLns.Count() ? 1 : 0; |
| aLnArr[2] = 2 < rFLns.Count() ? 2 : aLnArr[1]; |
| aLnArr[3] = rFLns.Count() - 1; |
| |
| for( sal_uInt8 nLine = 0; nLine < 4; ++nLine ) |
| { |
| _FndLine& rLine = *rFLns[ aLnArr[ nLine ] ]; |
| |
| sal_uInt16 aBoxArr[4]; |
| aBoxArr[0] = 0; |
| aBoxArr[1] = 1 < rLine.GetBoxes().Count() ? 1 : 0; |
| aBoxArr[2] = 2 < rLine.GetBoxes().Count() ? 2 : aBoxArr[1]; |
| aBoxArr[3] = rLine.GetBoxes().Count() - 1; |
| |
| for( sal_uInt8 nBox = 0; nBox < 4; ++nBox ) |
| { |
| SwTableBox* pFBox = rLine.GetBoxes()[ aBoxArr[ nBox ] ]->GetBox(); |
| // immer auf die 1. runterfallen |
| while( !pFBox->GetSttNd() ) |
| pFBox = pFBox->GetTabLines()[0]->GetTabBoxes()[0]; |
| |
| sal_uInt8 nPos = nLine * 4 + nBox; |
| SwNodeIndex aIdx( *pFBox->GetSttNd(), 1 ); |
| SwCntntNode* pCNd = aIdx.GetNode().GetCntntNode(); |
| if( !pCNd ) |
| pCNd = GetNodes().GoNext( &aIdx ); |
| |
| if( pCNd ) |
| rGet.UpdateFromSet( nPos, pCNd->GetSwAttrSet(), |
| SwTableAutoFmt::UPDATE_CHAR, 0 ); |
| rGet.UpdateFromSet( nPos, pFBox->GetFrmFmt()->GetAttrSet(), |
| SwTableAutoFmt::UPDATE_BOX, |
| GetNumberFormatter( sal_True ) ); |
| } |
| } |
| |
| return sal_True; |
| } |
| |
| String SwDoc::GetUniqueTblName() const |
| { |
| ResId aId( STR_TABLE_DEFNAME, *pSwResMgr ); |
| String aName( aId ); |
| xub_StrLen nNmLen = aName.Len(); |
| |
| sal_uInt16 nNum, nTmp, nFlagSize = ( pTblFrmFmtTbl->Count() / 8 ) +2; |
| sal_uInt16 n; |
| |
| sal_uInt8* pSetFlags = new sal_uInt8[ nFlagSize ]; |
| memset( pSetFlags, 0, nFlagSize ); |
| |
| for( n = 0; n < pTblFrmFmtTbl->Count(); ++n ) |
| { |
| const SwFrmFmt* pFmt = (*pTblFrmFmtTbl)[ n ]; |
| if( !pFmt->IsDefault() && IsUsed( *pFmt ) && |
| pFmt->GetName().Match( aName ) == nNmLen ) |
| { |
| // Nummer bestimmen und das Flag setzen |
| nNum = static_cast<sal_uInt16>(pFmt->GetName().Copy( nNmLen ).ToInt32()); |
| if( nNum-- && nNum < pTblFrmFmtTbl->Count() ) |
| pSetFlags[ nNum / 8 ] |= (0x01 << ( nNum & 0x07 )); |
| } |
| } |
| |
| // alle Nummern entsprechend geflag, also bestimme die richtige Nummer |
| nNum = pTblFrmFmtTbl->Count(); |
| for( n = 0; n < nFlagSize; ++n ) |
| if( 0xff != ( nTmp = pSetFlags[ n ] )) |
| { |
| // also die Nummer bestimmen |
| nNum = n * 8; |
| while( nTmp & 1 ) |
| ++nNum, nTmp >>= 1; |
| break; |
| } |
| |
| delete [] pSetFlags; |
| return aName += String::CreateFromInt32( ++nNum ); |
| } |
| |
| SwTableFmt* SwDoc::FindTblFmtByName( const String& rName, sal_Bool bAll ) const |
| { |
| const SwFmt* pRet = 0; |
| if( bAll ) |
| pRet = FindFmtByName( (SvPtrarr&)*pTblFrmFmtTbl, rName ); |
| else |
| { |
| // dann nur die, die im Doc gesetzt sind |
| for( sal_uInt16 n = 0; n < pTblFrmFmtTbl->Count(); ++n ) |
| { |
| const SwFrmFmt* pFmt = (*pTblFrmFmtTbl)[ n ]; |
| if( !pFmt->IsDefault() && IsUsed( *pFmt ) && |
| pFmt->GetName() == rName ) |
| { |
| pRet = pFmt; |
| break; |
| } |
| } |
| } |
| return (SwTableFmt*)pRet; |
| } |
| |
| sal_Bool SwDoc::SetColRowWidthHeight( SwTableBox& rAktBox, sal_uInt16 eType, |
| SwTwips nAbsDiff, SwTwips nRelDiff ) |
| { |
| SwTableNode* pTblNd = (SwTableNode*)rAktBox.GetSttNd()->FindTableNode(); |
| SwUndo* pUndo = 0; |
| |
| if( nsTblChgWidthHeightType::WH_FLAG_INSDEL & eType && pTblNd->GetTable().ISA( SwDDETable )) |
| return sal_False; |
| |
| SwTableFmlUpdate aMsgHnt( &pTblNd->GetTable() ); |
| aMsgHnt.eFlags = TBL_BOXPTR; |
| UpdateTblFlds( &aMsgHnt ); |
| |
| bool const bUndo(GetIDocumentUndoRedo().DoesUndo()); |
| sal_Bool bRet = sal_False; |
| switch( eType & 0xff ) |
| { |
| case nsTblChgWidthHeightType::WH_COL_LEFT: |
| case nsTblChgWidthHeightType::WH_COL_RIGHT: |
| case nsTblChgWidthHeightType::WH_CELL_LEFT: |
| case nsTblChgWidthHeightType::WH_CELL_RIGHT: |
| { |
| bRet = pTblNd->GetTable().SetColWidth( rAktBox, |
| eType, nAbsDiff, nRelDiff, |
| (bUndo) ? &pUndo : 0 ); |
| } |
| break; |
| case nsTblChgWidthHeightType::WH_ROW_TOP: |
| case nsTblChgWidthHeightType::WH_ROW_BOTTOM: |
| case nsTblChgWidthHeightType::WH_CELL_TOP: |
| case nsTblChgWidthHeightType::WH_CELL_BOTTOM: |
| bRet = pTblNd->GetTable().SetRowHeight( rAktBox, |
| eType, nAbsDiff, nRelDiff, |
| (bUndo) ? &pUndo : 0 ); |
| break; |
| } |
| |
| GetIDocumentUndoRedo().DoUndo(bUndo); // SetColWidth can turn it off |
| if( pUndo ) |
| { |
| GetIDocumentUndoRedo().AppendUndo( pUndo ); |
| } |
| |
| if( bRet ) |
| { |
| SetModified(); |
| if( nsTblChgWidthHeightType::WH_FLAG_INSDEL & eType ) |
| SetFieldsDirty( true, NULL, 0 ); |
| } |
| return bRet; |
| } |
| |
| |
| void SwDoc::ChkBoxNumFmt( SwTableBox& rBox, sal_Bool bCallUpdate ) |
| { |
| //JP 09.07.97: Optimierung: wenn die Box schon sagt, das es Text |
| // sein soll, dann bleibt das auch Text! |
| const SfxPoolItem* pNumFmtItem = 0; |
| if( SFX_ITEM_SET == rBox.GetFrmFmt()->GetItemState( RES_BOXATR_FORMAT, |
| sal_False, &pNumFmtItem ) && GetNumberFormatter()->IsTextFormat( |
| ((SwTblBoxNumFormat*)pNumFmtItem)->GetValue() )) |
| return ; |
| |
| SwUndoTblNumFmt* pUndo = 0; |
| |
| sal_Bool bIsEmptyTxtNd, bChgd = sal_True; |
| sal_uInt32 nFmtIdx; |
| double fNumber; |
| if( rBox.HasNumCntnt( fNumber, nFmtIdx, bIsEmptyTxtNd ) ) |
| { |
| if( !rBox.IsNumberChanged() ) |
| bChgd = sal_False; |
| else |
| { |
| if (GetIDocumentUndoRedo().DoesUndo()) |
| { |
| GetIDocumentUndoRedo().StartUndo( UNDO_TABLE_AUTOFMT, NULL ); |
| pUndo = new SwUndoTblNumFmt( rBox ); |
| pUndo->SetNumFmt( nFmtIdx, fNumber ); |
| } |
| |
| SwTableBoxFmt* pBoxFmt = (SwTableBoxFmt*)rBox.GetFrmFmt(); |
| SfxItemSet aBoxSet( GetAttrPool(), RES_BOXATR_FORMAT, RES_BOXATR_VALUE ); |
| |
| sal_Bool bSetNumFmt = IsInsTblFormatNum(), bLockModify = sal_True; |
| if( bSetNumFmt ) |
| { |
| if( !IsInsTblChangeNumFormat() ) |
| { |
| if( !pNumFmtItem ) |
| bSetNumFmt = sal_False; |
| else |
| { |
| sal_uLong nOldNumFmt = ((SwTblBoxNumFormat*)pNumFmtItem)-> |
| GetValue(); |
| SvNumberFormatter* pNumFmtr = GetNumberFormatter(); |
| |
| short nFmtType = pNumFmtr->GetType( nFmtIdx ); |
| if( nFmtType == pNumFmtr->GetType( nOldNumFmt ) || |
| NUMBERFORMAT_NUMBER == nFmtType ) |
| // eingstelltes und vorgegebenes NumFormat |
| // stimmen ueberein -> altes Format beibehalten |
| nFmtIdx = nOldNumFmt; |
| else |
| // eingstelltes und vorgegebenes NumFormat |
| // stimmen nicht ueberein -> als Text einfuegen |
| bLockModify = bSetNumFmt = sal_False; |
| } |
| } |
| |
| if( bSetNumFmt ) |
| { |
| pBoxFmt = (SwTableBoxFmt*)rBox.ClaimFrmFmt(); |
| |
| aBoxSet.Put( SwTblBoxValue( fNumber )); |
| aBoxSet.Put( SwTblBoxNumFormat( nFmtIdx )); |
| } |
| } |
| |
| // JP 28.04.98: Nur Formel zuruecksetzen reicht nicht. |
| // Sorge dafuer, das der Text auch entsprechend |
| // formatiert wird! |
| |
| if( !bSetNumFmt && !bIsEmptyTxtNd && pNumFmtItem ) |
| { |
| // JP 15.01.99: Nur Attribute zuruecksetzen reicht nicht. |
| // Sorge dafuer, das der Text auch entsprechend |
| // formatiert wird! |
| pBoxFmt->SetFmtAttr( *GetDfltAttr( RES_BOXATR_FORMAT )); |
| } |
| |
| if( bLockModify ) pBoxFmt->LockModify(); |
| pBoxFmt->ResetFmtAttr( RES_BOXATR_FORMAT, RES_BOXATR_VALUE ); |
| if( bLockModify ) pBoxFmt->UnlockModify(); |
| |
| if( bSetNumFmt ) |
| pBoxFmt->SetFmtAttr( aBoxSet ); |
| } |
| } |
| else |
| { |
| // es ist keine Zahl |
| const SfxPoolItem* pValueItem = 0, *pFmtItem = 0; |
| SwTableBoxFmt* pBoxFmt = (SwTableBoxFmt*)rBox.GetFrmFmt(); |
| if( SFX_ITEM_SET == pBoxFmt->GetItemState( RES_BOXATR_FORMAT, |
| sal_False, &pFmtItem ) || |
| SFX_ITEM_SET == pBoxFmt->GetItemState( RES_BOXATR_VALUE, |
| sal_False, &pValueItem )) |
| { |
| if (GetIDocumentUndoRedo().DoesUndo()) |
| { |
| GetIDocumentUndoRedo().StartUndo( UNDO_TABLE_AUTOFMT, NULL ); |
| pUndo = new SwUndoTblNumFmt( rBox ); |
| } |
| |
| pBoxFmt = (SwTableBoxFmt*)rBox.ClaimFrmFmt(); |
| |
| // alle Zahlenformate entfernen |
| sal_uInt16 nWhich1 = RES_BOXATR_FORMULA; |
| if( !bIsEmptyTxtNd ) |
| //JP 15.01.99: dieser Teil wurde doch schon oben abgeprueft! |
| /* && pFmtItem && !GetNumberFormatter()-> |
| IsTextFormat( ((SwTblBoxNumFormat*)pFmtItem)->GetValue() ) )*/ |
| { |
| nWhich1 = RES_BOXATR_FORMAT; |
| |
| // JP 15.01.99: Nur Attribute zuruecksetzen reicht nicht. |
| // Sorge dafuer, das der Text auch entsprechend |
| // formatiert wird! |
| pBoxFmt->SetFmtAttr( *GetDfltAttr( nWhich1 )); |
| } |
| pBoxFmt->ResetFmtAttr( nWhich1, RES_BOXATR_VALUE ); |
| } |
| else |
| bChgd = sal_False; |
| } |
| |
| if( bChgd ) |
| { |
| if( pUndo ) |
| { |
| pUndo->SetBox( rBox ); |
| GetIDocumentUndoRedo().AppendUndo(pUndo); |
| GetIDocumentUndoRedo().EndUndo( UNDO_END, NULL ); |
| } |
| |
| const SwTableNode* pTblNd = rBox.GetSttNd()->FindTableNode(); |
| if( bCallUpdate ) |
| { |
| SwTableFmlUpdate aTblUpdate( &pTblNd->GetTable() ); |
| UpdateTblFlds( &aTblUpdate ); |
| |
| // TL_CHART2: update charts (when cursor leaves cell and |
| // automatic update is enabled) |
| if (AUTOUPD_FIELD_AND_CHARTS == getFieldUpdateFlags(true)) |
| pTblNd->GetTable().UpdateCharts(); |
| } |
| SetModified(); |
| } |
| } |
| |
| void SwDoc::SetTblBoxFormulaAttrs( SwTableBox& rBox, const SfxItemSet& rSet ) |
| { |
| if (GetIDocumentUndoRedo().DoesUndo()) |
| { |
| GetIDocumentUndoRedo().AppendUndo( new SwUndoTblNumFmt(rBox, &rSet) ); |
| } |
| |
| SwFrmFmt* pBoxFmt = rBox.ClaimFrmFmt(); |
| if( SFX_ITEM_SET == rSet.GetItemState( RES_BOXATR_FORMULA )) |
| { |
| pBoxFmt->LockModify(); |
| pBoxFmt->ResetFmtAttr( RES_BOXATR_VALUE ); |
| pBoxFmt->UnlockModify(); |
| } |
| else if( SFX_ITEM_SET == rSet.GetItemState( RES_BOXATR_VALUE )) |
| { |
| pBoxFmt->LockModify(); |
| pBoxFmt->ResetFmtAttr( RES_BOXATR_FORMULA ); |
| pBoxFmt->UnlockModify(); |
| } |
| pBoxFmt->SetFmtAttr( rSet ); |
| SetModified(); |
| } |
| |
| void SwDoc::ClearBoxNumAttrs( const SwNodeIndex& rNode ) |
| { |
| SwStartNode* pSttNd; |
| if( 0 != ( pSttNd = rNode.GetNode(). |
| FindSttNodeByType( SwTableBoxStartNode )) && |
| 2 == pSttNd->EndOfSectionIndex() - pSttNd->GetIndex() ) |
| { |
| SwTableBox* pBox = pSttNd->FindTableNode()->GetTable(). |
| GetTblBox( pSttNd->GetIndex() ); |
| |
| const SfxPoolItem* pFmtItem = 0; |
| const SfxItemSet& rSet = pBox->GetFrmFmt()->GetAttrSet(); |
| if( SFX_ITEM_SET == rSet.GetItemState( RES_BOXATR_FORMAT, sal_False, &pFmtItem ) || |
| SFX_ITEM_SET == rSet.GetItemState( RES_BOXATR_FORMULA, sal_False ) || |
| SFX_ITEM_SET == rSet.GetItemState( RES_BOXATR_VALUE, sal_False )) |
| { |
| if (GetIDocumentUndoRedo().DoesUndo()) |
| { |
| GetIDocumentUndoRedo().AppendUndo(new SwUndoTblNumFmt(*pBox)); |
| } |
| |
| SwFrmFmt* pBoxFmt = pBox->ClaimFrmFmt(); |
| |
| //JP 01.09.97: TextFormate bleiben erhalten! |
| sal_uInt16 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->SetFmtAttr( *GetDfltAttr( RES_BOXATR_FORMAT )); |
| |
| pBoxFmt->ResetFmtAttr( nWhich1, RES_BOXATR_VALUE ); |
| SetModified(); |
| } |
| } |
| } |
| |
| // 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 |
| |
| sal_Bool SwDoc::InsCopyOfTbl( SwPosition& rInsPos, const SwSelBoxes& rBoxes, |
| const SwTable* pCpyTbl, sal_Bool bCpyName, sal_Bool bCorrPos ) |
| { |
| sal_Bool bRet; |
| |
| const SwTableNode* pSrcTblNd = pCpyTbl |
| ? pCpyTbl->GetTableNode() |
| : rBoxes[ 0 ]->GetSttNd()->FindTableNode(); |
| |
| SwTableNode * pInsTblNd = rInsPos.nNode.GetNode().FindTableNode(); |
| |
| bool const bUndo( GetIDocumentUndoRedo().DoesUndo() ); |
| if( !pCpyTbl && !pInsTblNd ) |
| { |
| SwUndoCpyTbl* pUndo = 0; |
| if (bUndo) |
| { |
| GetIDocumentUndoRedo().ClearRedo(); |
| pUndo = new SwUndoCpyTbl; |
| } |
| |
| { |
| ::sw::UndoGuard const undoGuard(GetIDocumentUndoRedo()); |
| bRet = pSrcTblNd->GetTable().MakeCopy( this, rInsPos, rBoxes, |
| sal_True, bCpyName ); |
| } |
| |
| if( pUndo ) |
| { |
| if( !bRet ) |
| { |
| delete pUndo; |
| pUndo = 0; |
| } |
| else |
| { |
| pInsTblNd = GetNodes()[ rInsPos.nNode.GetIndex() - 1 ]->FindTableNode(); |
| |
| pUndo->SetTableSttIdx( pInsTblNd->GetIndex() ); |
| GetIDocumentUndoRedo().AppendUndo( pUndo ); |
| } |
| } |
| } |
| else |
| { |
| RedlineMode_t eOld = GetRedlineMode(); |
| if( IsRedlineOn() ) |
| SetRedlineMode( (RedlineMode_t)(nsRedlineMode_t::REDLINE_ON | |
| nsRedlineMode_t::REDLINE_SHOW_INSERT | |
| nsRedlineMode_t::REDLINE_SHOW_DELETE)); |
| |
| SwUndoTblCpyTbl* pUndo = 0; |
| if (bUndo) |
| { |
| GetIDocumentUndoRedo().ClearRedo(); |
| pUndo = new SwUndoTblCpyTbl; |
| GetIDocumentUndoRedo().DoUndo(false); |
| } |
| |
| SwDoc* pCpyDoc = (SwDoc*)pSrcTblNd->GetDoc(); |
| sal_Bool bDelCpyDoc = pCpyDoc == this; |
| |
| if( bDelCpyDoc ) |
| { |
| // kopiere die Tabelle erstmal in ein temp. Doc |
| pCpyDoc = new SwDoc; |
| pCpyDoc->acquire(); |
| |
| SwPosition aPos( SwNodeIndex( pCpyDoc->GetNodes().GetEndOfContent() )); |
| if( !pSrcTblNd->GetTable().MakeCopy( pCpyDoc, aPos, rBoxes, sal_True, sal_True )) |
| { |
| if( pCpyDoc->release() == 0 ) |
| delete pCpyDoc; |
| |
| if( pUndo ) |
| { |
| GetIDocumentUndoRedo().DoUndo(bUndo); |
| delete pUndo; |
| pUndo = 0; |
| } |
| return sal_False; |
| } |
| aPos.nNode -= 1; // auf den EndNode der Tabelle |
| pSrcTblNd = aPos.nNode.GetNode().FindTableNode(); |
| } |
| |
| const SwStartNode* pSttNd = rInsPos.nNode.GetNode().FindTableBoxStartNode(); |
| |
| rInsPos.nContent.Assign( 0, 0 ); |
| |
| // no complex into complex, but copy into or from new model is welcome |
| if( ( !pSrcTblNd->GetTable().IsTblComplex() || pInsTblNd->GetTable().IsNewModel() ) |
| && ( bDelCpyDoc || rBoxes.Count() ) ) |
| { |
| // dann die Tabelle "relativ" kopieren |
| const SwSelBoxes* pBoxes; |
| SwSelBoxes aBoxes; |
| |
| if( bDelCpyDoc ) |
| { |
| SwTableBox* pBox = pInsTblNd->GetTable().GetTblBox( |
| pSttNd->GetIndex() ); |
| ASSERT( pBox, "Box steht nicht in dieser Tabelle" ); |
| aBoxes.Insert( pBox ); |
| pBoxes = &aBoxes; |
| } |
| else |
| pBoxes = &rBoxes; |
| |
| // kopiere die Tabelle in die selktierten Zellen. |
| bRet = pInsTblNd->GetTable().InsTable( pSrcTblNd->GetTable(), |
| *pBoxes, pUndo ); |
| } |
| else |
| { |
| SwNodeIndex aNdIdx( *pSttNd, 1 ); |
| bRet = pInsTblNd->GetTable().InsTable( pSrcTblNd->GetTable(), |
| aNdIdx, pUndo ); |
| } |
| |
| if( bDelCpyDoc ) |
| { |
| if( pCpyDoc->release() == 0 ) |
| delete pCpyDoc; |
| } |
| |
| if( pUndo ) |
| { |
| // falls die Tabelle nicht kopiert werden konnte, das Undo-Object |
| // wieder loeschen |
| GetIDocumentUndoRedo().DoUndo(bUndo); |
| if( !bRet && pUndo->IsEmpty() ) |
| delete pUndo; |
| else |
| { |
| GetIDocumentUndoRedo().AppendUndo(pUndo); |
| } |
| } |
| |
| if( bCorrPos ) |
| { |
| rInsPos.nNode = *pSttNd; |
| rInsPos.nContent.Assign( GetNodes().GoNext( &rInsPos.nNode ), 0 ); |
| } |
| SetRedlineMode( eOld ); |
| } |
| |
| if( bRet ) |
| { |
| SetModified(); |
| SetFieldsDirty( true, NULL, 0 ); |
| } |
| return bRet; |
| } |
| |
| |
| |
| sal_Bool SwDoc::_UnProtectTblCells( SwTable& rTbl ) |
| { |
| sal_Bool bChgd = sal_False; |
| SwUndoAttrTbl *const pUndo = (GetIDocumentUndoRedo().DoesUndo()) |
| ? new SwUndoAttrTbl( *rTbl.GetTableNode() ) |
| : 0; |
| |
| SwTableSortBoxes& rSrtBox = rTbl.GetTabSortBoxes(); |
| for( sal_uInt16 i = rSrtBox.Count(); i; ) |
| { |
| SwFrmFmt *pBoxFmt = rSrtBox[ --i ]->GetFrmFmt(); |
| if( pBoxFmt->GetProtect().IsCntntProtected() ) |
| { |
| pBoxFmt->ResetFmtAttr( RES_PROTECT ); |
| bChgd = sal_True; |
| } |
| } |
| |
| if( pUndo ) |
| { |
| if( bChgd ) |
| { |
| GetIDocumentUndoRedo().AppendUndo( pUndo ); |
| } |
| else |
| delete pUndo; |
| } |
| return bChgd; |
| } |
| |
| |
| sal_Bool SwDoc::UnProtectCells( const String& rName ) |
| { |
| sal_Bool bChgd = sal_False; |
| SwTableFmt* pFmt = FindTblFmtByName( rName ); |
| if( pFmt ) |
| { |
| bChgd = _UnProtectTblCells( *SwTable::FindTable( pFmt ) ); |
| if( bChgd ) |
| SetModified(); |
| } |
| |
| return bChgd; |
| } |
| |
| sal_Bool SwDoc::UnProtectCells( const SwSelBoxes& rBoxes ) |
| { |
| sal_Bool bChgd = sal_False; |
| if( rBoxes.Count() ) |
| { |
| SwUndoAttrTbl *const pUndo = (GetIDocumentUndoRedo().DoesUndo()) |
| ? new SwUndoAttrTbl( *rBoxes[0]->GetSttNd()->FindTableNode() ) |
| : 0; |
| |
| SvPtrarr aFmts( 16 ), aNewFmts( 16 ); |
| for( sal_uInt16 i = rBoxes.Count(); i; ) |
| { |
| SwTableBox* pBox = rBoxes[ --i ]; |
| SwFrmFmt* pBoxFmt = pBox->GetFrmFmt(); |
| if( pBoxFmt->GetProtect().IsCntntProtected() ) |
| { |
| sal_uInt16 nFnd = aFmts.GetPos( pBoxFmt ); |
| if( USHRT_MAX != nFnd ) |
| pBox->ChgFrmFmt( (SwTableBoxFmt*)aNewFmts[ nFnd ] ); |
| else |
| { |
| aFmts.Insert( pBoxFmt, aFmts.Count() ); |
| pBoxFmt = pBox->ClaimFrmFmt(); |
| pBoxFmt->ResetFmtAttr( RES_PROTECT ); |
| aNewFmts.Insert( pBoxFmt, aNewFmts.Count() ); |
| } |
| bChgd = sal_True; |
| } |
| } |
| |
| if( pUndo ) |
| { |
| if( bChgd ) |
| { |
| GetIDocumentUndoRedo().AppendUndo( pUndo ); |
| } |
| else |
| delete pUndo; |
| } |
| } |
| return bChgd; |
| } |
| |
| sal_Bool SwDoc::UnProtectTbls( const SwPaM& rPam ) |
| { |
| GetIDocumentUndoRedo().StartUndo(UNDO_EMPTY, NULL); |
| |
| sal_Bool bChgd = sal_False, bHasSel = rPam.HasMark() || |
| rPam.GetNext() != (SwPaM*)&rPam; |
| SwFrmFmts& rFmts = *GetTblFrmFmts(); |
| SwTable* pTbl; |
| const SwTableNode* pTblNd; |
| for( sal_uInt16 n = rFmts.Count(); n ; ) |
| if( 0 != (pTbl = SwTable::FindTable( rFmts[ --n ] )) && |
| 0 != (pTblNd = pTbl->GetTableNode() ) && |
| pTblNd->GetNodes().IsDocNodes() ) |
| { |
| sal_uLong nTblIdx = pTblNd->GetIndex(); |
| |
| // dann ueberpruefe ob Tabelle in der Selection liegt |
| if( bHasSel ) |
| { |
| int bFound = sal_False; |
| SwPaM* pTmp = (SwPaM*)&rPam; |
| do { |
| const SwPosition *pStt = pTmp->Start(), |
| *pEnd = pTmp->End(); |
| bFound = pStt->nNode.GetIndex() < nTblIdx && |
| nTblIdx < pEnd->nNode.GetIndex(); |
| |
| } while( !bFound && &rPam != ( pTmp = (SwPaM*)pTmp->GetNext() ) ); |
| if( !bFound ) |
| continue; // weitersuchen |
| } |
| |
| // dann mal den Schutz aufheben |
| bChgd |= _UnProtectTblCells( *pTbl ); |
| } |
| |
| GetIDocumentUndoRedo().EndUndo(UNDO_EMPTY, NULL); |
| if( bChgd ) |
| SetModified(); |
| |
| return bChgd; |
| } |
| |
| sal_Bool SwDoc::HasTblAnyProtection( const SwPosition* pPos, |
| const String* pTblName, |
| sal_Bool* pFullTblProtection ) |
| { |
| sal_Bool bHasProtection = sal_False; |
| SwTable* pTbl = 0; |
| if( pTblName ) |
| pTbl = SwTable::FindTable( FindTblFmtByName( *pTblName ) ); |
| else if( pPos ) |
| { |
| SwTableNode* pTblNd = pPos->nNode.GetNode().FindTableNode(); |
| if( pTblNd ) |
| pTbl = &pTblNd->GetTable(); |
| } |
| |
| if( pTbl ) |
| { |
| SwTableSortBoxes& rSrtBox = pTbl->GetTabSortBoxes(); |
| for( sal_uInt16 i = rSrtBox.Count(); i; ) |
| { |
| SwFrmFmt *pBoxFmt = rSrtBox[ --i ]->GetFrmFmt(); |
| if( pBoxFmt->GetProtect().IsCntntProtected() ) |
| { |
| if( !bHasProtection ) |
| { |
| bHasProtection = sal_True; |
| if( !pFullTblProtection ) |
| break; |
| *pFullTblProtection = sal_True; |
| } |
| } |
| else if( bHasProtection && pFullTblProtection ) |
| { |
| *pFullTblProtection = sal_False; |
| break; |
| } |
| } |
| } |
| return bHasProtection; |
| } |
| |
| #ifdef DEL_TABLE_REDLINES |
| lcl_DelRedlines::lcl_DelRedlines( const SwTableNode& rNd, |
| sal_Bool bCheckForOwnRedline ) |
| : pDoc( (SwDoc*)rNd.GetNodes().GetDoc() ) |
| { |
| pDoc->StartUndo(UNDO_EMPTY, NULL); |
| const SwRedlineTbl& rTbl = pDoc->GetRedlineTbl(); |
| if( !pDoc->IsIgnoreRedline() && rTbl.Count() ) |
| { |
| sal_Bool bDelete = sal_True; |
| if( bCheckForOwnRedline ) |
| { |
| sal_uInt16 nRedlPos = pDoc->GetRedlinePos( rNd, USHRT_MAX ); |
| sal_uInt32 nSttNd = rNd.GetIndex(), |
| nEndNd = rNd.EndOfSectionIndex(); |
| |
| for ( ; nRedlPos < rTbl.Count(); ++nRedlPos ) |
| { |
| const SwRedline* pRedline = rTbl[ nRedlPos ]; |
| const SwPosition* pStt = pRedline->Start(), |
| * pEnd = pStt == pRedline->GetPoint() |
| ? pRedline->GetMark() |
| : pRedline->GetPoint(); |
| if( pStt->nNode <= nSttNd ) |
| { |
| if( pEnd->nNode >= nEndNd && |
| pRedline->GetAuthor() == pDoc->GetRedlineAuthor() ) |
| { |
| bDelete = sal_False; |
| break; |
| } |
| } |
| else |
| break; |
| } |
| } |
| if( bDelete ) |
| { |
| SwPaM aPam(*rNd.EndOfSectionNode(), rNd); |
| pDoc->AcceptRedline( aPam, true ); |
| } |
| } |
| } |
| #endif |
| |
| |