1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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>
28 #include <IDocumentFieldsAccess.hxx>
29 #include <IDocumentState.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
54 for(const auto & pFieldType
: *pFieldTypes
)
56 // same ResId -> increment index
57 if(pFieldType
->Which() == nResId
)
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();
74 for(const auto & pFieldType
: *pFieldTypes
)
76 // same ResId -> increment index
77 if(pFieldType
->Which() == nResId
)
80 return pFieldType
.get();
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 );
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
);
123 void SwEditShell::FieldToText( SwFieldType
const * pType
)
125 if( !pType
->HasWriterListeners() )
128 CurrShell
aCurr( this );
130 StartUndo( SwUndoId::DELETE
);
132 SwPaM
* pPaM
= GetCursor();
133 const SwFieldHint
aHint(pPaM
, GetLayout());
134 pType
->CallSwClientNotify(aHint
);
136 Pop(PopMode::DeleteCurrent
);
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 );
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");
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();
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();
200 void SwEditShell::UpdateOneField(SwField
&rField
)
202 CurrShell
aCurr( this );
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(
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
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
240 SwPaM
aCurPam( *rPaM
.GetMark(), *rPaM
.GetPoint() );
241 SwPaM
aPam( *rPaM
.GetPoint() );
243 SwPosition
*pCurStt
= aCurPam
.Start(), *pCurEnd
=
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 ...
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() )
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() )
273 bTableSelBreak
= GetDoc()->getIDocumentFieldsAccess().UpdateField(
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
288 GetDoc()->getIDocumentState().SetModified();
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 );
319 GetDoc()->getIDocumentFieldsAccess().UpdateExpFields(nullptr, true);
322 #if HAVE_FEATURE_DBCONNECTIVITY && !ENABLE_FUZZERS
323 GetDoc()->GetDBManager()->CloseAll(); // close all database connections
329 SwDBManager
* SwEditShell::GetDBManager() const
331 #if HAVE_FEATURE_DBCONNECTIVITY && !ENABLE_FUZZERS
332 return GetDoc()->GetDBManager();
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();
411 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */