1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sw.hxx"
26
27 #include <com/sun/star/chart2/XChartDocument.hpp>
28 #include <hintids.hxx>
29 #include <hints.hxx>
30
31 #define _SVSTDARR_ULONGS
32 #include <svl/svstdarr.hxx>
33
34 #include <vcl/svapp.hxx>
35 #include <vcl/window.hxx>
36 #include <editeng/boxitem.hxx>
37 #include <swwait.hxx>
38 #include <fmtfsize.hxx>
39 #include <frmatr.hxx>
40 #include <editsh.hxx>
41 #include <doc.hxx>
42 #include <IDocumentUndoRedo.hxx>
43 #include <cntfrm.hxx>
44 #include <pam.hxx>
45 #include <ndtxt.hxx>
46 #include <fldbas.hxx>
47 #include <swtable.hxx>
48 #include <swundo.hxx>
49 #include <tblsel.hxx>
50 #include <edimp.hxx>
51 #include <tabfrm.hxx>
52 #include <cellfrm.hxx>
53 #include <cellatr.hxx>
54 #include <swtblfmt.hxx>
55 #include <swddetbl.hxx>
56 #include <mdiexp.hxx>
57 #include <unochart.hxx>
58
59 using namespace ::com::sun::star;
60 using namespace ::com::sun::star::uno;
61
62 extern void ClearFEShellTabCols();
63
64 //Added for bug 119954:Application crashed if undo/redo covert nest table to text
65 sal_Bool ConvertTableToText( const SwTableNode *pTableNode, sal_Unicode cCh );
66
ConvertNestedTablesToText(const SwTableLines & rTableLines,sal_Unicode cCh)67 void ConvertNestedTablesToText( const SwTableLines &rTableLines, sal_Unicode cCh )
68 {
69 for( sal_uInt16 n = 0; n < rTableLines.Count(); ++n )
70 {
71 SwTableLine* pTableLine = rTableLines[ n ];
72 for( sal_uInt16 i = 0; i < pTableLine->GetTabBoxes().Count(); ++i )
73 {
74 SwTableBox* pTableBox = pTableLine->GetTabBoxes()[ i ];
75 if ( !pTableBox->GetTabLines().Count() )
76 {
77 SwNodeIndex nodeIndex( *pTableBox->GetSttNd(), 1 );
78 SwNodeIndex endNodeIndex( *pTableBox->GetSttNd()->EndOfSectionNode() );
79 for( ; nodeIndex < endNodeIndex ; nodeIndex++ )
80 {
81 if ( SwTableNode* pTableNode = nodeIndex.GetNode().GetTableNode() )
82 ConvertTableToText( pTableNode, cCh );
83 }
84 }
85 else
86 {
87 ConvertNestedTablesToText( pTableBox->GetTabLines(), cCh );
88 }
89 }
90 }
91 }
92
ConvertTableToText(const SwTableNode * pConstTableNode,sal_Unicode cCh)93 sal_Bool ConvertTableToText( const SwTableNode *pConstTableNode, sal_Unicode cCh )
94 {
95 SwTableNode *pTableNode = const_cast< SwTableNode* >( pConstTableNode );
96 ConvertNestedTablesToText( pTableNode->GetTable().GetTabLines(), cCh );
97 return pTableNode->GetDoc()->TableToText( pTableNode, cCh );
98 }
99 //End for bug 119954
InsertTable(const SwInsertTableOptions & rInsTblOpts,sal_uInt16 nRows,sal_uInt16 nCols,sal_Int16 eAdj,const SwTableAutoFmt * pTAFmt)100 const SwTable& SwEditShell::InsertTable( const SwInsertTableOptions& rInsTblOpts,
101 sal_uInt16 nRows, sal_uInt16 nCols,
102 sal_Int16 eAdj,
103 const SwTableAutoFmt* pTAFmt )
104 {
105 StartAllAction();
106 SwPosition* pPos = GetCrsr()->GetPoint();
107
108 sal_Bool bEndUndo = 0 != pPos->nContent.GetIndex();
109 if( bEndUndo )
110 {
111 StartUndo( UNDO_START );
112 GetDoc()->SplitNode( *pPos, false );
113 }
114
115 /* #109161# If called from a shell the adjust item is propagated
116 from pPos to the new content nodes in the table.
117 */
118 const SwTable *pTable = GetDoc()->InsertTable( rInsTblOpts, *pPos,
119 nRows, nCols,
120 eAdj, pTAFmt,
121 0, sal_True );
122 if( bEndUndo )
123 EndUndo( UNDO_END );
124
125 EndAllAction();
126 return *pTable;
127 }
128
TextToTable(const SwInsertTableOptions & rInsTblOpts,sal_Unicode cCh,sal_Int16 eAdj,const SwTableAutoFmt * pTAFmt)129 sal_Bool SwEditShell::TextToTable( const SwInsertTableOptions& rInsTblOpts,
130 sal_Unicode cCh,
131 sal_Int16 eAdj,
132 const SwTableAutoFmt* pTAFmt )
133 {
134 SwWait aWait( *GetDoc()->GetDocShell(), true );
135 sal_Bool bRet = sal_False;
136 StartAllAction();
137 FOREACHPAM_START(this)
138 if( PCURCRSR->HasMark() )
139 bRet |= 0 != GetDoc()->TextToTable( rInsTblOpts, *PCURCRSR, cCh,
140 eAdj, pTAFmt );
141 FOREACHPAM_END()
142 EndAllAction();
143 return bRet;
144 }
145
TableToText(sal_Unicode cCh)146 sal_Bool SwEditShell::TableToText( sal_Unicode cCh )
147 {
148 SwWait aWait( *GetDoc()->GetDocShell(), true );
149 sal_Bool bRet = sal_False;
150 SwPaM* pCrsr = GetCrsr();
151 const SwTableNode* pTblNd =
152 GetDoc()->IsIdxInTbl( pCrsr->GetPoint()->nNode );
153 if( IsTableMode() )
154 {
155 ClearMark();
156 pCrsr = GetCrsr();
157 }
158 else if( !pTblNd || pCrsr->GetNext() != pCrsr )
159 return bRet;
160
161 // TL_CHART2:
162 // tell the charts about the table to be deleted and have them use their own data
163 GetDoc()->CreateChartInternalDataProviders( &pTblNd->GetTable() );
164
165 StartAllAction();
166
167 // verschiebe den akt. Cursor aus dem Tabellen Bereich
168 // angemeldet ist
169 SwNodeIndex aTabIdx( *pTblNd );
170 pCrsr->DeleteMark();
171 pCrsr->GetPoint()->nNode = *pTblNd->EndOfSectionNode();
172 pCrsr->GetPoint()->nContent.Assign( 0, 0 );
173 // SPoint und Mark aus dem Bereich verschieben !!!
174 pCrsr->SetMark();
175 pCrsr->DeleteMark();
176
177 //Modified for bug 119954:Application crashed if undo/redo covert nest table to text
178 StartUndo();//UNDO_START
179 bRet = ConvertTableToText( pTblNd, cCh );
180 EndUndo();//UNDO_END
181 //End for bug 119954
182 pCrsr->GetPoint()->nNode = aTabIdx;
183
184 SwCntntNode* pCNd = pCrsr->GetCntntNode();
185 if( !pCNd )
186 pCrsr->Move( fnMoveForward, fnGoCntnt );
187 else
188 pCrsr->GetPoint()->nContent.Assign( pCNd, 0 );
189
190 EndAllAction();
191 return bRet;
192 }
193
IsTextToTableAvailable() const194 sal_Bool SwEditShell::IsTextToTableAvailable() const
195 {
196 sal_Bool bOnlyText = sal_False;
197 FOREACHPAM_START(this)
198 if( PCURCRSR->HasMark() && *PCURCRSR->GetPoint() != *PCURCRSR->GetMark() )
199 {
200 bOnlyText = sal_True;
201
202 // pruefe ob in der Selection eine Tabelle liegt
203 sal_uLong nStt = PCURCRSR->GetMark()->nNode.GetIndex(),
204 nEnd = PCURCRSR->GetPoint()->nNode.GetIndex();
205 if( nStt > nEnd ) { sal_uLong n = nStt; nStt = nEnd; nEnd = n; }
206
207 for( ; nStt <= nEnd; ++nStt )
208 if( !GetDoc()->GetNodes()[ nStt ]->IsTxtNode() )
209 {
210 bOnlyText = sal_False;
211 break;
212 }
213
214 if( !bOnlyText )
215 break;
216 }
217 FOREACHPAM_END()
218
219 return bOnlyText;
220 }
221
InsertDDETable(const SwInsertTableOptions & rInsTblOpts,SwDDEFieldType * pDDEType,sal_uInt16 nRows,sal_uInt16 nCols,sal_Int16 eAdj)222 void SwEditShell::InsertDDETable( const SwInsertTableOptions& rInsTblOpts,
223 SwDDEFieldType* pDDEType,
224 sal_uInt16 nRows, sal_uInt16 nCols,
225 sal_Int16 eAdj )
226 {
227 SwPosition* pPos = GetCrsr()->GetPoint();
228
229 StartAllAction();
230
231 sal_Bool bEndUndo = 0 != pPos->nContent.GetIndex();
232 if( bEndUndo )
233 {
234 StartUndo( UNDO_START );
235 GetDoc()->SplitNode( *pPos, false );
236 }
237
238 const SwInsertTableOptions aInsTblOpts( rInsTblOpts.mnInsMode | tabopts::DEFAULT_BORDER,
239 rInsTblOpts.mnRowsToRepeat );
240 SwTable* pTbl = (SwTable*)GetDoc()->InsertTable( aInsTblOpts, *pPos,
241 nRows, nCols, eAdj );
242
243 SwTableNode* pTblNode = (SwTableNode*)pTbl->GetTabSortBoxes()[ 0 ]->
244 GetSttNd()->FindTableNode();
245 SwDDETable* pDDETbl = new SwDDETable( *pTbl, pDDEType );
246 pTblNode->SetNewTable( pDDETbl ); // setze die DDE-Tabelle
247
248 if( bEndUndo )
249 EndUndo( UNDO_END );
250
251 EndAllAction();
252 }
253
254 /*--------------------------------------------------------------------
255 Beschreibung: Tabellenfelder einer Tabelle updaten
256 --------------------------------------------------------------------*/
UpdateTable()257 void SwEditShell::UpdateTable()
258 {
259 const SwTableNode* pTblNd = IsCrsrInTbl();
260
261 // Keine Arme keine Kekse
262 if( pTblNd )
263 {
264 StartAllAction();
265 if( DoesUndo() )
266 StartUndo();
267 EndAllTblBoxEdit();
268 SwTableFmlUpdate aTblUpdate( (SwTable*)&pTblNd->GetTable() );
269 GetDoc()->UpdateTblFlds( &aTblUpdate );
270 if( DoesUndo() )
271 EndUndo();
272 EndAllAction();
273 }
274 }
275
276 // Change Modus erfragen/setzen
GetTblChgMode() const277 TblChgMode SwEditShell::GetTblChgMode() const
278 {
279 TblChgMode eMode;
280 const SwTableNode* pTblNd = IsCrsrInTbl();
281 if( pTblNd )
282 eMode = pTblNd->GetTable().GetTblChgMode();
283 else
284 eMode = GetTblChgDefaultMode();
285 return eMode;
286 }
287
SetTblChgMode(TblChgMode eMode)288 void SwEditShell::SetTblChgMode( TblChgMode eMode )
289 {
290 const SwTableNode* pTblNd = IsCrsrInTbl();
291
292 // Keine Arme keine Kekse
293 if( pTblNd )
294 {
295 ((SwTable&)pTblNd->GetTable()).SetTblChgMode( eMode );
296 if( !GetDoc()->IsModified() ) // Bug 57028
297 {
298 GetDoc()->GetIDocumentUndoRedo().SetUndoNoResetModified();
299 }
300 GetDoc()->SetModified();
301 }
302 }
303
GetTblBoxFormulaAttrs(SfxItemSet & rSet) const304 sal_Bool SwEditShell::GetTblBoxFormulaAttrs( SfxItemSet& rSet ) const
305 {
306 SwSelBoxes aBoxes;
307 if( IsTableMode() )
308 ::GetTblSelCrs( *this, aBoxes );
309 else
310 {
311 do {
312 SwFrm *pFrm = GetCurrFrm();
313 do {
314 pFrm = pFrm->GetUpper();
315 } while ( pFrm && !pFrm->IsCellFrm() );
316 if ( pFrm )
317 {
318 SwTableBox *pBox = (SwTableBox*)((SwCellFrm*)pFrm)->GetTabBox();
319 aBoxes.Insert( pBox );
320 }
321 } while( sal_False );
322 }
323
324 for( sal_uInt16 n = 0; n < aBoxes.Count(); ++n )
325 {
326 const SwTableBox* pSelBox = aBoxes[ n ];
327 const SwTableBoxFmt* pTblFmt = (SwTableBoxFmt*)pSelBox->GetFrmFmt();
328 if( !n )
329 {
330 // Formeln in die externe Darstellung bringen!
331 const SwTable& rTbl = pSelBox->GetSttNd()->FindTableNode()->GetTable();
332
333 SwTableFmlUpdate aTblUpdate( (SwTable*)&rTbl );
334 aTblUpdate.eFlags = TBL_BOXNAME;
335 ((SwDoc*)GetDoc())->UpdateTblFlds( &aTblUpdate );
336
337 rSet.Put( pTblFmt->GetAttrSet() );
338 }
339 else
340 rSet.MergeValues( pTblFmt->GetAttrSet() );
341 }
342 return 0 != rSet.Count();
343 }
344
SetTblBoxFormulaAttrs(const SfxItemSet & rSet)345 void SwEditShell::SetTblBoxFormulaAttrs( const SfxItemSet& rSet )
346 {
347 SET_CURR_SHELL( this );
348 SwSelBoxes aBoxes;
349 if( IsTableMode() )
350 ::GetTblSelCrs( *this, aBoxes );
351 else
352 {
353 do {
354 SwFrm *pFrm = GetCurrFrm();
355 do {
356 pFrm = pFrm->GetUpper();
357 } while ( pFrm && !pFrm->IsCellFrm() );
358 if ( pFrm )
359 {
360 SwTableBox *pBox = (SwTableBox*)((SwCellFrm*)pFrm)->GetTabBox();
361 aBoxes.Insert( pBox );
362 }
363 } while( sal_False );
364 }
365
366 // beim setzen einer Formel keine Ueberpruefung mehr vornehmen!
367 if( SFX_ITEM_SET == rSet.GetItemState( RES_BOXATR_FORMULA ))
368 ClearTblBoxCntnt();
369
370 StartAllAction();
371 GetDoc()->GetIDocumentUndoRedo().StartUndo( UNDO_START, NULL );
372 for( sal_uInt16 n = 0; n < aBoxes.Count(); ++n )
373 GetDoc()->SetTblBoxFormulaAttrs( *aBoxes[ n ], rSet );
374 GetDoc()->GetIDocumentUndoRedo().EndUndo( UNDO_END, NULL );
375 EndAllAction();
376 }
377
IsTableBoxTextFormat() const378 sal_Bool SwEditShell::IsTableBoxTextFormat() const
379 {
380 if( IsTableMode() )
381 return sal_False;
382
383 SwTableBox *pBox = 0;
384 {
385 SwFrm *pFrm = GetCurrFrm();
386 do {
387 pFrm = pFrm->GetUpper();
388 } while ( pFrm && !pFrm->IsCellFrm() );
389 if ( pFrm )
390 pBox = (SwTableBox*)((SwCellFrm*)pFrm)->GetTabBox();
391 }
392
393 if( !pBox )
394 return sal_False;
395
396 sal_uInt32 nFmt;
397 const SfxPoolItem* pItem;
398 if( SFX_ITEM_SET == pBox->GetFrmFmt()->GetAttrSet().GetItemState(
399 RES_BOXATR_FORMAT, sal_True, &pItem ))
400 {
401 nFmt = ((SwTblBoxNumFormat*)pItem)->GetValue();
402 return GetDoc()->GetNumberFormatter()->IsTextFormat( nFmt ) ||
403 NUMBERFORMAT_TEXT == nFmt;
404 }
405
406 sal_uLong nNd = pBox->IsValidNumTxtNd();
407 if( ULONG_MAX == nNd )
408 return sal_True;
409
410 const String& rTxt = GetDoc()->GetNodes()[ nNd ]->GetTxtNode()->GetTxt();
411 if( !rTxt.Len() )
412 return sal_False;
413
414 double fVal;
415 return !GetDoc()->GetNumberFormatter()->IsNumberFormat( rTxt, nFmt, fVal );
416 }
417
GetTableBoxText() const418 String SwEditShell::GetTableBoxText() const
419 {
420 String sRet;
421 if( !IsTableMode() )
422 {
423 SwTableBox *pBox = 0;
424 {
425 SwFrm *pFrm = GetCurrFrm();
426 do {
427 pFrm = pFrm->GetUpper();
428 } while ( pFrm && !pFrm->IsCellFrm() );
429 if ( pFrm )
430 pBox = (SwTableBox*)((SwCellFrm*)pFrm)->GetTabBox();
431 }
432
433 sal_uLong nNd;
434 if( pBox && ULONG_MAX != ( nNd = pBox->IsValidNumTxtNd() ) )
435 sRet = GetDoc()->GetNodes()[ nNd ]->GetTxtNode()->GetTxt();
436 }
437 return sRet;
438 }
439
SplitTable(sal_uInt16 eMode)440 sal_Bool SwEditShell::SplitTable( sal_uInt16 eMode )
441 {
442 sal_Bool bRet = sal_False;
443 SwPaM *pCrsr = GetCrsr();
444 if( pCrsr->GetNode()->FindTableNode() )
445 {
446 StartAllAction();
447 GetDoc()->GetIDocumentUndoRedo().StartUndo(UNDO_EMPTY, NULL);
448
449 bRet = GetDoc()->SplitTable( *pCrsr->GetPoint(), eMode, sal_True );
450
451 GetDoc()->GetIDocumentUndoRedo().EndUndo(UNDO_EMPTY, NULL);
452 ClearFEShellTabCols();
453 EndAllAction();
454 }
455 return bRet;
456 }
457
MergeTable(sal_Bool bWithPrev,sal_uInt16 nMode)458 sal_Bool SwEditShell::MergeTable( sal_Bool bWithPrev, sal_uInt16 nMode )
459 {
460 sal_Bool bRet = sal_False;
461 SwPaM *pCrsr = GetCrsr();
462 if( pCrsr->GetNode()->FindTableNode() )
463 {
464 StartAllAction();
465 GetDoc()->GetIDocumentUndoRedo().StartUndo(UNDO_EMPTY, NULL);
466
467 bRet = GetDoc()->MergeTable( *pCrsr->GetPoint(), bWithPrev, nMode );
468
469 GetDoc()->GetIDocumentUndoRedo().EndUndo(UNDO_EMPTY, NULL);
470 ClearFEShellTabCols();
471 EndAllAction();
472 }
473 return bRet;
474 }
475
CanMergeTable(sal_Bool bWithPrev,sal_Bool * pChkNxtPrv) const476 sal_Bool SwEditShell::CanMergeTable( sal_Bool bWithPrev, sal_Bool* pChkNxtPrv ) const
477 {
478 sal_Bool bRet = sal_False;
479 const SwPaM *pCrsr = GetCrsr();
480 const SwTableNode* pTblNd = pCrsr->GetNode()->FindTableNode();
481 if( pTblNd && !pTblNd->GetTable().ISA( SwDDETable ))
482 {
483 sal_Bool bNew = pTblNd->GetTable().IsNewModel();
484 const SwNodes& rNds = GetDoc()->GetNodes();
485 if( pChkNxtPrv )
486 {
487 const SwTableNode* pChkNd = rNds[ pTblNd->GetIndex() - 1 ]->FindTableNode();
488 if( pChkNd && !pChkNd->GetTable().ISA( SwDDETable ) &&
489 bNew == pChkNd->GetTable().IsNewModel() &&
490 // --> FME 2004-09-17 #117418# Consider table in table case
491 pChkNd->EndOfSectionIndex() == pTblNd->GetIndex() - 1 )
492 // <--
493 *pChkNxtPrv = sal_True, bRet = sal_True; // mit Prev ist moeglich
494 else
495 {
496 pChkNd = rNds[ pTblNd->EndOfSectionIndex() + 1 ]->GetTableNode();
497 if( pChkNd && !pChkNd->GetTable().ISA( SwDDETable ) &&
498 bNew == pChkNd->GetTable().IsNewModel() )
499 *pChkNxtPrv = sal_False, bRet = sal_True; // mit Next ist moeglich
500 }
501 }
502 else
503 {
504 const SwTableNode* pTmpTblNd = 0;
505
506 if( bWithPrev )
507 {
508 pTmpTblNd = rNds[ pTblNd->GetIndex() - 1 ]->FindTableNode();
509 // --> FME 2004-09-17 #117418# Consider table in table case
510 if ( pTmpTblNd && pTmpTblNd->EndOfSectionIndex() != pTblNd->GetIndex() - 1 )
511 pTmpTblNd = 0;
512 // <--
513 }
514 else
515 pTmpTblNd = rNds[ pTblNd->EndOfSectionIndex() + 1 ]->GetTableNode();
516
517 bRet = pTmpTblNd && !pTmpTblNd->GetTable().ISA( SwDDETable ) &&
518 bNew == pTmpTblNd->GetTable().IsNewModel();
519 }
520 }
521 return bRet;
522 }
523
524 // setze das InsertDB als Tabelle Undo auf:
AppendUndoForInsertFromDB(sal_Bool bIsTable)525 void SwEditShell::AppendUndoForInsertFromDB( sal_Bool bIsTable )
526 {
527 GetDoc()->AppendUndoForInsertFromDB( *GetCrsr(), bIsTable );
528 }
529
530