merge the formfield patch from ooo-build
[ooovba.git] / sw / source / core / edit / edtab.cxx
blobb4e6ceb991939473d495723bfe08f0bdb4df8287
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: edtab.cxx,v $
10 * $Revision: 1.22 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
34 #include <com/sun/star/chart2/XChartDocument.hpp>
35 #include <hintids.hxx>
36 #include <hints.hxx>
38 #define _SVSTDARR_ULONGS
39 #include <svtools/svstdarr.hxx>
41 #ifndef _APP_HXX //autogen
42 #include <vcl/svapp.hxx>
43 #endif
44 #include <vcl/window.hxx>
45 #include <svx/boxitem.hxx>
46 #include <swwait.hxx>
47 #include <fmtfsize.hxx>
48 #include <frmatr.hxx>
49 #include <editsh.hxx>
50 #include <doc.hxx>
51 #include <cntfrm.hxx>
52 #include <pam.hxx>
53 #include <ndtxt.hxx>
54 #include <fldbas.hxx>
55 #include <swtable.hxx>
56 #include <swundo.hxx>
57 #include <tblsel.hxx>
58 #include <edimp.hxx>
59 #include <tabfrm.hxx>
60 #include <cellfrm.hxx>
61 #include <cellatr.hxx>
62 #include <swtblfmt.hxx>
63 #include <swddetbl.hxx>
64 #include <mdiexp.hxx>
65 #include <unochart.hxx>
67 using namespace ::com::sun::star;
68 using namespace ::com::sun::star::uno;
70 extern void ClearFEShellTabCols();
72 const SwTable& SwEditShell::InsertTable( const SwInsertTableOptions& rInsTblOpts,
73 USHORT nRows, USHORT nCols,
74 sal_Int16 eAdj,
75 const SwTableAutoFmt* pTAFmt )
77 StartAllAction();
78 SwPosition* pPos = GetCrsr()->GetPoint();
80 BOOL bEndUndo = 0 != pPos->nContent.GetIndex();
81 if( bEndUndo )
83 StartUndo( UNDO_START );
84 GetDoc()->SplitNode( *pPos, false );
87 /* #109161# If called from a shell the adjust item is propagated
88 from pPos to the new content nodes in the table.
90 const SwTable *pTable = GetDoc()->InsertTable( rInsTblOpts, *pPos,
91 nRows, nCols,
92 eAdj, pTAFmt,
93 0, TRUE );
94 if( bEndUndo )
95 EndUndo( UNDO_END );
97 EndAllAction();
98 return *pTable;
101 BOOL SwEditShell::TextToTable( const SwInsertTableOptions& rInsTblOpts,
102 sal_Unicode cCh,
103 sal_Int16 eAdj,
104 const SwTableAutoFmt* pTAFmt )
106 SwWait aWait( *GetDoc()->GetDocShell(), TRUE );
107 BOOL bRet = FALSE;
108 StartAllAction();
109 FOREACHPAM_START(this)
110 if( PCURCRSR->HasMark() )
111 bRet |= 0 != GetDoc()->TextToTable( rInsTblOpts, *PCURCRSR, cCh,
112 eAdj, pTAFmt );
113 FOREACHPAM_END()
114 EndAllAction();
115 return bRet;
118 BOOL SwEditShell::TableToText( sal_Unicode cCh )
120 SwWait aWait( *GetDoc()->GetDocShell(), TRUE );
121 BOOL bRet = FALSE;
122 SwPaM* pCrsr = GetCrsr();
123 const SwTableNode* pTblNd =
124 GetDoc()->IsIdxInTbl( pCrsr->GetPoint()->nNode );
125 if( IsTableMode() )
127 ClearMark();
128 pCrsr = GetCrsr();
130 else if( !pTblNd || pCrsr->GetNext() != pCrsr )
131 return bRet;
133 // TL_CHART2:
134 // tell the charts about the table to be deleted and have them use their own data
135 GetDoc()->CreateChartInternalDataProviders( &pTblNd->GetTable() );
137 StartAllAction();
139 // verschiebe den akt. Cursor aus dem Tabellen Bereich
140 // angemeldet ist
141 SwNodeIndex aTabIdx( *pTblNd );
142 pCrsr->DeleteMark();
143 pCrsr->GetPoint()->nNode = *pTblNd->EndOfSectionNode();
144 pCrsr->GetPoint()->nContent.Assign( 0, 0 );
145 // SPoint und Mark aus dem Bereich verschieben !!!
146 pCrsr->SetMark();
147 pCrsr->DeleteMark();
149 bRet = GetDoc()->TableToText( pTblNd, cCh );
150 pCrsr->GetPoint()->nNode = aTabIdx;
152 SwCntntNode* pCNd = pCrsr->GetCntntNode();
153 if( !pCNd )
154 pCrsr->Move( fnMoveForward, fnGoCntnt );
155 else
156 pCrsr->GetPoint()->nContent.Assign( pCNd, 0 );
158 EndAllAction();
159 return bRet;
162 BOOL SwEditShell::IsTextToTableAvailable() const
164 BOOL bOnlyText = FALSE;
165 FOREACHPAM_START(this)
166 if( PCURCRSR->HasMark() && *PCURCRSR->GetPoint() != *PCURCRSR->GetMark() )
168 bOnlyText = TRUE;
170 // pruefe ob in der Selection eine Tabelle liegt
171 ULONG nStt = PCURCRSR->GetMark()->nNode.GetIndex(),
172 nEnd = PCURCRSR->GetPoint()->nNode.GetIndex();
173 if( nStt > nEnd ) { ULONG n = nStt; nStt = nEnd; nEnd = n; }
175 for( ; nStt <= nEnd; ++nStt )
176 if( !GetDoc()->GetNodes()[ nStt ]->IsTxtNode() )
178 bOnlyText = FALSE;
179 break;
182 if( !bOnlyText )
183 break;
185 FOREACHPAM_END()
187 return bOnlyText;
190 void SwEditShell::InsertDDETable( const SwInsertTableOptions& rInsTblOpts,
191 SwDDEFieldType* pDDEType,
192 USHORT nRows, USHORT nCols,
193 sal_Int16 eAdj )
195 SwPosition* pPos = GetCrsr()->GetPoint();
197 StartAllAction();
199 BOOL bEndUndo = 0 != pPos->nContent.GetIndex();
200 if( bEndUndo )
202 StartUndo( UNDO_START );
203 GetDoc()->SplitNode( *pPos, false );
206 const SwInsertTableOptions aInsTblOpts( rInsTblOpts.mnInsMode | tabopts::DEFAULT_BORDER,
207 rInsTblOpts.mnRowsToRepeat );
208 SwTable* pTbl = (SwTable*)GetDoc()->InsertTable( aInsTblOpts, *pPos,
209 nRows, nCols, eAdj );
211 SwTableNode* pTblNode = (SwTableNode*)pTbl->GetTabSortBoxes()[ 0 ]->
212 GetSttNd()->FindTableNode();
213 SwDDETable* pDDETbl = new SwDDETable( *pTbl, pDDEType );
214 pTblNode->SetNewTable( pDDETbl ); // setze die DDE-Tabelle
216 if( bEndUndo )
217 EndUndo( UNDO_END );
219 EndAllAction();
222 /*--------------------------------------------------------------------
223 Beschreibung: Tabellenfelder einer Tabelle updaten
224 --------------------------------------------------------------------*/
225 void SwEditShell::UpdateTable()
227 const SwTableNode* pTblNd = IsCrsrInTbl();
229 // Keine Arme keine Kekse
230 if( pTblNd )
232 StartAllAction();
233 if( DoesUndo() )
234 StartUndo();
235 EndAllTblBoxEdit();
236 SwTableFmlUpdate aTblUpdate( (SwTable*)&pTblNd->GetTable() );
237 GetDoc()->UpdateTblFlds( &aTblUpdate );
238 if( DoesUndo() )
239 EndUndo();
240 EndAllAction();
244 // Change Modus erfragen/setzen
245 TblChgMode SwEditShell::GetTblChgMode() const
247 TblChgMode eMode;
248 const SwTableNode* pTblNd = IsCrsrInTbl();
249 if( pTblNd )
250 eMode = pTblNd->GetTable().GetTblChgMode();
251 else
252 eMode = GetTblChgDefaultMode();
253 return eMode;
256 void SwEditShell::SetTblChgMode( TblChgMode eMode )
258 const SwTableNode* pTblNd = IsCrsrInTbl();
260 // Keine Arme keine Kekse
261 if( pTblNd )
263 ((SwTable&)pTblNd->GetTable()).SetTblChgMode( eMode );
264 if( !GetDoc()->IsModified() ) // Bug 57028
265 GetDoc()->SetUndoNoResetModified();
266 GetDoc()->SetModified();
270 BOOL SwEditShell::GetTblBoxFormulaAttrs( SfxItemSet& rSet ) const
272 SwSelBoxes aBoxes;
273 if( IsTableMode() )
274 ::GetTblSelCrs( *this, aBoxes );
275 else
277 do {
278 SwFrm *pFrm = GetCurrFrm();
279 do {
280 pFrm = pFrm->GetUpper();
281 } while ( pFrm && !pFrm->IsCellFrm() );
282 if ( pFrm )
284 SwTableBox *pBox = (SwTableBox*)((SwCellFrm*)pFrm)->GetTabBox();
285 aBoxes.Insert( pBox );
287 } while( FALSE );
290 for( USHORT n = 0; n < aBoxes.Count(); ++n )
292 const SwTableBox* pSelBox = aBoxes[ n ];
293 const SwTableBoxFmt* pTblFmt = (SwTableBoxFmt*)pSelBox->GetFrmFmt();
294 if( !n )
296 // Formeln in die externe Darstellung bringen!
297 const SwTable& rTbl = pSelBox->GetSttNd()->FindTableNode()->GetTable();
299 SwTableFmlUpdate aTblUpdate( (SwTable*)&rTbl );
300 aTblUpdate.eFlags = TBL_BOXNAME;
301 ((SwDoc*)GetDoc())->UpdateTblFlds( &aTblUpdate );
303 rSet.Put( pTblFmt->GetAttrSet() );
305 else
306 rSet.MergeValues( pTblFmt->GetAttrSet() );
308 return 0 != rSet.Count();
311 void SwEditShell::SetTblBoxFormulaAttrs( const SfxItemSet& rSet )
313 SET_CURR_SHELL( this );
314 SwSelBoxes aBoxes;
315 if( IsTableMode() )
316 ::GetTblSelCrs( *this, aBoxes );
317 else
319 do {
320 SwFrm *pFrm = GetCurrFrm();
321 do {
322 pFrm = pFrm->GetUpper();
323 } while ( pFrm && !pFrm->IsCellFrm() );
324 if ( pFrm )
326 SwTableBox *pBox = (SwTableBox*)((SwCellFrm*)pFrm)->GetTabBox();
327 aBoxes.Insert( pBox );
329 } while( FALSE );
332 // beim setzen einer Formel keine Ueberpruefung mehr vornehmen!
333 if( SFX_ITEM_SET == rSet.GetItemState( RES_BOXATR_FORMULA ))
334 ClearTblBoxCntnt();
336 StartAllAction();
337 GetDoc()->StartUndo( UNDO_START, NULL );
338 for( USHORT n = 0; n < aBoxes.Count(); ++n )
339 GetDoc()->SetTblBoxFormulaAttrs( *aBoxes[ n ], rSet );
340 GetDoc()->EndUndo( UNDO_END, NULL );
341 EndAllAction();
344 BOOL SwEditShell::IsTableBoxTextFormat() const
346 if( IsTableMode() )
347 return FALSE;
349 SwTableBox *pBox = 0;
351 SwFrm *pFrm = GetCurrFrm();
352 do {
353 pFrm = pFrm->GetUpper();
354 } while ( pFrm && !pFrm->IsCellFrm() );
355 if ( pFrm )
356 pBox = (SwTableBox*)((SwCellFrm*)pFrm)->GetTabBox();
359 if( !pBox )
360 return FALSE;
362 sal_uInt32 nFmt;
363 const SfxPoolItem* pItem;
364 if( SFX_ITEM_SET == pBox->GetFrmFmt()->GetAttrSet().GetItemState(
365 RES_BOXATR_FORMAT, TRUE, &pItem ))
367 nFmt = ((SwTblBoxNumFormat*)pItem)->GetValue();
368 return GetDoc()->GetNumberFormatter()->IsTextFormat( nFmt ) ||
369 NUMBERFORMAT_TEXT == nFmt;
372 ULONG nNd = pBox->IsValidNumTxtNd();
373 if( ULONG_MAX == nNd )
374 return TRUE;
376 const String& rTxt = GetDoc()->GetNodes()[ nNd ]->GetTxtNode()->GetTxt();
377 if( !rTxt.Len() )
378 return FALSE;
380 double fVal;
381 return !GetDoc()->GetNumberFormatter()->IsNumberFormat( rTxt, nFmt, fVal );
384 String SwEditShell::GetTableBoxText() const
386 String sRet;
387 if( !IsTableMode() )
389 SwTableBox *pBox = 0;
391 SwFrm *pFrm = GetCurrFrm();
392 do {
393 pFrm = pFrm->GetUpper();
394 } while ( pFrm && !pFrm->IsCellFrm() );
395 if ( pFrm )
396 pBox = (SwTableBox*)((SwCellFrm*)pFrm)->GetTabBox();
399 ULONG nNd;
400 if( pBox && ULONG_MAX != ( nNd = pBox->IsValidNumTxtNd() ) )
401 sRet = GetDoc()->GetNodes()[ nNd ]->GetTxtNode()->GetTxt();
403 return sRet;
406 BOOL SwEditShell::SplitTable( USHORT eMode )
408 BOOL bRet = FALSE;
409 SwPaM *pCrsr = GetCrsr();
410 if( pCrsr->GetNode()->FindTableNode() )
412 StartAllAction();
413 GetDoc()->StartUndo(UNDO_EMPTY, NULL);
415 bRet = GetDoc()->SplitTable( *pCrsr->GetPoint(), eMode, TRUE );
417 GetDoc()->EndUndo(UNDO_EMPTY, NULL);
418 ClearFEShellTabCols();
419 EndAllAction();
421 return bRet;
424 BOOL SwEditShell::MergeTable( BOOL bWithPrev, USHORT nMode )
426 BOOL bRet = FALSE;
427 SwPaM *pCrsr = GetCrsr();
428 if( pCrsr->GetNode()->FindTableNode() )
430 StartAllAction();
431 GetDoc()->StartUndo(UNDO_EMPTY, NULL);
433 bRet = GetDoc()->MergeTable( *pCrsr->GetPoint(), bWithPrev, nMode );
435 GetDoc()->EndUndo(UNDO_EMPTY, NULL);
436 ClearFEShellTabCols();
437 EndAllAction();
439 return bRet;
442 BOOL SwEditShell::CanMergeTable( BOOL bWithPrev, BOOL* pChkNxtPrv ) const
444 BOOL bRet = FALSE;
445 const SwPaM *pCrsr = GetCrsr();
446 const SwTableNode* pTblNd = pCrsr->GetNode()->FindTableNode();
447 if( pTblNd && !pTblNd->GetTable().ISA( SwDDETable ))
449 BOOL bNew = pTblNd->GetTable().IsNewModel();
450 const SwNodes& rNds = GetDoc()->GetNodes();
451 if( pChkNxtPrv )
453 const SwTableNode* pChkNd = rNds[ pTblNd->GetIndex() - 1 ]->FindTableNode();
454 if( pChkNd && !pChkNd->GetTable().ISA( SwDDETable ) &&
455 bNew == pChkNd->GetTable().IsNewModel() &&
456 // --> FME 2004-09-17 #117418# Consider table in table case
457 pChkNd->EndOfSectionIndex() == pTblNd->GetIndex() - 1 )
458 // <--
459 *pChkNxtPrv = TRUE, bRet = TRUE; // mit Prev ist moeglich
460 else
462 pChkNd = rNds[ pTblNd->EndOfSectionIndex() + 1 ]->GetTableNode();
463 if( pChkNd && !pChkNd->GetTable().ISA( SwDDETable ) &&
464 bNew == pChkNd->GetTable().IsNewModel() )
465 *pChkNxtPrv = FALSE, bRet = TRUE; // mit Next ist moeglich
468 else
470 const SwTableNode* pTmpTblNd = 0;
472 if( bWithPrev )
474 pTmpTblNd = rNds[ pTblNd->GetIndex() - 1 ]->FindTableNode();
475 // --> FME 2004-09-17 #117418# Consider table in table case
476 if ( pTmpTblNd && pTmpTblNd->EndOfSectionIndex() != pTblNd->GetIndex() - 1 )
477 pTmpTblNd = 0;
478 // <--
480 else
481 pTmpTblNd = rNds[ pTblNd->EndOfSectionIndex() + 1 ]->GetTableNode();
483 bRet = pTmpTblNd && !pTmpTblNd->GetTable().ISA( SwDDETable ) &&
484 bNew == pTmpTblNd->GetTable().IsNewModel();
487 return bRet;
490 // setze das InsertDB als Tabelle Undo auf:
491 void SwEditShell::AppendUndoForInsertFromDB( BOOL bIsTable )
493 GetDoc()->AppendUndoForInsertFromDB( *GetCrsr(), bIsTable );