xref: /AOO41X/main/sw/source/core/edit/edtab.cxx (revision 8ef2f12b1aeba1404ab3c221e6e26281826cc4fc)
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