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