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