xref: /AOO41X/main/sw/source/core/edit/edtab.cxx (revision 707fc0d4d52eb4f69d89a98ffec6918ca5de6326)
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 const SwTable& SwEditShell::InsertTable( const SwInsertTableOptions& rInsTblOpts,
65                                          sal_uInt16 nRows, sal_uInt16 nCols,
66                                          sal_Int16 eAdj,
67                                          const SwTableAutoFmt* pTAFmt )
68 {
69     StartAllAction();
70     SwPosition* pPos = GetCrsr()->GetPoint();
71 
72     sal_Bool bEndUndo = 0 != pPos->nContent.GetIndex();
73     if( bEndUndo )
74     {
75         StartUndo( UNDO_START );
76         GetDoc()->SplitNode( *pPos, false );
77     }
78 
79     /* #109161# If called from a shell the adjust item is propagated
80         from pPos to the new content nodes in the table.
81      */
82     const SwTable *pTable = GetDoc()->InsertTable( rInsTblOpts, *pPos,
83                                                    nRows, nCols,
84                                                    eAdj, pTAFmt,
85                                                    0, sal_True );
86     if( bEndUndo )
87         EndUndo( UNDO_END );
88 
89     EndAllAction();
90     return *pTable;
91 }
92 
93 sal_Bool SwEditShell::TextToTable( const SwInsertTableOptions& rInsTblOpts,
94                                sal_Unicode cCh,
95                                sal_Int16 eAdj,
96                                const SwTableAutoFmt* pTAFmt )
97 {
98     SwWait aWait( *GetDoc()->GetDocShell(), sal_True );
99     sal_Bool bRet = sal_False;
100     StartAllAction();
101     FOREACHPAM_START(this)
102         if( PCURCRSR->HasMark() )
103             bRet |= 0 != GetDoc()->TextToTable( rInsTblOpts, *PCURCRSR, cCh,
104                                                 eAdj, pTAFmt );
105     FOREACHPAM_END()
106     EndAllAction();
107     return bRet;
108 }
109 
110 sal_Bool SwEditShell::TableToText( sal_Unicode cCh )
111 {
112     SwWait aWait( *GetDoc()->GetDocShell(), sal_True );
113     sal_Bool bRet = sal_False;
114     SwPaM* pCrsr = GetCrsr();
115     const SwTableNode* pTblNd =
116             GetDoc()->IsIdxInTbl( pCrsr->GetPoint()->nNode );
117     if( IsTableMode() )
118     {
119         ClearMark();
120         pCrsr = GetCrsr();
121     }
122     else if( !pTblNd || pCrsr->GetNext() != pCrsr )
123         return bRet;
124 
125     // TL_CHART2:
126     // tell the charts about the table to be deleted and have them use their own data
127     GetDoc()->CreateChartInternalDataProviders( &pTblNd->GetTable() );
128 
129     StartAllAction();
130 
131     // verschiebe den akt. Cursor aus dem Tabellen Bereich
132     // angemeldet ist
133     SwNodeIndex aTabIdx( *pTblNd );
134     pCrsr->DeleteMark();
135     pCrsr->GetPoint()->nNode = *pTblNd->EndOfSectionNode();
136     pCrsr->GetPoint()->nContent.Assign( 0, 0 );
137     // SPoint und Mark aus dem Bereich verschieben !!!
138     pCrsr->SetMark();
139     pCrsr->DeleteMark();
140 
141     bRet = GetDoc()->TableToText( pTblNd, cCh );
142     pCrsr->GetPoint()->nNode = aTabIdx;
143 
144     SwCntntNode* pCNd = pCrsr->GetCntntNode();
145     if( !pCNd )
146         pCrsr->Move( fnMoveForward, fnGoCntnt );
147     else
148         pCrsr->GetPoint()->nContent.Assign( pCNd, 0 );
149 
150     EndAllAction();
151     return bRet;
152 }
153 
154 sal_Bool SwEditShell::IsTextToTableAvailable() const
155 {
156     sal_Bool bOnlyText = sal_False;
157     FOREACHPAM_START(this)
158         if( PCURCRSR->HasMark() && *PCURCRSR->GetPoint() != *PCURCRSR->GetMark() )
159         {
160             bOnlyText = sal_True;
161 
162             // pruefe ob in der Selection eine Tabelle liegt
163             sal_uLong nStt = PCURCRSR->GetMark()->nNode.GetIndex(),
164                   nEnd = PCURCRSR->GetPoint()->nNode.GetIndex();
165             if( nStt > nEnd )   { sal_uLong n = nStt; nStt = nEnd; nEnd = n; }
166 
167             for( ; nStt <= nEnd; ++nStt )
168                 if( !GetDoc()->GetNodes()[ nStt ]->IsTxtNode() )
169                 {
170                     bOnlyText = sal_False;
171                     break;
172                 }
173 
174             if( !bOnlyText )
175                 break;
176         }
177     FOREACHPAM_END()
178 
179     return bOnlyText;
180 }
181 
182 void SwEditShell::InsertDDETable( const SwInsertTableOptions& rInsTblOpts,
183                                   SwDDEFieldType* pDDEType,
184                                   sal_uInt16 nRows, sal_uInt16 nCols,
185                                   sal_Int16 eAdj )
186 {
187     SwPosition* pPos = GetCrsr()->GetPoint();
188 
189     StartAllAction();
190 
191     sal_Bool bEndUndo = 0 != pPos->nContent.GetIndex();
192     if( bEndUndo )
193     {
194         StartUndo( UNDO_START );
195         GetDoc()->SplitNode( *pPos, false );
196     }
197 
198     const SwInsertTableOptions aInsTblOpts( rInsTblOpts.mnInsMode | tabopts::DEFAULT_BORDER,
199                                             rInsTblOpts.mnRowsToRepeat );
200     SwTable* pTbl = (SwTable*)GetDoc()->InsertTable( aInsTblOpts, *pPos,
201                                                      nRows, nCols, eAdj );
202 
203     SwTableNode* pTblNode = (SwTableNode*)pTbl->GetTabSortBoxes()[ 0 ]->
204                                                 GetSttNd()->FindTableNode();
205     SwDDETable* pDDETbl = new SwDDETable( *pTbl, pDDEType );
206     pTblNode->SetNewTable( pDDETbl );       // setze die DDE-Tabelle
207 
208     if( bEndUndo )
209         EndUndo( UNDO_END );
210 
211     EndAllAction();
212 }
213 
214 /*--------------------------------------------------------------------
215     Beschreibung: Tabellenfelder einer Tabelle updaten
216  --------------------------------------------------------------------*/
217 void SwEditShell::UpdateTable()
218 {
219     const SwTableNode* pTblNd = IsCrsrInTbl();
220 
221     // Keine Arme keine Kekse
222     if( pTblNd )
223     {
224         StartAllAction();
225         if( DoesUndo() )
226             StartUndo();
227         EndAllTblBoxEdit();
228         SwTableFmlUpdate aTblUpdate( (SwTable*)&pTblNd->GetTable() );
229         GetDoc()->UpdateTblFlds( &aTblUpdate );
230         if( DoesUndo() )
231             EndUndo();
232         EndAllAction();
233     }
234 }
235 
236     // Change Modus erfragen/setzen
237 TblChgMode SwEditShell::GetTblChgMode() const
238 {
239     TblChgMode eMode;
240     const SwTableNode* pTblNd = IsCrsrInTbl();
241     if( pTblNd )
242         eMode = pTblNd->GetTable().GetTblChgMode();
243     else
244         eMode = GetTblChgDefaultMode();
245     return eMode;
246 }
247 
248 void SwEditShell::SetTblChgMode( TblChgMode eMode )
249 {
250     const SwTableNode* pTblNd = IsCrsrInTbl();
251 
252     // Keine Arme keine Kekse
253     if( pTblNd )
254     {
255         ((SwTable&)pTblNd->GetTable()).SetTblChgMode( eMode );
256         if( !GetDoc()->IsModified() )   // Bug 57028
257         {
258             GetDoc()->GetIDocumentUndoRedo().SetUndoNoResetModified();
259         }
260         GetDoc()->SetModified();
261     }
262 }
263 
264 sal_Bool SwEditShell::GetTblBoxFormulaAttrs( SfxItemSet& rSet ) const
265 {
266     SwSelBoxes aBoxes;
267     if( IsTableMode() )
268         ::GetTblSelCrs( *this, aBoxes );
269     else
270     {
271         do {
272             SwFrm *pFrm = GetCurrFrm();
273             do {
274                 pFrm = pFrm->GetUpper();
275             } while ( pFrm && !pFrm->IsCellFrm() );
276             if ( pFrm )
277             {
278                 SwTableBox *pBox = (SwTableBox*)((SwCellFrm*)pFrm)->GetTabBox();
279                 aBoxes.Insert( pBox );
280             }
281         } while( sal_False );
282     }
283 
284     for( sal_uInt16 n = 0; n < aBoxes.Count(); ++n )
285     {
286         const SwTableBox* pSelBox = aBoxes[ n ];
287         const SwTableBoxFmt* pTblFmt = (SwTableBoxFmt*)pSelBox->GetFrmFmt();
288         if( !n )
289         {
290             // Formeln in die externe Darstellung bringen!
291             const SwTable& rTbl = pSelBox->GetSttNd()->FindTableNode()->GetTable();
292 
293             SwTableFmlUpdate aTblUpdate( (SwTable*)&rTbl );
294             aTblUpdate.eFlags = TBL_BOXNAME;
295             ((SwDoc*)GetDoc())->UpdateTblFlds( &aTblUpdate );
296 
297             rSet.Put( pTblFmt->GetAttrSet() );
298         }
299         else
300             rSet.MergeValues( pTblFmt->GetAttrSet() );
301     }
302     return 0 != rSet.Count();
303 }
304 
305 void SwEditShell::SetTblBoxFormulaAttrs( const SfxItemSet& rSet )
306 {
307     SET_CURR_SHELL( this );
308     SwSelBoxes aBoxes;
309     if( IsTableMode() )
310         ::GetTblSelCrs( *this, aBoxes );
311     else
312     {
313         do {
314             SwFrm *pFrm = GetCurrFrm();
315             do {
316                 pFrm = pFrm->GetUpper();
317             } while ( pFrm && !pFrm->IsCellFrm() );
318             if ( pFrm )
319             {
320                 SwTableBox *pBox = (SwTableBox*)((SwCellFrm*)pFrm)->GetTabBox();
321                 aBoxes.Insert( pBox );
322             }
323         } while( sal_False );
324     }
325 
326     // beim setzen einer Formel keine Ueberpruefung mehr vornehmen!
327     if( SFX_ITEM_SET == rSet.GetItemState( RES_BOXATR_FORMULA ))
328         ClearTblBoxCntnt();
329 
330     StartAllAction();
331     GetDoc()->GetIDocumentUndoRedo().StartUndo( UNDO_START, NULL );
332     for( sal_uInt16 n = 0; n < aBoxes.Count(); ++n )
333         GetDoc()->SetTblBoxFormulaAttrs( *aBoxes[ n ], rSet );
334     GetDoc()->GetIDocumentUndoRedo().EndUndo( UNDO_END, NULL );
335     EndAllAction();
336 }
337 
338 sal_Bool SwEditShell::IsTableBoxTextFormat() const
339 {
340     if( IsTableMode() )
341         return sal_False;
342 
343     SwTableBox *pBox = 0;
344     {
345         SwFrm *pFrm = GetCurrFrm();
346         do {
347             pFrm = pFrm->GetUpper();
348         } while ( pFrm && !pFrm->IsCellFrm() );
349         if ( pFrm )
350             pBox = (SwTableBox*)((SwCellFrm*)pFrm)->GetTabBox();
351     }
352 
353     if( !pBox )
354         return sal_False;
355 
356     sal_uInt32 nFmt;
357     const SfxPoolItem* pItem;
358     if( SFX_ITEM_SET == pBox->GetFrmFmt()->GetAttrSet().GetItemState(
359         RES_BOXATR_FORMAT, sal_True, &pItem ))
360     {
361         nFmt = ((SwTblBoxNumFormat*)pItem)->GetValue();
362         return GetDoc()->GetNumberFormatter()->IsTextFormat( nFmt ) ||
363                 NUMBERFORMAT_TEXT == nFmt;
364     }
365 
366     sal_uLong nNd = pBox->IsValidNumTxtNd();
367     if( ULONG_MAX == nNd )
368         return sal_True;
369 
370     const String& rTxt = GetDoc()->GetNodes()[ nNd ]->GetTxtNode()->GetTxt();
371     if( !rTxt.Len() )
372         return sal_False;
373 
374     double fVal;
375     return !GetDoc()->GetNumberFormatter()->IsNumberFormat( rTxt, nFmt, fVal );
376 }
377 
378 String SwEditShell::GetTableBoxText() const
379 {
380     String sRet;
381     if( !IsTableMode() )
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         sal_uLong nNd;
394         if( pBox && ULONG_MAX != ( nNd = pBox->IsValidNumTxtNd() ) )
395             sRet = GetDoc()->GetNodes()[ nNd ]->GetTxtNode()->GetTxt();
396     }
397     return sRet;
398 }
399 
400 sal_Bool SwEditShell::SplitTable( sal_uInt16 eMode )
401 {
402     sal_Bool bRet = sal_False;
403     SwPaM *pCrsr = GetCrsr();
404     if( pCrsr->GetNode()->FindTableNode() )
405     {
406         StartAllAction();
407         GetDoc()->GetIDocumentUndoRedo().StartUndo(UNDO_EMPTY, NULL);
408 
409         bRet = GetDoc()->SplitTable( *pCrsr->GetPoint(), eMode, sal_True );
410 
411         GetDoc()->GetIDocumentUndoRedo().EndUndo(UNDO_EMPTY, NULL);
412         ClearFEShellTabCols();
413         EndAllAction();
414     }
415     return bRet;
416 }
417 
418 sal_Bool SwEditShell::MergeTable( sal_Bool bWithPrev, sal_uInt16 nMode )
419 {
420     sal_Bool bRet = sal_False;
421     SwPaM *pCrsr = GetCrsr();
422     if( pCrsr->GetNode()->FindTableNode() )
423     {
424         StartAllAction();
425         GetDoc()->GetIDocumentUndoRedo().StartUndo(UNDO_EMPTY, NULL);
426 
427         bRet = GetDoc()->MergeTable( *pCrsr->GetPoint(), bWithPrev, nMode );
428 
429         GetDoc()->GetIDocumentUndoRedo().EndUndo(UNDO_EMPTY, NULL);
430         ClearFEShellTabCols();
431         EndAllAction();
432     }
433     return bRet;
434 }
435 
436 sal_Bool SwEditShell::CanMergeTable( sal_Bool bWithPrev, sal_Bool* pChkNxtPrv ) const
437 {
438     sal_Bool bRet = sal_False;
439     const SwPaM *pCrsr = GetCrsr();
440     const SwTableNode* pTblNd = pCrsr->GetNode()->FindTableNode();
441     if( pTblNd && !pTblNd->GetTable().ISA( SwDDETable ))
442     {
443         sal_Bool bNew = pTblNd->GetTable().IsNewModel();
444         const SwNodes& rNds = GetDoc()->GetNodes();
445         if( pChkNxtPrv )
446         {
447             const SwTableNode* pChkNd = rNds[ pTblNd->GetIndex() - 1 ]->FindTableNode();
448             if( pChkNd && !pChkNd->GetTable().ISA( SwDDETable ) &&
449                 bNew == pChkNd->GetTable().IsNewModel() &&
450                 // --> FME 2004-09-17 #117418# Consider table in table case
451                 pChkNd->EndOfSectionIndex() == pTblNd->GetIndex() - 1 )
452                 // <--
453                 *pChkNxtPrv = sal_True, bRet = sal_True;        // mit Prev ist moeglich
454             else
455             {
456                 pChkNd = rNds[ pTblNd->EndOfSectionIndex() + 1 ]->GetTableNode();
457                 if( pChkNd && !pChkNd->GetTable().ISA( SwDDETable ) &&
458                     bNew == pChkNd->GetTable().IsNewModel() )
459                     *pChkNxtPrv = sal_False, bRet = sal_True;       // mit Next ist moeglich
460             }
461         }
462         else
463         {
464             const SwTableNode* pTmpTblNd = 0;
465 
466             if( bWithPrev )
467             {
468                 pTmpTblNd = rNds[ pTblNd->GetIndex() - 1 ]->FindTableNode();
469                 // --> FME 2004-09-17 #117418# Consider table in table case
470                 if ( pTmpTblNd && pTmpTblNd->EndOfSectionIndex() != pTblNd->GetIndex() - 1 )
471                     pTmpTblNd = 0;
472                 // <--
473             }
474             else
475                 pTmpTblNd = rNds[ pTblNd->EndOfSectionIndex() + 1 ]->GetTableNode();
476 
477             bRet = pTmpTblNd && !pTmpTblNd->GetTable().ISA( SwDDETable ) &&
478                    bNew == pTmpTblNd->GetTable().IsNewModel();
479         }
480     }
481     return bRet;
482 }
483 
484         // setze das InsertDB als Tabelle Undo auf:
485 void SwEditShell::AppendUndoForInsertFromDB( sal_Bool bIsTable )
486 {
487     GetDoc()->AppendUndoForInsertFromDB( *GetCrsr(), bIsTable );
488 }
489 
490