Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / sw / source / core / edit / edfld.cxx
blobf77ae8d97e07d68ca71928d4d8d0b7ae2fe95b76
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>
21 #include <config_fuzzers.h>
23 #include <osl/diagnose.h>
24 #include <unotools/charclass.hxx>
25 #include <editsh.hxx>
26 #include <fldbas.hxx>
27 #include <doc.hxx>
28 #include <IDocumentFieldsAccess.hxx>
29 #include <IDocumentState.hxx>
30 #include <docary.hxx>
31 #include <fmtfld.hxx>
32 #include <txtfld.hxx>
33 #include <pamtyp.hxx>
34 #include <expfld.hxx>
35 #include <swundo.hxx>
36 #include <dbmgr.hxx>
37 #include <hints.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 o3tl::narrowing<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 pType->CallSwClientNotify(aHint);
136 Pop(PopMode::DeleteCurrent);
137 EndAllAction();
138 EndUndo( SwUndoId::DELETE );
141 /// add a field at the cursor position
142 bool SwEditShell::InsertField(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 bool bSuccess(false);
153 for(const SwPaM& rPaM : GetCursor()->GetRingContainer()) // for each PaM
155 bSuccess |= GetDoc()->getIDocumentContentOperations().InsertPoolItem(rPaM, aField, nInsertFlags);
156 OSL_ENSURE( bSuccess, "Doc->Insert(Field) failed");
159 EndAllAction();
160 return bSuccess;
163 /// Are the PaMs positioned on fields?
164 static SwTextField* lcl_FindInputField( SwDoc* pDoc, const SwField& rField )
166 // Search field via its address. For input fields this needs to be done in protected fields.
167 SwTextField* pTField = nullptr;
168 if (SwFieldIds::Input == rField.Which()
169 || (SwFieldIds::SetExp == rField.Which()
170 && static_cast<const SwSetExpField&>(rField).GetInputFlag()
171 && (static_cast<SwSetExpFieldType*>(rField.GetTyp())->GetType()
172 & nsSwGetSetExpType::GSE_STRING)))
174 for (const SfxPoolItem* pItem : pDoc->GetAttrPool().GetItemSurrogates(RES_TXTATR_INPUTFIELD))
176 auto pFormatField = dynamic_cast<const SwFormatField*>(pItem);
177 if( pFormatField && pFormatField->GetField() == &rField )
179 pTField = const_cast<SwFormatField*>(pFormatField)->GetTextField();
180 break;
184 else if( SwFieldIds::SetExp == rField.Which()
185 && static_cast<const SwSetExpField&>(rField).GetInputFlag() )
187 for (const SfxPoolItem* pItem : pDoc->GetAttrPool().GetItemSurrogates(RES_TXTATR_FIELD))
189 auto pFormatField = dynamic_cast<const SwFormatField*>(pItem);
190 if( pFormatField && pFormatField->GetField() == &rField )
192 pTField = const_cast<SwFormatField*>(pFormatField)->GetTextField();
193 break;
197 return pTField;
200 void SwEditShell::UpdateOneField(SwField &rField)
202 CurrShell aCurr( this );
203 StartAllAction();
205 // If there are no selections so take the value of the current cursor position.
206 SwPaM* pCursor = GetCursor();
207 SwTextField *pTextField;
208 SwFormatField *pFormatField;
210 if ( !pCursor->IsMultiSelection() && !pCursor->HasMark())
212 pTextField = GetTextFieldAtPos(pCursor->Start(), ::sw::GetTextAttrMode::Default);
214 if (!pTextField) // #i30221#
215 pTextField = lcl_FindInputField( GetDoc(), rField);
217 if (pTextField != nullptr)
219 GetDoc()->getIDocumentFieldsAccess().UpdateField(
220 pTextField,
221 rField,
222 true);
226 // bOkay (instead of return because of EndAllAction) becomes false,
227 // 1) if only one PaM has more than one field or
228 // 2) if there are mixed field types
229 bool bOkay = true;
230 bool bTableSelBreak = false;
232 SwMsgPoolItem aFieldHint( RES_TXTATR_FIELD ); // Search-Hint
233 SwMsgPoolItem aAnnotationFieldHint( RES_TXTATR_ANNOTATION );
234 SwMsgPoolItem aInputFieldHint( RES_TXTATR_INPUTFIELD );
235 for(SwPaM& rPaM : GetCursor()->GetRingContainer()) // for each PaM
237 if( rPaM.HasMark() && bOkay ) // ... with selection
239 // copy of the PaM
240 SwPaM aCurPam( *rPaM.GetMark(), *rPaM.GetPoint() );
241 SwPaM aPam( *rPaM.GetPoint() );
243 SwPosition *pCurStt = aCurPam.Start(), *pCurEnd =
244 aCurPam.End();
246 * In case that there are two contiguous fields in a PaM, the aPam goes step by step
247 * to the end. aCurPam is reduced in each loop. If aCurPam was searched completely,
248 * the loop terminates because Start = End.
251 // Search for SwTextField ...
252 while( bOkay
253 && pCurStt->GetContentIndex() != pCurEnd->GetContentIndex()
254 && (sw::FindAttrImpl(aPam, aFieldHint, fnMoveForward, aCurPam, true, GetLayout())
255 || sw::FindAttrImpl(aPam, aAnnotationFieldHint, fnMoveForward, aCurPam, false, GetLayout())
256 || sw::FindAttrImpl(aPam, aInputFieldHint, fnMoveForward, aCurPam, false, GetLayout())))
258 // if only one PaM has more than one field ...
259 if( aPam.Start()->GetContentIndex() != pCurStt->GetContentIndex() )
260 bOkay = false;
262 pTextField = GetTextFieldAtPos(pCurStt, ::sw::GetTextAttrMode::Default);
263 if( nullptr != pTextField )
265 pFormatField = const_cast<SwFormatField*>(&pTextField->GetFormatField());
266 SwField *pCurField = pFormatField->GetField();
268 // if there are mixed field types
269 if( pCurField->GetTyp()->Which() !=
270 rField.GetTyp()->Which() )
271 bOkay = false;
273 bTableSelBreak = GetDoc()->getIDocumentFieldsAccess().UpdateField(
274 pTextField,
275 rField,
276 false);
278 // The search area is reduced by the found area:
279 pCurStt->AdjustContent(+1);
283 if( bTableSelBreak ) // If table section and table formula are updated -> finish
284 break;
288 GetDoc()->getIDocumentState().SetModified();
289 EndAllAction();
292 SwDBData const & SwEditShell::GetDBData() const
294 return GetDoc()->GetDBData();
297 void SwEditShell::ChgDBData(const SwDBData& rNewData)
299 GetDoc()->ChgDBData(rNewData);
302 void SwEditShell::GetAllUsedDB( std::vector<OUString>& rDBNameList,
303 std::vector<OUString> const * pAllDBNames )
305 GetDoc()->GetAllUsedDB( rDBNameList, pAllDBNames );
308 void SwEditShell::ChangeDBFields( const std::vector<OUString>& rOldNames,
309 const OUString& rNewName )
311 GetDoc()->ChangeDBFields( rOldNames, rNewName );
314 /// Update all expression fields
315 void SwEditShell::UpdateExpFields(bool bCloseDB)
317 CurrShell aCurr( this );
318 StartAllAction();
319 GetDoc()->getIDocumentFieldsAccess().UpdateExpFields(nullptr, true);
320 if (bCloseDB)
322 #if HAVE_FEATURE_DBCONNECTIVITY && !ENABLE_FUZZERS
323 GetDoc()->GetDBManager()->CloseAll(); // close all database connections
324 #endif
326 EndAllAction();
329 SwDBManager* SwEditShell::GetDBManager() const
331 #if HAVE_FEATURE_DBCONNECTIVITY && !ENABLE_FUZZERS
332 return GetDoc()->GetDBManager();
333 #else
334 return NULL;
335 #endif
338 /// insert field type
339 SwFieldType* SwEditShell::InsertFieldType(const SwFieldType& rFieldType)
341 return GetDoc()->getIDocumentFieldsAccess().InsertFieldType(rFieldType);
344 void SwEditShell::LockExpFields()
346 GetDoc()->getIDocumentFieldsAccess().LockExpFields();
349 void SwEditShell::UnlockExpFields()
351 GetDoc()->getIDocumentFieldsAccess().UnlockExpFields();
354 bool SwEditShell::IsExpFieldsLocked() const
356 return GetDoc()->getIDocumentFieldsAccess().IsExpFieldsLocked();
359 void SwEditShell::SetFieldUpdateFlags( SwFieldUpdateFlags eFlags )
361 getIDocumentSettingAccess().setFieldUpdateFlags( eFlags );
364 SwFieldUpdateFlags SwEditShell::GetFieldUpdateFlags() const
366 return getIDocumentSettingAccess().getFieldUpdateFlags( false );
369 void SwEditShell::SetLabelDoc( bool bFlag )
371 GetDoc()->GetDocumentSettingManager().set(DocumentSettingId::LABEL_DOCUMENT, bFlag );
374 bool SwEditShell::IsLabelDoc() const
376 return getIDocumentSettingAccess().get(DocumentSettingId::LABEL_DOCUMENT);
379 void SwEditShell::ChangeAuthorityData(const SwAuthEntry* pNewData)
381 GetDoc()->ChangeAuthorityData(pNewData);
384 bool SwEditShell::IsAnyDatabaseFieldInDoc()const
386 // Similar to: SwDoc::GetDBDesc
387 const SwFieldTypes * pFieldTypes = GetDoc()->getIDocumentFieldsAccess().GetFieldTypes();
388 for(const auto & pFieldType : *pFieldTypes)
390 if(IsUsed(*pFieldType))
392 switch(pFieldType->Which())
394 case SwFieldIds::Database:
395 case SwFieldIds::DbNextSet:
396 case SwFieldIds::DbNumSet:
397 case SwFieldIds::DbSetNumber:
399 std::vector<SwFormatField*> vFields;
400 pFieldType->GatherFields(vFields);
401 return vFields.size();
403 break;
404 default: break;
408 return false;
411 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */