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