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