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