/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /// count field types with a ResId, if SwFieldIds::Unknown count all size_t SwEditShell::GetFieldTypeCount(SwFieldIds nResId ) const { const SwFieldTypes* pFieldTypes = GetDoc()->getIDocumentFieldsAccess().GetFieldTypes(); if(nResId == SwFieldIds::Unknown) { return static_cast(pFieldTypes->size()); } // all types with the same ResId size_t nIdx = 0; for(const auto & pFieldType : *pFieldTypes) { // same ResId -> increment index if(pFieldType->Which() == nResId) nIdx++; } return nIdx; } /// get field types with a ResId, if 0 get all SwFieldType* SwEditShell::GetFieldType(size_t nField, SwFieldIds nResId ) const { const SwFieldTypes* pFieldTypes = GetDoc()->getIDocumentFieldsAccess().GetFieldTypes(); if(nResId == SwFieldIds::Unknown && nField < pFieldTypes->size()) { return (*pFieldTypes)[nField].get(); } size_t nIdx = 0; for(const auto & pFieldType : *pFieldTypes) { // same ResId -> increment index if(pFieldType->Which() == nResId) { if(nIdx == nField) return pFieldType.get(); nIdx++; } } return nullptr; } /// get first type with given ResId and name SwFieldType* SwEditShell::GetFieldType(SwFieldIds nResId, const OUString& rName) const { return GetDoc()->getIDocumentFieldsAccess().GetFieldType( nResId, rName, false ); } /// delete field type void SwEditShell::RemoveFieldType(size_t nField) { GetDoc()->getIDocumentFieldsAccess().RemoveFieldType(nField); } /// delete field type based on its name void SwEditShell::RemoveFieldType(SwFieldIds nResId, const OUString& rStr) { const SwFieldTypes* pFieldTypes = GetDoc()->getIDocumentFieldsAccess().GetFieldTypes(); const SwFieldTypes::size_type nSize = pFieldTypes->size(); const CharClass& rCC = GetAppCharClass(); OUString aTmp( rCC.lowercase( rStr )); for(SwFieldTypes::size_type i = 0; i < nSize; ++i) { // same ResId -> increment index SwFieldType* pFieldType = (*pFieldTypes)[i].get(); if( pFieldType->Which() == nResId ) { if( aTmp == rCC.lowercase( pFieldType->GetName() ) ) { GetDoc()->getIDocumentFieldsAccess().RemoveFieldType(i); return; } } } } void SwEditShell::FieldToText( SwFieldType const * pType ) { if( !pType->HasWriterListeners() ) return; SET_CURR_SHELL( this ); StartAllAction(); StartUndo( SwUndoId::DELETE ); Push(); SwPaM* pPaM = GetCursor(); // TODO: this is really hackish SwFieldHint aHint(pPaM, GetLayout()); SwIterator aIter(*pType); for( SwClient* pClient = aIter.First(); pClient; pClient = aIter.Next() ) { pPaM->DeleteMark(); pClient->SwClientNotifyCall( *pType, aHint ); } Pop(PopMode::DeleteCurrent); EndAllAction(); EndUndo( SwUndoId::DELETE ); } /// add a field at the cursor position void SwEditShell::Insert2(SwField const & rField, const bool bForceExpandHints) { SET_CURR_SHELL( this ); StartAllAction(); SwFormatField aField( rField ); const SetAttrMode nInsertFlags = bForceExpandHints ? SetAttrMode::FORCEHINTEXPAND : SetAttrMode::DEFAULT; for(const SwPaM& rPaM : GetCursor()->GetRingContainer()) // for each PaM { const bool bSuccess(GetDoc()->getIDocumentContentOperations().InsertPoolItem(rPaM, aField, nInsertFlags)); OSL_ENSURE( bSuccess, "Doc->Insert(Field) failed"); } EndAllAction(); } /// Are the PaMs positioned on fields? static SwTextField* lcl_FindInputField( SwDoc* pDoc, SwField& rField ) { // Search field via its address. For input fields this needs to be done in protected fields. SwTextField* pTField = nullptr; if (SwFieldIds::Input == rField.Which() || (SwFieldIds::SetExp == rField.Which() && static_cast(rField).GetInputFlag() && (static_cast(rField.GetTyp())->GetType() & nsSwGetSetExpType::GSE_STRING))) { for (const SfxPoolItem* pItem : pDoc->GetAttrPool().GetItemSurrogates(RES_TXTATR_INPUTFIELD)) { auto pFormatField = dynamic_cast(pItem); if( pFormatField && pFormatField->GetField() == &rField ) { pTField = const_cast(pFormatField)->GetTextField(); break; } } } else if( SwFieldIds::SetExp == rField.Which() && static_cast(rField).GetInputFlag() ) { for (const SfxPoolItem* pItem : pDoc->GetAttrPool().GetItemSurrogates(RES_TXTATR_FIELD)) { auto pFormatField = dynamic_cast(pItem); if( pFormatField && pFormatField->GetField() == &rField ) { pTField = const_cast(pFormatField)->GetTextField(); break; } } } return pTField; } void SwEditShell::UpdateOneField(SwField &rField) { SET_CURR_SHELL( this ); StartAllAction(); { // If there are no selections so take the value of the current cursor position. SwMsgPoolItem* pMsgHint = nullptr; SwRefMarkFieldUpdate aRefMkHt( GetOut() ); SwFieldIds nFieldWhich = rField.GetTyp()->Which(); if( SwFieldIds::GetRef == nFieldWhich ) pMsgHint = &aRefMkHt; SwPaM* pCursor = GetCursor(); SwTextField *pTextField; SwFormatField *pFormatField; if ( !pCursor->IsMultiSelection() && !pCursor->HasMark()) { pTextField = GetTextFieldAtPos( pCursor->Start(), true ); if (!pTextField) // #i30221# pTextField = lcl_FindInputField( GetDoc(), rField); if (pTextField != nullptr) GetDoc()->getIDocumentFieldsAccess().UpdateField(pTextField, rField, pMsgHint, true); } // bOkay (instead of return because of EndAllAction) becomes false, // 1) if only one PaM has more than one field or // 2) if there are mixed field types bool bOkay = true; bool bTableSelBreak = false; SwMsgPoolItem aFieldHint( RES_TXTATR_FIELD ); // Search-Hint SwMsgPoolItem aAnnotationFieldHint( RES_TXTATR_ANNOTATION ); SwMsgPoolItem aInputFieldHint( RES_TXTATR_INPUTFIELD ); for(SwPaM& rPaM : GetCursor()->GetRingContainer()) // for each PaM { if( rPaM.HasMark() && bOkay ) // ... with selection { // copy of the PaM SwPaM aCurPam( *rPaM.GetMark(), *rPaM.GetPoint() ); SwPaM aPam( *rPaM.GetPoint() ); SwPosition *pCurStt = aCurPam.Start(), *pCurEnd = aCurPam.End(); /* * In case that there are two contiguous fields in a PaM, the aPam goes step by step * to the end. aCurPam is reduced in each loop. If aCurPam was searched completely, * the loop terminates because Start = End. */ // Search for SwTextField ... while( bOkay && pCurStt->nContent != pCurEnd->nContent && (sw::FindAttrImpl(aPam, aFieldHint, fnMoveForward, aCurPam, true, GetLayout()) || sw::FindAttrImpl(aPam, aAnnotationFieldHint, fnMoveForward, aCurPam, false, GetLayout()) || sw::FindAttrImpl(aPam, aInputFieldHint, fnMoveForward, aCurPam, false, GetLayout()))) { // if only one PaM has more than one field ... if( aPam.Start()->nContent != pCurStt->nContent ) bOkay = false; if( nullptr != (pTextField = GetTextFieldAtPos( pCurStt, true )) ) { pFormatField = const_cast(&pTextField->GetFormatField()); SwField *pCurField = pFormatField->GetField(); // if there are mixed field types if( pCurField->GetTyp()->Which() != rField.GetTyp()->Which() ) bOkay = false; bTableSelBreak = GetDoc()->getIDocumentFieldsAccess().UpdateField(pTextField, rField, pMsgHint, false); } // The search area is reduced by the found area: ++pCurStt->nContent; } } if( bTableSelBreak ) // If table section and table formula are updated -> finish break; } } GetDoc()->getIDocumentState().SetModified(); EndAllAction(); } SwDBData const & SwEditShell::GetDBData() const { return GetDoc()->GetDBData(); } const SwDBData& SwEditShell::GetDBDesc() const { return GetDoc()->GetDBDesc(); } void SwEditShell::ChgDBData(const SwDBData& rNewData) { GetDoc()->ChgDBData(rNewData); } void SwEditShell::GetAllUsedDB( std::vector& rDBNameList, std::vector const * pAllDBNames ) { GetDoc()->GetAllUsedDB( rDBNameList, pAllDBNames ); } void SwEditShell::ChangeDBFields( const std::vector& rOldNames, const OUString& rNewName ) { GetDoc()->ChangeDBFields( rOldNames, rNewName ); } /// Update all expression fields void SwEditShell::UpdateExpFields(bool bCloseDB) { SET_CURR_SHELL( this ); StartAllAction(); GetDoc()->getIDocumentFieldsAccess().UpdateExpFields(nullptr, true); if (bCloseDB) { #if HAVE_FEATURE_DBCONNECTIVITY GetDoc()->GetDBManager()->CloseAll(); // close all database connections #endif } EndAllAction(); } SwDBManager* SwEditShell::GetDBManager() const { #if HAVE_FEATURE_DBCONNECTIVITY return GetDoc()->GetDBManager(); #else return NULL; #endif } /// insert field type SwFieldType* SwEditShell::InsertFieldType(const SwFieldType& rFieldType) { return GetDoc()->getIDocumentFieldsAccess().InsertFieldType(rFieldType); } void SwEditShell::LockExpFields() { GetDoc()->getIDocumentFieldsAccess().LockExpFields(); } void SwEditShell::UnlockExpFields() { GetDoc()->getIDocumentFieldsAccess().UnlockExpFields(); } bool SwEditShell::IsExpFieldsLocked() const { return GetDoc()->getIDocumentFieldsAccess().IsExpFieldsLocked(); } void SwEditShell::SetFieldUpdateFlags( SwFieldUpdateFlags eFlags ) { getIDocumentSettingAccess().setFieldUpdateFlags( eFlags ); } SwFieldUpdateFlags SwEditShell::GetFieldUpdateFlags() const { return getIDocumentSettingAccess().getFieldUpdateFlags( false ); } void SwEditShell::SetLabelDoc( bool bFlag ) { GetDoc()->GetDocumentSettingManager().set(DocumentSettingId::LABEL_DOCUMENT, bFlag ); } bool SwEditShell::IsLabelDoc() const { return getIDocumentSettingAccess().get(DocumentSettingId::LABEL_DOCUMENT); } void SwEditShell::ChangeAuthorityData(const SwAuthEntry* pNewData) { GetDoc()->ChangeAuthorityData(pNewData); } bool SwEditShell::IsAnyDatabaseFieldInDoc()const { const SwFieldTypes * pFieldTypes = GetDoc()->getIDocumentFieldsAccess().GetFieldTypes(); for(const auto & pFieldType : *pFieldTypes) { if(IsUsed(*pFieldType)) { switch(pFieldType->Which()) { case SwFieldIds::Database: case SwFieldIds::DbNextSet: case SwFieldIds::DbNumSet: case SwFieldIds::DbSetNumber: { std::vector vFields; pFieldType->GatherFields(vFields); return vFields.size(); } break; default: break; } } } return false; } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */