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