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