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 pDoc
->ForEachFormatField(RES_TXTATR_INPUTFIELD
,
175 [&rField
, &pTField
] (const SwFormatField
& rFormatField
) -> bool
177 if( rFormatField
.GetField() == &rField
)
179 pTField
= const_cast<SwFormatField
&>(rFormatField
).GetTextField();
185 else if( SwFieldIds::SetExp
== rField
.Which()
186 && static_cast<const SwSetExpField
&>(rField
).GetInputFlag() )
188 pDoc
->ForEachFormatField(RES_TXTATR_FIELD
,
189 [&rField
, &pTField
] (const SwFormatField
& rFormatField
) -> bool
191 if( rFormatField
.GetField() == &rField
)
193 pTField
= const_cast<SwFormatField
&>(rFormatField
).GetTextField();
202 void SwEditShell::UpdateOneField(SwField
&rField
)
204 CurrShell
aCurr( this );
207 // If there are no selections so take the value of the current cursor position.
208 SwPaM
* pCursor
= GetCursor();
209 SwTextField
*pTextField
;
210 SwFormatField
*pFormatField
;
212 if ( !pCursor
->IsMultiSelection() && !pCursor
->HasMark())
214 pTextField
= GetTextFieldAtPos(pCursor
->Start(), ::sw::GetTextAttrMode::Default
);
216 if (!pTextField
) // #i30221#
217 pTextField
= lcl_FindInputField( GetDoc(), rField
);
219 if (pTextField
!= nullptr)
221 GetDoc()->getIDocumentFieldsAccess().UpdateField(
228 // bOkay (instead of return because of EndAllAction) becomes false,
229 // 1) if only one PaM has more than one field or
230 // 2) if there are mixed field types
232 bool bTableSelBreak
= false;
234 SwMsgPoolItem
aFieldHint( RES_TXTATR_FIELD
); // Search-Hint
235 SwMsgPoolItem
aAnnotationFieldHint( RES_TXTATR_ANNOTATION
);
236 SwMsgPoolItem
aInputFieldHint( RES_TXTATR_INPUTFIELD
);
237 for(SwPaM
& rPaM
: GetCursor()->GetRingContainer()) // for each PaM
239 if( rPaM
.HasMark() && bOkay
) // ... with selection
242 SwPaM
aCurPam( *rPaM
.GetMark(), *rPaM
.GetPoint() );
243 SwPaM
aPam( *rPaM
.GetPoint() );
245 SwPosition
*pCurStt
= aCurPam
.Start(), *pCurEnd
=
248 * In case that there are two contiguous fields in a PaM, the aPam goes step by step
249 * to the end. aCurPam is reduced in each loop. If aCurPam was searched completely,
250 * the loop terminates because Start = End.
253 // Search for SwTextField ...
255 && pCurStt
->GetContentIndex() != pCurEnd
->GetContentIndex()
256 && (sw::FindAttrImpl(aPam
, aFieldHint
, fnMoveForward
, aCurPam
, true, GetLayout())
257 || sw::FindAttrImpl(aPam
, aAnnotationFieldHint
, fnMoveForward
, aCurPam
, false, GetLayout())
258 || sw::FindAttrImpl(aPam
, aInputFieldHint
, fnMoveForward
, aCurPam
, false, GetLayout())))
260 // if only one PaM has more than one field ...
261 if( aPam
.Start()->GetContentIndex() != pCurStt
->GetContentIndex() )
264 pTextField
= GetTextFieldAtPos(pCurStt
, ::sw::GetTextAttrMode::Default
);
265 if( nullptr != pTextField
)
267 pFormatField
= const_cast<SwFormatField
*>(&pTextField
->GetFormatField());
268 SwField
*pCurField
= pFormatField
->GetField();
270 // if there are mixed field types
271 if( pCurField
->GetTyp()->Which() !=
272 rField
.GetTyp()->Which() )
275 bTableSelBreak
= GetDoc()->getIDocumentFieldsAccess().UpdateField(
280 // The search area is reduced by the found area:
281 pCurStt
->AdjustContent(+1);
285 if( bTableSelBreak
) // If table section and table formula are updated -> finish
290 GetDoc()->getIDocumentState().SetModified();
294 SwDBData
const & SwEditShell::GetDBData() const
296 return GetDoc()->GetDBData();
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 );
321 GetDoc()->getIDocumentFieldsAccess().UpdateExpFields(nullptr, true);
324 #if HAVE_FEATURE_DBCONNECTIVITY && !ENABLE_FUZZERS
325 GetDoc()->GetDBManager()->CloseAll(); // close all database connections
331 SwDBManager
* SwEditShell::GetDBManager() const
333 #if HAVE_FEATURE_DBCONNECTIVITY && !ENABLE_FUZZERS
334 return GetDoc()->GetDBManager();
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 // Similar to: SwDoc::GetDBDesc
389 const SwFieldTypes
* pFieldTypes
= GetDoc()->getIDocumentFieldsAccess().GetFieldTypes();
390 for(const auto & pFieldType
: *pFieldTypes
)
392 if(IsUsed(*pFieldType
))
394 switch(pFieldType
->Which())
396 case SwFieldIds::Database
:
397 case SwFieldIds::DbNextSet
:
398 case SwFieldIds::DbNumSet
:
399 case SwFieldIds::DbSetNumber
:
401 std::vector
<SwFormatField
*> vFields
;
402 pFieldType
->GatherFields(vFields
);
403 return vFields
.size();
413 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */