android: Update app-specific/MIME type icons
[LibreOffice.git] / sw / source / core / fields / docufld.cxx
blobe604985e7d0faf9eb6796dbfc687821737b77aac
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 <textapi.hxx>
25 #include <hintids.hxx>
26 #include <com/sun/star/frame/XModel.hpp>
27 #include <com/sun/star/text/XText.hpp>
28 #include <com/sun/star/script/Converter.hpp>
29 #include <com/sun/star/text/PlaceholderType.hpp>
30 #include <com/sun/star/text/TemplateDisplayFormat.hpp>
31 #include <com/sun/star/text/PageNumberType.hpp>
32 #include <com/sun/star/text/FilenameDisplayFormat.hpp>
33 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
34 #include <com/sun/star/document/XDocumentProperties.hpp>
35 #include <com/sun/star/util/Date.hpp>
36 #include <com/sun/star/util/Duration.hpp>
37 #include <o3tl/any.hxx>
38 #include <o3tl/string_view.hxx>
39 #include <unotools/localedatawrapper.hxx>
40 #include <comphelper/processfactory.hxx>
41 #include <comphelper/string.hxx>
42 #include <tools/urlobj.hxx>
43 #include <svl/numformat.hxx>
44 #include <svl/urihelper.hxx>
45 #include <unotools/useroptions.hxx>
46 #include <unotools/syslocale.hxx>
47 #include <libxml/xmlstring.h>
48 #include <libxml/xmlwriter.h>
50 #include <tools/time.hxx>
51 #include <tools/datetime.hxx>
53 #include <com/sun/star/util/DateTime.hpp>
55 #include <swmodule.hxx>
56 #include <sfx2/docfile.hxx>
57 #include <sfx2/doctempl.hxx>
58 #include <fmtfld.hxx>
59 #include <txtfld.hxx>
60 #include <charfmt.hxx>
61 #include <docstat.hxx>
62 #include <pagedesc.hxx>
63 #include <fmtpdsc.hxx>
64 #include <doc.hxx>
65 #include <IDocumentFieldsAccess.hxx>
66 #include <IDocumentStatistics.hxx>
67 #include <IDocumentStylePoolAccess.hxx>
68 #include <IDocumentLayoutAccess.hxx>
69 #include <rootfrm.hxx>
70 #include <pagefrm.hxx>
71 #include <cntfrm.hxx>
72 #include <pam.hxx>
73 #include <utility>
74 #include <viewsh.hxx>
75 #include <dbmgr.hxx>
76 #include <shellres.hxx>
77 #include <docufld.hxx>
78 #include <flddat.hxx>
79 #include <docfld.hxx>
80 #include <ndtxt.hxx>
81 #include <expfld.hxx>
82 #include <poolfmt.hxx>
83 #include <docsh.hxx>
84 #include <unofldmid.h>
85 #include <swunohelper.hxx>
86 #include <strings.hrc>
88 #include <editeng/outlobj.hxx>
89 #include <calbck.hxx>
90 #include <hints.hxx>
92 #define URL_DECODE INetURLObject::DecodeMechanism::Unambiguous
94 using namespace ::com::sun::star;
95 using namespace ::com::sun::star::uno;
96 using namespace nsSwDocInfoSubType;
98 SwPageNumberFieldType::SwPageNumberFieldType()
99 : SwFieldType( SwFieldIds::PageNumber ),
100 m_nNumberingType( SVX_NUM_ARABIC ),
101 m_bVirtual( false )
105 OUString SwPageNumberFieldType::Expand( SvxNumType nFormat, short nOff,
106 sal_uInt16 const nPageNumber, sal_uInt16 const nMaxPage,
107 const OUString& rUserStr, LanguageType nLang ) const
109 SvxNumType nTmpFormat = (SVX_NUM_PAGEDESC == nFormat) ? m_nNumberingType : nFormat;
110 int const nTmp = nPageNumber + nOff;
112 if (0 > nTmp || SVX_NUM_NUMBER_NONE == nTmpFormat || (!m_bVirtual && nTmp > nMaxPage))
113 return OUString();
115 if( SVX_NUM_CHAR_SPECIAL == nTmpFormat )
116 return rUserStr;
118 return FormatNumber( nTmp, nTmpFormat, nLang );
121 std::unique_ptr<SwFieldType> SwPageNumberFieldType::Copy() const
123 std::unique_ptr<SwPageNumberFieldType> pTmp(new SwPageNumberFieldType());
125 pTmp->m_nNumberingType = m_nNumberingType;
126 pTmp->m_bVirtual = m_bVirtual;
128 return pTmp;
131 void SwPageNumberFieldType::ChangeExpansion( SwDoc* pDoc,
132 bool bVirt,
133 const SvxNumType* pNumFormat )
135 if( pNumFormat )
136 m_nNumberingType = *pNumFormat;
138 m_bVirtual = false;
139 if (!(bVirt && pDoc))
140 return;
142 // check the flag since the layout NEVER sets it back
143 const SfxItemPool &rPool = pDoc->GetAttrPool();
144 for (const SfxPoolItem* pItem : rPool.GetItemSurrogates(RES_PAGEDESC))
146 auto pDesc = dynamic_cast<const SwFormatPageDesc*>(pItem);
147 if( pDesc && pDesc->GetNumOffset() && pDesc->GetDefinedIn() )
149 const SwContentNode* pNd = dynamic_cast<const SwContentNode*>( pDesc->GetDefinedIn() );
150 if( pNd )
152 if (SwIterator<SwFrame, SwContentNode, sw::IteratorMode::UnwrapMulti>(*pNd).First())
153 // sw_redlinehide: not sure if this should happen only if
154 // it's the first node, because that's where RES_PAGEDESC
155 // is effective?
156 m_bVirtual = true;
158 else if( dynamic_cast< const SwFormat* >(pDesc->GetDefinedIn()) != nullptr)
160 SwAutoFormatGetDocNode aGetHt( &pDoc->GetNodes() );
161 m_bVirtual = !pDesc->GetDefinedIn()->GetInfo( aGetHt );
162 break;
168 SwPageNumberField::SwPageNumberField(SwPageNumberFieldType* pTyp,
169 sal_uInt16 nSub, sal_uInt32 nFormat, short nOff,
170 sal_uInt16 const nPageNumber, sal_uInt16 const nMaxPage)
171 : SwField(pTyp, nFormat), m_nSubType(nSub), m_nOffset(nOff)
172 , m_nPageNumber(nPageNumber)
173 , m_nMaxPage(nMaxPage)
177 void SwPageNumberField::ChangeExpansion(sal_uInt16 const nPageNumber,
178 sal_uInt16 const nMaxPage)
180 m_nPageNumber = nPageNumber;
181 m_nMaxPage = nMaxPage;
184 OUString SwPageNumberField::ExpandImpl(SwRootFrame const*const) const
186 OUString sRet;
187 SwPageNumberFieldType* pFieldType = static_cast<SwPageNumberFieldType*>(GetTyp());
189 if( PG_NEXT == m_nSubType && 1 != m_nOffset )
191 sRet = pFieldType->Expand(static_cast<SvxNumType>(GetFormat()), 1, m_nPageNumber, m_nMaxPage, m_sUserStr, GetLanguage());
192 if (!sRet.isEmpty())
194 sRet = pFieldType->Expand(static_cast<SvxNumType>(GetFormat()), m_nOffset, m_nPageNumber, m_nMaxPage, m_sUserStr, GetLanguage());
197 else if( PG_PREV == m_nSubType && -1 != m_nOffset )
199 sRet = pFieldType->Expand(static_cast<SvxNumType>(GetFormat()), -1, m_nPageNumber, m_nMaxPage, m_sUserStr, GetLanguage());
200 if (!sRet.isEmpty())
202 sRet = pFieldType->Expand(static_cast<SvxNumType>(GetFormat()), m_nOffset, m_nPageNumber, m_nMaxPage, m_sUserStr, GetLanguage());
205 else
206 sRet = pFieldType->Expand(static_cast<SvxNumType>(GetFormat()), m_nOffset, m_nPageNumber, m_nMaxPage, m_sUserStr, GetLanguage());
207 return sRet;
210 std::unique_ptr<SwField> SwPageNumberField::Copy() const
212 std::unique_ptr<SwPageNumberField> pTmp(new SwPageNumberField(
213 static_cast<SwPageNumberFieldType*>(GetTyp()), m_nSubType,
214 GetFormat(), m_nOffset, m_nPageNumber, m_nMaxPage));
215 pTmp->SetLanguage( GetLanguage() );
216 pTmp->SetUserString( m_sUserStr );
217 return std::unique_ptr<SwField>(pTmp.release());
220 OUString SwPageNumberField::GetPar2() const
222 return OUString::number(m_nOffset);
225 void SwPageNumberField::SetPar2(const OUString& rStr)
227 m_nOffset = static_cast<short>(rStr.toInt32());
230 sal_uInt16 SwPageNumberField::GetSubType() const
232 return m_nSubType;
235 bool SwPageNumberField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
237 switch( nWhichId )
239 case FIELD_PROP_FORMAT:
240 rAny <<= static_cast<sal_Int16>(GetFormat());
241 break;
242 case FIELD_PROP_USHORT1:
243 rAny <<= m_nOffset;
244 break;
245 case FIELD_PROP_SUBTYPE:
247 text::PageNumberType eType;
248 eType = text::PageNumberType_CURRENT;
249 if(m_nSubType == PG_PREV)
250 eType = text::PageNumberType_PREV;
251 else if(m_nSubType == PG_NEXT)
252 eType = text::PageNumberType_NEXT;
253 rAny <<= eType;
255 break;
256 case FIELD_PROP_PAR1:
257 rAny <<= m_sUserStr;
258 break;
260 default:
261 assert(false);
263 return true;
266 bool SwPageNumberField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
268 bool bRet = true;
269 sal_Int16 nSet = 0;
270 switch( nWhichId )
272 case FIELD_PROP_FORMAT:
273 rAny >>= nSet;
275 // TODO: where do the defines come from?
276 if(nSet <= SVX_NUM_PAGEDESC )
277 SetFormat(nSet);
278 break;
279 case FIELD_PROP_USHORT1:
280 rAny >>= nSet;
281 m_nOffset = nSet;
282 break;
283 case FIELD_PROP_SUBTYPE:
284 switch( static_cast<text::PageNumberType>(SWUnoHelper::GetEnumAsInt32( rAny )) )
286 case text::PageNumberType_CURRENT:
287 m_nSubType = PG_RANDOM;
288 break;
289 case text::PageNumberType_PREV:
290 m_nSubType = PG_PREV;
291 break;
292 case text::PageNumberType_NEXT:
293 m_nSubType = PG_NEXT;
294 break;
295 default:
296 bRet = false;
298 break;
299 case FIELD_PROP_PAR1:
300 rAny >>= m_sUserStr;
301 break;
303 default:
304 assert(false);
306 return bRet;
309 SwAuthorFieldType::SwAuthorFieldType()
310 : SwFieldType( SwFieldIds::Author )
314 OUString SwAuthorFieldType::Expand(sal_uLong nFormat)
316 SvtUserOptions& rOpt = SW_MOD()->GetUserOptions();
317 if((nFormat & 0xff) == AF_NAME)
319 // Prefer the view's redline author name.
320 // (set in SwXTextDocument::initializeForTiledRendering)
321 std::size_t nAuthor = SW_MOD()->GetRedlineAuthor();
322 OUString sAuthor = SW_MOD()->GetRedlineAuthor(nAuthor);
323 if (sAuthor.isEmpty())
324 return rOpt.GetFullName();
326 return sAuthor;
329 return rOpt.GetID();
332 std::unique_ptr<SwFieldType> SwAuthorFieldType::Copy() const
334 return std::make_unique<SwAuthorFieldType>();
337 SwAuthorField::SwAuthorField(SwAuthorFieldType* pTyp, sal_uInt32 nFormat)
338 : SwField(pTyp, nFormat)
340 m_aContent = SwAuthorFieldType::Expand(GetFormat());
343 OUString SwAuthorField::ExpandImpl(SwRootFrame const*const) const
345 if (!IsFixed())
346 const_cast<SwAuthorField*>(this)->m_aContent =
347 SwAuthorFieldType::Expand(GetFormat());
349 return m_aContent;
352 std::unique_ptr<SwField> SwAuthorField::Copy() const
354 std::unique_ptr<SwAuthorField> pTmp(new SwAuthorField( static_cast<SwAuthorFieldType*>(GetTyp()),
355 GetFormat()));
356 pTmp->SetExpansion(m_aContent);
357 return std::unique_ptr<SwField>(pTmp.release());
360 bool SwAuthorField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
362 switch( nWhichId )
364 case FIELD_PROP_BOOL1:
365 rAny <<= (GetFormat() & 0xff) == AF_NAME;
366 break;
368 case FIELD_PROP_BOOL2:
369 rAny <<= IsFixed();
370 break;
372 case FIELD_PROP_PAR1:
373 rAny <<= m_aContent;
374 break;
376 case FIELD_PROP_TITLE:
377 break;
379 default:
380 assert(false);
382 return true;
385 bool SwAuthorField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
387 switch( nWhichId )
389 case FIELD_PROP_BOOL1:
390 SetFormat( *o3tl::doAccess<bool>(rAny) ? AF_NAME : AF_SHORTCUT );
391 break;
393 case FIELD_PROP_BOOL2:
394 if( *o3tl::doAccess<bool>(rAny) )
395 SetFormat( GetFormat() | AF_FIXED);
396 else
397 SetFormat( GetFormat() & ~AF_FIXED);
398 break;
400 case FIELD_PROP_PAR1:
401 rAny >>= m_aContent;
402 break;
404 case FIELD_PROP_TITLE:
405 break;
407 default:
408 assert(false);
410 return true;
413 SwFileNameFieldType::SwFileNameFieldType(SwDoc& rDocument)
414 : SwFieldType( SwFieldIds::Filename )
415 , m_rDoc(rDocument)
419 OUString SwFileNameFieldType::Expand(sal_uLong nFormat) const
421 OUString aRet;
422 const SwDocShell* pDShell = m_rDoc.GetDocShell();
423 if( pDShell && pDShell->HasName() )
425 const INetURLObject& rURLObj = pDShell->GetMedium()->GetURLObject();
426 switch( nFormat & ~FF_FIXED )
428 case FF_PATH:
430 if( INetProtocol::File == rURLObj.GetProtocol() )
432 INetURLObject aTemp(rURLObj);
433 aTemp.removeSegment();
434 // last slash should belong to the pathname
435 aRet = aTemp.PathToFileName();
437 else
439 aRet = URIHelper::removePassword(
440 rURLObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ),
441 INetURLObject::EncodeMechanism::WasEncoded, URL_DECODE );
442 const sal_Int32 nPos = aRet.indexOf(rURLObj.GetLastName( URL_DECODE ));
443 if (nPos>=0)
445 aRet = aRet.copy(0, nPos);
449 break;
451 case FF_NAME:
452 aRet = rURLObj.GetLastName( INetURLObject::DecodeMechanism::WithCharset );
453 break;
455 case FF_NAME_NOEXT:
456 aRet = rURLObj.GetBase();
457 break;
459 default:
460 if( INetProtocol::File == rURLObj.GetProtocol() )
461 aRet = rURLObj.GetFull();
462 else
463 aRet = URIHelper::removePassword(
464 rURLObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ),
465 INetURLObject::EncodeMechanism::WasEncoded, URL_DECODE );
468 return aRet;
471 std::unique_ptr<SwFieldType> SwFileNameFieldType::Copy() const
473 return std::make_unique<SwFileNameFieldType>(m_rDoc);
476 SwFileNameField::SwFileNameField(SwFileNameFieldType* pTyp, sal_uInt32 nFormat)
477 : SwField(pTyp, nFormat)
479 m_aContent = static_cast<SwFileNameFieldType*>(GetTyp())->Expand(GetFormat());
482 OUString SwFileNameField::ExpandImpl(SwRootFrame const*const) const
484 if (!IsFixed())
485 const_cast<SwFileNameField*>(this)->m_aContent = static_cast<SwFileNameFieldType*>(GetTyp())->Expand(GetFormat());
487 return m_aContent;
490 std::unique_ptr<SwField> SwFileNameField::Copy() const
492 std::unique_ptr<SwFileNameField> pTmp(
493 new SwFileNameField(static_cast<SwFileNameFieldType*>(GetTyp()), GetFormat()));
494 pTmp->SetExpansion(m_aContent);
496 return std::unique_ptr<SwField>(pTmp.release());
499 bool SwFileNameField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
501 switch( nWhichId )
503 case FIELD_PROP_FORMAT:
505 sal_Int16 nRet;
506 switch( GetFormat() &(~FF_FIXED) )
508 case FF_PATH:
509 nRet = text::FilenameDisplayFormat::PATH;
510 break;
511 case FF_NAME_NOEXT:
512 nRet = text::FilenameDisplayFormat::NAME;
513 break;
514 case FF_NAME:
515 nRet = text::FilenameDisplayFormat::NAME_AND_EXT;
516 break;
517 default: nRet = text::FilenameDisplayFormat::FULL;
519 rAny <<= nRet;
521 break;
523 case FIELD_PROP_BOOL2:
524 rAny <<= IsFixed();
525 break;
527 case FIELD_PROP_PAR3:
528 rAny <<= m_aContent;
529 break;
531 default:
532 assert(false);
534 return true;
537 bool SwFileNameField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
539 switch( nWhichId )
541 case FIELD_PROP_FORMAT:
543 //JP 24.10.2001: int32 because in UnoField.cxx a putvalue is
544 // called with a int32 value! But normally we need
545 // here only a int16
546 sal_Int32 nType = 0;
547 rAny >>= nType;
548 bool bFixed = IsFixed();
549 switch( nType )
551 case text::FilenameDisplayFormat::PATH:
552 nType = FF_PATH;
553 break;
554 case text::FilenameDisplayFormat::NAME:
555 nType = FF_NAME_NOEXT;
556 break;
557 case text::FilenameDisplayFormat::NAME_AND_EXT:
558 nType = FF_NAME;
559 break;
560 default: nType = FF_PATHNAME;
562 if(bFixed)
563 nType |= FF_FIXED;
564 SetFormat(nType);
566 break;
568 case FIELD_PROP_BOOL2:
569 if( *o3tl::doAccess<bool>(rAny) )
570 SetFormat( GetFormat() | FF_FIXED);
571 else
572 SetFormat( GetFormat() & ~FF_FIXED);
573 break;
575 case FIELD_PROP_PAR3:
576 rAny >>= m_aContent;
577 break;
579 default:
580 assert(false);
582 return true;
585 SwTemplNameFieldType::SwTemplNameFieldType(SwDoc& rDocument)
586 : SwFieldType( SwFieldIds::TemplateName )
587 , m_rDoc(rDocument)
591 OUString SwTemplNameFieldType::Expand(sal_uLong nFormat) const
593 OSL_ENSURE( nFormat < FF_END, "Expand: no valid Format!" );
595 OUString aRet;
596 SwDocShell *pDocShell(m_rDoc.GetDocShell());
597 OSL_ENSURE(pDocShell, "no SwDocShell");
598 if (pDocShell) {
599 uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
600 pDocShell->GetModel(), uno::UNO_QUERY_THROW);
601 uno::Reference<document::XDocumentProperties> xDocProps(
602 xDPS->getDocumentProperties());
603 OSL_ENSURE(xDocProps.is(), "Doc has no DocumentProperties");
605 if( FF_UI_NAME == nFormat )
606 aRet = xDocProps->getTemplateName();
607 else if( !xDocProps->getTemplateURL().isEmpty() )
609 if( FF_UI_RANGE == nFormat )
611 // for getting region names!
612 SfxDocumentTemplates aFac;
613 OUString sTmp;
614 OUString sRegion;
615 aFac.GetLogicNames( xDocProps->getTemplateURL(), sRegion, sTmp );
616 aRet = sRegion;
618 else
620 INetURLObject aPathName( xDocProps->getTemplateURL() );
621 if( FF_NAME == nFormat )
622 aRet = aPathName.GetLastName(URL_DECODE);
623 else if( FF_NAME_NOEXT == nFormat )
624 aRet = aPathName.GetBase();
625 else
627 if( FF_PATH == nFormat )
629 aPathName.removeSegment();
630 aRet = aPathName.GetFull();
632 else
633 aRet = aPathName.GetFull();
638 return aRet;
641 std::unique_ptr<SwFieldType> SwTemplNameFieldType::Copy() const
643 return std::make_unique<SwTemplNameFieldType>(m_rDoc);
646 SwTemplNameField::SwTemplNameField(SwTemplNameFieldType* pTyp, sal_uInt32 nFormat)
647 : SwField(pTyp, nFormat)
650 OUString SwTemplNameField::ExpandImpl(SwRootFrame const*const) const
652 return static_cast<SwTemplNameFieldType*>(GetTyp())->Expand(GetFormat());
655 std::unique_ptr<SwField> SwTemplNameField::Copy() const
657 return std::make_unique<SwTemplNameField>(static_cast<SwTemplNameFieldType*>(GetTyp()), GetFormat());
660 bool SwTemplNameField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
662 switch ( nWhichId )
664 case FIELD_PROP_FORMAT:
666 sal_Int16 nRet;
667 switch( GetFormat() )
669 case FF_PATH: nRet = text::FilenameDisplayFormat::PATH; break;
670 case FF_NAME_NOEXT: nRet = text::FilenameDisplayFormat::NAME; break;
671 case FF_NAME: nRet = text::FilenameDisplayFormat::NAME_AND_EXT; break;
672 case FF_UI_RANGE: nRet = text::TemplateDisplayFormat::AREA; break;
673 case FF_UI_NAME: nRet = text::TemplateDisplayFormat::TITLE; break;
674 default: nRet = text::FilenameDisplayFormat::FULL;
677 rAny <<= nRet;
679 break;
681 default:
682 assert(false);
684 return true;
687 bool SwTemplNameField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
689 switch ( nWhichId )
691 case FIELD_PROP_FORMAT:
693 //JP 24.10.2001: int32 because in UnoField.cxx a putvalue is
694 // called with a int32 value! But normally we need
695 // here only a int16
696 sal_Int32 nType = 0;
697 rAny >>= nType;
698 switch( nType )
700 case text::FilenameDisplayFormat::PATH:
701 SetFormat(FF_PATH);
702 break;
703 case text::FilenameDisplayFormat::NAME:
704 SetFormat(FF_NAME_NOEXT);
705 break;
706 case text::FilenameDisplayFormat::NAME_AND_EXT:
707 SetFormat(FF_NAME);
708 break;
709 case text::TemplateDisplayFormat::AREA :
710 SetFormat(FF_UI_RANGE);
711 break;
712 case text::TemplateDisplayFormat::TITLE :
713 SetFormat(FF_UI_NAME);
714 break;
715 default: SetFormat(FF_PATHNAME);
718 break;
720 default:
721 assert(false);
723 return true;
726 SwDocStatFieldType::SwDocStatFieldType(SwDoc& rDocument)
727 : SwFieldType(SwFieldIds::DocStat)
728 , m_rDoc(rDocument)
729 , m_nNumberingType(SVX_NUM_ARABIC)
733 OUString SwDocStatFieldType::Expand(sal_uInt16 nSubType, SvxNumType nFormat) const
735 sal_uInt32 nVal = 0;
736 const SwDocStat& rDStat = m_rDoc.getIDocumentStatistics().GetDocStat();
737 switch( nSubType )
739 case DS_TBL: nVal = rDStat.nTable; break;
740 case DS_GRF: nVal = rDStat.nGrf; break;
741 case DS_OLE: nVal = rDStat.nOLE; break;
742 case DS_PARA: nVal = rDStat.nPara; break;
743 case DS_WORD: nVal = rDStat.nWord; break;
744 case DS_CHAR: nVal = rDStat.nChar; break;
745 case DS_PAGE:
746 if( m_rDoc.getIDocumentLayoutAccess().GetCurrentLayout() )
747 const_cast<SwDocStat &>(rDStat).nPage = m_rDoc.getIDocumentLayoutAccess().GetCurrentLayout()->GetPageNum();
748 nVal = rDStat.nPage;
749 if( SVX_NUM_PAGEDESC == nFormat )
750 nFormat = m_nNumberingType;
751 break;
752 default:
753 OSL_FAIL( "SwDocStatFieldType::Expand: unknown SubType" );
756 if( nVal <= SHRT_MAX )
757 return FormatNumber( nVal, nFormat );
759 return OUString::number( nVal );
762 std::unique_ptr<SwFieldType> SwDocStatFieldType::Copy() const
764 return std::make_unique<SwDocStatFieldType>(m_rDoc);
768 * @param pTyp
769 * @param nSub SubType
770 * @param nFormat
772 SwDocStatField::SwDocStatField(SwDocStatFieldType* pTyp, sal_uInt16 nSub, sal_uInt32 nFormat)
773 : SwField(pTyp, nFormat),
774 m_nSubType(nSub)
777 OUString SwDocStatField::ExpandImpl(SwRootFrame const*const) const
779 return static_cast<SwDocStatFieldType*>(GetTyp())->Expand(m_nSubType, static_cast<SvxNumType>(GetFormat()));
782 std::unique_ptr<SwField> SwDocStatField::Copy() const
784 return std::make_unique<SwDocStatField>(
785 static_cast<SwDocStatFieldType*>(GetTyp()), m_nSubType, GetFormat() );
788 sal_uInt16 SwDocStatField::GetSubType() const
790 return m_nSubType;
793 void SwDocStatField::SetSubType(sal_uInt16 nSub)
795 m_nSubType = nSub;
798 void SwDocStatField::ChangeExpansion( const SwFrame* pFrame )
800 if( DS_PAGE == m_nSubType && SVX_NUM_PAGEDESC == GetFormat() )
801 static_cast<SwDocStatFieldType*>(GetTyp())->SetNumFormat(
802 pFrame->FindPageFrame()->GetPageDesc()->GetNumType().GetNumberingType() );
805 bool SwDocStatField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
807 switch ( nWhichId )
809 case FIELD_PROP_USHORT2:
810 rAny <<= static_cast<sal_Int16>(GetFormat());
811 break;
813 default:
814 assert(false);
816 return true;
819 bool SwDocStatField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
821 bool bRet = false;
822 switch ( nWhichId )
824 case FIELD_PROP_USHORT2:
826 sal_Int16 nSet = 0;
827 rAny >>= nSet;
828 if(nSet <= SVX_NUM_CHARS_LOWER_LETTER_N &&
829 nSet != SVX_NUM_CHAR_SPECIAL &&
830 nSet != SVX_NUM_BITMAP)
832 SetFormat(nSet);
833 bRet = true;
836 break;
838 default:
839 assert(false);
841 return bRet;
844 // Document info field type
846 SwDocInfoFieldType::SwDocInfoFieldType(SwDoc* pDc)
847 : SwValueFieldType( pDc, SwFieldIds::DocInfo )
851 std::unique_ptr<SwFieldType> SwDocInfoFieldType::Copy() const
853 return std::make_unique<SwDocInfoFieldType>(GetDoc());
856 static void lcl_GetLocalDataWrapper( LanguageType nLang,
857 const LocaleDataWrapper **ppAppLocalData,
858 const LocaleDataWrapper **ppLocalData )
860 SvtSysLocale aLocale;
861 *ppAppLocalData = &aLocale.GetLocaleData();
862 *ppLocalData = *ppAppLocalData;
863 if( nLang != (*ppLocalData)->getLanguageTag().getLanguageType() )
864 *ppLocalData = new LocaleDataWrapper(LanguageTag( nLang ));
867 OUString SwDocInfoFieldType::Expand( sal_uInt16 nSub, sal_uInt32 nFormat,
868 LanguageType nLang, const OUString& rName ) const
870 const LocaleDataWrapper *pAppLocalData = nullptr, *pLocalData = nullptr;
871 SwDocShell *pDocShell(GetDoc()->GetDocShell());
872 OSL_ENSURE(pDocShell, "no SwDocShell");
873 if (!pDocShell) { return OUString(); }
875 uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
876 pDocShell->GetModel(), uno::UNO_QUERY_THROW);
877 uno::Reference<document::XDocumentProperties> xDocProps(
878 xDPS->getDocumentProperties());
879 OSL_ENSURE(xDocProps.is(), "Doc has no DocumentProperties");
881 sal_uInt16 nExtSub = nSub & 0xff00;
882 nSub &= 0xff; // do not consider extended SubTypes
884 OUString aStr;
885 switch(nSub)
887 case DI_TITLE: aStr = xDocProps->getTitle(); break;
888 case DI_SUBJECT:aStr = xDocProps->getSubject(); break;
889 case DI_KEYS: aStr = ::comphelper::string::convertCommaSeparated(
890 xDocProps->getKeywords());
891 break;
892 case DI_COMMENT:aStr = xDocProps->getDescription(); break;
893 case DI_DOCNO: aStr = OUString::number(
894 xDocProps->getEditingCycles() );
895 break;
896 case DI_EDIT:
897 if ( !nFormat )
899 lcl_GetLocalDataWrapper( nLang, &pAppLocalData, &pLocalData );
900 sal_Int32 dur = xDocProps->getEditingDuration();
901 // If Seconds > 0 then bSec should be TRUE otherwise Seconds
902 // information will be lost if file has EditTime in Seconds format.
903 aStr = pLocalData->getTime( tools::Time(dur/3600, (dur%3600)/60, dur%60),
904 dur%60 > 0);
906 else
908 sal_Int32 dur = xDocProps->getEditingDuration();
909 double fVal = tools::Time(dur/3600, (dur%3600)/60, dur%60).GetTimeInDays();
910 aStr = ExpandValue(fVal, nFormat, nLang);
912 break;
913 case DI_CUSTOM:
915 OUString sVal;
918 uno::Any aAny;
919 uno::Reference < beans::XPropertySet > xSet(
920 xDocProps->getUserDefinedProperties(),
921 uno::UNO_QUERY_THROW);
922 aAny = xSet->getPropertyValue( rName );
924 uno::Reference < script::XTypeConverter > xConverter( script::Converter::create(comphelper::getProcessComponentContext()) );
925 uno::Any aNew = xConverter->convertToSimpleType( aAny, uno::TypeClass_STRING );
926 aNew >>= sVal;
928 catch (uno::Exception&) {}
929 return sVal;
932 default:
934 OUString aName( xDocProps->getAuthor() );
935 util::DateTime uDT( xDocProps->getCreationDate() );
936 DateTime aDate(uDT);
937 if( nSub == DI_CREATE )
938 ; // that's it !!
939 else if( nSub == DI_CHANGE )
941 aName = xDocProps->getModifiedBy();
942 uDT = xDocProps->getModificationDate();
943 aDate = DateTime(uDT);
945 else if( nSub == DI_PRINT )
947 aName = xDocProps->getPrintedBy();
948 uDT = xDocProps->getPrintDate();
949 aDate = DateTime(uDT);
951 else
952 break;
954 if (aDate.IsValidAndGregorian())
956 switch (nExtSub & ~DI_SUB_FIXED)
958 case DI_SUB_AUTHOR:
959 aStr = aName;
960 break;
962 case DI_SUB_TIME:
963 if (!nFormat)
965 lcl_GetLocalDataWrapper( nLang, &pAppLocalData,
966 &pLocalData );
967 aStr = pLocalData->getTime( aDate,
968 false);
970 else
972 // start the number formatter
973 double fVal = SwDateTimeField::GetDateTime( *GetDoc(),
974 aDate);
975 aStr = ExpandValue(fVal, nFormat, nLang);
977 break;
979 case DI_SUB_DATE:
980 if (!nFormat)
982 lcl_GetLocalDataWrapper( nLang, &pAppLocalData,
983 &pLocalData );
984 aStr = pLocalData->getDate( aDate );
986 else
988 // start the number formatter
989 double fVal = SwDateTimeField::GetDateTime( *GetDoc(),
990 aDate);
991 aStr = ExpandValue(fVal, nFormat, nLang);
993 break;
997 break;
1000 if( pAppLocalData != pLocalData )
1001 delete pLocalData;
1003 return aStr;
1006 // document info field
1008 SwDocInfoField::SwDocInfoField(SwDocInfoFieldType* pTyp, sal_uInt16 nSub, const OUString& rName, sal_uInt32 nFormat) :
1009 SwValueField(pTyp, nFormat), m_nSubType(nSub)
1011 m_aName = rName;
1012 m_aContent = static_cast<SwDocInfoFieldType*>(GetTyp())->Expand(m_nSubType, nFormat, GetLanguage(), m_aName);
1015 SwDocInfoField::SwDocInfoField(SwDocInfoFieldType* pTyp, sal_uInt16 nSub, const OUString& rName, const OUString& rValue, sal_uInt32 nFormat) :
1016 SwValueField(pTyp, nFormat), m_nSubType(nSub)
1018 m_aName = rName;
1019 m_aContent = rValue;
1022 template<class T>
1023 static double lcl_TimeToDouble( const T& rTime )
1025 const double fNanoSecondsPerDay = 86400000000000.0;
1026 return ( (rTime.Hours * SAL_CONST_INT64(3600000000000))
1027 + (rTime.Minutes * SAL_CONST_INT64( 60000000000))
1028 + (rTime.Seconds * SAL_CONST_INT64( 1000000000))
1029 + (rTime.NanoSeconds))
1030 / fNanoSecondsPerDay;
1033 template<class D>
1034 static double lcl_DateToDouble( const D& rDate, const Date& rNullDate )
1036 tools::Long nDate = Date::DateToDays( rDate.Day, rDate.Month, rDate.Year );
1037 tools::Long nNullDate = Date::DateToDays( rNullDate.GetDay(), rNullDate.GetMonth(), rNullDate.GetYear() );
1038 return double( nDate - nNullDate );
1041 OUString SwDocInfoField::ExpandImpl(SwRootFrame const*const) const
1043 if ( ( m_nSubType & 0xFF ) == DI_CUSTOM )
1045 // custom properties currently need special treatment
1046 // We don't have a secure way to detect "real" custom properties in Word import of text
1047 // fields, so we treat *every* unknown property as a custom property, even the "built-in"
1048 // section in Word's document summary information stream as these properties have not been
1049 // inserted when the document summary information was imported, we do it here.
1050 // This approach is still a lot better than the old one to import such fields as
1051 // "user fields" and simple text
1052 SwDocShell* pDocShell = GetDoc()->GetDocShell();
1053 if( !pDocShell )
1054 return m_aContent;
1057 uno::Reference<document::XDocumentPropertiesSupplier> xDPS( pDocShell->GetModel(), uno::UNO_QUERY_THROW);
1058 uno::Reference<document::XDocumentProperties> xDocProps( xDPS->getDocumentProperties());
1059 uno::Reference < beans::XPropertySet > xSet( xDocProps->getUserDefinedProperties(), uno::UNO_QUERY_THROW);
1060 uno::Reference < beans::XPropertySetInfo > xSetInfo = xSet->getPropertySetInfo();
1062 uno::Any aAny;
1063 if( xSetInfo->hasPropertyByName( m_aName ) )
1064 aAny = xSet->getPropertyValue( m_aName );
1065 if ( aAny.getValueType() != cppu::UnoType<void>::get() )
1067 // "void" type means that the property has not been inserted until now
1068 if ( !IsFixed() )
1070 // if the field is "fixed" we don't update it from the property
1071 OUString sVal;
1072 uno::Reference < script::XTypeConverter > xConverter( script::Converter::create(comphelper::getProcessComponentContext()) );
1073 util::Date aDate;
1074 util::DateTime aDateTime;
1075 util::Duration aDuration;
1076 if( aAny >>= aDate)
1078 SvNumberFormatter* pFormatter = pDocShell->GetDoc()->GetNumberFormatter();
1079 const Date& rNullDate = pFormatter->GetNullDate();
1080 sVal = ExpandValue( lcl_DateToDouble<util::Date>( aDate, rNullDate ), GetFormat(), GetLanguage());
1082 else if( aAny >>= aDateTime )
1084 double fDateTime = lcl_TimeToDouble<util::DateTime>( aDateTime );
1085 SvNumberFormatter* pFormatter = pDocShell->GetDoc()->GetNumberFormatter();
1086 const Date& rNullDate = pFormatter->GetNullDate();
1087 fDateTime += lcl_DateToDouble<util::DateTime>( aDateTime, rNullDate );
1088 sVal = ExpandValue( fDateTime, GetFormat(), GetLanguage());
1090 else if( aAny >>= aDuration )
1092 sVal = OUStringChar(aDuration.Negative ? '-' : '+')
1093 + SwViewShell::GetShellRes()->sDurationFormat;
1094 sVal = sVal.replaceFirst("%1", OUString::number( aDuration.Years ) );
1095 sVal = sVal.replaceFirst("%2", OUString::number( aDuration.Months ) );
1096 sVal = sVal.replaceFirst("%3", OUString::number( aDuration.Days ) );
1097 sVal = sVal.replaceFirst("%4", OUString::number( aDuration.Hours ) );
1098 sVal = sVal.replaceFirst("%5", OUString::number( aDuration.Minutes) );
1099 sVal = sVal.replaceFirst("%6", OUString::number( aDuration.Seconds) );
1101 else
1103 uno::Any aNew = xConverter->convertToSimpleType( aAny, uno::TypeClass_STRING );
1104 aNew >>= sVal;
1106 const_cast<SwDocInfoField*>(this)->m_aContent = sVal;
1110 catch (uno::Exception&) {}
1112 else if ( !IsFixed() )
1113 const_cast<SwDocInfoField*>(this)->m_aContent = static_cast<SwDocInfoFieldType*>(GetTyp())->Expand(m_nSubType, GetFormat(), GetLanguage(), m_aName);
1115 return m_aContent;
1118 OUString SwDocInfoField::GetFieldName() const
1120 OUString aStr(SwFieldType::GetTypeStr(GetTypeId()) + ":");
1122 sal_uInt16 const nSub = m_nSubType & 0xff;
1124 switch (nSub)
1126 case DI_CUSTOM:
1127 aStr += m_aName;
1128 break;
1130 default:
1131 aStr += SwViewShell::GetShellRes()
1132 ->aDocInfoLst[ nSub - DI_SUBTYPE_BEGIN ];
1133 break;
1135 if (IsFixed())
1137 aStr += " " + SwViewShell::GetShellRes()->aFixedStr;
1139 return aStr;
1142 std::unique_ptr<SwField> SwDocInfoField::Copy() const
1144 std::unique_ptr<SwDocInfoField> pField(new SwDocInfoField(static_cast<SwDocInfoFieldType*>(GetTyp()), m_nSubType, m_aName, GetFormat()));
1145 pField->SetAutomaticLanguage(IsAutomaticLanguage());
1146 pField->m_aContent = m_aContent;
1148 return std::unique_ptr<SwField>(pField.release());
1151 sal_uInt16 SwDocInfoField::GetSubType() const
1153 return m_nSubType;
1156 void SwDocInfoField::SetSubType(sal_uInt16 nSub)
1158 m_nSubType = nSub;
1161 void SwDocInfoField::SetLanguage(LanguageType nLng)
1163 if (!GetFormat())
1164 SwField::SetLanguage(nLng);
1165 else
1166 SwValueField::SetLanguage(nLng);
1169 bool SwDocInfoField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
1171 switch( nWhichId )
1173 case FIELD_PROP_PAR1:
1174 rAny <<= m_aContent;
1175 break;
1177 case FIELD_PROP_PAR4:
1178 rAny <<= m_aName;
1179 break;
1181 case FIELD_PROP_USHORT1:
1182 rAny <<= static_cast<sal_Int16>(m_aContent.toInt32());
1183 break;
1185 case FIELD_PROP_BOOL1:
1186 rAny <<= 0 != (m_nSubType & DI_SUB_FIXED);
1187 break;
1189 case FIELD_PROP_FORMAT:
1190 rAny <<= static_cast<sal_Int32>(GetFormat());
1191 break;
1193 case FIELD_PROP_DOUBLE:
1195 double fVal = GetValue();
1196 rAny <<= fVal;
1198 break;
1199 case FIELD_PROP_PAR3:
1200 rAny <<= ExpandImpl(nullptr);
1201 break;
1202 case FIELD_PROP_BOOL2:
1204 sal_uInt16 nExtSub = (m_nSubType & 0xff00) & ~DI_SUB_FIXED;
1205 rAny <<= nExtSub == DI_SUB_DATE;
1207 break;
1208 default:
1209 return SwField::QueryValue(rAny, nWhichId);
1211 return true;
1214 bool SwDocInfoField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
1216 sal_Int32 nValue = 0;
1217 switch( nWhichId )
1219 case FIELD_PROP_PAR1:
1220 if( m_nSubType & DI_SUB_FIXED )
1221 rAny >>= m_aContent;
1222 break;
1224 case FIELD_PROP_USHORT1:
1225 if( m_nSubType & DI_SUB_FIXED )
1227 rAny >>= nValue;
1228 m_aContent = OUString::number(nValue);
1230 break;
1232 case FIELD_PROP_BOOL1:
1233 if(*o3tl::doAccess<bool>(rAny))
1234 m_nSubType |= DI_SUB_FIXED;
1235 else
1236 m_nSubType &= ~DI_SUB_FIXED;
1237 break;
1238 case FIELD_PROP_FORMAT:
1240 rAny >>= nValue;
1241 if( nValue >= 0)
1242 SetFormat(nValue);
1244 break;
1246 case FIELD_PROP_PAR3:
1247 rAny >>= m_aContent;
1248 break;
1249 case FIELD_PROP_BOOL2:
1250 m_nSubType &= 0xf0ff;
1251 if(*o3tl::doAccess<bool>(rAny))
1252 m_nSubType |= DI_SUB_DATE;
1253 else
1254 m_nSubType |= DI_SUB_TIME;
1255 break;
1256 default:
1257 return SwField::PutValue(rAny, nWhichId);
1259 return true;
1262 SwHiddenTextFieldType::SwHiddenTextFieldType( bool bSetHidden )
1263 : SwFieldType( SwFieldIds::HiddenText ), m_bHidden( bSetHidden )
1267 std::unique_ptr<SwFieldType> SwHiddenTextFieldType::Copy() const
1269 return std::make_unique<SwHiddenTextFieldType>( m_bHidden );
1272 void SwHiddenTextFieldType::SetHiddenFlag( bool bSetHidden )
1274 if( m_bHidden != bSetHidden )
1276 m_bHidden = bSetHidden;
1277 UpdateFields(); // notify all HiddenTexts
1281 SwHiddenTextField::SwHiddenTextField( SwHiddenTextFieldType* pFieldType,
1282 bool bConditional,
1283 OUString aCond,
1284 const OUString& rStr,
1285 bool bHidden,
1286 SwFieldTypesEnum nSub) :
1287 SwField( pFieldType ), m_aCond(std::move(aCond)), m_nSubType(nSub),
1288 m_bCanToggle(bConditional), m_bIsHidden(bHidden), m_bValid(false)
1290 if(m_nSubType == SwFieldTypesEnum::ConditionalText)
1292 sal_Int32 nPos = 0;
1293 m_aTRUEText = rStr.getToken(0, '|', nPos);
1295 if(nPos != -1)
1297 m_aFALSEText = rStr.getToken(0, '|', nPos);
1298 if(nPos != -1)
1300 m_aContent = rStr.getToken(0, '|', nPos);
1301 m_bValid = true;
1305 else
1306 m_aTRUEText = rStr;
1309 SwHiddenTextField::SwHiddenTextField( SwHiddenTextFieldType* pFieldType,
1310 OUString aCond,
1311 OUString aTrue,
1312 OUString aFalse,
1313 SwFieldTypesEnum nSub)
1314 : SwField( pFieldType ), m_aTRUEText(std::move(aTrue)), m_aFALSEText(std::move(aFalse)), m_aCond(std::move(aCond)), m_nSubType(nSub),
1315 m_bIsHidden(true), m_bValid(false)
1317 m_bCanToggle = !m_aCond.isEmpty();
1320 OUString SwHiddenTextField::ExpandImpl(SwRootFrame const*const) const
1322 // Type: !Hidden -> show always
1323 // Hide -> evaluate condition
1325 if( SwFieldTypesEnum::ConditionalText == m_nSubType )
1327 if( m_bValid )
1328 return m_aContent;
1330 if( m_bCanToggle && !m_bIsHidden )
1331 return m_aTRUEText;
1333 else if( !static_cast<SwHiddenTextFieldType*>(GetTyp())->GetHiddenFlag() ||
1334 ( m_bCanToggle && m_bIsHidden ))
1335 return m_aTRUEText;
1337 return m_aFALSEText;
1340 /// get current field value and cache it
1341 void SwHiddenTextField::Evaluate(SwDoc& rDoc)
1343 if( SwFieldTypesEnum::ConditionalText != m_nSubType )
1344 return;
1346 #if !HAVE_FEATURE_DBCONNECTIVITY || ENABLE_FUZZERS
1347 (void) rDoc;
1348 #else
1349 SwDBManager* pMgr = rDoc.GetDBManager();
1350 #endif
1351 m_bValid = false;
1352 OUString sTmpName = (m_bCanToggle && !m_bIsHidden) ? m_aTRUEText : m_aFALSEText;
1354 // Database expressions need to be different from normal text. Therefore, normal text is set
1355 // in quotes. If the latter exist they will be removed. If not, check if potential DB name.
1356 // Only if there are two or more dots and no quotes, we assume a database.
1357 if (sTmpName.getLength()>1 &&
1358 sTmpName.startsWith("\"") &&
1359 sTmpName.endsWith("\""))
1361 m_aContent = sTmpName.copy(1, sTmpName.getLength() - 2);
1362 m_bValid = true;
1364 else if(sTmpName.indexOf('\"')<0 &&
1365 comphelper::string::getTokenCount(sTmpName, '.') > 2)
1367 sTmpName = ::ReplacePoint(sTmpName);
1368 if(sTmpName.startsWith("[") && sTmpName.endsWith("]"))
1369 { // remove brackets
1370 sTmpName = sTmpName.copy(1, sTmpName.getLength() - 2);
1372 #if HAVE_FEATURE_DBCONNECTIVITY && !ENABLE_FUZZERS
1373 if( pMgr)
1375 sal_Int32 nIdx{ 0 };
1376 OUString sDBName( GetDBName( sTmpName, rDoc ));
1377 OUString sDataSource(sDBName.getToken(0, DB_DELIM, nIdx));
1378 OUString sDataTableOrQuery(sDBName.getToken(0, DB_DELIM, nIdx));
1379 if( pMgr->IsInMerge() && !sDBName.isEmpty() &&
1380 pMgr->IsDataSourceOpen( sDataSource,
1381 sDataTableOrQuery, false))
1383 double fNumber;
1384 pMgr->GetMergeColumnCnt(GetColumnName( sTmpName ),
1385 GetLanguage(), m_aContent, &fNumber );
1386 m_bValid = true;
1388 else if( !sDBName.isEmpty() && !sDataSource.isEmpty() &&
1389 !sDataTableOrQuery.isEmpty() )
1390 m_bValid = true;
1392 #endif
1396 OUString SwHiddenTextField::GetFieldName() const
1398 OUString aStr = SwFieldType::GetTypeStr(m_nSubType) +
1399 " " + m_aCond + " " + m_aTRUEText;
1401 if (m_nSubType == SwFieldTypesEnum::ConditionalText)
1403 aStr += " : " + m_aFALSEText;
1405 return aStr;
1408 std::unique_ptr<SwField> SwHiddenTextField::Copy() const
1410 std::unique_ptr<SwHiddenTextField> pField(
1411 new SwHiddenTextField(static_cast<SwHiddenTextFieldType*>(GetTyp()), m_aCond,
1412 m_aTRUEText, m_aFALSEText));
1413 pField->m_bIsHidden = m_bIsHidden;
1414 pField->m_bValid = m_bValid;
1415 pField->m_aContent = m_aContent;
1416 pField->SetFormat(GetFormat());
1417 pField->m_nSubType = m_nSubType;
1418 return std::unique_ptr<SwField>(pField.release());
1421 /// set condition
1422 void SwHiddenTextField::SetPar1(const OUString& rStr)
1424 m_aCond = rStr;
1425 m_bCanToggle = !m_aCond.isEmpty();
1428 OUString SwHiddenTextField::GetPar1() const
1430 return m_aCond;
1433 /// set True/False text
1434 void SwHiddenTextField::SetPar2(const OUString& rStr)
1436 if (m_nSubType == SwFieldTypesEnum::ConditionalText)
1438 sal_Int32 nPos = rStr.indexOf('|');
1439 if (nPos == -1)
1440 m_aTRUEText = rStr;
1441 else
1443 m_aTRUEText = rStr.copy(0, nPos);
1444 m_aFALSEText = rStr.copy(nPos + 1);
1447 else
1448 m_aTRUEText = rStr;
1451 /// get True/False text
1452 OUString SwHiddenTextField::GetPar2() const
1454 if(m_nSubType != SwFieldTypesEnum::ConditionalText)
1456 return m_aTRUEText;
1458 return m_aTRUEText + "|" + m_aFALSEText;
1461 sal_uInt16 SwHiddenTextField::GetSubType() const
1463 return static_cast<sal_uInt16>(m_nSubType);
1466 bool SwHiddenTextField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
1468 switch( nWhichId )
1470 case FIELD_PROP_PAR1:
1471 rAny <<= m_aCond;
1472 break;
1473 case FIELD_PROP_PAR2:
1474 rAny <<= m_aTRUEText;
1475 break;
1476 case FIELD_PROP_PAR3:
1477 rAny <<= m_aFALSEText;
1478 break;
1479 case FIELD_PROP_PAR4 :
1480 rAny <<= m_aContent;
1481 break;
1482 case FIELD_PROP_BOOL1:
1483 rAny <<= m_bIsHidden;
1484 break;
1485 default:
1486 assert(false);
1488 return true;
1491 bool SwHiddenTextField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
1493 switch( nWhichId )
1495 case FIELD_PROP_PAR1:
1497 OUString sVal;
1498 rAny >>= sVal;
1499 SetPar1(sVal);
1501 break;
1502 case FIELD_PROP_PAR2:
1503 rAny >>= m_aTRUEText;
1504 break;
1505 case FIELD_PROP_PAR3:
1506 rAny >>= m_aFALSEText;
1507 break;
1508 case FIELD_PROP_BOOL1:
1509 m_bIsHidden = *o3tl::doAccess<bool>(rAny);
1510 break;
1511 case FIELD_PROP_PAR4:
1512 rAny >>= m_aContent;
1513 m_bValid = true;
1514 break;
1515 default:
1516 assert(false);
1518 return true;
1521 OUString SwHiddenTextField::GetColumnName(const OUString& rName)
1523 sal_Int32 nPos = rName.indexOf(DB_DELIM);
1524 if( nPos>=0 )
1526 nPos = rName.indexOf(DB_DELIM, nPos + 1);
1528 if( nPos>=0 )
1529 return rName.copy(nPos + 1);
1531 return rName;
1534 OUString SwHiddenTextField::GetDBName(std::u16string_view rName, SwDoc& rDoc)
1536 size_t nPos = rName.find(DB_DELIM);
1537 if( nPos != std::u16string_view::npos )
1539 nPos = rName.find(DB_DELIM, nPos + 1);
1541 if( nPos != std::u16string_view::npos )
1542 return OUString(rName.substr(0, nPos));
1545 SwDBData aData = rDoc.GetDBData();
1546 return aData.sDataSource + OUStringChar(DB_DELIM) + aData.sCommand;
1549 // [aFieldDefinition] value sample : " IF A == B \"TrueText\" \"FalseText\""
1550 void SwHiddenTextField::ParseIfFieldDefinition(std::u16string_view aFieldDefinition,
1551 OUString& rCondition,
1552 OUString& rTrue,
1553 OUString& rFalse)
1555 // get all positions inside the input string where words are started
1557 // In: " IF A == B \"TrueText\" \"FalseText\""
1558 // 0 1 2 3
1559 // 01234567890 123456789 01 2345678901 2
1561 // result:
1562 // [1, 4, 6, 9, 11, 22]
1563 std::vector<sal_Int32> wordPosition;
1565 bool quoted = false;
1566 bool insideWord = false;
1567 for (size_t i = 0; i < aFieldDefinition.size(); i++)
1569 if (quoted)
1571 if (aFieldDefinition[i] == '\"')
1573 quoted = false;
1574 insideWord = false;
1577 else
1579 if (aFieldDefinition[i] == ' ')
1581 // word delimiter
1582 insideWord = false;
1584 else
1586 if (insideWord)
1588 quoted = (aFieldDefinition[i] == '\"');
1590 else
1592 insideWord = true;
1593 wordPosition.push_back(i);
1594 quoted = (aFieldDefinition[i] == '\"');
1601 // first word is always "IF"
1602 // last two words are: true-case and false-case,
1603 // everything before is treated as condition expression
1604 // => we need at least 4 words to be inside the input string
1605 if (wordPosition.size() < 4)
1607 return;
1611 const sal_Int32 conditionBegin = wordPosition[1];
1612 const sal_Int32 trueBegin = wordPosition[wordPosition.size() - 2];
1613 const sal_Int32 falseBegin = wordPosition[wordPosition.size() - 1];
1615 const sal_Int32 conditionLength = trueBegin - conditionBegin;
1616 const sal_Int32 trueLength = falseBegin - trueBegin;
1618 // Syntax
1619 // OUString::copy( sal_Int32 beginIndex, sal_Int32 count )
1620 rCondition = o3tl::trim(aFieldDefinition.substr(conditionBegin, conditionLength));
1621 rTrue = o3tl::trim(aFieldDefinition.substr(trueBegin, trueLength));
1622 rFalse = o3tl::trim(aFieldDefinition.substr(falseBegin));
1624 // remove quotes
1625 if (rCondition.getLength() >= 2)
1627 if (rCondition[0] == '\"' && rCondition[rCondition.getLength() - 1] == '\"')
1628 rCondition = rCondition.copy(1, rCondition.getLength() - 2);
1630 if (rTrue.getLength() >= 2)
1632 if (rTrue[0] == '\"' && rTrue[rTrue.getLength() - 1] == '\"')
1633 rTrue = rTrue.copy(1, rTrue.getLength() - 2);
1635 if (rFalse.getLength() >= 2)
1637 if (rFalse[0] == '\"' && rFalse[rFalse.getLength() - 1] == '\"')
1638 rFalse = rFalse.copy(1, rFalse.getLength() - 2);
1641 // Note: do not make trim once again, while this is a user defined data
1644 // field type for line height 0
1646 SwHiddenParaFieldType::SwHiddenParaFieldType()
1647 : SwFieldType( SwFieldIds::HiddenPara )
1651 std::unique_ptr<SwFieldType> SwHiddenParaFieldType::Copy() const
1653 return std::make_unique<SwHiddenParaFieldType>();
1656 // field for line height 0
1658 SwHiddenParaField::SwHiddenParaField(SwHiddenParaFieldType* pTyp, OUString aStr)
1659 : SwField(pTyp), m_aCond(std::move(aStr))
1661 m_bIsHidden = false;
1664 OUString SwHiddenParaField::ExpandImpl(SwRootFrame const*const) const
1666 return OUString();
1669 std::unique_ptr<SwField> SwHiddenParaField::Copy() const
1671 std::unique_ptr<SwHiddenParaField> pField(new SwHiddenParaField(static_cast<SwHiddenParaFieldType*>(GetTyp()), m_aCond));
1672 pField->m_bIsHidden = m_bIsHidden;
1673 return std::unique_ptr<SwField>(pField.release());
1676 bool SwHiddenParaField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
1678 switch ( nWhichId )
1680 case FIELD_PROP_PAR1:
1681 rAny <<= m_aCond;
1682 break;
1683 case FIELD_PROP_BOOL1:
1684 rAny <<= m_bIsHidden;
1685 break;
1687 default:
1688 assert(false);
1690 return true;
1693 bool SwHiddenParaField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
1695 switch ( nWhichId )
1697 case FIELD_PROP_PAR1:
1698 rAny >>= m_aCond;
1699 break;
1700 case FIELD_PROP_BOOL1:
1701 m_bIsHidden = *o3tl::doAccess<bool>(rAny);
1702 break;
1704 default:
1705 assert(false);
1707 return true;
1710 /// set condition
1711 void SwHiddenParaField::SetPar1(const OUString& rStr)
1713 m_aCond = rStr;
1716 OUString SwHiddenParaField::GetPar1() const
1718 return m_aCond;
1721 // PostIt field type
1723 SwPostItFieldType::SwPostItFieldType(SwDoc& rDoc)
1724 : SwFieldType( SwFieldIds::Postit )
1725 , mrDoc(rDoc)
1728 std::unique_ptr<SwFieldType> SwPostItFieldType::Copy() const
1730 return std::make_unique<SwPostItFieldType>(mrDoc);
1733 // PostIt field
1735 sal_uInt32 SwPostItField::s_nLastPostItId = 1;
1737 SwPostItField::SwPostItField( SwPostItFieldType* pT,
1738 OUString aAuthor,
1739 OUString aText,
1740 OUString aInitials,
1741 OUString aName,
1742 const DateTime& rDateTime,
1743 const bool bResolved,
1744 const sal_uInt32 nPostItId,
1745 const sal_uInt32 nParentId,
1746 const sal_uInt32 nParaId
1748 : SwField( pT )
1749 , m_sText( std::move(aText) )
1750 , m_sAuthor( std::move(aAuthor) )
1751 , m_sInitials( std::move(aInitials) )
1752 , m_sName( std::move(aName) )
1753 , m_aDateTime( rDateTime )
1754 , m_bResolved( bResolved )
1755 , m_nParentId( nParentId )
1756 , m_nParaId( nParaId )
1758 m_nPostItId = nPostItId == 0 ? s_nLastPostItId++ : nPostItId;
1761 SwPostItField::~SwPostItField()
1763 if ( m_xTextObject.is() )
1765 m_xTextObject->DisposeEditSource();
1768 mpText.reset();
1771 OUString SwPostItField::ExpandImpl(SwRootFrame const*const) const
1773 return OUString();
1776 OUString SwPostItField::GetDescription() const
1778 return SwResId(STR_NOTE);
1781 void SwPostItField::SetResolved(bool bNewState)
1783 m_bResolved = bNewState;
1786 void SwPostItField::ToggleResolved()
1788 m_bResolved = !m_bResolved;
1791 bool SwPostItField::GetResolved() const
1793 return m_bResolved;
1796 std::unique_ptr<SwField> SwPostItField::Copy() const
1798 std::unique_ptr<SwPostItField> pRet(new SwPostItField( static_cast<SwPostItFieldType*>(GetTyp()), m_sAuthor, m_sText, m_sInitials, m_sName,
1799 m_aDateTime, m_bResolved, m_nPostItId, m_nParentId, m_nParaId));
1800 if (mpText)
1801 pRet->SetTextObject( *mpText );
1803 // Note: member <m_xTextObject> not copied.
1805 return std::unique_ptr<SwField>(pRet.release());
1808 /// set author
1809 void SwPostItField::SetPar1(const OUString& rStr)
1811 m_sAuthor = rStr;
1814 /// get author
1815 OUString SwPostItField::GetPar1() const
1817 return m_sAuthor;
1820 /// set the PostIt's text
1821 void SwPostItField::SetPar2(const OUString& rStr)
1823 m_sText = rStr;
1826 /// get the PostIt's text
1827 OUString SwPostItField::GetPar2() const
1829 return m_sText;
1833 void SwPostItField::SetName(const OUString& rName)
1835 m_sName = rName;
1839 void SwPostItField::SetTextObject( std::optional<OutlinerParaObject> pText )
1841 mpText = std::move(pText);
1844 sal_Int32 SwPostItField::GetNumberOfParagraphs() const
1846 return mpText ? mpText->Count() : 1;
1849 void SwPostItField::SetPostItId(const sal_uInt32 nPostItId)
1851 m_nPostItId = nPostItId == 0 ? s_nLastPostItId++ : nPostItId;
1854 void SwPostItField::SetParentId(const sal_uInt32 nParentId)
1856 m_nParentId = nParentId;
1859 void SwPostItField::SetParaId(const sal_uInt32 nParaId)
1861 m_nParaId = nParaId;
1864 bool SwPostItField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
1866 switch( nWhichId )
1868 case FIELD_PROP_PAR1:
1869 rAny <<= m_sAuthor;
1870 break;
1871 case FIELD_PROP_PAR2:
1873 rAny <<= m_sText;
1874 break;
1876 case FIELD_PROP_PAR3:
1877 rAny <<= m_sInitials;
1878 break;
1879 case FIELD_PROP_PAR4:
1880 rAny <<= m_sName;
1881 break;
1882 case FIELD_PROP_BOOL1:
1883 rAny <<= m_bResolved;
1884 break;
1885 case FIELD_PROP_TEXT:
1887 if ( !m_xTextObject.is() )
1889 SwPostItFieldType* pGetType = static_cast<SwPostItFieldType*>(GetTyp());
1890 SwDoc& rDoc = pGetType->GetDoc();
1891 auto pObj = std::make_unique<SwTextAPIEditSource>( &rDoc );
1892 const_cast <SwPostItField*> (this)->m_xTextObject = new SwTextAPIObject( std::move(pObj) );
1895 if ( mpText )
1896 m_xTextObject->SetText( *mpText );
1897 else
1898 m_xTextObject->SetString( m_sText );
1900 uno::Reference < text::XText > xText( m_xTextObject );
1901 rAny <<= xText;
1902 break;
1904 case FIELD_PROP_DATE:
1906 rAny <<= m_aDateTime.GetUNODate();
1908 break;
1909 case FIELD_PROP_DATE_TIME:
1911 rAny <<= m_aDateTime.GetUNODateTime();
1913 break;
1914 case FIELD_PROP_PAR5:
1916 rAny <<= OUString(OUString::number(m_nParentId, 16).toAsciiUpperCase());
1918 break;
1919 case FIELD_PROP_PAR6:
1921 rAny <<= OUString(OUString::number(m_nPostItId, 16).toAsciiUpperCase());
1923 break;
1924 default:
1925 assert(false);
1927 return true;
1930 bool SwPostItField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
1932 switch( nWhichId )
1934 case FIELD_PROP_PAR1:
1935 rAny >>= m_sAuthor;
1936 break;
1937 case FIELD_PROP_PAR2:
1938 rAny >>= m_sText;
1939 //#i100374# new string via api, delete complex text object so SwPostItNote picks up the new string
1940 mpText.reset();
1941 break;
1942 case FIELD_PROP_PAR3:
1943 rAny >>= m_sInitials;
1944 break;
1945 case FIELD_PROP_PAR4:
1946 rAny >>= m_sName;
1947 break;
1948 case FIELD_PROP_BOOL1:
1949 rAny >>= m_bResolved;
1950 break;
1951 case FIELD_PROP_TEXT:
1952 OSL_FAIL("Not implemented!");
1953 break;
1954 case FIELD_PROP_DATE:
1955 if( auto aSetDate = o3tl::tryAccess<util::Date>(rAny) )
1957 m_aDateTime = Date(aSetDate->Day, aSetDate->Month, aSetDate->Year);
1959 break;
1960 case FIELD_PROP_DATE_TIME:
1962 util::DateTime aDateTimeValue;
1963 if(!(rAny >>= aDateTimeValue))
1964 return false;
1965 m_aDateTime = DateTime(aDateTimeValue);
1967 break;
1968 case FIELD_PROP_PAR5:
1970 OUString sTemp;
1971 rAny >>= sTemp;
1972 m_nParentId = sTemp.toInt32(16);
1974 break;
1975 case FIELD_PROP_PAR6:
1977 OUString sTemp;
1978 rAny >>= sTemp;
1979 m_nPostItId = sTemp.toInt32(16);
1981 break;
1982 default:
1983 assert(false);
1985 return true;
1988 void SwPostItField::dumpAsXml(xmlTextWriterPtr pWriter) const
1990 (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SwPostItField"));
1991 (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("name"), BAD_CAST(GetName().toUtf8().getStr()));
1993 SwField::dumpAsXml(pWriter);
1995 (void)xmlTextWriterStartElement(pWriter, BAD_CAST("mpText"));
1996 (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("ptr"), "%p", mpText ? &*mpText : nullptr);
1997 if (mpText)
1998 mpText->dumpAsXml(pWriter);
1999 (void)xmlTextWriterEndElement(pWriter);
2001 (void)xmlTextWriterEndElement(pWriter);
2004 // extended user information field type
2006 SwExtUserFieldType::SwExtUserFieldType()
2007 : SwFieldType( SwFieldIds::ExtUser )
2011 std::unique_ptr<SwFieldType> SwExtUserFieldType::Copy() const
2013 return std::make_unique<SwExtUserFieldType>();
2016 OUString SwExtUserFieldType::Expand(sal_uInt16 nSub )
2018 UserOptToken nRet = static_cast<UserOptToken>(USHRT_MAX);
2019 switch(nSub)
2021 case EU_FIRSTNAME: nRet = UserOptToken::FirstName; break;
2022 case EU_NAME: nRet = UserOptToken::LastName; break;
2023 case EU_SHORTCUT: nRet = UserOptToken::ID; break;
2025 case EU_COMPANY: nRet = UserOptToken::Company; break;
2026 case EU_STREET: nRet = UserOptToken::Street; break;
2027 case EU_TITLE: nRet = UserOptToken::Title; break;
2028 case EU_POSITION: nRet = UserOptToken::Position; break;
2029 case EU_PHONE_PRIVATE: nRet = UserOptToken::TelephoneHome; break;
2030 case EU_PHONE_COMPANY: nRet = UserOptToken::TelephoneWork; break;
2031 case EU_FAX: nRet = UserOptToken::Fax; break;
2032 case EU_EMAIL: nRet = UserOptToken::Email; break;
2033 case EU_COUNTRY: nRet = UserOptToken::Country; break;
2034 case EU_ZIP: nRet = UserOptToken::Zip; break;
2035 case EU_CITY: nRet = UserOptToken::City; break;
2036 case EU_STATE: nRet = UserOptToken::State; break;
2037 case EU_FATHERSNAME: nRet = UserOptToken::FathersName; break;
2038 case EU_APARTMENT: nRet = UserOptToken::Apartment; break;
2039 default: OSL_ENSURE( false, "Field unknown");
2041 if( static_cast<UserOptToken>(USHRT_MAX) != nRet )
2043 SvtUserOptions& rUserOpt = SW_MOD()->GetUserOptions();
2044 return rUserOpt.GetToken( nRet );
2046 return OUString();
2049 // extended user information field
2051 SwExtUserField::SwExtUserField(SwExtUserFieldType* pTyp, sal_uInt16 nSubTyp, sal_uInt32 nFormat) :
2052 SwField(pTyp, nFormat), m_nType(nSubTyp)
2054 m_aContent = SwExtUserFieldType::Expand(m_nType);
2057 OUString SwExtUserField::ExpandImpl(SwRootFrame const*const) const
2059 if (!IsFixed())
2060 const_cast<SwExtUserField*>(this)->m_aContent = SwExtUserFieldType::Expand(m_nType);
2062 return m_aContent;
2065 std::unique_ptr<SwField> SwExtUserField::Copy() const
2067 std::unique_ptr<SwExtUserField> pField(new SwExtUserField(static_cast<SwExtUserFieldType*>(GetTyp()), m_nType, GetFormat()));
2068 pField->SetExpansion(m_aContent);
2070 return std::unique_ptr<SwField>(pField.release());
2073 sal_uInt16 SwExtUserField::GetSubType() const
2075 return m_nType;
2078 void SwExtUserField::SetSubType(sal_uInt16 nSub)
2080 m_nType = nSub;
2083 bool SwExtUserField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
2085 switch( nWhichId )
2087 case FIELD_PROP_PAR1:
2088 rAny <<= m_aContent;
2089 break;
2091 case FIELD_PROP_USHORT1:
2093 sal_Int16 nTmp = m_nType;
2094 rAny <<= nTmp;
2096 break;
2097 case FIELD_PROP_BOOL1:
2098 rAny <<= IsFixed();
2099 break;
2100 default:
2101 assert(false);
2103 return true;
2106 bool SwExtUserField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
2108 switch( nWhichId )
2110 case FIELD_PROP_PAR1:
2111 rAny >>= m_aContent;
2112 break;
2114 case FIELD_PROP_USHORT1:
2116 sal_Int16 nTmp = 0;
2117 rAny >>= nTmp;
2118 m_nType = nTmp;
2120 break;
2121 case FIELD_PROP_BOOL1:
2122 if( *o3tl::doAccess<bool>(rAny) )
2123 SetFormat(GetFormat() | AF_FIXED);
2124 else
2125 SetFormat(GetFormat() & ~AF_FIXED);
2126 break;
2127 default:
2128 assert(false);
2130 return true;
2133 // field type for relative page numbers
2135 SwRefPageSetFieldType::SwRefPageSetFieldType()
2136 : SwFieldType( SwFieldIds::RefPageSet )
2140 std::unique_ptr<SwFieldType> SwRefPageSetFieldType::Copy() const
2142 return std::make_unique<SwRefPageSetFieldType>();
2145 // overridden since there is nothing to update
2146 void SwRefPageSetFieldType::SwClientNotify(const SwModify&, const SfxHint&)
2150 // field for relative page numbers
2152 SwRefPageSetField::SwRefPageSetField( SwRefPageSetFieldType* pTyp,
2153 short nOff, bool bFlag )
2154 : SwField( pTyp ), m_nOffset( nOff ), m_bOn( bFlag )
2158 OUString SwRefPageSetField::ExpandImpl(SwRootFrame const*const) const
2160 return OUString();
2163 std::unique_ptr<SwField> SwRefPageSetField::Copy() const
2165 return std::make_unique<SwRefPageSetField>( static_cast<SwRefPageSetFieldType*>(GetTyp()), m_nOffset, m_bOn );
2168 OUString SwRefPageSetField::GetPar2() const
2170 return OUString::number(GetOffset());
2173 void SwRefPageSetField::SetPar2(const OUString& rStr)
2175 SetOffset( static_cast<short>(rStr.toInt32()) );
2178 bool SwRefPageSetField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
2180 switch( nWhichId )
2182 case FIELD_PROP_BOOL1:
2183 rAny <<= m_bOn;
2184 break;
2185 case FIELD_PROP_USHORT1:
2186 rAny <<= static_cast<sal_Int16>(m_nOffset);
2187 break;
2188 default:
2189 assert(false);
2191 return true;
2194 bool SwRefPageSetField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
2196 switch( nWhichId )
2198 case FIELD_PROP_BOOL1:
2199 m_bOn = *o3tl::doAccess<bool>(rAny);
2200 break;
2201 case FIELD_PROP_USHORT1:
2202 rAny >>=m_nOffset;
2203 break;
2204 default:
2205 assert(false);
2207 return true;
2210 // relative page numbers - query field
2212 SwRefPageGetFieldType::SwRefPageGetFieldType( SwDoc& rDc )
2213 : SwFieldType( SwFieldIds::RefPageGet ), m_rDoc( rDc ), m_nNumberingType( SVX_NUM_ARABIC )
2217 std::unique_ptr<SwFieldType> SwRefPageGetFieldType::Copy() const
2219 std::unique_ptr<SwRefPageGetFieldType> pNew(new SwRefPageGetFieldType( m_rDoc ));
2220 pNew->m_nNumberingType = m_nNumberingType;
2221 return pNew;
2224 void SwRefPageGetFieldType::SwClientNotify(const SwModify&, const SfxHint& rHint)
2226 if (rHint.GetId() != SfxHintId::SwLegacyModify)
2227 return;
2228 auto pLegacy = static_cast<const sw::LegacyModifyHint*>(&rHint);
2229 auto const ModifyImpl = [this](SwRootFrame const*const pLayout)
2231 // first collect all SetPageRefFields
2232 SetGetExpFields aTmpLst;
2233 if (MakeSetList(aTmpLst, pLayout))
2235 std::vector<SwFormatField*> vFields;
2236 GatherFields(vFields);
2237 for(auto pFormatField: vFields)
2238 UpdateField(pFormatField->GetTextField(), aTmpLst, pLayout);
2242 // update all GetReference fields
2243 if( !pLegacy->m_pNew && !pLegacy->m_pOld && HasWriterListeners() )
2245 SwRootFrame const* pLayout(nullptr);
2246 SwRootFrame const* pLayoutRLHidden(nullptr);
2247 for (SwRootFrame const*const pLay : m_rDoc.GetAllLayouts())
2249 if (pLay->IsHideRedlines())
2251 pLayoutRLHidden = pLay;
2253 else
2255 pLayout = pLay;
2258 ModifyImpl(pLayout);
2259 if (pLayoutRLHidden)
2261 ModifyImpl(pLayoutRLHidden);
2265 // forward to text fields, they "expand" the text
2266 CallSwClientNotify(rHint);
2269 bool SwRefPageGetFieldType::MakeSetList(SetGetExpFields& rTmpLst,
2270 SwRootFrame const*const pLayout)
2272 IDocumentRedlineAccess const& rIDRA(m_rDoc.getIDocumentRedlineAccess());
2273 std::vector<SwFormatField*> vFields;
2274 m_rDoc.getIDocumentFieldsAccess().GetSysFieldType(SwFieldIds::RefPageSet)->GatherFields(vFields);
2275 for(auto pFormatField: vFields)
2277 // update only the GetRef fields
2278 const SwTextField* pTField = pFormatField->GetTextField();
2279 if (!pLayout || !pLayout->IsHideRedlines() || !sw::IsFieldDeletedInModel(rIDRA, *pTField))
2281 const SwTextNode& rTextNd = pTField->GetTextNode();
2283 // Always the first! (in Tab-Headline, header/footer )
2284 Point aPt;
2285 std::pair<Point, bool> const tmp(aPt, false);
2286 const SwContentFrame *const pFrame = rTextNd.getLayoutFrame(
2287 pLayout, nullptr, &tmp);
2289 std::unique_ptr<SetGetExpField> pNew;
2291 if( !pFrame ||
2292 pFrame->IsInDocBody() ||
2293 // #i31868#
2294 // Check if pFrame is not yet connected to the layout.
2295 !pFrame->FindPageFrame() )
2297 pNew.reset( new SetGetExpField( rTextNd, pTField ) );
2299 else
2301 // create index for determination of the TextNode
2302 SwPosition aPos( m_rDoc.GetNodes().GetEndOfPostIts() );
2303 bool const bResult = GetBodyTextNode( m_rDoc, aPos, *pFrame );
2304 OSL_ENSURE(bResult, "where is the Field?");
2305 pNew.reset( new SetGetExpField( aPos.GetNode(), pTField,
2306 aPos.GetContentIndex() ) );
2309 rTmpLst.insert( std::move(pNew) );
2312 return !rTmpLst.empty();
2315 void SwRefPageGetFieldType::UpdateField( SwTextField const * pTextField,
2316 SetGetExpFields const & rSetList,
2317 SwRootFrame const*const pLayout)
2319 SwRefPageGetField* pGetField = const_cast<SwRefPageGetField*>(static_cast<const SwRefPageGetField*>(pTextField->GetFormatField().GetField()));
2320 pGetField->SetText( OUString(), pLayout );
2322 // then search the correct RefPageSet field
2323 SwTextNode* pTextNode = &pTextField->GetTextNode();
2324 if( pTextNode->StartOfSectionIndex() >
2325 m_rDoc.GetNodes().GetEndOfExtras().GetIndex() )
2327 SetGetExpField aEndField( *pTextNode, pTextField );
2329 SetGetExpFields::const_iterator itLast = rSetList.lower_bound( &aEndField );
2331 if( itLast != rSetList.begin() )
2333 --itLast;
2334 const SwTextField* pRefTextField = (*itLast)->GetTextField();
2335 const SwRefPageSetField* pSetField =
2336 static_cast<const SwRefPageSetField*>(pRefTextField->GetFormatField().GetField());
2337 if( pSetField->IsOn() )
2339 // determine the correct offset
2340 Point aPt;
2341 std::pair<Point, bool> const tmp(aPt, false);
2342 const SwContentFrame *const pFrame = pTextNode->getLayoutFrame(
2343 pLayout, nullptr, &tmp);
2344 const SwContentFrame *const pRefFrame = pRefTextField->GetTextNode().getLayoutFrame(
2345 pLayout, nullptr, &tmp);
2346 const SwPageFrame* pPgFrame = nullptr;
2347 short nDiff = 1;
2348 if ( pFrame && pRefFrame )
2350 pPgFrame = pFrame->FindPageFrame();
2351 nDiff = pPgFrame->GetPhyPageNum() -
2352 pRefFrame->FindPageFrame()->GetPhyPageNum() + 1;
2355 SvxNumType nTmpFormat = SVX_NUM_PAGEDESC == static_cast<SvxNumType>(pGetField->GetFormat())
2356 ? ( !pPgFrame
2357 ? SVX_NUM_ARABIC
2358 : pPgFrame->GetPageDesc()->GetNumType().GetNumberingType() )
2359 : static_cast<SvxNumType>(pGetField->GetFormat());
2360 const short nPageNum = std::max<short>(0, pSetField->GetOffset() + nDiff);
2361 pGetField->SetText(FormatNumber(nPageNum, nTmpFormat), pLayout);
2365 // start formatting
2366 const_cast<SwFormatField&>(pTextField->GetFormatField()).ForceUpdateTextNode();
2369 // queries for relative page numbering
2371 SwRefPageGetField::SwRefPageGetField( SwRefPageGetFieldType* pTyp,
2372 sal_uInt32 nFormat )
2373 : SwField( pTyp, nFormat )
2377 void SwRefPageGetField::SetText(const OUString& rText,
2378 SwRootFrame const*const pLayout)
2380 if (!pLayout || !pLayout->IsHideRedlines())
2382 m_sText = rText;
2384 if (!pLayout || pLayout->IsHideRedlines())
2386 m_sTextRLHidden = rText;
2390 OUString SwRefPageGetField::ExpandImpl(SwRootFrame const*const pLayout) const
2392 return pLayout && pLayout->IsHideRedlines() ? m_sTextRLHidden : m_sText;
2395 std::unique_ptr<SwField> SwRefPageGetField::Copy() const
2397 std::unique_ptr<SwRefPageGetField> pCpy(new SwRefPageGetField(
2398 static_cast<SwRefPageGetFieldType*>(GetTyp()), GetFormat() ));
2399 pCpy->m_sText = m_sText;
2400 pCpy->m_sTextRLHidden = m_sTextRLHidden;
2401 return std::unique_ptr<SwField>(pCpy.release());
2404 void SwRefPageGetField::ChangeExpansion(const SwFrame& rFrame,
2405 const SwTextField* pField )
2407 // only fields in Footer, Header, FootNote, Flys
2408 SwRefPageGetFieldType* pGetType = static_cast<SwRefPageGetFieldType*>(GetTyp());
2409 SwDoc& rDoc = pGetType->GetDoc();
2410 if( pField->GetTextNode().StartOfSectionIndex() >
2411 rDoc.GetNodes().GetEndOfExtras().GetIndex() )
2412 return;
2414 SwRootFrame const& rLayout(*rFrame.getRootFrame());
2415 OUString & rText(rLayout.IsHideRedlines() ? m_sTextRLHidden : m_sText);
2416 rText.clear();
2418 OSL_ENSURE(!rFrame.IsInDocBody(), "Flag incorrect, frame is in DocBody");
2420 // collect all SetPageRefFields
2421 SetGetExpFields aTmpLst;
2422 if (!pGetType->MakeSetList(aTmpLst, &rLayout))
2423 return ;
2425 // create index for determination of the TextNode
2426 SwPosition aPos( rDoc.GetNodes() );
2427 SwTextNode* pTextNode = const_cast<SwTextNode*>(GetBodyTextNode(rDoc, aPos, rFrame));
2429 // If no layout exists, ChangeExpansion is called for header and
2430 // footer lines via layout formatting without existing TextNode.
2431 if(!pTextNode)
2432 return;
2434 SetGetExpField aEndField( aPos.GetNode(), pField, aPos.GetContentIndex() );
2436 SetGetExpFields::const_iterator itLast = aTmpLst.lower_bound( &aEndField );
2438 if( itLast == aTmpLst.begin() )
2439 return; // there is no corresponding set-field in front
2440 --itLast;
2442 const SwTextField* pRefTextField = (*itLast)->GetTextField();
2443 const SwRefPageSetField* pSetField =
2444 static_cast<const SwRefPageSetField*>(pRefTextField->GetFormatField().GetField());
2445 Point aPt;
2446 std::pair<Point, bool> const tmp(aPt, false);
2447 const SwContentFrame *const pRefFrame = pRefTextField->GetTextNode().getLayoutFrame(
2448 &rLayout, nullptr, &tmp);
2449 if( !(pSetField->IsOn() && pRefFrame) )
2450 return;
2452 // determine the correct offset
2453 const SwPageFrame* pPgFrame = rFrame.FindPageFrame();
2454 const short nDiff = pPgFrame->GetPhyPageNum() -
2455 pRefFrame->FindPageFrame()->GetPhyPageNum() + 1;
2457 SwRefPageGetField* pGetField = const_cast<SwRefPageGetField*>(static_cast<const SwRefPageGetField*>(pField->GetFormatField().GetField()));
2458 SvxNumType nTmpFormat = SVX_NUM_PAGEDESC == pGetField->GetFormat()
2459 ? pPgFrame->GetPageDesc()->GetNumType().GetNumberingType()
2460 : static_cast<SvxNumType>(pGetField->GetFormat());
2461 const short nPageNum = std::max<short>(0, pSetField->GetOffset() + nDiff);
2462 pGetField->SetText(FormatNumber(nPageNum, nTmpFormat), &rLayout);
2465 bool SwRefPageGetField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
2467 switch( nWhichId )
2469 case FIELD_PROP_USHORT1:
2470 rAny <<= static_cast<sal_Int16>(GetFormat());
2471 break;
2472 case FIELD_PROP_PAR1:
2473 rAny <<= m_sText;
2474 break;
2475 default:
2476 assert(false);
2478 return true;
2481 bool SwRefPageGetField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
2483 switch( nWhichId )
2485 case FIELD_PROP_USHORT1:
2487 sal_Int16 nSet = 0;
2488 rAny >>= nSet;
2489 if(nSet <= SVX_NUM_PAGEDESC )
2490 SetFormat(nSet);
2492 break;
2493 case FIELD_PROP_PAR1:
2494 rAny >>= m_sText;
2495 m_sTextRLHidden = m_sText;
2496 break;
2497 default:
2498 assert(false);
2500 return true;
2503 // field type to jump to and edit
2505 SwJumpEditFieldType::SwJumpEditFieldType( SwDoc& rD )
2506 : SwFieldType( SwFieldIds::JumpEdit ), m_rDoc( rD ), m_aDep( *this )
2510 std::unique_ptr<SwFieldType> SwJumpEditFieldType::Copy() const
2512 return std::make_unique<SwJumpEditFieldType>( m_rDoc );
2515 SwCharFormat* SwJumpEditFieldType::GetCharFormat()
2517 SwCharFormat* pFormat = m_rDoc.getIDocumentStylePoolAccess().GetCharFormatFromPool( RES_POOLCHR_JUMPEDIT );
2518 m_aDep.StartListening(pFormat);
2519 return pFormat;
2522 SwJumpEditField::SwJumpEditField( SwJumpEditFieldType* pTyp, sal_uInt32 nForm,
2523 OUString aText, OUString aHelp )
2524 : SwField( pTyp, nForm ), m_sText( std::move(aText) ), m_sHelp( std::move(aHelp) )
2528 OUString SwJumpEditField::ExpandImpl(SwRootFrame const*const) const
2530 return "<" + m_sText + ">";
2533 std::unique_ptr<SwField> SwJumpEditField::Copy() const
2535 return std::make_unique<SwJumpEditField>( static_cast<SwJumpEditFieldType*>(GetTyp()), GetFormat(),
2536 m_sText, m_sHelp );
2539 /// get place holder text
2540 OUString SwJumpEditField::GetPar1() const
2542 return m_sText;
2545 /// set place holder text
2546 void SwJumpEditField::SetPar1(const OUString& rStr)
2548 m_sText = rStr;
2551 /// get hint text
2552 OUString SwJumpEditField::GetPar2() const
2554 return m_sHelp;
2557 /// set hint text
2558 void SwJumpEditField::SetPar2(const OUString& rStr)
2560 m_sHelp = rStr;
2563 bool SwJumpEditField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
2565 switch( nWhichId )
2567 case FIELD_PROP_USHORT1:
2569 sal_Int16 nRet;
2570 switch( GetFormat() )
2572 case JE_FMT_TABLE: nRet = text::PlaceholderType::TABLE; break;
2573 case JE_FMT_FRAME: nRet = text::PlaceholderType::TEXTFRAME; break;
2574 case JE_FMT_GRAPHIC:nRet = text::PlaceholderType::GRAPHIC; break;
2575 case JE_FMT_OLE: nRet = text::PlaceholderType::OBJECT; break;
2576 default:
2577 nRet = text::PlaceholderType::TEXT; break;
2579 rAny <<= nRet;
2581 break;
2582 case FIELD_PROP_PAR1 :
2583 rAny <<= m_sHelp;
2584 break;
2585 case FIELD_PROP_PAR2 :
2586 rAny <<= m_sText;
2587 break;
2588 default:
2589 assert(false);
2591 return true;
2594 bool SwJumpEditField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
2596 switch( nWhichId )
2598 case FIELD_PROP_USHORT1:
2600 //JP 24.10.2001: int32 because in UnoField.cxx a putvalue is
2601 // called with a int32 value! But normally we need
2602 // here only a int16
2603 sal_Int32 nSet = 0;
2604 rAny >>= nSet;
2605 switch( nSet )
2607 case text::PlaceholderType::TEXT : SetFormat(JE_FMT_TEXT); break;
2608 case text::PlaceholderType::TABLE : SetFormat(JE_FMT_TABLE); break;
2609 case text::PlaceholderType::TEXTFRAME: SetFormat(JE_FMT_FRAME); break;
2610 case text::PlaceholderType::GRAPHIC : SetFormat(JE_FMT_GRAPHIC); break;
2611 case text::PlaceholderType::OBJECT : SetFormat(JE_FMT_OLE); break;
2614 break;
2615 case FIELD_PROP_PAR1 :
2616 rAny >>= m_sHelp;
2617 break;
2618 case FIELD_PROP_PAR2 :
2619 rAny >>= m_sText;
2620 break;
2621 default:
2622 assert(false);
2624 return true;
2627 // combined character field type
2629 SwCombinedCharFieldType::SwCombinedCharFieldType()
2630 : SwFieldType( SwFieldIds::CombinedChars )
2634 std::unique_ptr<SwFieldType> SwCombinedCharFieldType::Copy() const
2636 return std::make_unique<SwCombinedCharFieldType>();
2639 // combined character field
2641 SwCombinedCharField::SwCombinedCharField( SwCombinedCharFieldType* pFTyp,
2642 const OUString& rChars )
2643 : SwField( pFTyp, 0 ),
2644 m_sCharacters( rChars.copy( 0, std::min<sal_Int32>(rChars.getLength(), MAX_COMBINED_CHARACTERS) ))
2648 OUString SwCombinedCharField::ExpandImpl(SwRootFrame const*const) const
2650 return m_sCharacters;
2653 std::unique_ptr<SwField> SwCombinedCharField::Copy() const
2655 return std::make_unique<SwCombinedCharField>( static_cast<SwCombinedCharFieldType*>(GetTyp()),
2656 m_sCharacters );
2659 OUString SwCombinedCharField::GetPar1() const
2661 return m_sCharacters;
2664 void SwCombinedCharField::SetPar1(const OUString& rStr)
2666 m_sCharacters = rStr.copy(0, std::min<sal_Int32>(rStr.getLength(), MAX_COMBINED_CHARACTERS));
2669 bool SwCombinedCharField::QueryValue( uno::Any& rAny,
2670 sal_uInt16 nWhichId ) const
2672 switch( nWhichId )
2674 case FIELD_PROP_PAR1:
2675 rAny <<= m_sCharacters;
2676 break;
2677 default:
2678 assert(false);
2680 return true;
2683 bool SwCombinedCharField::PutValue( const uno::Any& rAny,
2684 sal_uInt16 nWhichId )
2686 switch( nWhichId )
2688 case FIELD_PROP_PAR1:
2690 OUString sTmp;
2691 rAny >>= sTmp;
2692 SetPar1(sTmp);
2694 break;
2695 default:
2696 assert(false);
2698 return true;
2701 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */