nss: upgrade to release 3.73
[LibreOffice.git] / sw / source / core / edit / edfld.cxx
blobc83f442b716055c939f8d37e8dc0a97be58237c3
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <config_features.h>
22 #include <osl/diagnose.h>
23 #include <unotools/charclass.hxx>
24 #include <editsh.hxx>
25 #include <fldbas.hxx>
26 #include <doc.hxx>
27 #include <IDocumentFieldsAccess.hxx>
28 #include <IDocumentState.hxx>
29 #include <docary.hxx>
30 #include <fmtfld.hxx>
31 #include <txtfld.hxx>
32 #include <pamtyp.hxx>
33 #include <expfld.hxx>
34 #include <swundo.hxx>
35 #include <dbmgr.hxx>
36 #include <hints.hxx>
37 #include <calbck.hxx>
38 #include <fieldhint.hxx>
39 #include <DocumentSettingManager.hxx>
40 #include <IDocumentContentOperations.hxx>
42 /// count field types with a ResId, if SwFieldIds::Unknown count all
43 size_t SwEditShell::GetFieldTypeCount(SwFieldIds nResId ) const
45 const SwFieldTypes* pFieldTypes = GetDoc()->getIDocumentFieldsAccess().GetFieldTypes();
47 if(nResId == SwFieldIds::Unknown)
49 return static_cast<sal_uInt16>(pFieldTypes->size());
52 // all types with the same ResId
53 size_t nIdx = 0;
54 for(const auto & pFieldType : *pFieldTypes)
56 // same ResId -> increment index
57 if(pFieldType->Which() == nResId)
58 nIdx++;
60 return nIdx;
63 /// get field types with a ResId, if 0 get all
64 SwFieldType* SwEditShell::GetFieldType(size_t nField, SwFieldIds nResId ) const
66 const SwFieldTypes* pFieldTypes = GetDoc()->getIDocumentFieldsAccess().GetFieldTypes();
68 if(nResId == SwFieldIds::Unknown && nField < pFieldTypes->size())
70 return (*pFieldTypes)[nField].get();
73 size_t nIdx = 0;
74 for(const auto & pFieldType : *pFieldTypes)
76 // same ResId -> increment index
77 if(pFieldType->Which() == nResId)
79 if(nIdx == nField)
80 return pFieldType.get();
81 nIdx++;
84 return nullptr;
87 /// get first type with given ResId and name
88 SwFieldType* SwEditShell::GetFieldType(SwFieldIds nResId, const OUString& rName) const
90 return GetDoc()->getIDocumentFieldsAccess().GetFieldType( nResId, rName, false );
93 /// delete field type
94 void SwEditShell::RemoveFieldType(size_t nField)
96 GetDoc()->getIDocumentFieldsAccess().RemoveFieldType(nField);
99 /// delete field type based on its name
100 void SwEditShell::RemoveFieldType(SwFieldIds nResId, const OUString& rStr)
102 const SwFieldTypes* pFieldTypes = GetDoc()->getIDocumentFieldsAccess().GetFieldTypes();
103 const SwFieldTypes::size_type nSize = pFieldTypes->size();
104 const CharClass& rCC = GetAppCharClass();
106 OUString aTmp( rCC.lowercase( rStr ));
108 for(SwFieldTypes::size_type i = 0; i < nSize; ++i)
110 // same ResId -> increment index
111 SwFieldType* pFieldType = (*pFieldTypes)[i].get();
112 if( pFieldType->Which() == nResId )
114 if( aTmp == rCC.lowercase( pFieldType->GetName() ) )
116 GetDoc()->getIDocumentFieldsAccess().RemoveFieldType(i);
117 return;
123 void SwEditShell::FieldToText( SwFieldType const * pType )
125 if( !pType->HasWriterListeners() )
126 return;
128 CurrShell aCurr( this );
129 StartAllAction();
130 StartUndo( SwUndoId::DELETE );
131 Push();
132 SwPaM* pPaM = GetCursor();
133 const SwFieldHint aHint(pPaM, GetLayout());
134 CallSwClientNotify(aHint);
136 Pop(PopMode::DeleteCurrent);
137 EndAllAction();
138 EndUndo( SwUndoId::DELETE );
141 /// add a field at the cursor position
142 void SwEditShell::Insert2(SwField const & rField, const bool bForceExpandHints)
144 CurrShell aCurr( this );
145 StartAllAction();
146 SwFormatField aField( rField );
148 const SetAttrMode nInsertFlags = bForceExpandHints
149 ? SetAttrMode::FORCEHINTEXPAND
150 : SetAttrMode::DEFAULT;
152 for(const SwPaM& rPaM : GetCursor()->GetRingContainer()) // for each PaM
154 const bool bSuccess(GetDoc()->getIDocumentContentOperations().InsertPoolItem(rPaM, aField, nInsertFlags));
155 OSL_ENSURE( bSuccess, "Doc->Insert(Field) failed");
158 EndAllAction();
161 /// Are the PaMs positioned on fields?
162 static SwTextField* lcl_FindInputField( SwDoc* pDoc, SwField& rField )
164 // Search field via its address. For input fields this needs to be done in protected fields.
165 SwTextField* pTField = nullptr;
166 if (SwFieldIds::Input == rField.Which()
167 || (SwFieldIds::SetExp == rField.Which()
168 && static_cast<SwSetExpField&>(rField).GetInputFlag()
169 && (static_cast<SwSetExpFieldType*>(rField.GetTyp())->GetType()
170 & nsSwGetSetExpType::GSE_STRING)))
172 for (const SfxPoolItem* pItem : pDoc->GetAttrPool().GetItemSurrogates(RES_TXTATR_INPUTFIELD))
174 auto pFormatField = dynamic_cast<const SwFormatField*>(pItem);
175 if( pFormatField && pFormatField->GetField() == &rField )
177 pTField = const_cast<SwFormatField*>(pFormatField)->GetTextField();
178 break;
182 else if( SwFieldIds::SetExp == rField.Which()
183 && static_cast<SwSetExpField&>(rField).GetInputFlag() )
185 for (const SfxPoolItem* pItem : pDoc->GetAttrPool().GetItemSurrogates(RES_TXTATR_FIELD))
187 auto pFormatField = dynamic_cast<const SwFormatField*>(pItem);
188 if( pFormatField && pFormatField->GetField() == &rField )
190 pTField = const_cast<SwFormatField*>(pFormatField)->GetTextField();
191 break;
195 return pTField;
198 void SwEditShell::UpdateOneField(SwField &rField)
200 CurrShell aCurr( this );
201 StartAllAction();
203 // If there are no selections so take the value of the current cursor position.
204 SwMsgPoolItem* pMsgHint = nullptr;
205 SwRefMarkFieldUpdate aRefMkHt( GetOut() );
206 SwFieldIds nFieldWhich = rField.GetTyp()->Which();
207 if( SwFieldIds::GetRef == nFieldWhich )
208 pMsgHint = &aRefMkHt;
210 SwPaM* pCursor = GetCursor();
211 SwTextField *pTextField;
212 SwFormatField *pFormatField;
214 if ( !pCursor->IsMultiSelection() && !pCursor->HasMark())
216 pTextField = GetTextFieldAtPos( pCursor->Start(), true );
218 if (!pTextField) // #i30221#
219 pTextField = lcl_FindInputField( GetDoc(), rField);
221 if (pTextField != nullptr)
222 GetDoc()->getIDocumentFieldsAccess().UpdateField(pTextField, rField, pMsgHint, true);
225 // bOkay (instead of return because of EndAllAction) becomes false,
226 // 1) if only one PaM has more than one field or
227 // 2) if there are mixed field types
228 bool bOkay = true;
229 bool bTableSelBreak = false;
231 SwMsgPoolItem aFieldHint( RES_TXTATR_FIELD ); // Search-Hint
232 SwMsgPoolItem aAnnotationFieldHint( RES_TXTATR_ANNOTATION );
233 SwMsgPoolItem aInputFieldHint( RES_TXTATR_INPUTFIELD );
234 for(SwPaM& rPaM : GetCursor()->GetRingContainer()) // for each PaM
236 if( rPaM.HasMark() && bOkay ) // ... with selection
238 // copy of the PaM
239 SwPaM aCurPam( *rPaM.GetMark(), *rPaM.GetPoint() );
240 SwPaM aPam( *rPaM.GetPoint() );
242 SwPosition *pCurStt = aCurPam.Start(), *pCurEnd =
243 aCurPam.End();
245 * In case that there are two contiguous fields in a PaM, the aPam goes step by step
246 * to the end. aCurPam is reduced in each loop. If aCurPam was searched completely,
247 * the loop terminates because Start = End.
250 // Search for SwTextField ...
251 while( bOkay
252 && pCurStt->nContent != pCurEnd->nContent
253 && (sw::FindAttrImpl(aPam, aFieldHint, fnMoveForward, aCurPam, true, GetLayout())
254 || sw::FindAttrImpl(aPam, aAnnotationFieldHint, fnMoveForward, aCurPam, false, GetLayout())
255 || sw::FindAttrImpl(aPam, aInputFieldHint, fnMoveForward, aCurPam, false, GetLayout())))
257 // if only one PaM has more than one field ...
258 if( aPam.Start()->nContent != pCurStt->nContent )
259 bOkay = false;
261 pTextField = GetTextFieldAtPos( pCurStt, true );
262 if( nullptr != pTextField )
264 pFormatField = const_cast<SwFormatField*>(&pTextField->GetFormatField());
265 SwField *pCurField = pFormatField->GetField();
267 // if there are mixed field types
268 if( pCurField->GetTyp()->Which() !=
269 rField.GetTyp()->Which() )
270 bOkay = false;
272 bTableSelBreak = GetDoc()->getIDocumentFieldsAccess().UpdateField(pTextField, rField,
273 pMsgHint, false);
275 // The search area is reduced by the found area:
276 ++pCurStt->nContent;
280 if( bTableSelBreak ) // If table section and table formula are updated -> finish
281 break;
285 GetDoc()->getIDocumentState().SetModified();
286 EndAllAction();
289 SwDBData const & SwEditShell::GetDBData() const
291 return GetDoc()->GetDBData();
294 const SwDBData& SwEditShell::GetDBDesc() const
296 return GetDoc()->GetDBDesc();
299 void SwEditShell::ChgDBData(const SwDBData& rNewData)
301 GetDoc()->ChgDBData(rNewData);
304 void SwEditShell::GetAllUsedDB( std::vector<OUString>& rDBNameList,
305 std::vector<OUString> const * pAllDBNames )
307 GetDoc()->GetAllUsedDB( rDBNameList, pAllDBNames );
310 void SwEditShell::ChangeDBFields( const std::vector<OUString>& rOldNames,
311 const OUString& rNewName )
313 GetDoc()->ChangeDBFields( rOldNames, rNewName );
316 /// Update all expression fields
317 void SwEditShell::UpdateExpFields(bool bCloseDB)
319 CurrShell aCurr( this );
320 StartAllAction();
321 GetDoc()->getIDocumentFieldsAccess().UpdateExpFields(nullptr, true);
322 if (bCloseDB)
324 #if HAVE_FEATURE_DBCONNECTIVITY
325 GetDoc()->GetDBManager()->CloseAll(); // close all database connections
326 #endif
328 EndAllAction();
331 SwDBManager* SwEditShell::GetDBManager() const
333 #if HAVE_FEATURE_DBCONNECTIVITY
334 return GetDoc()->GetDBManager();
335 #else
336 return NULL;
337 #endif
340 /// insert field type
341 SwFieldType* SwEditShell::InsertFieldType(const SwFieldType& rFieldType)
343 return GetDoc()->getIDocumentFieldsAccess().InsertFieldType(rFieldType);
346 void SwEditShell::LockExpFields()
348 GetDoc()->getIDocumentFieldsAccess().LockExpFields();
351 void SwEditShell::UnlockExpFields()
353 GetDoc()->getIDocumentFieldsAccess().UnlockExpFields();
356 bool SwEditShell::IsExpFieldsLocked() const
358 return GetDoc()->getIDocumentFieldsAccess().IsExpFieldsLocked();
361 void SwEditShell::SetFieldUpdateFlags( SwFieldUpdateFlags eFlags )
363 getIDocumentSettingAccess().setFieldUpdateFlags( eFlags );
366 SwFieldUpdateFlags SwEditShell::GetFieldUpdateFlags() const
368 return getIDocumentSettingAccess().getFieldUpdateFlags( false );
371 void SwEditShell::SetLabelDoc( bool bFlag )
373 GetDoc()->GetDocumentSettingManager().set(DocumentSettingId::LABEL_DOCUMENT, bFlag );
376 bool SwEditShell::IsLabelDoc() const
378 return getIDocumentSettingAccess().get(DocumentSettingId::LABEL_DOCUMENT);
381 void SwEditShell::ChangeAuthorityData(const SwAuthEntry* pNewData)
383 GetDoc()->ChangeAuthorityData(pNewData);
386 bool SwEditShell::IsAnyDatabaseFieldInDoc()const
388 const SwFieldTypes * pFieldTypes = GetDoc()->getIDocumentFieldsAccess().GetFieldTypes();
389 for(const auto & pFieldType : *pFieldTypes)
391 if(IsUsed(*pFieldType))
393 switch(pFieldType->Which())
395 case SwFieldIds::Database:
396 case SwFieldIds::DbNextSet:
397 case SwFieldIds::DbNumSet:
398 case SwFieldIds::DbSetNumber:
400 std::vector<SwFormatField*> vFields;
401 pFieldType->GatherFields(vFields);
402 return vFields.size();
404 break;
405 default: break;
409 return false;
412 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */