Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <unotools/charclass.hxx>
21 : #include <editsh.hxx>
22 : #include <fldbas.hxx>
23 : #include <ndtxt.hxx> // GetCurFld
24 : #include <doc.hxx>
25 : #include <docary.hxx>
26 : #include <fmtfld.hxx>
27 : #include <txtfld.hxx>
28 : #include <edimp.hxx>
29 : #include <dbfld.hxx>
30 : #include <expfld.hxx>
31 : #include <flddat.hxx>
32 : #include <swundo.hxx>
33 : #include <dbmgr.hxx>
34 : #include <swddetbl.hxx>
35 : #include <hints.hxx>
36 : #include <switerator.hxx>
37 : #include <fieldhint.hxx>
38 :
39 : /*--------------------------------------------------------------------
40 : Beschreibung: Feldtypen zu einer ResId zaehlen
41 : wenn 0 alle zaehlen
42 : --------------------------------------------------------------------*/
43 :
44 0 : sal_uInt16 SwEditShell::GetFldTypeCount(sal_uInt16 nResId, sal_Bool bUsed ) const
45 : {
46 0 : const SwFldTypes* pFldTypes = GetDoc()->GetFldTypes();
47 0 : const sal_uInt16 nSize = pFldTypes->size();
48 :
49 0 : if(nResId == USHRT_MAX)
50 : {
51 0 : if(!bUsed)
52 0 : return nSize;
53 : else
54 : {
55 0 : sal_uInt16 nUsed = 0;
56 0 : for ( sal_uInt16 i = 0; i < nSize; i++ )
57 : {
58 0 : if(IsUsed(*(*pFldTypes)[i]))
59 0 : nUsed++;
60 : }
61 0 : return nUsed;
62 : }
63 : }
64 :
65 : // Alle Typen mit gleicher ResId
66 0 : sal_uInt16 nIdx = 0;
67 0 : for(sal_uInt16 i = 0; i < nSize; ++i)
68 : { // Gleiche ResId -> Index erhoehen
69 0 : SwFieldType& rFldType = *((*pFldTypes)[i]);
70 0 : if(rFldType.Which() == nResId)
71 0 : nIdx++;
72 : }
73 0 : return nIdx;
74 : }
75 :
76 : /*--------------------------------------------------------------------
77 : Beschreibung: Feldtypen zu einer ResId finden
78 : wenn 0 alle finden
79 : --------------------------------------------------------------------*/
80 0 : SwFieldType* SwEditShell::GetFldType(sal_uInt16 nFld, sal_uInt16 nResId, sal_Bool bUsed ) const
81 : {
82 0 : const SwFldTypes* pFldTypes = GetDoc()->GetFldTypes();
83 0 : const sal_uInt16 nSize = pFldTypes->size();
84 :
85 0 : if(nResId == USHRT_MAX && nFld < nSize)
86 : {
87 0 : if(!bUsed)
88 0 : return (*pFldTypes)[nFld];
89 : else
90 : {
91 0 : sal_uInt16 i, nUsed = 0;
92 0 : for ( i = 0; i < nSize; i++ )
93 : {
94 0 : if(IsUsed(*(*pFldTypes)[i]))
95 : {
96 0 : if(nUsed == nFld)
97 0 : break;
98 0 : nUsed++;
99 : }
100 : }
101 0 : return i < nSize ? (*pFldTypes)[i] : 0;
102 : }
103 : }
104 :
105 0 : sal_uInt16 nIdx = 0;
106 0 : for(sal_uInt16 i = 0; i < nSize; ++i)
107 : { // Gleiche ResId -> Index erhoehen
108 0 : SwFieldType* pFldType = (*pFldTypes)[i];
109 0 : if(pFldType->Which() == nResId)
110 : {
111 0 : if (!bUsed || IsUsed(*pFldType))
112 : {
113 0 : if(nIdx == nFld)
114 0 : return pFldType;
115 0 : nIdx++;
116 : }
117 : }
118 : }
119 0 : return 0;
120 : }
121 :
122 : /*--------------------------------------------------------------------
123 : Beschreibung: Den ersten Typen mit ResId und Namen finden
124 : --------------------------------------------------------------------*/
125 0 : SwFieldType* SwEditShell::GetFldType(sal_uInt16 nResId, const String& rName) const
126 : {
127 0 : return GetDoc()->GetFldType( nResId, rName, false );
128 : }
129 :
130 : /*--------------------------------------------------------------------
131 : Beschreibung: Feldtypen loeschen
132 : --------------------------------------------------------------------*/
133 0 : void SwEditShell::RemoveFldType(sal_uInt16 nFld, sal_uInt16 nResId)
134 : {
135 0 : if( USHRT_MAX == nResId )
136 : {
137 0 : GetDoc()->RemoveFldType(nFld);
138 0 : return;
139 : }
140 :
141 0 : const SwFldTypes* pFldTypes = GetDoc()->GetFldTypes();
142 0 : const sal_uInt16 nSize = pFldTypes->size();
143 0 : sal_uInt16 nIdx = 0;
144 0 : for( sal_uInt16 i = 0; i < nSize; ++i )
145 : // Gleiche ResId -> Index erhoehen
146 0 : if( (*pFldTypes)[i]->Which() == nResId &&
147 : nIdx++ == nFld )
148 : {
149 0 : GetDoc()->RemoveFldType( i );
150 0 : return;
151 : }
152 : }
153 :
154 : /*--------------------------------------------------------------------
155 : Beschreibung: FieldType ueber Name loeschen
156 : --------------------------------------------------------------------*/
157 0 : void SwEditShell::RemoveFldType(sal_uInt16 nResId, const String& rStr)
158 : {
159 0 : const SwFldTypes* pFldTypes = GetDoc()->GetFldTypes();
160 0 : const sal_uInt16 nSize = pFldTypes->size();
161 0 : const CharClass& rCC = GetAppCharClass();
162 :
163 0 : String aTmp( rCC.lowercase( rStr ));
164 :
165 0 : for(sal_uInt16 i = 0; i < nSize; ++i)
166 : {
167 : // Gleiche ResId -> Index erhoehen
168 0 : SwFieldType* pFldType = (*pFldTypes)[i];
169 0 : if( pFldType->Which() == nResId )
170 : {
171 0 : if( aTmp.Equals( rCC.lowercase( pFldType->GetName() ) ))
172 : {
173 0 : GetDoc()->RemoveFldType(i);
174 0 : return;
175 : }
176 : }
177 0 : }
178 : }
179 :
180 :
181 0 : void SwEditShell::FieldToText( SwFieldType* pType )
182 : {
183 0 : if( !pType->GetDepends() )
184 0 : return;
185 :
186 0 : SET_CURR_SHELL( this );
187 0 : StartAllAction();
188 0 : StartUndo( UNDO_DELETE );
189 0 : Push();
190 0 : SwPaM* pPaM = GetCrsr();
191 :
192 0 : SwFieldHint aHint( pPaM );
193 0 : SwClientIter aIter( *pType );
194 0 : for ( SwClient* pClient = aIter.GoStart(); pClient; pClient = ++aIter )
195 : {
196 0 : pPaM->DeleteMark();
197 0 : pClient->SwClientNotifyCall( *pType, aHint );
198 : }
199 :
200 0 : Pop( sal_False );
201 0 : EndAllAction();
202 0 : EndUndo( UNDO_DELETE );
203 : }
204 :
205 : /*************************************************************************
206 : |*
207 : |* SwEditShell::Insert( SwField )
208 : |*
209 : |* Beschreibung an der Cursorposition ein Feld einfuegen
210 : |* Quelle: vgl. SwEditShell::Insert( String )
211 : |*
212 : *************************************************************************/
213 0 : void SwEditShell::Insert2(SwField& rFld, const bool bForceExpandHints)
214 : {
215 0 : SET_CURR_SHELL( this );
216 0 : StartAllAction();
217 0 : SwFmtFld aFld( rFld );
218 :
219 : const SetAttrMode nInsertFlags = (bForceExpandHints)
220 : ? nsSetAttrMode::SETATTR_FORCEHINTEXPAND
221 0 : : nsSetAttrMode::SETATTR_DEFAULT;
222 :
223 0 : FOREACHPAM_START(this) // fuer jeden PaM
224 0 : bool bSuccess(GetDoc()->InsertPoolItem(*PCURCRSR, aFld, nInsertFlags));
225 : OSL_ENSURE( bSuccess, "Doc->Insert(Field) failed");
226 : (void) bSuccess;
227 0 : FOREACHPAM_END() // fuer jeden PaM
228 :
229 0 : EndAllAction();
230 0 : }
231 :
232 : /*************************************************************************
233 : |*
234 : |* SwEditShell::GetCurFld()
235 : |*
236 : |* Beschreibung Stehen die PaMs auf Feldern ?
237 : |* Quelle: edtfrm.cxx:
238 : |*
239 : *************************************************************************/
240 :
241 0 : inline SwTxtFld *GetDocTxtFld( const SwPosition* pPos )
242 : {
243 0 : SwTxtNode * const pNode = pPos->nNode.GetNode().GetTxtNode();
244 : return (pNode)
245 : ? static_cast<SwTxtFld*>( pNode->GetTxtAttrForCharAt(
246 0 : pPos->nContent.GetIndex(), RES_TXTATR_FIELD ))
247 0 : : 0;
248 : }
249 :
250 0 : SwField* SwEditShell::GetCurFld() const
251 : {
252 : // Wenn es keine Selektionen gibt, gilt der Wert der aktuellen
253 : // Cursor-Position.
254 :
255 0 : SwPaM* pCrsr = GetCrsr();
256 0 : SwTxtFld *pTxtFld = GetDocTxtFld( pCrsr->Start() );
257 0 : SwField *pCurFld = NULL;
258 :
259 : /* Field was only recognized if no selection was
260 : present. Now it is recognized if either the cursor is in the
261 : field or the selection spans exactly over the field. */
262 0 : if( pTxtFld &&
263 0 : pCrsr->GetNext() == pCrsr &&
264 0 : pCrsr->Start()->nNode == pCrsr->End()->nNode &&
265 0 : (pCrsr->End()->nContent.GetIndex() -
266 0 : pCrsr->Start()->nContent.GetIndex()) <= 1)
267 : {
268 0 : pCurFld = (SwField*)pTxtFld->GetFld().GetFld();
269 : // TabellenFormel ? wandel internen in externen Namen um
270 0 : if( RES_TABLEFLD == pCurFld->GetTyp()->Which() )
271 : {
272 0 : const SwTableNode* pTblNd = IsCrsrInTbl();
273 0 : ((SwTblField*)pCurFld)->PtrToBoxNm( pTblNd ? &pTblNd->GetTable() : 0 );
274 : }
275 :
276 : }
277 :
278 : /* removed handling of multi-selections */
279 :
280 0 : return pCurFld;
281 : }
282 :
283 :
284 : /*************************************************************************
285 : |*
286 : |* SwEditShell::UpdateFlds()
287 : |*
288 : |* Beschreibung Stehen die PaMs auf Feldern ?
289 : |*
290 : *************************************************************************/
291 0 : static SwTxtFld* lcl_FindInputFld( SwDoc* pDoc, SwField& rFld )
292 : {
293 : // suche das Feld ueber seine Addresse. Muss fuer InputFelder in
294 : // geschuetzten Feldern erfolgen
295 0 : SwTxtFld* pTFld = 0;
296 0 : if( RES_INPUTFLD == rFld.Which() || ( RES_SETEXPFLD == rFld.Which() &&
297 0 : ((SwSetExpField&)rFld).GetInputFlag() ) )
298 : {
299 : const SfxPoolItem* pItem;
300 : sal_uInt32 n, nMaxItems =
301 0 : pDoc->GetAttrPool().GetItemCount2( RES_TXTATR_FIELD );
302 0 : for( n = 0; n < nMaxItems; ++n )
303 0 : if( 0 != (pItem =
304 0 : pDoc->GetAttrPool().GetItem2( RES_TXTATR_FIELD, n ) )
305 0 : && ((SwFmtFld*)pItem)->GetFld() == &rFld )
306 : {
307 0 : pTFld = ((SwFmtFld*)pItem)->GetTxtFld();
308 0 : break;
309 : }
310 : }
311 0 : return pTFld;
312 : }
313 :
314 0 : void SwEditShell::UpdateFlds( SwField &rFld )
315 : {
316 0 : SET_CURR_SHELL( this );
317 0 : StartAllAction();
318 : {
319 0 : SwField *pCurFld = 0;
320 :
321 : // Wenn es keine Selektionen gibt, gilt der Wert der aktuellen
322 : // Cursor-Position.
323 0 : SwMsgPoolItem* pMsgHnt = 0;
324 0 : SwRefMarkFldUpdate aRefMkHt( GetOut() );
325 0 : sal_uInt16 nFldWhich = rFld.GetTyp()->Which();
326 0 : if( RES_GETREFFLD == nFldWhich )
327 0 : pMsgHnt = &aRefMkHt;
328 :
329 0 : SwPaM* pCrsr = GetCrsr();
330 : SwTxtFld *pTxtFld;
331 : SwFmtFld *pFmtFld;
332 :
333 0 : if ( pCrsr->GetNext() == pCrsr && !pCrsr->HasMark())
334 : {
335 0 : pTxtFld = GetDocTxtFld(pCrsr->Start());
336 :
337 0 : if (!pTxtFld) // #i30221#
338 0 : pTxtFld = lcl_FindInputFld( GetDoc(), rFld);
339 :
340 0 : if (pTxtFld != 0)
341 0 : GetDoc()->UpdateFld(pTxtFld, rFld, pMsgHnt, sal_True);
342 : }
343 :
344 : // bOkay (statt return wg. EndAllAction) wird false,
345 : // 1) wenn nur ein Pam mehr als ein Feld enthaelt oder
346 : // 2) bei gemischten Feldtypen
347 0 : bool bOkay = true;
348 0 : sal_Bool bTblSelBreak = sal_False;
349 :
350 0 : SwMsgPoolItem aHint( RES_TXTATR_FIELD ); // Such-Hint
351 0 : FOREACHPAM_START(this) // fuer jeden PaM
352 0 : if( PCURCRSR->HasMark() && bOkay ) // ... mit Selektion
353 : {
354 : // Kopie des PaM
355 0 : SwPaM aCurPam( *PCURCRSR->GetMark(), *PCURCRSR->GetPoint() );
356 0 : SwPaM aPam( *PCURCRSR->GetPoint() );
357 :
358 0 : SwPosition *pCurStt = aCurPam.Start(), *pCurEnd =
359 0 : aCurPam.End();
360 : /*
361 : * Fuer den Fall, dass zwei aneinanderliegende Felder in einem
362 : * PaM liegen, hangelt sich aPam portionsweise bis zum Ende.
363 : * aCurPam wird dabei nach jeder Schleifenrunde verkuerzt.
364 : * Wenn aCurPam vollstaendig durchsucht wurde, ist Start = End
365 : * und die Schleife terminiert.
366 : */
367 :
368 : // Suche nach SwTxtFld ...
369 0 : while( bOkay
370 0 : && pCurStt->nContent != pCurEnd->nContent
371 0 : && aPam.Find( aHint, sal_False, fnMoveForward, &aCurPam ) )
372 : {
373 : // wenn nur ein Pam mehr als ein Feld enthaelt ...
374 0 : if( aPam.Start()->nContent != pCurStt->nContent )
375 0 : bOkay = false;
376 :
377 0 : if( 0 != (pTxtFld = GetDocTxtFld( pCurStt )) )
378 : {
379 0 : pFmtFld = (SwFmtFld*)&pTxtFld->GetFld();
380 0 : pCurFld = pFmtFld->GetFld();
381 :
382 : // bei gemischten Feldtypen
383 0 : if( pCurFld->GetTyp()->Which() !=
384 0 : rFld.GetTyp()->Which() )
385 0 : bOkay = false;
386 :
387 0 : bTblSelBreak = GetDoc()->UpdateFld(pTxtFld, rFld,
388 0 : pMsgHnt, sal_False);
389 : }
390 : // Der Suchbereich wird um den gefundenen Bereich
391 : // verkuerzt.
392 0 : pCurStt->nContent++;
393 0 : }
394 : }
395 :
396 0 : if( bTblSelBreak ) // wenn Tabellen Selektion und Tabellen-
397 0 : break; // Formel aktualisiert wurde -> beenden
398 :
399 0 : FOREACHPAM_END() // fuer jeden PaM
400 : }
401 0 : GetDoc()->SetModified();
402 0 : EndAllAction();
403 0 : }
404 :
405 : /*--------------------------------------------------
406 : Liefert den logischen fuer die Datenbank zurueck
407 : --------------------------------------------------*/
408 :
409 0 : SwDBData SwEditShell::GetDBData() const
410 : {
411 0 : return GetDoc()->GetDBData();
412 : }
413 :
414 0 : const SwDBData& SwEditShell::GetDBDesc() const
415 : {
416 0 : return GetDoc()->GetDBDesc();
417 : }
418 :
419 0 : void SwEditShell::ChgDBData(const SwDBData& rNewData)
420 : {
421 0 : GetDoc()->ChgDBData(rNewData);
422 0 : }
423 :
424 0 : void SwEditShell::GetAllUsedDB( std::vector<String>& rDBNameList,
425 : std::vector<String>* pAllDBNames )
426 : {
427 0 : GetDoc()->GetAllUsedDB( rDBNameList, pAllDBNames );
428 0 : }
429 :
430 0 : void SwEditShell::ChangeDBFields( const std::vector<String>& rOldNames,
431 : const String& rNewName )
432 : {
433 0 : GetDoc()->ChangeDBFields( rOldNames, rNewName );
434 0 : }
435 :
436 : /*--------------------------------------------------------------------
437 : Beschreibung: Alle Expression-Felder erneuern
438 : --------------------------------------------------------------------*/
439 0 : void SwEditShell::UpdateExpFlds(sal_Bool bCloseDB)
440 : {
441 0 : SET_CURR_SHELL( this );
442 0 : StartAllAction();
443 0 : GetDoc()->UpdateExpFlds(NULL, true);
444 0 : if (bCloseDB)
445 0 : GetDoc()->GetNewDBMgr()->CloseAll(); // Alle Datenbankverbindungen dichtmachen
446 0 : EndAllAction();
447 0 : }
448 :
449 0 : SwNewDBMgr* SwEditShell::GetNewDBMgr() const
450 : {
451 0 : return GetDoc()->GetNewDBMgr();
452 : }
453 :
454 : /*--------------------------------------------------------------------
455 : Beschreibung: Feldtypen einfuegen
456 : --------------------------------------------------------------------*/
457 0 : SwFieldType* SwEditShell::InsertFldType(const SwFieldType& rFldType)
458 : {
459 0 : return GetDoc()->InsertFldType(rFldType);
460 : }
461 :
462 0 : void SwEditShell::LockExpFlds()
463 : {
464 0 : GetDoc()->LockExpFlds();
465 0 : }
466 :
467 0 : void SwEditShell::UnlockExpFlds()
468 : {
469 0 : GetDoc()->UnlockExpFlds();
470 0 : }
471 :
472 :
473 0 : void SwEditShell::SetFldUpdateFlags( SwFldUpdateFlags eFlags )
474 : {
475 0 : getIDocumentSettingAccess()->setFieldUpdateFlags( eFlags );
476 0 : }
477 :
478 0 : SwFldUpdateFlags SwEditShell::GetFldUpdateFlags(sal_Bool bDocSettings) const
479 : {
480 0 : return getIDocumentSettingAccess()->getFieldUpdateFlags( !bDocSettings );
481 : }
482 :
483 0 : void SwEditShell::SetLabelDoc( sal_Bool bFlag )
484 : {
485 0 : GetDoc()->set(IDocumentSettingAccess::LABEL_DOCUMENT, bFlag );
486 0 : }
487 :
488 1264 : sal_Bool SwEditShell::IsLabelDoc() const
489 : {
490 1264 : return getIDocumentSettingAccess()->get(IDocumentSettingAccess::LABEL_DOCUMENT);
491 : }
492 :
493 0 : void SwEditShell::ChangeAuthorityData(const SwAuthEntry* pNewData)
494 : {
495 0 : GetDoc()->ChangeAuthorityData(pNewData);
496 0 : }
497 :
498 0 : sal_Bool SwEditShell::IsAnyDatabaseFieldInDoc()const
499 : {
500 0 : const SwFldTypes * pFldTypes = GetDoc()->GetFldTypes();
501 0 : const sal_uInt16 nSize = pFldTypes->size();
502 0 : for(sal_uInt16 i = 0; i < nSize; ++i)
503 : {
504 0 : SwFieldType& rFldType = *((*pFldTypes)[i]);
505 0 : sal_uInt16 nWhich = rFldType.Which();
506 0 : if(IsUsed(rFldType))
507 : {
508 0 : switch(nWhich)
509 : {
510 : case RES_DBFLD:
511 : case RES_DBNEXTSETFLD:
512 : case RES_DBNUMSETFLD:
513 : case RES_DBSETNUMBERFLD:
514 : {
515 0 : SwIterator<SwFmtFld,SwFieldType> aIter( rFldType );
516 0 : SwFmtFld* pFld = aIter.First();
517 0 : while(pFld)
518 : {
519 0 : if(pFld->IsFldInDoc())
520 0 : return sal_True;
521 0 : pFld = aIter.Next();
522 0 : }
523 : }
524 0 : break;
525 : }
526 : }
527 : }
528 0 : return sal_False;
529 : }
530 :
531 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|