xref: /trunk/main/sw/source/core/edit/edfld.cxx (revision dec99bbd)
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 
GetFldTypeCount(sal_uInt16 nResId,sal_Bool bUsed) const51 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  --------------------------------------------------------------------*/
GetFldType(sal_uInt16 nFld,sal_uInt16 nResId,sal_Bool bUsed) const87 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  --------------------------------------------------------------------*/
GetFldType(sal_uInt16 nResId,const String & rName) const132 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  --------------------------------------------------------------------*/
RemoveFldType(sal_uInt16 nFld,sal_uInt16 nResId)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  --------------------------------------------------------------------*/
RemoveFldType(sal_uInt16 nResId,const String & rStr)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 
FieldToText(SwFieldType * pType)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 *************************************************************************/
Insert2(SwField & rFld,const bool bForceExpandHints)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 *************************************************************************/
lcl_FindInputFld(SwDoc * pDoc,SwField & rFld)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 
UpdateFlds(SwField & rFld)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 aAnnotationFldHint( RES_TXTATR_ANNOTATION );
320 		SwMsgPoolItem aInputFldHint( RES_TXTATR_INPUTFIELD );
321 		FOREACHPAM_START(this)						// fuer jeden PaM
322 			if( PCURCRSR->HasMark() && bOkay )		// ... mit Selektion
323 			{
324 				// Kopie des PaM
325 				SwPaM aCurPam( *PCURCRSR->GetMark(), *PCURCRSR->GetPoint() );
326 				SwPaM aPam( *PCURCRSR->GetPoint() );
327 
328 				SwPosition *pCurStt = aCurPam.Start(), *pCurEnd =
329                     aCurPam.End();
330 				/*
331 				 * Fuer den Fall, dass zwei aneinanderliegende Felder in einem
332 				 * PaM liegen, hangelt sich aPam portionsweise bis zum Ende.
333 				 * aCurPam wird dabei nach jeder Schleifenrunde verkuerzt.
334 				 * Wenn aCurPam vollstaendig durchsucht wurde, ist Start = End
335 				 * und die Schleife terminiert.
336 				 */
337 
338 				// Suche nach SwTxtFld ...
339 				while(	bOkay
340 					 && pCurStt->nContent != pCurEnd->nContent
341 					 && ( aPam.Find( aFldHint, sal_False, fnMoveForward, &aCurPam )
342                           || aPam.Find( aAnnotationFldHint, sal_False, fnMoveForward, &aCurPam )
343                           || aPam.Find( aInputFldHint, sal_False, fnMoveForward, &aCurPam ) ) )
344 				{
345 					//	wenn nur ein Pam mehr als ein Feld enthaelt ...
346 					if( aPam.Start()->nContent != pCurStt->nContent )
347 						bOkay = sal_False;
348 
349 					if( 0 != (pTxtFld = GetTxtFldAtPos( pCurStt, true )) )
350 					{
351 						pFmtFld = (SwFmtFld*)&pTxtFld->GetFmtFld();
352 						pCurFld = pFmtFld->GetField();
353 
354 						// bei gemischten Feldtypen
355 						if( pCurFld->GetTyp()->Which() !=
356                             rFld.GetTyp()->Which() )
357 							bOkay = sal_False;
358 
359                         bTblSelBreak = GetDoc()->UpdateFld(pTxtFld, rFld,
360                                                            pMsgHnt, sal_False); // #111840#
361 					}
362 					// Der Suchbereich wird um den gefundenen Bereich
363 					// verkuerzt.
364 					pCurStt->nContent++;
365 				}
366 			}
367 
368 			if( bTblSelBreak )		// wenn Tabellen Selektion und Tabellen-
369 				break;				// Formel aktualisiert wurde -> beenden
370 
371 		FOREACHPAM_END()					  // fuer jeden PaM
372 	}
373 	GetDoc()->SetModified();
374 	EndAllAction();
375 }
376 
377 /*-----------------13.05.92 10:54-------------------
378  Liefert den logischen fuer die Datenbank zurueck
379  --------------------------------------------------*/
380 
GetDBData() const381 SwDBData SwEditShell::GetDBData() const
382 {
383 	return GetDoc()->GetDBData();
384 }
385 
GetDBDesc() const386 const SwDBData& SwEditShell::GetDBDesc() const
387 {
388 	return GetDoc()->GetDBDesc();
389 }
390 
ChgDBData(const SwDBData & rNewData)391 void SwEditShell::ChgDBData(const SwDBData& rNewData)
392 {
393 	GetDoc()->ChgDBData(rNewData);
394 }
395 
GetAllUsedDB(SvStringsDtor & rDBNameList,SvStringsDtor * pAllDBNames)396 void SwEditShell::GetAllUsedDB( SvStringsDtor& rDBNameList,
397 								SvStringsDtor* pAllDBNames )
398 {
399 	GetDoc()->GetAllUsedDB( rDBNameList, pAllDBNames );
400 }
401 
ChangeDBFields(const SvStringsDtor & rOldNames,const String & rNewName)402 void SwEditShell::ChangeDBFields( const SvStringsDtor& rOldNames,
403 									const String& rNewName )
404 {
405 	GetDoc()->ChangeDBFields( rOldNames, rNewName );
406 }
407 
408 /*--------------------------------------------------------------------
409 	Beschreibung:  Alle Expression-Felder erneuern
410  --------------------------------------------------------------------*/
UpdateExpFlds(sal_Bool bCloseDB)411 void SwEditShell::UpdateExpFlds(sal_Bool bCloseDB)
412 {
413 	SET_CURR_SHELL( this );
414 	StartAllAction();
415 	GetDoc()->UpdateExpFlds(NULL, true);
416 	if (bCloseDB)
417 		GetDoc()->GetNewDBMgr()->CloseAll();	// Alle Datenbankverbindungen dichtmachen
418 	EndAllAction();
419 }
420 
GetNewDBMgr() const421 SwNewDBMgr* SwEditShell::GetNewDBMgr() const
422 {
423 	return GetDoc()->GetNewDBMgr();
424 }
425 
426 /*--------------------------------------------------------------------
427 	Beschreibung: Feldtypen einfuegen
428  --------------------------------------------------------------------*/
InsertFldType(const SwFieldType & rFldType)429 SwFieldType* SwEditShell::InsertFldType(const SwFieldType& rFldType)
430 {
431 	return GetDoc()->InsertFldType(rFldType);
432 }
433 
LockExpFlds()434 void SwEditShell::LockExpFlds()
435 {
436 	GetDoc()->LockExpFlds();
437 }
438 
UnlockExpFlds()439 void SwEditShell::UnlockExpFlds()
440 {
441 	GetDoc()->UnlockExpFlds();
442 }
443 
444 
SetFldUpdateFlags(SwFldUpdateFlags eFlags)445 void SwEditShell::SetFldUpdateFlags( SwFldUpdateFlags eFlags )
446 {
447     getIDocumentSettingAccess()->setFieldUpdateFlags( eFlags );
448 }
449 
GetFldUpdateFlags(sal_Bool bDocSettings) const450 SwFldUpdateFlags SwEditShell::GetFldUpdateFlags(sal_Bool bDocSettings) const
451 {
452     return getIDocumentSettingAccess()->getFieldUpdateFlags( !bDocSettings );
453 }
454 
SetFixFields(sal_Bool bOnlyTimeDate,const DateTime * pNewDateTime)455 void SwEditShell::SetFixFields( sal_Bool bOnlyTimeDate,
456 								const DateTime* pNewDateTime )
457 {
458 	SET_CURR_SHELL( this );
459 	sal_Bool bUnLockView = !IsViewLocked();
460 	LockView( sal_True );
461 	StartAllAction();
462 	GetDoc()->SetFixFields( bOnlyTimeDate, pNewDateTime );
463 	EndAllAction();
464 	if( bUnLockView )
465 		LockView( sal_False );
466 }
467 
SetLabelDoc(sal_Bool bFlag)468 void SwEditShell::SetLabelDoc( sal_Bool bFlag )
469 {
470 	GetDoc()->set(IDocumentSettingAccess::LABEL_DOCUMENT, bFlag );
471 }
472 
IsLabelDoc() const473 sal_Bool SwEditShell::IsLabelDoc() const
474 {
475     return getIDocumentSettingAccess()->get(IDocumentSettingAccess::LABEL_DOCUMENT);
476 }
477 /* -----------------------------21.12.99 12:53--------------------------------
478 
479  ---------------------------------------------------------------------------*/
ChangeAuthorityData(const SwAuthEntry * pNewData)480 void SwEditShell::ChangeAuthorityData(const SwAuthEntry* pNewData)
481 {
482 	GetDoc()->ChangeAuthorityData(pNewData);
483 }
484 /* -----------------------------03.08.2001 12:04------------------------------
485 
486  ---------------------------------------------------------------------------*/
IsAnyDatabaseFieldInDoc() const487 sal_Bool SwEditShell::IsAnyDatabaseFieldInDoc()const
488 {
489     const SwFldTypes * pFldTypes = GetDoc()->GetFldTypes();
490     const sal_uInt16 nSize = pFldTypes->Count();
491     for(sal_uInt16 i = 0; i < nSize; ++i)
492     {
493         SwFieldType& rFldType = *((*pFldTypes)[i]);
494         sal_uInt16 nWhich = rFldType.Which();
495         if(IsUsed(rFldType))
496         {
497             switch(nWhich)
498             {
499                 case RES_DBFLD:
500                 case RES_DBNEXTSETFLD:
501                 case RES_DBNUMSETFLD:
502                 case RES_DBSETNUMBERFLD:
503                 {
504                     SwIterator<SwFmtFld,SwFieldType> aIter( rFldType );
505                     SwFmtFld* pFld = aIter.First();
506                     while(pFld)
507                     {
508                         if(pFld->IsFldInDoc())
509                             return sal_True;
510                         pFld = aIter.Next();
511                     }
512                 }
513                 break;
514             }
515         }
516     }
517     return sal_False;
518 }
519