/************************************************************** * * 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 #include #include #define _SVSTDARR_ULONGS #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace ::com::sun::star; using namespace ::com::sun::star::uno; extern void ClearFEShellTabCols(); //Added for bug 119954:Application crashed if undo/redo covert nest table to text sal_Bool ConvertTableToText( const SwTableNode *pTableNode, sal_Unicode cCh ); void ConvertNestedTablesToText( const SwTableLines &rTableLines, sal_Unicode cCh ) { for( sal_uInt16 n = 0; n < rTableLines.Count(); ++n ) { SwTableLine* pTableLine = rTableLines[ n ]; for( sal_uInt16 i = 0; i < pTableLine->GetTabBoxes().Count(); ++i ) { SwTableBox* pTableBox = pTableLine->GetTabBoxes()[ i ]; if ( !pTableBox->GetTabLines().Count() ) { SwNodeIndex nodeIndex( *pTableBox->GetSttNd(), 1 ); SwNodeIndex endNodeIndex( *pTableBox->GetSttNd()->EndOfSectionNode() ); for( ; nodeIndex < endNodeIndex ; nodeIndex++ ) { if ( SwTableNode* pTableNode = nodeIndex.GetNode().GetTableNode() ) ConvertTableToText( pTableNode, cCh ); } } else { ConvertNestedTablesToText( pTableBox->GetTabLines(), cCh ); } } } } sal_Bool ConvertTableToText( const SwTableNode *pConstTableNode, sal_Unicode cCh ) { SwTableNode *pTableNode = const_cast< SwTableNode* >( pConstTableNode ); ConvertNestedTablesToText( pTableNode->GetTable().GetTabLines(), cCh ); return pTableNode->GetDoc()->TableToText( pTableNode, cCh ); } //End for bug 119954 const SwTable& SwEditShell::InsertTable( const SwInsertTableOptions& rInsTblOpts, sal_uInt16 nRows, sal_uInt16 nCols, sal_Int16 eAdj, const SwTableAutoFmt* pTAFmt ) { StartAllAction(); SwPosition* pPos = GetCrsr()->GetPoint(); sal_Bool bEndUndo = 0 != pPos->nContent.GetIndex(); if( bEndUndo ) { StartUndo( UNDO_START ); GetDoc()->SplitNode( *pPos, false ); } /* #109161# If called from a shell the adjust item is propagated from pPos to the new content nodes in the table. */ const SwTable *pTable = GetDoc()->InsertTable( rInsTblOpts, *pPos, nRows, nCols, eAdj, pTAFmt, 0, sal_True ); if( bEndUndo ) EndUndo( UNDO_END ); EndAllAction(); return *pTable; } sal_Bool SwEditShell::TextToTable( const SwInsertTableOptions& rInsTblOpts, sal_Unicode cCh, sal_Int16 eAdj, const SwTableAutoFmt* pTAFmt ) { SwWait aWait( *GetDoc()->GetDocShell(), true ); sal_Bool bRet = sal_False; StartAllAction(); FOREACHPAM_START(this) if( PCURCRSR->HasMark() ) bRet |= 0 != GetDoc()->TextToTable( rInsTblOpts, *PCURCRSR, cCh, eAdj, pTAFmt ); FOREACHPAM_END() EndAllAction(); return bRet; } sal_Bool SwEditShell::TableToText( sal_Unicode cCh ) { SwWait aWait( *GetDoc()->GetDocShell(), true ); sal_Bool bRet = sal_False; SwPaM* pCrsr = GetCrsr(); const SwTableNode* pTblNd = GetDoc()->IsIdxInTbl( pCrsr->GetPoint()->nNode ); if( IsTableMode() ) { ClearMark(); pCrsr = GetCrsr(); } else if( !pTblNd || pCrsr->GetNext() != pCrsr ) return bRet; // TL_CHART2: // tell the charts about the table to be deleted and have them use their own data GetDoc()->CreateChartInternalDataProviders( &pTblNd->GetTable() ); StartAllAction(); // verschiebe den akt. Cursor aus dem Tabellen Bereich // angemeldet ist SwNodeIndex aTabIdx( *pTblNd ); pCrsr->DeleteMark(); pCrsr->GetPoint()->nNode = *pTblNd->EndOfSectionNode(); pCrsr->GetPoint()->nContent.Assign( 0, 0 ); // SPoint und Mark aus dem Bereich verschieben !!! pCrsr->SetMark(); pCrsr->DeleteMark(); //Modified for bug 119954:Application crashed if undo/redo covert nest table to text StartUndo();//UNDO_START bRet = ConvertTableToText( pTblNd, cCh ); EndUndo();//UNDO_END //End for bug 119954 pCrsr->GetPoint()->nNode = aTabIdx; SwCntntNode* pCNd = pCrsr->GetCntntNode(); if( !pCNd ) pCrsr->Move( fnMoveForward, fnGoCntnt ); else pCrsr->GetPoint()->nContent.Assign( pCNd, 0 ); EndAllAction(); return bRet; } sal_Bool SwEditShell::IsTextToTableAvailable() const { sal_Bool bOnlyText = sal_False; FOREACHPAM_START(this) if( PCURCRSR->HasMark() && *PCURCRSR->GetPoint() != *PCURCRSR->GetMark() ) { bOnlyText = sal_True; // pruefe ob in der Selection eine Tabelle liegt sal_uLong nStt = PCURCRSR->GetMark()->nNode.GetIndex(), nEnd = PCURCRSR->GetPoint()->nNode.GetIndex(); if( nStt > nEnd ) { sal_uLong n = nStt; nStt = nEnd; nEnd = n; } for( ; nStt <= nEnd; ++nStt ) if( !GetDoc()->GetNodes()[ nStt ]->IsTxtNode() ) { bOnlyText = sal_False; break; } if( !bOnlyText ) break; } FOREACHPAM_END() return bOnlyText; } void SwEditShell::InsertDDETable( const SwInsertTableOptions& rInsTblOpts, SwDDEFieldType* pDDEType, sal_uInt16 nRows, sal_uInt16 nCols, sal_Int16 eAdj ) { SwPosition* pPos = GetCrsr()->GetPoint(); StartAllAction(); sal_Bool bEndUndo = 0 != pPos->nContent.GetIndex(); if( bEndUndo ) { StartUndo( UNDO_START ); GetDoc()->SplitNode( *pPos, false ); } const SwInsertTableOptions aInsTblOpts( rInsTblOpts.mnInsMode | tabopts::DEFAULT_BORDER, rInsTblOpts.mnRowsToRepeat ); SwTable* pTbl = (SwTable*)GetDoc()->InsertTable( aInsTblOpts, *pPos, nRows, nCols, eAdj ); SwTableNode* pTblNode = (SwTableNode*)pTbl->GetTabSortBoxes()[ 0 ]-> GetSttNd()->FindTableNode(); SwDDETable* pDDETbl = new SwDDETable( *pTbl, pDDEType ); pTblNode->SetNewTable( pDDETbl ); // setze die DDE-Tabelle if( bEndUndo ) EndUndo( UNDO_END ); EndAllAction(); } /*-------------------------------------------------------------------- Beschreibung: Tabellenfelder einer Tabelle updaten --------------------------------------------------------------------*/ void SwEditShell::UpdateTable() { const SwTableNode* pTblNd = IsCrsrInTbl(); // Keine Arme keine Kekse if( pTblNd ) { StartAllAction(); if( DoesUndo() ) StartUndo(); EndAllTblBoxEdit(); SwTableFmlUpdate aTblUpdate( (SwTable*)&pTblNd->GetTable() ); GetDoc()->UpdateTblFlds( &aTblUpdate ); if( DoesUndo() ) EndUndo(); EndAllAction(); } } // Change Modus erfragen/setzen TblChgMode SwEditShell::GetTblChgMode() const { TblChgMode eMode; const SwTableNode* pTblNd = IsCrsrInTbl(); if( pTblNd ) eMode = pTblNd->GetTable().GetTblChgMode(); else eMode = GetTblChgDefaultMode(); return eMode; } void SwEditShell::SetTblChgMode( TblChgMode eMode ) { const SwTableNode* pTblNd = IsCrsrInTbl(); // Keine Arme keine Kekse if( pTblNd ) { ((SwTable&)pTblNd->GetTable()).SetTblChgMode( eMode ); if( !GetDoc()->IsModified() ) // Bug 57028 { GetDoc()->GetIDocumentUndoRedo().SetUndoNoResetModified(); } GetDoc()->SetModified(); } } sal_Bool SwEditShell::GetTblBoxFormulaAttrs( SfxItemSet& rSet ) const { SwSelBoxes aBoxes; if( IsTableMode() ) ::GetTblSelCrs( *this, aBoxes ); else { do { SwFrm *pFrm = GetCurrFrm(); do { pFrm = pFrm->GetUpper(); } while ( pFrm && !pFrm->IsCellFrm() ); if ( pFrm ) { SwTableBox *pBox = (SwTableBox*)((SwCellFrm*)pFrm)->GetTabBox(); aBoxes.Insert( pBox ); } } while( sal_False ); } for( sal_uInt16 n = 0; n < aBoxes.Count(); ++n ) { const SwTableBox* pSelBox = aBoxes[ n ]; const SwTableBoxFmt* pTblFmt = (SwTableBoxFmt*)pSelBox->GetFrmFmt(); if( !n ) { // Formeln in die externe Darstellung bringen! const SwTable& rTbl = pSelBox->GetSttNd()->FindTableNode()->GetTable(); SwTableFmlUpdate aTblUpdate( (SwTable*)&rTbl ); aTblUpdate.eFlags = TBL_BOXNAME; ((SwDoc*)GetDoc())->UpdateTblFlds( &aTblUpdate ); rSet.Put( pTblFmt->GetAttrSet() ); } else rSet.MergeValues( pTblFmt->GetAttrSet() ); } return 0 != rSet.Count(); } void SwEditShell::SetTblBoxFormulaAttrs( const SfxItemSet& rSet ) { SET_CURR_SHELL( this ); SwSelBoxes aBoxes; if( IsTableMode() ) ::GetTblSelCrs( *this, aBoxes ); else { do { SwFrm *pFrm = GetCurrFrm(); do { pFrm = pFrm->GetUpper(); } while ( pFrm && !pFrm->IsCellFrm() ); if ( pFrm ) { SwTableBox *pBox = (SwTableBox*)((SwCellFrm*)pFrm)->GetTabBox(); aBoxes.Insert( pBox ); } } while( sal_False ); } // beim setzen einer Formel keine Ueberpruefung mehr vornehmen! if( SFX_ITEM_SET == rSet.GetItemState( RES_BOXATR_FORMULA )) ClearTblBoxCntnt(); StartAllAction(); GetDoc()->GetIDocumentUndoRedo().StartUndo( UNDO_START, NULL ); for( sal_uInt16 n = 0; n < aBoxes.Count(); ++n ) GetDoc()->SetTblBoxFormulaAttrs( *aBoxes[ n ], rSet ); GetDoc()->GetIDocumentUndoRedo().EndUndo( UNDO_END, NULL ); EndAllAction(); } sal_Bool SwEditShell::IsTableBoxTextFormat() const { if( IsTableMode() ) return sal_False; SwTableBox *pBox = 0; { SwFrm *pFrm = GetCurrFrm(); do { pFrm = pFrm->GetUpper(); } while ( pFrm && !pFrm->IsCellFrm() ); if ( pFrm ) pBox = (SwTableBox*)((SwCellFrm*)pFrm)->GetTabBox(); } if( !pBox ) return sal_False; sal_uInt32 nFmt; const SfxPoolItem* pItem; if( SFX_ITEM_SET == pBox->GetFrmFmt()->GetAttrSet().GetItemState( RES_BOXATR_FORMAT, sal_True, &pItem )) { nFmt = ((SwTblBoxNumFormat*)pItem)->GetValue(); return GetDoc()->GetNumberFormatter()->IsTextFormat( nFmt ) || NUMBERFORMAT_TEXT == nFmt; } sal_uLong nNd = pBox->IsValidNumTxtNd(); if( ULONG_MAX == nNd ) return sal_True; const String& rTxt = GetDoc()->GetNodes()[ nNd ]->GetTxtNode()->GetTxt(); if( !rTxt.Len() ) return sal_False; double fVal; return !GetDoc()->GetNumberFormatter()->IsNumberFormat( rTxt, nFmt, fVal ); } String SwEditShell::GetTableBoxText() const { String sRet; if( !IsTableMode() ) { SwTableBox *pBox = 0; { SwFrm *pFrm = GetCurrFrm(); do { pFrm = pFrm->GetUpper(); } while ( pFrm && !pFrm->IsCellFrm() ); if ( pFrm ) pBox = (SwTableBox*)((SwCellFrm*)pFrm)->GetTabBox(); } sal_uLong nNd; if( pBox && ULONG_MAX != ( nNd = pBox->IsValidNumTxtNd() ) ) sRet = GetDoc()->GetNodes()[ nNd ]->GetTxtNode()->GetTxt(); } return sRet; } sal_Bool SwEditShell::SplitTable( sal_uInt16 eMode ) { sal_Bool bRet = sal_False; SwPaM *pCrsr = GetCrsr(); if( pCrsr->GetNode()->FindTableNode() ) { StartAllAction(); GetDoc()->GetIDocumentUndoRedo().StartUndo(UNDO_EMPTY, NULL); bRet = GetDoc()->SplitTable( *pCrsr->GetPoint(), eMode, sal_True ); GetDoc()->GetIDocumentUndoRedo().EndUndo(UNDO_EMPTY, NULL); ClearFEShellTabCols(); EndAllAction(); } return bRet; } sal_Bool SwEditShell::MergeTable( sal_Bool bWithPrev, sal_uInt16 nMode ) { sal_Bool bRet = sal_False; SwPaM *pCrsr = GetCrsr(); if( pCrsr->GetNode()->FindTableNode() ) { StartAllAction(); GetDoc()->GetIDocumentUndoRedo().StartUndo(UNDO_EMPTY, NULL); bRet = GetDoc()->MergeTable( *pCrsr->GetPoint(), bWithPrev, nMode ); GetDoc()->GetIDocumentUndoRedo().EndUndo(UNDO_EMPTY, NULL); ClearFEShellTabCols(); EndAllAction(); } return bRet; } sal_Bool SwEditShell::CanMergeTable( sal_Bool bWithPrev, sal_Bool* pChkNxtPrv ) const { sal_Bool bRet = sal_False; const SwPaM *pCrsr = GetCrsr(); const SwTableNode* pTblNd = pCrsr->GetNode()->FindTableNode(); if( pTblNd && !pTblNd->GetTable().ISA( SwDDETable )) { sal_Bool bNew = pTblNd->GetTable().IsNewModel(); const SwNodes& rNds = GetDoc()->GetNodes(); if( pChkNxtPrv ) { const SwTableNode* pChkNd = rNds[ pTblNd->GetIndex() - 1 ]->FindTableNode(); if( pChkNd && !pChkNd->GetTable().ISA( SwDDETable ) && bNew == pChkNd->GetTable().IsNewModel() && // --> FME 2004-09-17 #117418# Consider table in table case pChkNd->EndOfSectionIndex() == pTblNd->GetIndex() - 1 ) // <-- *pChkNxtPrv = sal_True, bRet = sal_True; // mit Prev ist moeglich else { pChkNd = rNds[ pTblNd->EndOfSectionIndex() + 1 ]->GetTableNode(); if( pChkNd && !pChkNd->GetTable().ISA( SwDDETable ) && bNew == pChkNd->GetTable().IsNewModel() ) *pChkNxtPrv = sal_False, bRet = sal_True; // mit Next ist moeglich } } else { const SwTableNode* pTmpTblNd = 0; if( bWithPrev ) { pTmpTblNd = rNds[ pTblNd->GetIndex() - 1 ]->FindTableNode(); // --> FME 2004-09-17 #117418# Consider table in table case if ( pTmpTblNd && pTmpTblNd->EndOfSectionIndex() != pTblNd->GetIndex() - 1 ) pTmpTblNd = 0; // <-- } else pTmpTblNd = rNds[ pTblNd->EndOfSectionIndex() + 1 ]->GetTableNode(); bRet = pTmpTblNd && !pTmpTblNd->GetTable().ISA( SwDDETable ) && bNew == pTmpTblNd->GetTable().IsNewModel(); } } return bRet; } // setze das InsertDB als Tabelle Undo auf: void SwEditShell::AppendUndoForInsertFromDB( sal_Bool bIsTable ) { GetDoc()->AppendUndoForInsertFromDB( *GetCrsr(), bIsTable ); }