xref: /aoo42x/main/sw/source/core/edit/edfld.cxx (revision 69a74367)
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 
28 #include <unotools/charclass.hxx>
29 #include <editsh.hxx>
30 #include <fldbas.hxx>
31 #include <doc.hxx>
32 #include <docary.hxx>
33 #include <fmtfld.hxx>
34 #include <txtfld.hxx>
35 #include <edimp.hxx>
36 #include <dbfld.hxx>
37 #include <expfld.hxx>
38 #include <flddat.hxx>
39 #include <swundo.hxx>
40 #include <dbmgr.hxx>
41 #include <swddetbl.hxx>
42 #include <hints.hxx>
43 #include <switerator.hxx>
44 #include <fieldhint.hxx>
45 
46 /*--------------------------------------------------------------------
47 	Beschreibung: Feldtypen zu einer ResId zaehlen
48 				  wenn 0 alle zaehlen
49  --------------------------------------------------------------------*/
50 
51 sal_uInt16 SwEditShell::GetFldTypeCount(sal_uInt16 nResId, sal_Bool bUsed ) const
52 {
53 	const SwFldTypes* pFldTypes = GetDoc()->GetFldTypes();
54 	const sal_uInt16 nSize = pFldTypes->Count();
55 
56 	if(nResId == USHRT_MAX)
57 	{
58 		if(!bUsed)
59 			return nSize;
60 		else
61 		{
62 			sal_uInt16 nUsed = 0;
63 			for ( sal_uInt16 i = 0; i < nSize; i++ )
64 			{
65 				if(IsUsed(*(*pFldTypes)[i]))
66 					nUsed++;
67 			}
68 			return nUsed;
69 		}
70 	}
71 
72 	// Alle Typen mit gleicher ResId
73 	sal_uInt16 nIdx  = 0;
74 	for(sal_uInt16 i = 0; i < nSize; ++i)
75 	{   // Gleiche ResId -> Index erhoehen
76 		SwFieldType& rFldType = *((*pFldTypes)[i]);
77 		if(rFldType.Which() == nResId)
78 			nIdx++;
79 	}
80 	return nIdx;
81 }
82 
83 /*--------------------------------------------------------------------
84 	Beschreibung: Feldtypen zu einer ResId finden
85 				  wenn 0 alle finden
86  --------------------------------------------------------------------*/
87 SwFieldType* SwEditShell::GetFldType(sal_uInt16 nFld, sal_uInt16 nResId, sal_Bool bUsed ) const
88 {
89 	const SwFldTypes* pFldTypes = GetDoc()->GetFldTypes();
90 	const sal_uInt16 nSize = pFldTypes->Count();
91 
92 	if(nResId == USHRT_MAX && nFld < nSize)
93 	{
94 		if(!bUsed)
95 			return (*pFldTypes)[nFld];
96 		else
97 		{
98 			sal_uInt16 i, nUsed = 0;
99 			for ( i = 0; i < nSize; i++ )
100 			{
101 				if(IsUsed(*(*pFldTypes)[i]))
102 				{
103 					if(nUsed == nFld)
104 						break;
105 					nUsed++;
106 				}
107 			}
108 			return i < nSize ? (*pFldTypes)[i] : 0;
109 		}
110 	}
111 
112 	sal_uInt16 nIdx = 0;
113 	for(sal_uInt16 i = 0; i < nSize; ++i)
114 	{   // Gleiche ResId -> Index erhoehen
115 		SwFieldType* pFldType = (*pFldTypes)[i];
116 		if(pFldType->Which() == nResId)
117 		{
118 			if (!bUsed || IsUsed(*pFldType))
119 			{
120 				if(nIdx == nFld)
121 					return pFldType;
122 				nIdx++;
123 			}
124 		}
125 	}
126 	return 0;
127 }
128 
129 /*--------------------------------------------------------------------
130 	Beschreibung: Den ersten Typen mit ResId und Namen finden
131  --------------------------------------------------------------------*/
132 SwFieldType* SwEditShell::GetFldType(sal_uInt16 nResId, const String& rName) const
133 {
134 	return GetDoc()->GetFldType( nResId, rName, false );
135 }
136 
137 /*--------------------------------------------------------------------
138 	Beschreibung: Feldtypen loeschen
139  --------------------------------------------------------------------*/
140 void SwEditShell::RemoveFldType(sal_uInt16 nFld, sal_uInt16 nResId)
141 {
142 	if( USHRT_MAX == nResId )
143 	{
144 		GetDoc()->RemoveFldType(nFld);
145 		return;
146 	}
147 
148 	const SwFldTypes* pFldTypes = GetDoc()->GetFldTypes();
149 	const sal_uInt16 nSize = pFldTypes->Count();
150 	sal_uInt16 nIdx = 0;
151 	for( sal_uInt16 i = 0; i < nSize; ++i )
152 		// Gleiche ResId -> Index erhoehen
153 		if( (*pFldTypes)[i]->Which() == nResId &&
154 			nIdx++ == nFld )
155 		{
156 			GetDoc()->RemoveFldType( i );
157 			return;
158 		}
159 }
160 
161 /*--------------------------------------------------------------------
162 	Beschreibung: FieldType ueber Name loeschen
163  --------------------------------------------------------------------*/
164 void SwEditShell::RemoveFldType(sal_uInt16 nResId, const String& rStr)
165 {
166 	const SwFldTypes* pFldTypes = GetDoc()->GetFldTypes();
167 	const sal_uInt16 nSize = pFldTypes->Count();
168 	const CharClass& rCC = GetAppCharClass();
169 
170 	String aTmp( rCC.lower( rStr ));
171 
172 	for(sal_uInt16 i = 0; i < nSize; ++i)
173 	{
174 		// Gleiche ResId -> Index erhoehen
175 		SwFieldType* pFldType = (*pFldTypes)[i];
176 		if( pFldType->Which() == nResId )
177 		{
178 			if( aTmp.Equals( rCC.lower( pFldType->GetName() ) ))
179 			{
180 				GetDoc()->RemoveFldType(i);
181 				return;
182 			}
183 		}
184 	}
185 }
186 
187 
188 void SwEditShell::FieldToText( SwFieldType* pType )
189 {
190 	if( !pType->GetDepends() )
191 		return;
192 
193 	SET_CURR_SHELL( this );
194 	StartAllAction();
195 	StartUndo( UNDO_DELETE );
196 	Push();
197 	SwPaM* pPaM = GetCrsr();
198 
199     SwFieldHint aHint( pPaM );
200 	SwClientIter aIter( *pType );
201     for ( SwClient* pClient = aIter.GoStart(); pClient; pClient = ++aIter )
202     {
203         pPaM->DeleteMark();
204         pClient->SwClientNotifyCall( *pType, aHint );
205  	}
206 
207 	Pop( sal_False );
208 	EndAllAction();
209 	EndUndo( UNDO_DELETE );
210 }
211 
212 /*************************************************************************
213 |*
214 |*					SwEditShell::Insert( SwField )
215 |*
216 |*	  Beschreibung	an der Cursorposition ein Feld einfuegen
217 |*	  Quelle:		vgl. SwEditShell::Insert( String )
218 |*
219 *************************************************************************/
220 void SwEditShell::Insert2(SwField& rFld, const bool bForceExpandHints)
221 {
222     SET_CURR_SHELL( this );
223     StartAllAction();
224     SwFmtFld aFld( rFld );
225 
226     const SetAttrMode nInsertFlags = (bForceExpandHints)
227         ? nsSetAttrMode::SETATTR_FORCEHINTEXPAND
228         : nsSetAttrMode::SETATTR_DEFAULT;
229 
230     FOREACHPAM_START(this)
231         const bool bSuccess(GetDoc()->InsertPoolItem(*PCURCRSR, aFld, nInsertFlags));
232         ASSERT( bSuccess, "Doc->Insert(Field) failed");
233         (void) bSuccess;
234     FOREACHPAM_END()
235 
236     EndAllAction();
237 }
238 
239 
240 
241 /*************************************************************************
242 |*
243 |*					SwEditShell::UpdateFlds()
244 |*
245 |*	  Beschreibung	Stehen die PaMs auf Feldern ?
246 |*					BP 12.05.92
247 |*
248 *************************************************************************/
249 SwTxtFld* lcl_FindInputFld( SwDoc* pDoc, SwField& rFld )
250 {
251     SwTxtFld* pTFld = 0;
252     if( RES_INPUTFLD == rFld.Which() )
253     {
254         const SfxPoolItem* pItem = NULL;
255         const sal_uInt32 nMaxItems =
256             pDoc->GetAttrPool().GetItemCount2( RES_TXTATR_INPUTFIELD );
257         for( sal_uInt32 n = 0; n < nMaxItems; ++n )
258             if( 0 != (pItem = pDoc->GetAttrPool().GetItem2( RES_TXTATR_INPUTFIELD, n ) )
259                 && ((SwFmtFld*)pItem)->GetField() == &rFld )
260             {
261                 pTFld = ((SwFmtFld*)pItem)->GetTxtFld();
262                 break;
263             }
264     }
265     else if( RES_SETEXPFLD == rFld.Which()
266         && ((SwSetExpField&)rFld).GetInputFlag() )
267     {
268         const SfxPoolItem* pItem = NULL;
269         const sal_uInt32 nMaxItems =
270             pDoc->GetAttrPool().GetItemCount2( RES_TXTATR_FIELD );
271         for( sal_uInt32 n = 0; n < nMaxItems; ++n )
272             if( 0 != (pItem = pDoc->GetAttrPool().GetItem2( RES_TXTATR_FIELD, n ) )
273                 && ((SwFmtFld*)pItem)->GetField() == &rFld )
274             {
275                 pTFld = ((SwFmtFld*)pItem)->GetTxtFld();
276                 break;
277             }
278     }
279     return pTFld;
280 }
281 
282 void SwEditShell::UpdateFlds( SwField &rFld )
283 {
284 	SET_CURR_SHELL( this );
285 	StartAllAction();
286 	{
287 		SwField *pCurFld = 0;
288 
289 		// Wenn es keine Selektionen gibt, gilt der Wert der aktuellen
290 		// Cursor-Position.
291 		SwMsgPoolItem* pMsgHnt = 0;
292 		SwRefMarkFldUpdate aRefMkHt( GetOut() );
293 		sal_uInt16 nFldWhich = rFld.GetTyp()->Which();
294 		if( RES_GETREFFLD == nFldWhich )
295 			pMsgHnt = &aRefMkHt;
296 
297 		SwPaM* pCrsr = GetCrsr();
298 		SwTxtFld *pTxtFld;
299 		SwFmtFld *pFmtFld;
300 
301         if ( pCrsr->GetNext() == pCrsr && !pCrsr->HasMark())
302         {
303             pTxtFld = GetTxtFldAtPos( pCrsr->Start(), true );
304 
305             if (!pTxtFld) // #i30221#
306                 pTxtFld = lcl_FindInputFld( GetDoc(), rFld);
307 
308             if (pTxtFld != 0)
309                 GetDoc()->UpdateFld(pTxtFld, rFld, pMsgHnt, sal_True); // #111840#
310         }
311 
312 		// bOkay (statt return wg. EndAllAction) wird sal_False,
313 		// 1) wenn nur ein Pam mehr als ein Feld enthaelt oder
314 		// 2) bei gemischten Feldtypen
315 		sal_Bool bOkay = sal_True;
316 		sal_Bool bTblSelBreak = sal_False;
317 
318 		SwMsgPoolItem aFldHint( RES_TXTATR_FIELD );
319 		SwMsgPoolItem aInputFldHint( RES_TXTATR_INPUTFIELD );
320 		FOREACHPAM_START(this)						// fuer jeden PaM
321 			if( PCURCRSR->HasMark() && bOkay )		// ... mit Selektion
322 			{
323 				// Kopie des PaM
324 				SwPaM aCurPam( *PCURCRSR->GetMark(), *PCURCRSR->GetPoint() );
325 				SwPaM aPam( *PCURCRSR->GetPoint() );
326 
327 				SwPosition *pCurStt = aCurPam.Start(), *pCurEnd =
328                     aCurPam.End();
329 				/*
330 				 * Fuer den Fall, dass zwei aneinanderliegende Felder in einem
331 				 * PaM liegen, hangelt sich aPam portionsweise bis zum Ende.
332 				 * aCurPam wird dabei nach jeder Schleifenrunde verkuerzt.
333 				 * Wenn aCurPam vollstaendig durchsucht wurde, ist Start = End
334 				 * und die Schleife terminiert.
335 				 */
336 
337 				// Suche nach SwTxtFld ...
338 				while(	bOkay
339 					 && pCurStt->nContent != pCurEnd->nContent
340 					 && ( aPam.Find( aFldHint, sal_False, fnMoveForward, &aCurPam )
341                           || aPam.Find( aInputFldHint, sal_False, fnMoveForward, &aCurPam ) ) )
342 				{
343 					//	wenn nur ein Pam mehr als ein Feld enthaelt ...
344 					if( aPam.Start()->nContent != pCurStt->nContent )
345 						bOkay = sal_False;
346 
347 					if( 0 != (pTxtFld = GetTxtFldAtPos( pCurStt, true )) )
348 					{
349 						pFmtFld = (SwFmtFld*)&pTxtFld->GetFmtFld();
350 						pCurFld = pFmtFld->GetField();
351 
352 						// bei gemischten Feldtypen
353 						if( pCurFld->GetTyp()->Which() !=
354                             rFld.GetTyp()->Which() )
355 							bOkay = sal_False;
356 
357                         bTblSelBreak = GetDoc()->UpdateFld(pTxtFld, rFld,
358                                                            pMsgHnt, sal_False); // #111840#
359 					}
360 					// Der Suchbereich wird um den gefundenen Bereich
361 					// verkuerzt.
362 					pCurStt->nContent++;
363 				}
364 			}
365 
366 			if( bTblSelBreak )		// wenn Tabellen Selektion und Tabellen-
367 				break;				// Formel aktualisiert wurde -> beenden
368 
369 		FOREACHPAM_END()					  // fuer jeden PaM
370 	}
371 	GetDoc()->SetModified();
372 	EndAllAction();
373 }
374 
375 /*-----------------13.05.92 10:54-------------------
376  Liefert den logischen fuer die Datenbank zurueck
377  --------------------------------------------------*/
378 
379 SwDBData SwEditShell::GetDBData() const
380 {
381 	return GetDoc()->GetDBData();
382 }
383 
384 const SwDBData& SwEditShell::GetDBDesc() const
385 {
386 	return GetDoc()->GetDBDesc();
387 }
388 
389 void SwEditShell::ChgDBData(const SwDBData& rNewData)
390 {
391 	GetDoc()->ChgDBData(rNewData);
392 }
393 
394 void SwEditShell::GetAllUsedDB( SvStringsDtor& rDBNameList,
395 								SvStringsDtor* pAllDBNames )
396 {
397 	GetDoc()->GetAllUsedDB( rDBNameList, pAllDBNames );
398 }
399 
400 void SwEditShell::ChangeDBFields( const SvStringsDtor& rOldNames,
401 									const String& rNewName )
402 {
403 	GetDoc()->ChangeDBFields( rOldNames, rNewName );
404 }
405 
406 /*--------------------------------------------------------------------
407 	Beschreibung:  Alle Expression-Felder erneuern
408  --------------------------------------------------------------------*/
409 void SwEditShell::UpdateExpFlds(sal_Bool bCloseDB)
410 {
411 	SET_CURR_SHELL( this );
412 	StartAllAction();
413 	GetDoc()->UpdateExpFlds(NULL, true);
414 	if (bCloseDB)
415 		GetDoc()->GetNewDBMgr()->CloseAll();	// Alle Datenbankverbindungen dichtmachen
416 	EndAllAction();
417 }
418 
419 SwNewDBMgr* SwEditShell::GetNewDBMgr() const
420 {
421 	return GetDoc()->GetNewDBMgr();
422 }
423 
424 /*--------------------------------------------------------------------
425 	Beschreibung: Feldtypen einfuegen
426  --------------------------------------------------------------------*/
427 SwFieldType* SwEditShell::InsertFldType(const SwFieldType& rFldType)
428 {
429 	return GetDoc()->InsertFldType(rFldType);
430 }
431 
432 void SwEditShell::LockExpFlds()
433 {
434 	GetDoc()->LockExpFlds();
435 }
436 
437 void SwEditShell::UnlockExpFlds()
438 {
439 	GetDoc()->UnlockExpFlds();
440 }
441 
442 
443 void SwEditShell::SetFldUpdateFlags( SwFldUpdateFlags eFlags )
444 {
445     getIDocumentSettingAccess()->setFieldUpdateFlags( eFlags );
446 }
447 
448 SwFldUpdateFlags SwEditShell::GetFldUpdateFlags(sal_Bool bDocSettings) const
449 {
450     return getIDocumentSettingAccess()->getFieldUpdateFlags( !bDocSettings );
451 }
452 
453 void SwEditShell::SetFixFields( sal_Bool bOnlyTimeDate,
454 								const DateTime* pNewDateTime )
455 {
456 	SET_CURR_SHELL( this );
457 	sal_Bool bUnLockView = !IsViewLocked();
458 	LockView( sal_True );
459 	StartAllAction();
460 	GetDoc()->SetFixFields( bOnlyTimeDate, pNewDateTime );
461 	EndAllAction();
462 	if( bUnLockView )
463 		LockView( sal_False );
464 }
465 
466 void SwEditShell::SetLabelDoc( sal_Bool bFlag )
467 {
468 	GetDoc()->set(IDocumentSettingAccess::LABEL_DOCUMENT, bFlag );
469 }
470 
471 sal_Bool SwEditShell::IsLabelDoc() const
472 {
473     return getIDocumentSettingAccess()->get(IDocumentSettingAccess::LABEL_DOCUMENT);
474 }
475 /* -----------------------------21.12.99 12:53--------------------------------
476 
477  ---------------------------------------------------------------------------*/
478 void SwEditShell::ChangeAuthorityData(const SwAuthEntry* pNewData)
479 {
480 	GetDoc()->ChangeAuthorityData(pNewData);
481 }
482 /* -----------------------------03.08.2001 12:04------------------------------
483 
484  ---------------------------------------------------------------------------*/
485 sal_Bool SwEditShell::IsAnyDatabaseFieldInDoc()const
486 {
487     const SwFldTypes * pFldTypes = GetDoc()->GetFldTypes();
488     const sal_uInt16 nSize = pFldTypes->Count();
489     for(sal_uInt16 i = 0; i < nSize; ++i)
490     {
491         SwFieldType& rFldType = *((*pFldTypes)[i]);
492         sal_uInt16 nWhich = rFldType.Which();
493         if(IsUsed(rFldType))
494         {
495             switch(nWhich)
496             {
497                 case RES_DBFLD:
498                 case RES_DBNEXTSETFLD:
499                 case RES_DBNUMSETFLD:
500                 case RES_DBSETNUMBERFLD:
501                 {
502                     SwIterator<SwFmtFld,SwFieldType> aIter( rFldType );
503                     SwFmtFld* pFld = aIter.First();
504                     while(pFld)
505                     {
506                         if(pFld->IsFldInDoc())
507                             return sal_True;
508                         pFld = aIter.Next();
509                     }
510                 }
511                 break;
512             }
513         }
514     }
515     return sal_False;
516 }
517