nss: upgrade to release 3.73
[LibreOffice.git] / sw / source / core / fields / docufld.cxx
blobb32c4937ed1e2137bd14767e3b5de7cc5e85f833
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>
22 #include <textapi.hxx>
24 #include <hintids.hxx>
25 #include <com/sun/star/frame/XModel.hpp>
26 #include <com/sun/star/text/XText.hpp>
27 #include <com/sun/star/script/Converter.hpp>
28 #include <com/sun/star/text/PlaceholderType.hpp>
29 #include <com/sun/star/text/TemplateDisplayFormat.hpp>
30 #include <com/sun/star/text/PageNumberType.hpp>
31 #include <com/sun/star/text/FilenameDisplayFormat.hpp>
32 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
33 #include <com/sun/star/document/XDocumentProperties.hpp>
34 #include <com/sun/star/util/Date.hpp>
35 #include <com/sun/star/util/Duration.hpp>
36 #include <o3tl/any.hxx>
37 #include <unotools/localedatawrapper.hxx>
38 #include <comphelper/processfactory.hxx>
39 #include <comphelper/string.hxx>
40 #include <tools/urlobj.hxx>
41 #include <svl/urihelper.hxx>
42 #include <unotools/useroptions.hxx>
43 #include <unotools/syslocale.hxx>
44 #include <svl/zforlist.hxx>
45 #include <libxml/xmlstring.h>
46 #include <libxml/xmlwriter.h>
48 #include <tools/time.hxx>
49 #include <tools/datetime.hxx>
51 #include <com/sun/star/util/DateTime.hpp>
53 #include <swmodule.hxx>
54 #include <sfx2/docfile.hxx>
55 #include <sfx2/doctempl.hxx>
56 #include <fmtfld.hxx>
57 #include <txtfld.hxx>
58 #include <charfmt.hxx>
59 #include <docstat.hxx>
60 #include <pagedesc.hxx>
61 #include <fmtpdsc.hxx>
62 #include <doc.hxx>
63 #include <IDocumentFieldsAccess.hxx>
64 #include <IDocumentStatistics.hxx>
65 #include <IDocumentStylePoolAccess.hxx>
66 #include <IDocumentLayoutAccess.hxx>
67 #include <rootfrm.hxx>
68 #include <pagefrm.hxx>
69 #include <cntfrm.hxx>
70 #include <pam.hxx>
71 #include <viewsh.hxx>
72 #include <dbmgr.hxx>
73 #include <shellres.hxx>
74 #include <docufld.hxx>
75 #include <flddat.hxx>
76 #include <docfld.hxx>
77 #include <ndtxt.hxx>
78 #include <expfld.hxx>
79 #include <poolfmt.hxx>
80 #include <docsh.hxx>
81 #include <unofldmid.h>
82 #include <swunohelper.hxx>
83 #include <strings.hrc>
85 #include <editeng/outlobj.hxx>
86 #include <calbck.hxx>
87 #include <hints.hxx>
89 #define URL_DECODE INetURLObject::DecodeMechanism::Unambiguous
91 using namespace ::com::sun::star;
92 using namespace ::com::sun::star::uno;
93 using namespace nsSwDocInfoSubType;
95 SwPageNumberFieldType::SwPageNumberFieldType()
96 : SwFieldType( SwFieldIds::PageNumber ),
97 m_nNumberingType( SVX_NUM_ARABIC ),
98 m_bVirtual( false )
102 OUString SwPageNumberFieldType::Expand( SvxNumType nFormat, short nOff,
103 sal_uInt16 const nPageNumber, sal_uInt16 const nMaxPage,
104 const OUString& rUserStr, LanguageType nLang ) const
106 SvxNumType nTmpFormat = (SVX_NUM_PAGEDESC == nFormat) ? m_nNumberingType : nFormat;
107 int const nTmp = nPageNumber + nOff;
109 if (0 > nTmp || SVX_NUM_NUMBER_NONE == nTmpFormat || (!m_bVirtual && nTmp > nMaxPage))
110 return OUString();
112 if( SVX_NUM_CHAR_SPECIAL == nTmpFormat )
113 return rUserStr;
115 return FormatNumber( nTmp, nTmpFormat, nLang );
118 std::unique_ptr<SwFieldType> SwPageNumberFieldType::Copy() const
120 std::unique_ptr<SwPageNumberFieldType> pTmp(new SwPageNumberFieldType());
122 pTmp->m_nNumberingType = m_nNumberingType;
123 pTmp->m_bVirtual = m_bVirtual;
125 return pTmp;
128 void SwPageNumberFieldType::ChangeExpansion( SwDoc* pDoc,
129 bool bVirt,
130 const SvxNumType* pNumFormat )
132 if( pNumFormat )
133 m_nNumberingType = *pNumFormat;
135 m_bVirtual = false;
136 if (!(bVirt && pDoc))
137 return;
139 // check the flag since the layout NEVER sets it back
140 const SfxItemPool &rPool = pDoc->GetAttrPool();
141 for (const SfxPoolItem* pItem : rPool.GetItemSurrogates(RES_PAGEDESC))
143 auto pDesc = dynamic_cast<const SwFormatPageDesc*>(pItem);
144 if( pDesc && pDesc->GetNumOffset() && pDesc->GetDefinedIn() )
146 const SwContentNode* pNd = dynamic_cast<const SwContentNode*>( pDesc->GetDefinedIn() );
147 if( pNd )
149 if (SwIterator<SwFrame, SwContentNode, sw::IteratorMode::UnwrapMulti>(*pNd).First())
150 // sw_redlinehide: not sure if this should happen only if
151 // it's the first node, because that's where RES_PAGEDESC
152 // is effective?
153 m_bVirtual = true;
155 else if( dynamic_cast< const SwFormat* >(pDesc->GetDefinedIn()) != nullptr)
157 SwAutoFormatGetDocNode aGetHt( &pDoc->GetNodes() );
158 m_bVirtual = !pDesc->GetDefinedIn()->GetInfo( aGetHt );
159 break;
165 SwPageNumberField::SwPageNumberField(SwPageNumberFieldType* pTyp,
166 sal_uInt16 nSub, sal_uInt32 nFormat, short nOff,
167 sal_uInt16 const nPageNumber, sal_uInt16 const nMaxPage)
168 : SwField(pTyp, nFormat), m_nSubType(nSub), m_nOffset(nOff)
169 , m_nPageNumber(nPageNumber)
170 , m_nMaxPage(nMaxPage)
174 void SwPageNumberField::ChangeExpansion(sal_uInt16 const nPageNumber,
175 sal_uInt16 const nMaxPage)
177 m_nPageNumber = nPageNumber;
178 m_nMaxPage = nMaxPage;
181 OUString SwPageNumberField::ExpandImpl(SwRootFrame const*const) const
183 OUString sRet;
184 SwPageNumberFieldType* pFieldType = static_cast<SwPageNumberFieldType*>(GetTyp());
186 if( PG_NEXT == m_nSubType && 1 != m_nOffset )
188 sRet = pFieldType->Expand(static_cast<SvxNumType>(GetFormat()), 1, m_nPageNumber, m_nMaxPage, m_sUserStr, GetLanguage());
189 if (!sRet.isEmpty())
191 sRet = pFieldType->Expand(static_cast<SvxNumType>(GetFormat()), m_nOffset, m_nPageNumber, m_nMaxPage, m_sUserStr, GetLanguage());
194 else if( PG_PREV == m_nSubType && -1 != m_nOffset )
196 sRet = pFieldType->Expand(static_cast<SvxNumType>(GetFormat()), -1, m_nPageNumber, m_nMaxPage, m_sUserStr, GetLanguage());
197 if (!sRet.isEmpty())
199 sRet = pFieldType->Expand(static_cast<SvxNumType>(GetFormat()), m_nOffset, m_nPageNumber, m_nMaxPage, m_sUserStr, GetLanguage());
202 else
203 sRet = pFieldType->Expand(static_cast<SvxNumType>(GetFormat()), m_nOffset, m_nPageNumber, m_nMaxPage, m_sUserStr, GetLanguage());
204 return sRet;
207 std::unique_ptr<SwField> SwPageNumberField::Copy() const
209 std::unique_ptr<SwPageNumberField> pTmp(new SwPageNumberField(
210 static_cast<SwPageNumberFieldType*>(GetTyp()), m_nSubType,
211 GetFormat(), m_nOffset, m_nPageNumber, m_nMaxPage));
212 pTmp->SetLanguage( GetLanguage() );
213 pTmp->SetUserString( m_sUserStr );
214 return std::unique_ptr<SwField>(pTmp.release());
217 OUString SwPageNumberField::GetPar2() const
219 return OUString::number(m_nOffset);
222 void SwPageNumberField::SetPar2(const OUString& rStr)
224 m_nOffset = static_cast<short>(rStr.toInt32());
227 sal_uInt16 SwPageNumberField::GetSubType() const
229 return m_nSubType;
232 bool SwPageNumberField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
234 switch( nWhichId )
236 case FIELD_PROP_FORMAT:
237 rAny <<= static_cast<sal_Int16>(GetFormat());
238 break;
239 case FIELD_PROP_USHORT1:
240 rAny <<= m_nOffset;
241 break;
242 case FIELD_PROP_SUBTYPE:
244 text::PageNumberType eType;
245 eType = text::PageNumberType_CURRENT;
246 if(m_nSubType == PG_PREV)
247 eType = text::PageNumberType_PREV;
248 else if(m_nSubType == PG_NEXT)
249 eType = text::PageNumberType_NEXT;
250 rAny <<= eType;
252 break;
253 case FIELD_PROP_PAR1:
254 rAny <<= m_sUserStr;
255 break;
257 default:
258 assert(false);
260 return true;
263 bool SwPageNumberField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
265 bool bRet = true;
266 sal_Int16 nSet = 0;
267 switch( nWhichId )
269 case FIELD_PROP_FORMAT:
270 rAny >>= nSet;
272 // TODO: where do the defines come from?
273 if(nSet <= SVX_NUM_PAGEDESC )
274 SetFormat(nSet);
275 break;
276 case FIELD_PROP_USHORT1:
277 rAny >>= nSet;
278 m_nOffset = nSet;
279 break;
280 case FIELD_PROP_SUBTYPE:
281 switch( static_cast<text::PageNumberType>(SWUnoHelper::GetEnumAsInt32( rAny )) )
283 case text::PageNumberType_CURRENT:
284 m_nSubType = PG_RANDOM;
285 break;
286 case text::PageNumberType_PREV:
287 m_nSubType = PG_PREV;
288 break;
289 case text::PageNumberType_NEXT:
290 m_nSubType = PG_NEXT;
291 break;
292 default:
293 bRet = false;
295 break;
296 case FIELD_PROP_PAR1:
297 rAny >>= m_sUserStr;
298 break;
300 default:
301 assert(false);
303 return bRet;
306 SwAuthorFieldType::SwAuthorFieldType()
307 : SwFieldType( SwFieldIds::Author )
311 OUString SwAuthorFieldType::Expand(sal_uLong nFormat)
313 SvtUserOptions& rOpt = SW_MOD()->GetUserOptions();
314 if((nFormat & 0xff) == AF_NAME)
315 return rOpt.GetFullName();
317 return rOpt.GetID();
320 std::unique_ptr<SwFieldType> SwAuthorFieldType::Copy() const
322 return std::make_unique<SwAuthorFieldType>();
325 SwAuthorField::SwAuthorField(SwAuthorFieldType* pTyp, sal_uInt32 nFormat)
326 : SwField(pTyp, nFormat)
328 m_aContent = SwAuthorFieldType::Expand(GetFormat());
331 OUString SwAuthorField::ExpandImpl(SwRootFrame const*const) const
333 if (!IsFixed())
334 const_cast<SwAuthorField*>(this)->m_aContent =
335 SwAuthorFieldType::Expand(GetFormat());
337 return m_aContent;
340 std::unique_ptr<SwField> SwAuthorField::Copy() const
342 std::unique_ptr<SwAuthorField> pTmp(new SwAuthorField( static_cast<SwAuthorFieldType*>(GetTyp()),
343 GetFormat()));
344 pTmp->SetExpansion(m_aContent);
345 return std::unique_ptr<SwField>(pTmp.release());
348 bool SwAuthorField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
350 switch( nWhichId )
352 case FIELD_PROP_BOOL1:
353 rAny <<= (GetFormat() & 0xff) == AF_NAME;
354 break;
356 case FIELD_PROP_BOOL2:
357 rAny <<= IsFixed();
358 break;
360 case FIELD_PROP_PAR1:
361 rAny <<= m_aContent;
362 break;
364 default:
365 assert(false);
367 return true;
370 bool SwAuthorField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
372 switch( nWhichId )
374 case FIELD_PROP_BOOL1:
375 SetFormat( *o3tl::doAccess<bool>(rAny) ? AF_NAME : AF_SHORTCUT );
376 break;
378 case FIELD_PROP_BOOL2:
379 if( *o3tl::doAccess<bool>(rAny) )
380 SetFormat( GetFormat() | AF_FIXED);
381 else
382 SetFormat( GetFormat() & ~AF_FIXED);
383 break;
385 case FIELD_PROP_PAR1:
386 rAny >>= m_aContent;
387 break;
389 default:
390 assert(false);
392 return true;
395 SwFileNameFieldType::SwFileNameFieldType(SwDoc& rDocument)
396 : SwFieldType( SwFieldIds::Filename )
397 , m_rDoc(rDocument)
401 OUString SwFileNameFieldType::Expand(sal_uLong nFormat) const
403 OUString aRet;
404 const SwDocShell* pDShell = m_rDoc.GetDocShell();
405 if( pDShell && pDShell->HasName() )
407 const INetURLObject& rURLObj = pDShell->GetMedium()->GetURLObject();
408 switch( nFormat & ~FF_FIXED )
410 case FF_PATH:
412 if( INetProtocol::File == rURLObj.GetProtocol() )
414 INetURLObject aTemp(rURLObj);
415 aTemp.removeSegment();
416 // last slash should belong to the pathname
417 aRet = aTemp.PathToFileName();
419 else
421 aRet = URIHelper::removePassword(
422 rURLObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ),
423 INetURLObject::EncodeMechanism::WasEncoded, URL_DECODE );
424 const sal_Int32 nPos = aRet.indexOf(rURLObj.GetLastName( URL_DECODE ));
425 if (nPos>=0)
427 aRet = aRet.copy(0, nPos);
431 break;
433 case FF_NAME:
434 aRet = rURLObj.GetLastName( INetURLObject::DecodeMechanism::WithCharset );
435 break;
437 case FF_NAME_NOEXT:
438 aRet = rURLObj.GetBase();
439 break;
441 default:
442 if( INetProtocol::File == rURLObj.GetProtocol() )
443 aRet = rURLObj.GetFull();
444 else
445 aRet = URIHelper::removePassword(
446 rURLObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ),
447 INetURLObject::EncodeMechanism::WasEncoded, URL_DECODE );
450 return aRet;
453 std::unique_ptr<SwFieldType> SwFileNameFieldType::Copy() const
455 return std::make_unique<SwFileNameFieldType>(m_rDoc);
458 SwFileNameField::SwFileNameField(SwFileNameFieldType* pTyp, sal_uInt32 nFormat)
459 : SwField(pTyp, nFormat)
461 m_aContent = static_cast<SwFileNameFieldType*>(GetTyp())->Expand(GetFormat());
464 OUString SwFileNameField::ExpandImpl(SwRootFrame const*const) const
466 if (!IsFixed())
467 const_cast<SwFileNameField*>(this)->m_aContent = static_cast<SwFileNameFieldType*>(GetTyp())->Expand(GetFormat());
469 return m_aContent;
472 std::unique_ptr<SwField> SwFileNameField::Copy() const
474 std::unique_ptr<SwFileNameField> pTmp(
475 new SwFileNameField(static_cast<SwFileNameFieldType*>(GetTyp()), GetFormat()));
476 pTmp->SetExpansion(m_aContent);
478 return std::unique_ptr<SwField>(pTmp.release());
481 bool SwFileNameField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
483 switch( nWhichId )
485 case FIELD_PROP_FORMAT:
487 sal_Int16 nRet;
488 switch( GetFormat() &(~FF_FIXED) )
490 case FF_PATH:
491 nRet = text::FilenameDisplayFormat::PATH;
492 break;
493 case FF_NAME_NOEXT:
494 nRet = text::FilenameDisplayFormat::NAME;
495 break;
496 case FF_NAME:
497 nRet = text::FilenameDisplayFormat::NAME_AND_EXT;
498 break;
499 default: nRet = text::FilenameDisplayFormat::FULL;
501 rAny <<= nRet;
503 break;
505 case FIELD_PROP_BOOL2:
506 rAny <<= IsFixed();
507 break;
509 case FIELD_PROP_PAR3:
510 rAny <<= m_aContent;
511 break;
513 default:
514 assert(false);
516 return true;
519 bool SwFileNameField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
521 switch( nWhichId )
523 case FIELD_PROP_FORMAT:
525 //JP 24.10.2001: int32 because in UnoField.cxx a putvalue is
526 // called with a int32 value! But normally we need
527 // here only a int16
528 sal_Int32 nType = 0;
529 rAny >>= nType;
530 bool bFixed = IsFixed();
531 switch( nType )
533 case text::FilenameDisplayFormat::PATH:
534 nType = FF_PATH;
535 break;
536 case text::FilenameDisplayFormat::NAME:
537 nType = FF_NAME_NOEXT;
538 break;
539 case text::FilenameDisplayFormat::NAME_AND_EXT:
540 nType = FF_NAME;
541 break;
542 default: nType = FF_PATHNAME;
544 if(bFixed)
545 nType |= FF_FIXED;
546 SetFormat(nType);
548 break;
550 case FIELD_PROP_BOOL2:
551 if( *o3tl::doAccess<bool>(rAny) )
552 SetFormat( GetFormat() | FF_FIXED);
553 else
554 SetFormat( GetFormat() & ~FF_FIXED);
555 break;
557 case FIELD_PROP_PAR3:
558 rAny >>= m_aContent;
559 break;
561 default:
562 assert(false);
564 return true;
567 SwTemplNameFieldType::SwTemplNameFieldType(SwDoc& rDocument)
568 : SwFieldType( SwFieldIds::TemplateName )
569 , m_rDoc(rDocument)
573 OUString SwTemplNameFieldType::Expand(sal_uLong nFormat) const
575 OSL_ENSURE( nFormat < FF_END, "Expand: no valid Format!" );
577 OUString aRet;
578 SwDocShell *pDocShell(m_rDoc.GetDocShell());
579 OSL_ENSURE(pDocShell, "no SwDocShell");
580 if (pDocShell) {
581 uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
582 pDocShell->GetModel(), uno::UNO_QUERY_THROW);
583 uno::Reference<document::XDocumentProperties> xDocProps(
584 xDPS->getDocumentProperties());
585 OSL_ENSURE(xDocProps.is(), "Doc has no DocumentProperties");
587 if( FF_UI_NAME == nFormat )
588 aRet = xDocProps->getTemplateName();
589 else if( !xDocProps->getTemplateURL().isEmpty() )
591 if( FF_UI_RANGE == nFormat )
593 // for getting region names!
594 SfxDocumentTemplates aFac;
595 OUString sTmp;
596 OUString sRegion;
597 aFac.GetLogicNames( xDocProps->getTemplateURL(), sRegion, sTmp );
598 aRet = sRegion;
600 else
602 INetURLObject aPathName( xDocProps->getTemplateURL() );
603 if( FF_NAME == nFormat )
604 aRet = aPathName.GetLastName(URL_DECODE);
605 else if( FF_NAME_NOEXT == nFormat )
606 aRet = aPathName.GetBase();
607 else
609 if( FF_PATH == nFormat )
611 aPathName.removeSegment();
612 aRet = aPathName.GetFull();
614 else
615 aRet = aPathName.GetFull();
620 return aRet;
623 std::unique_ptr<SwFieldType> SwTemplNameFieldType::Copy() const
625 return std::make_unique<SwTemplNameFieldType>(m_rDoc);
628 SwTemplNameField::SwTemplNameField(SwTemplNameFieldType* pTyp, sal_uInt32 nFormat)
629 : SwField(pTyp, nFormat)
632 OUString SwTemplNameField::ExpandImpl(SwRootFrame const*const) const
634 return static_cast<SwTemplNameFieldType*>(GetTyp())->Expand(GetFormat());
637 std::unique_ptr<SwField> SwTemplNameField::Copy() const
639 return std::make_unique<SwTemplNameField>(static_cast<SwTemplNameFieldType*>(GetTyp()), GetFormat());
642 bool SwTemplNameField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
644 switch ( nWhichId )
646 case FIELD_PROP_FORMAT:
648 sal_Int16 nRet;
649 switch( GetFormat() )
651 case FF_PATH: nRet = text::FilenameDisplayFormat::PATH; break;
652 case FF_NAME_NOEXT: nRet = text::FilenameDisplayFormat::NAME; break;
653 case FF_NAME: nRet = text::FilenameDisplayFormat::NAME_AND_EXT; break;
654 case FF_UI_RANGE: nRet = text::TemplateDisplayFormat::AREA; break;
655 case FF_UI_NAME: nRet = text::TemplateDisplayFormat::TITLE; break;
656 default: nRet = text::FilenameDisplayFormat::FULL;
659 rAny <<= nRet;
661 break;
663 default:
664 assert(false);
666 return true;
669 bool SwTemplNameField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
671 switch ( nWhichId )
673 case FIELD_PROP_FORMAT:
675 //JP 24.10.2001: int32 because in UnoField.cxx a putvalue is
676 // called with a int32 value! But normally we need
677 // here only a int16
678 sal_Int32 nType = 0;
679 rAny >>= nType;
680 switch( nType )
682 case text::FilenameDisplayFormat::PATH:
683 SetFormat(FF_PATH);
684 break;
685 case text::FilenameDisplayFormat::NAME:
686 SetFormat(FF_NAME_NOEXT);
687 break;
688 case text::FilenameDisplayFormat::NAME_AND_EXT:
689 SetFormat(FF_NAME);
690 break;
691 case text::TemplateDisplayFormat::AREA :
692 SetFormat(FF_UI_RANGE);
693 break;
694 case text::TemplateDisplayFormat::TITLE :
695 SetFormat(FF_UI_NAME);
696 break;
697 default: SetFormat(FF_PATHNAME);
700 break;
702 default:
703 assert(false);
705 return true;
708 SwDocStatFieldType::SwDocStatFieldType(SwDoc& rDocument)
709 : SwFieldType(SwFieldIds::DocStat)
710 , m_rDoc(rDocument)
711 , m_nNumberingType(SVX_NUM_ARABIC)
715 OUString SwDocStatFieldType::Expand(sal_uInt16 nSubType, SvxNumType nFormat) const
717 sal_uInt32 nVal = 0;
718 const SwDocStat& rDStat = m_rDoc.getIDocumentStatistics().GetDocStat();
719 switch( nSubType )
721 case DS_TBL: nVal = rDStat.nTable; break;
722 case DS_GRF: nVal = rDStat.nGrf; break;
723 case DS_OLE: nVal = rDStat.nOLE; break;
724 case DS_PARA: nVal = rDStat.nPara; break;
725 case DS_WORD: nVal = rDStat.nWord; break;
726 case DS_CHAR: nVal = rDStat.nChar; break;
727 case DS_PAGE:
728 if( m_rDoc.getIDocumentLayoutAccess().GetCurrentLayout() )
729 const_cast<SwDocStat &>(rDStat).nPage = m_rDoc.getIDocumentLayoutAccess().GetCurrentLayout()->GetPageNum();
730 nVal = rDStat.nPage;
731 if( SVX_NUM_PAGEDESC == nFormat )
732 nFormat = m_nNumberingType;
733 break;
734 default:
735 OSL_FAIL( "SwDocStatFieldType::Expand: unknown SubType" );
738 if( nVal <= SHRT_MAX )
739 return FormatNumber( nVal, nFormat );
741 return OUString::number( nVal );
744 std::unique_ptr<SwFieldType> SwDocStatFieldType::Copy() const
746 return std::make_unique<SwDocStatFieldType>(m_rDoc);
750 * @param pTyp
751 * @param nSub SubType
752 * @param nFormat
754 SwDocStatField::SwDocStatField(SwDocStatFieldType* pTyp, sal_uInt16 nSub, sal_uInt32 nFormat)
755 : SwField(pTyp, nFormat),
756 m_nSubType(nSub)
759 OUString SwDocStatField::ExpandImpl(SwRootFrame const*const) const
761 return static_cast<SwDocStatFieldType*>(GetTyp())->Expand(m_nSubType, static_cast<SvxNumType>(GetFormat()));
764 std::unique_ptr<SwField> SwDocStatField::Copy() const
766 return std::make_unique<SwDocStatField>(
767 static_cast<SwDocStatFieldType*>(GetTyp()), m_nSubType, GetFormat() );
770 sal_uInt16 SwDocStatField::GetSubType() const
772 return m_nSubType;
775 void SwDocStatField::SetSubType(sal_uInt16 nSub)
777 m_nSubType = nSub;
780 void SwDocStatField::ChangeExpansion( const SwFrame* pFrame )
782 if( DS_PAGE == m_nSubType && SVX_NUM_PAGEDESC == GetFormat() )
783 static_cast<SwDocStatFieldType*>(GetTyp())->SetNumFormat(
784 pFrame->FindPageFrame()->GetPageDesc()->GetNumType().GetNumberingType() );
787 bool SwDocStatField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
789 switch ( nWhichId )
791 case FIELD_PROP_USHORT2:
792 rAny <<= static_cast<sal_Int16>(GetFormat());
793 break;
795 default:
796 assert(false);
798 return true;
801 bool SwDocStatField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
803 bool bRet = false;
804 switch ( nWhichId )
806 case FIELD_PROP_USHORT2:
808 sal_Int16 nSet = 0;
809 rAny >>= nSet;
810 if(nSet <= SVX_NUM_CHARS_LOWER_LETTER_N &&
811 nSet != SVX_NUM_CHAR_SPECIAL &&
812 nSet != SVX_NUM_BITMAP)
814 SetFormat(nSet);
815 bRet = true;
818 break;
820 default:
821 assert(false);
823 return bRet;
826 // Document info field type
828 SwDocInfoFieldType::SwDocInfoFieldType(SwDoc* pDc)
829 : SwValueFieldType( pDc, SwFieldIds::DocInfo )
833 std::unique_ptr<SwFieldType> SwDocInfoFieldType::Copy() const
835 return std::make_unique<SwDocInfoFieldType>(GetDoc());
838 static void lcl_GetLocalDataWrapper( LanguageType nLang,
839 const LocaleDataWrapper **ppAppLocalData,
840 const LocaleDataWrapper **ppLocalData )
842 SvtSysLocale aLocale;
843 *ppAppLocalData = &aLocale.GetLocaleData();
844 *ppLocalData = *ppAppLocalData;
845 if( nLang != (*ppLocalData)->getLanguageTag().getLanguageType() )
846 *ppLocalData = new LocaleDataWrapper(LanguageTag( nLang ));
849 OUString SwDocInfoFieldType::Expand( sal_uInt16 nSub, sal_uInt32 nFormat,
850 LanguageType nLang, const OUString& rName ) const
852 const LocaleDataWrapper *pAppLocalData = nullptr, *pLocalData = nullptr;
853 SwDocShell *pDocShell(GetDoc()->GetDocShell());
854 OSL_ENSURE(pDocShell, "no SwDocShell");
855 if (!pDocShell) { return OUString(); }
857 uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
858 pDocShell->GetModel(), uno::UNO_QUERY_THROW);
859 uno::Reference<document::XDocumentProperties> xDocProps(
860 xDPS->getDocumentProperties());
861 OSL_ENSURE(xDocProps.is(), "Doc has no DocumentProperties");
863 sal_uInt16 nExtSub = nSub & 0xff00;
864 nSub &= 0xff; // do not consider extended SubTypes
866 OUString aStr;
867 switch(nSub)
869 case DI_TITLE: aStr = xDocProps->getTitle(); break;
870 case DI_SUBJECT:aStr = xDocProps->getSubject(); break;
871 case DI_KEYS: aStr = ::comphelper::string::convertCommaSeparated(
872 xDocProps->getKeywords());
873 break;
874 case DI_COMMENT:aStr = xDocProps->getDescription(); break;
875 case DI_DOCNO: aStr = OUString::number(
876 xDocProps->getEditingCycles() );
877 break;
878 case DI_EDIT:
879 if ( !nFormat )
881 lcl_GetLocalDataWrapper( nLang, &pAppLocalData, &pLocalData );
882 sal_Int32 dur = xDocProps->getEditingDuration();
883 // If Seconds > 0 then bSec should be TRUE otherwise Seconds
884 // information will be lost if file has EditTime in Seconds format.
885 aStr = pLocalData->getTime( tools::Time(dur/3600, (dur%3600)/60, dur%60),
886 dur%60 > 0);
888 else
890 sal_Int32 dur = xDocProps->getEditingDuration();
891 double fVal = tools::Time(dur/3600, (dur%3600)/60, dur%60).GetTimeInDays();
892 aStr = ExpandValue(fVal, nFormat, nLang);
894 break;
895 case DI_CUSTOM:
897 OUString sVal;
900 uno::Any aAny;
901 uno::Reference < beans::XPropertySet > xSet(
902 xDocProps->getUserDefinedProperties(),
903 uno::UNO_QUERY_THROW);
904 aAny = xSet->getPropertyValue( rName );
906 uno::Reference < script::XTypeConverter > xConverter( script::Converter::create(comphelper::getProcessComponentContext()) );
907 uno::Any aNew = xConverter->convertToSimpleType( aAny, uno::TypeClass_STRING );
908 aNew >>= sVal;
910 catch (uno::Exception&) {}
911 return sVal;
914 default:
916 OUString aName( xDocProps->getAuthor() );
917 util::DateTime uDT( xDocProps->getCreationDate() );
918 DateTime aDate(uDT);
919 if( nSub == DI_CREATE )
920 ; // that's it !!
921 else if( nSub == DI_CHANGE )
923 aName = xDocProps->getModifiedBy();
924 uDT = xDocProps->getModificationDate();
925 aDate = DateTime(uDT);
927 else if( nSub == DI_PRINT )
929 aName = xDocProps->getPrintedBy();
930 uDT = xDocProps->getPrintDate();
931 aDate = DateTime(uDT);
933 else
934 break;
936 if (aDate.IsValidAndGregorian())
938 switch (nExtSub & ~DI_SUB_FIXED)
940 case DI_SUB_AUTHOR:
941 aStr = aName;
942 break;
944 case DI_SUB_TIME:
945 if (!nFormat)
947 lcl_GetLocalDataWrapper( nLang, &pAppLocalData,
948 &pLocalData );
949 aStr = pLocalData->getTime( aDate,
950 false);
952 else
954 // start the number formatter
955 double fVal = SwDateTimeField::GetDateTime( *GetDoc(),
956 aDate);
957 aStr = ExpandValue(fVal, nFormat, nLang);
959 break;
961 case DI_SUB_DATE:
962 if (!nFormat)
964 lcl_GetLocalDataWrapper( nLang, &pAppLocalData,
965 &pLocalData );
966 aStr = pLocalData->getDate( aDate );
968 else
970 // start the number formatter
971 double fVal = SwDateTimeField::GetDateTime( *GetDoc(),
972 aDate);
973 aStr = ExpandValue(fVal, nFormat, nLang);
975 break;
979 break;
982 if( pAppLocalData != pLocalData )
983 delete pLocalData;
985 return aStr;
988 // document info field
990 SwDocInfoField::SwDocInfoField(SwDocInfoFieldType* pTyp, sal_uInt16 nSub, const OUString& rName, sal_uInt32 nFormat) :
991 SwValueField(pTyp, nFormat), m_nSubType(nSub)
993 m_aName = rName;
994 m_aContent = static_cast<SwDocInfoFieldType*>(GetTyp())->Expand(m_nSubType, nFormat, GetLanguage(), m_aName);
997 SwDocInfoField::SwDocInfoField(SwDocInfoFieldType* pTyp, sal_uInt16 nSub, const OUString& rName, const OUString& rValue, sal_uInt32 nFormat) :
998 SwValueField(pTyp, nFormat), m_nSubType(nSub)
1000 m_aName = rName;
1001 m_aContent = rValue;
1004 template<class T>
1005 static double lcl_TimeToDouble( const T& rTime )
1007 const double fNanoSecondsPerDay = 86400000000000.0;
1008 return ( (rTime.Hours * SAL_CONST_INT64(3600000000000))
1009 + (rTime.Minutes * SAL_CONST_INT64( 60000000000))
1010 + (rTime.Seconds * SAL_CONST_INT64( 1000000000))
1011 + (rTime.NanoSeconds))
1012 / fNanoSecondsPerDay;
1015 template<class D>
1016 static double lcl_DateToDouble( const D& rDate, const Date& rNullDate )
1018 tools::Long nDate = Date::DateToDays( rDate.Day, rDate.Month, rDate.Year );
1019 tools::Long nNullDate = Date::DateToDays( rNullDate.GetDay(), rNullDate.GetMonth(), rNullDate.GetYear() );
1020 return double( nDate - nNullDate );
1023 OUString SwDocInfoField::ExpandImpl(SwRootFrame const*const) const
1025 if ( ( m_nSubType & 0xFF ) == DI_CUSTOM )
1027 // custom properties currently need special treatment
1028 // We don't have a secure way to detect "real" custom properties in Word import of text
1029 // fields, so we treat *every* unknown property as a custom property, even the "built-in"
1030 // section in Word's document summary information stream as these properties have not been
1031 // inserted when the document summary information was imported, we do it here.
1032 // This approach is still a lot better than the old one to import such fields as
1033 // "user fields" and simple text
1034 SwDocShell* pDocShell = GetDoc()->GetDocShell();
1035 if( !pDocShell )
1036 return m_aContent;
1039 uno::Reference<document::XDocumentPropertiesSupplier> xDPS( pDocShell->GetModel(), uno::UNO_QUERY_THROW);
1040 uno::Reference<document::XDocumentProperties> xDocProps( xDPS->getDocumentProperties());
1041 uno::Reference < beans::XPropertySet > xSet( xDocProps->getUserDefinedProperties(), uno::UNO_QUERY_THROW);
1042 uno::Reference < beans::XPropertySetInfo > xSetInfo = xSet->getPropertySetInfo();
1044 uno::Any aAny;
1045 if( xSetInfo->hasPropertyByName( m_aName ) )
1046 aAny = xSet->getPropertyValue( m_aName );
1047 if ( aAny.getValueType() != cppu::UnoType<void>::get() )
1049 // "void" type means that the property has not been inserted until now
1050 if ( !IsFixed() )
1052 // if the field is "fixed" we don't update it from the property
1053 OUString sVal;
1054 uno::Reference < script::XTypeConverter > xConverter( script::Converter::create(comphelper::getProcessComponentContext()) );
1055 util::Date aDate;
1056 util::DateTime aDateTime;
1057 util::Duration aDuration;
1058 if( aAny >>= aDate)
1060 SvNumberFormatter* pFormatter = pDocShell->GetDoc()->GetNumberFormatter();
1061 const Date& rNullDate = pFormatter->GetNullDate();
1062 sVal = ExpandValue( lcl_DateToDouble<util::Date>( aDate, rNullDate ), GetFormat(), GetLanguage());
1064 else if( aAny >>= aDateTime )
1066 double fDateTime = lcl_TimeToDouble<util::DateTime>( aDateTime );
1067 SvNumberFormatter* pFormatter = pDocShell->GetDoc()->GetNumberFormatter();
1068 const Date& rNullDate = pFormatter->GetNullDate();
1069 fDateTime += lcl_DateToDouble<util::DateTime>( aDateTime, rNullDate );
1070 sVal = ExpandValue( fDateTime, GetFormat(), GetLanguage());
1072 else if( aAny >>= aDuration )
1074 sVal = OUStringChar(aDuration.Negative ? '-' : '+')
1075 + SwViewShell::GetShellRes()->sDurationFormat;
1076 sVal = sVal.replaceFirst("%1", OUString::number( aDuration.Years ) );
1077 sVal = sVal.replaceFirst("%2", OUString::number( aDuration.Months ) );
1078 sVal = sVal.replaceFirst("%3", OUString::number( aDuration.Days ) );
1079 sVal = sVal.replaceFirst("%4", OUString::number( aDuration.Hours ) );
1080 sVal = sVal.replaceFirst("%5", OUString::number( aDuration.Minutes) );
1081 sVal = sVal.replaceFirst("%6", OUString::number( aDuration.Seconds) );
1083 else
1085 uno::Any aNew = xConverter->convertToSimpleType( aAny, uno::TypeClass_STRING );
1086 aNew >>= sVal;
1088 const_cast<SwDocInfoField*>(this)->m_aContent = sVal;
1092 catch (uno::Exception&) {}
1094 else if ( !IsFixed() )
1095 const_cast<SwDocInfoField*>(this)->m_aContent = static_cast<SwDocInfoFieldType*>(GetTyp())->Expand(m_nSubType, GetFormat(), GetLanguage(), m_aName);
1097 return m_aContent;
1100 OUString SwDocInfoField::GetFieldName() const
1102 OUString aStr(SwFieldType::GetTypeStr(GetTypeId()) + ":");
1104 sal_uInt16 const nSub = m_nSubType & 0xff;
1106 switch (nSub)
1108 case DI_CUSTOM:
1109 aStr += m_aName;
1110 break;
1112 default:
1113 aStr += SwViewShell::GetShellRes()
1114 ->aDocInfoLst[ nSub - DI_SUBTYPE_BEGIN ];
1115 break;
1117 if (IsFixed())
1119 aStr += " " + SwViewShell::GetShellRes()->aFixedStr;
1121 return aStr;
1124 std::unique_ptr<SwField> SwDocInfoField::Copy() const
1126 std::unique_ptr<SwDocInfoField> pField(new SwDocInfoField(static_cast<SwDocInfoFieldType*>(GetTyp()), m_nSubType, m_aName, GetFormat()));
1127 pField->SetAutomaticLanguage(IsAutomaticLanguage());
1128 pField->m_aContent = m_aContent;
1130 return std::unique_ptr<SwField>(pField.release());
1133 sal_uInt16 SwDocInfoField::GetSubType() const
1135 return m_nSubType;
1138 void SwDocInfoField::SetSubType(sal_uInt16 nSub)
1140 m_nSubType = nSub;
1143 void SwDocInfoField::SetLanguage(LanguageType nLng)
1145 if (!GetFormat())
1146 SwField::SetLanguage(nLng);
1147 else
1148 SwValueField::SetLanguage(nLng);
1151 bool SwDocInfoField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
1153 switch( nWhichId )
1155 case FIELD_PROP_PAR1:
1156 rAny <<= m_aContent;
1157 break;
1159 case FIELD_PROP_PAR4:
1160 rAny <<= m_aName;
1161 break;
1163 case FIELD_PROP_USHORT1:
1164 rAny <<= static_cast<sal_Int16>(m_aContent.toInt32());
1165 break;
1167 case FIELD_PROP_BOOL1:
1168 rAny <<= 0 != (m_nSubType & DI_SUB_FIXED);
1169 break;
1171 case FIELD_PROP_FORMAT:
1172 rAny <<= static_cast<sal_Int32>(GetFormat());
1173 break;
1175 case FIELD_PROP_DOUBLE:
1177 double fVal = GetValue();
1178 rAny <<= fVal;
1180 break;
1181 case FIELD_PROP_PAR3:
1182 rAny <<= ExpandImpl(nullptr);
1183 break;
1184 case FIELD_PROP_BOOL2:
1186 sal_uInt16 nExtSub = (m_nSubType & 0xff00) & ~DI_SUB_FIXED;
1187 rAny <<= nExtSub == DI_SUB_DATE;
1189 break;
1190 default:
1191 return SwField::QueryValue(rAny, nWhichId);
1193 return true;
1196 bool SwDocInfoField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
1198 sal_Int32 nValue = 0;
1199 switch( nWhichId )
1201 case FIELD_PROP_PAR1:
1202 if( m_nSubType & DI_SUB_FIXED )
1203 rAny >>= m_aContent;
1204 break;
1206 case FIELD_PROP_USHORT1:
1207 if( m_nSubType & DI_SUB_FIXED )
1209 rAny >>= nValue;
1210 m_aContent = OUString::number(nValue);
1212 break;
1214 case FIELD_PROP_BOOL1:
1215 if(*o3tl::doAccess<bool>(rAny))
1216 m_nSubType |= DI_SUB_FIXED;
1217 else
1218 m_nSubType &= ~DI_SUB_FIXED;
1219 break;
1220 case FIELD_PROP_FORMAT:
1222 rAny >>= nValue;
1223 if( nValue >= 0)
1224 SetFormat(nValue);
1226 break;
1228 case FIELD_PROP_PAR3:
1229 rAny >>= m_aContent;
1230 break;
1231 case FIELD_PROP_BOOL2:
1232 m_nSubType &= 0xf0ff;
1233 if(*o3tl::doAccess<bool>(rAny))
1234 m_nSubType |= DI_SUB_DATE;
1235 else
1236 m_nSubType |= DI_SUB_TIME;
1237 break;
1238 default:
1239 return SwField::PutValue(rAny, nWhichId);
1241 return true;
1244 SwHiddenTextFieldType::SwHiddenTextFieldType( bool bSetHidden )
1245 : SwFieldType( SwFieldIds::HiddenText ), m_bHidden( bSetHidden )
1249 std::unique_ptr<SwFieldType> SwHiddenTextFieldType::Copy() const
1251 return std::make_unique<SwHiddenTextFieldType>( m_bHidden );
1254 void SwHiddenTextFieldType::SetHiddenFlag( bool bSetHidden )
1256 if( m_bHidden != bSetHidden )
1258 m_bHidden = bSetHidden;
1259 UpdateFields(); // notify all HiddenTexts
1263 SwHiddenTextField::SwHiddenTextField( SwHiddenTextFieldType* pFieldType,
1264 bool bConditional,
1265 const OUString& rCond,
1266 const OUString& rStr,
1267 bool bHidden,
1268 SwFieldTypesEnum nSub) :
1269 SwField( pFieldType ), m_aCond(rCond), m_nSubType(nSub),
1270 m_bCanToggle(bConditional), m_bIsHidden(bHidden), m_bValid(false)
1272 if(m_nSubType == SwFieldTypesEnum::ConditionalText)
1274 sal_Int32 nPos = 0;
1275 m_aTRUEText = rStr.getToken(0, '|', nPos);
1277 if(nPos != -1)
1279 m_aFALSEText = rStr.getToken(0, '|', nPos);
1280 if(nPos != -1)
1282 m_aContent = rStr.getToken(0, '|', nPos);
1283 m_bValid = true;
1287 else
1288 m_aTRUEText = rStr;
1291 SwHiddenTextField::SwHiddenTextField( SwHiddenTextFieldType* pFieldType,
1292 const OUString& rCond,
1293 const OUString& rTrue,
1294 const OUString& rFalse,
1295 SwFieldTypesEnum nSub)
1296 : SwField( pFieldType ), m_aTRUEText(rTrue), m_aFALSEText(rFalse), m_aCond(rCond), m_nSubType(nSub),
1297 m_bIsHidden(true), m_bValid(false)
1299 m_bCanToggle = !m_aCond.isEmpty();
1302 OUString SwHiddenTextField::ExpandImpl(SwRootFrame const*const) const
1304 // Type: !Hidden -> show always
1305 // Hide -> evaluate condition
1307 if( SwFieldTypesEnum::ConditionalText == m_nSubType )
1309 if( m_bValid )
1310 return m_aContent;
1312 if( m_bCanToggle && !m_bIsHidden )
1313 return m_aTRUEText;
1315 else if( !static_cast<SwHiddenTextFieldType*>(GetTyp())->GetHiddenFlag() ||
1316 ( m_bCanToggle && m_bIsHidden ))
1317 return m_aTRUEText;
1319 return m_aFALSEText;
1322 /// get current field value and cache it
1323 void SwHiddenTextField::Evaluate(SwDoc& rDoc)
1325 if( SwFieldTypesEnum::ConditionalText != m_nSubType )
1326 return;
1328 #if !HAVE_FEATURE_DBCONNECTIVITY
1329 (void) rDoc;
1330 #else
1331 SwDBManager* pMgr = rDoc.GetDBManager();
1332 #endif
1333 m_bValid = false;
1334 OUString sTmpName = (m_bCanToggle && !m_bIsHidden) ? m_aTRUEText : m_aFALSEText;
1336 // Database expressions need to be different from normal text. Therefore, normal text is set
1337 // in quotes. If the latter exist they will be removed. If not, check if potential DB name.
1338 // Only if there are two or more dots and no quotes, we assume a database.
1339 if (sTmpName.getLength()>1 &&
1340 sTmpName.startsWith("\"") &&
1341 sTmpName.endsWith("\""))
1343 m_aContent = sTmpName.copy(1, sTmpName.getLength() - 2);
1344 m_bValid = true;
1346 else if(sTmpName.indexOf('\"')<0 &&
1347 comphelper::string::getTokenCount(sTmpName, '.') > 2)
1349 sTmpName = ::ReplacePoint(sTmpName);
1350 if(sTmpName.startsWith("[") && sTmpName.endsWith("]"))
1351 { // remove brackets
1352 sTmpName = sTmpName.copy(1, sTmpName.getLength() - 2);
1354 #if HAVE_FEATURE_DBCONNECTIVITY
1355 if( pMgr)
1357 sal_Int32 nIdx{ 0 };
1358 OUString sDBName( GetDBName( sTmpName, rDoc ));
1359 OUString sDataSource(sDBName.getToken(0, DB_DELIM, nIdx));
1360 OUString sDataTableOrQuery(sDBName.getToken(0, DB_DELIM, nIdx));
1361 if( pMgr->IsInMerge() && !sDBName.isEmpty() &&
1362 pMgr->IsDataSourceOpen( sDataSource,
1363 sDataTableOrQuery, false))
1365 double fNumber;
1366 pMgr->GetMergeColumnCnt(GetColumnName( sTmpName ),
1367 GetLanguage(), m_aContent, &fNumber );
1368 m_bValid = true;
1370 else if( !sDBName.isEmpty() && !sDataSource.isEmpty() &&
1371 !sDataTableOrQuery.isEmpty() )
1372 m_bValid = true;
1374 #endif
1378 OUString SwHiddenTextField::GetFieldName() const
1380 OUString aStr = SwFieldType::GetTypeStr(m_nSubType) +
1381 " " + m_aCond + " " + m_aTRUEText;
1383 if (m_nSubType == SwFieldTypesEnum::ConditionalText)
1385 aStr += " : " + m_aFALSEText;
1387 return aStr;
1390 std::unique_ptr<SwField> SwHiddenTextField::Copy() const
1392 std::unique_ptr<SwHiddenTextField> pField(
1393 new SwHiddenTextField(static_cast<SwHiddenTextFieldType*>(GetTyp()), m_aCond,
1394 m_aTRUEText, m_aFALSEText));
1395 pField->m_bIsHidden = m_bIsHidden;
1396 pField->m_bValid = m_bValid;
1397 pField->m_aContent = m_aContent;
1398 pField->SetFormat(GetFormat());
1399 pField->m_nSubType = m_nSubType;
1400 return std::unique_ptr<SwField>(pField.release());
1403 /// set condition
1404 void SwHiddenTextField::SetPar1(const OUString& rStr)
1406 m_aCond = rStr;
1407 m_bCanToggle = !m_aCond.isEmpty();
1410 OUString SwHiddenTextField::GetPar1() const
1412 return m_aCond;
1415 /// set True/False text
1416 void SwHiddenTextField::SetPar2(const OUString& rStr)
1418 if (m_nSubType == SwFieldTypesEnum::ConditionalText)
1420 sal_Int32 nPos = rStr.indexOf('|');
1421 if (nPos == -1)
1422 m_aTRUEText = rStr;
1423 else
1425 m_aTRUEText = rStr.copy(0, nPos);
1426 m_aFALSEText = rStr.copy(nPos + 1);
1429 else
1430 m_aTRUEText = rStr;
1433 /// get True/False text
1434 OUString SwHiddenTextField::GetPar2() const
1436 if(m_nSubType != SwFieldTypesEnum::ConditionalText)
1438 return m_aTRUEText;
1440 return m_aTRUEText + "|" + m_aFALSEText;
1443 sal_uInt16 SwHiddenTextField::GetSubType() const
1445 return static_cast<sal_uInt16>(m_nSubType);
1448 bool SwHiddenTextField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
1450 switch( nWhichId )
1452 case FIELD_PROP_PAR1:
1453 rAny <<= m_aCond;
1454 break;
1455 case FIELD_PROP_PAR2:
1456 rAny <<= m_aTRUEText;
1457 break;
1458 case FIELD_PROP_PAR3:
1459 rAny <<= m_aFALSEText;
1460 break;
1461 case FIELD_PROP_PAR4 :
1462 rAny <<= m_aContent;
1463 break;
1464 case FIELD_PROP_BOOL1:
1465 rAny <<= m_bIsHidden;
1466 break;
1467 default:
1468 assert(false);
1470 return true;
1473 bool SwHiddenTextField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
1475 switch( nWhichId )
1477 case FIELD_PROP_PAR1:
1479 OUString sVal;
1480 rAny >>= sVal;
1481 SetPar1(sVal);
1483 break;
1484 case FIELD_PROP_PAR2:
1485 rAny >>= m_aTRUEText;
1486 break;
1487 case FIELD_PROP_PAR3:
1488 rAny >>= m_aFALSEText;
1489 break;
1490 case FIELD_PROP_BOOL1:
1491 m_bIsHidden = *o3tl::doAccess<bool>(rAny);
1492 break;
1493 case FIELD_PROP_PAR4:
1494 rAny >>= m_aContent;
1495 m_bValid = true;
1496 break;
1497 default:
1498 assert(false);
1500 return true;
1503 OUString SwHiddenTextField::GetColumnName(const OUString& rName)
1505 sal_Int32 nPos = rName.indexOf(DB_DELIM);
1506 if( nPos>=0 )
1508 nPos = rName.indexOf(DB_DELIM, nPos + 1);
1510 if( nPos>=0 )
1511 return rName.copy(nPos + 1);
1513 return rName;
1516 OUString SwHiddenTextField::GetDBName(const OUString& rName, SwDoc& rDoc)
1518 sal_Int32 nPos = rName.indexOf(DB_DELIM);
1519 if( nPos>=0 )
1521 nPos = rName.indexOf(DB_DELIM, nPos + 1);
1523 if( nPos>=0 )
1524 return rName.copy(0, nPos);
1527 SwDBData aData = rDoc.GetDBData();
1528 return aData.sDataSource + OUStringChar(DB_DELIM) + aData.sCommand;
1531 // [aFieldDefinition] value sample : " IF A == B \"TrueText\" \"FalseText\""
1532 void SwHiddenTextField::ParseIfFieldDefinition(const OUString& aFieldDefinition,
1533 OUString& rCondition,
1534 OUString& rTrue,
1535 OUString& rFalse)
1537 // get all positions inside the input string where words are started
1539 // In: " IF A == B \"TrueText\" \"FalseText\""
1540 // 0 1 2 3
1541 // 01234567890 123456789 01 2345678901 2
1543 // result:
1544 // [1, 4, 6, 9, 11, 22]
1545 std::vector<sal_Int32> wordPosition;
1547 bool quoted = false;
1548 bool insideWord = false;
1549 for (sal_Int32 i = 0; i < aFieldDefinition.getLength(); i++)
1551 if (quoted)
1553 if (aFieldDefinition[i] == '\"')
1555 quoted = false;
1556 insideWord = false;
1559 else
1561 if (aFieldDefinition[i] == ' ')
1563 // word delimiter
1564 insideWord = false;
1566 else
1568 if (insideWord)
1570 quoted = (aFieldDefinition[i] == '\"');
1572 else
1574 insideWord = true;
1575 wordPosition.push_back(i);
1576 quoted = (aFieldDefinition[i] == '\"');
1583 // first word is always "IF"
1584 // last two words are: true-case and false-case,
1585 // everything before is treated as condition expression
1586 // => we need at least 4 words to be inside the input string
1587 if (wordPosition.size() < 4)
1589 return;
1593 const sal_Int32 conditionBegin = wordPosition[1];
1594 const sal_Int32 trueBegin = wordPosition[wordPosition.size() - 2];
1595 const sal_Int32 falseBegin = wordPosition[wordPosition.size() - 1];
1597 const sal_Int32 conditionLength = trueBegin - conditionBegin;
1598 const sal_Int32 trueLength = falseBegin - trueBegin;
1600 // Syntax
1601 // OUString::copy( sal_Int32 beginIndex, sal_Int32 count )
1602 rCondition = aFieldDefinition.copy(conditionBegin, conditionLength);
1603 rTrue = aFieldDefinition.copy(trueBegin, trueLength);
1604 rFalse = aFieldDefinition.copy(falseBegin);
1606 // trim
1607 rCondition = rCondition.trim();
1608 rTrue = rTrue.trim();
1609 rFalse = rFalse.trim();
1611 // remove quotes
1612 if (rCondition.getLength() >= 2)
1614 if (rCondition[0] == '\"' && rCondition[rCondition.getLength() - 1] == '\"')
1615 rCondition = rCondition.copy(1, rCondition.getLength() - 2);
1617 if (rTrue.getLength() >= 2)
1619 if (rTrue[0] == '\"' && rTrue[rTrue.getLength() - 1] == '\"')
1620 rTrue = rTrue.copy(1, rTrue.getLength() - 2);
1622 if (rFalse.getLength() >= 2)
1624 if (rFalse[0] == '\"' && rFalse[rFalse.getLength() - 1] == '\"')
1625 rFalse = rFalse.copy(1, rFalse.getLength() - 2);
1628 // Note: do not make trim once again, while this is a user defined data
1631 // field type for line height 0
1633 SwHiddenParaFieldType::SwHiddenParaFieldType()
1634 : SwFieldType( SwFieldIds::HiddenPara )
1638 std::unique_ptr<SwFieldType> SwHiddenParaFieldType::Copy() const
1640 return std::make_unique<SwHiddenParaFieldType>();
1643 // field for line height 0
1645 SwHiddenParaField::SwHiddenParaField(SwHiddenParaFieldType* pTyp, const OUString& rStr)
1646 : SwField(pTyp), m_aCond(rStr)
1648 m_bIsHidden = false;
1651 OUString SwHiddenParaField::ExpandImpl(SwRootFrame const*const) const
1653 return OUString();
1656 std::unique_ptr<SwField> SwHiddenParaField::Copy() const
1658 std::unique_ptr<SwHiddenParaField> pField(new SwHiddenParaField(static_cast<SwHiddenParaFieldType*>(GetTyp()), m_aCond));
1659 pField->m_bIsHidden = m_bIsHidden;
1660 return std::unique_ptr<SwField>(pField.release());
1663 bool SwHiddenParaField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
1665 switch ( nWhichId )
1667 case FIELD_PROP_PAR1:
1668 rAny <<= m_aCond;
1669 break;
1670 case FIELD_PROP_BOOL1:
1671 rAny <<= m_bIsHidden;
1672 break;
1674 default:
1675 assert(false);
1677 return true;
1680 bool SwHiddenParaField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
1682 switch ( nWhichId )
1684 case FIELD_PROP_PAR1:
1685 rAny >>= m_aCond;
1686 break;
1687 case FIELD_PROP_BOOL1:
1688 m_bIsHidden = *o3tl::doAccess<bool>(rAny);
1689 break;
1691 default:
1692 assert(false);
1694 return true;
1697 /// set condition
1698 void SwHiddenParaField::SetPar1(const OUString& rStr)
1700 m_aCond = rStr;
1703 OUString SwHiddenParaField::GetPar1() const
1705 return m_aCond;
1708 // PostIt field type
1710 SwPostItFieldType::SwPostItFieldType(SwDoc& rDoc)
1711 : SwFieldType( SwFieldIds::Postit )
1712 , mrDoc(rDoc)
1715 std::unique_ptr<SwFieldType> SwPostItFieldType::Copy() const
1717 return std::make_unique<SwPostItFieldType>(mrDoc);
1720 // PostIt field
1722 sal_uInt32 SwPostItField::s_nLastPostItId = 1;
1724 SwPostItField::SwPostItField( SwPostItFieldType* pT,
1725 const OUString& rAuthor,
1726 const OUString& rText,
1727 const OUString& rInitials,
1728 const OUString& rName,
1729 const DateTime& rDateTime,
1730 const bool bResolved,
1731 const sal_uInt32 nPostItId
1733 : SwField( pT )
1734 , m_sText( rText )
1735 , m_sAuthor( rAuthor )
1736 , m_sInitials( rInitials )
1737 , m_sName( rName )
1738 , m_aDateTime( rDateTime )
1739 , m_bResolved( bResolved )
1741 m_nPostItId = nPostItId == 0 ? s_nLastPostItId++ : nPostItId;
1744 SwPostItField::~SwPostItField()
1746 if ( m_xTextObject.is() )
1748 m_xTextObject->DisposeEditSource();
1751 mpText.reset();
1754 OUString SwPostItField::ExpandImpl(SwRootFrame const*const) const
1756 return OUString();
1759 OUString SwPostItField::GetDescription() const
1761 return SwResId(STR_NOTE);
1764 void SwPostItField::SetResolved(bool bNewState)
1766 m_bResolved = bNewState;
1769 void SwPostItField::ToggleResolved()
1771 m_bResolved = !m_bResolved;
1774 bool SwPostItField::GetResolved() const
1776 return m_bResolved;
1779 std::unique_ptr<SwField> SwPostItField::Copy() const
1781 std::unique_ptr<SwPostItField> pRet(new SwPostItField( static_cast<SwPostItFieldType*>(GetTyp()), m_sAuthor, m_sText, m_sInitials, m_sName,
1782 m_aDateTime, m_bResolved, m_nPostItId));
1783 if (mpText)
1784 pRet->SetTextObject( std::make_unique<OutlinerParaObject>(*mpText) );
1786 // Note: member <m_xTextObject> not copied.
1788 return std::unique_ptr<SwField>(pRet.release());
1791 /// set author
1792 void SwPostItField::SetPar1(const OUString& rStr)
1794 m_sAuthor = rStr;
1797 /// get author
1798 OUString SwPostItField::GetPar1() const
1800 return m_sAuthor;
1803 /// set the PostIt's text
1804 void SwPostItField::SetPar2(const OUString& rStr)
1806 m_sText = rStr;
1809 /// get the PostIt's text
1810 OUString SwPostItField::GetPar2() const
1812 return m_sText;
1816 void SwPostItField::SetName(const OUString& rName)
1818 m_sName = rName;
1822 void SwPostItField::SetTextObject( std::unique_ptr<OutlinerParaObject> pText )
1824 mpText = std::move(pText);
1827 sal_Int32 SwPostItField::GetNumberOfParagraphs() const
1829 return mpText ? mpText->Count() : 1;
1832 bool SwPostItField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
1834 switch( nWhichId )
1836 case FIELD_PROP_PAR1:
1837 rAny <<= m_sAuthor;
1838 break;
1839 case FIELD_PROP_PAR2:
1841 rAny <<= m_sText;
1842 break;
1844 case FIELD_PROP_PAR3:
1845 rAny <<= m_sInitials;
1846 break;
1847 case FIELD_PROP_PAR4:
1848 rAny <<= m_sName;
1849 break;
1850 case FIELD_PROP_BOOL1:
1851 rAny <<= m_bResolved;
1852 break;
1853 case FIELD_PROP_TEXT:
1855 if ( !m_xTextObject.is() )
1857 SwPostItFieldType* pGetType = static_cast<SwPostItFieldType*>(GetTyp());
1858 SwDoc& rDoc = pGetType->GetDoc();
1859 auto pObj = std::make_unique<SwTextAPIEditSource>( &rDoc );
1860 const_cast <SwPostItField*> (this)->m_xTextObject = new SwTextAPIObject( std::move(pObj) );
1863 if ( mpText )
1864 m_xTextObject->SetText( *mpText );
1865 else
1866 m_xTextObject->SetString( m_sText );
1868 uno::Reference < text::XText > xText( m_xTextObject.get() );
1869 rAny <<= xText;
1870 break;
1872 case FIELD_PROP_DATE:
1874 rAny <<= m_aDateTime.GetUNODate();
1876 break;
1877 case FIELD_PROP_DATE_TIME:
1879 rAny <<= m_aDateTime.GetUNODateTime();
1881 break;
1882 default:
1883 assert(false);
1885 return true;
1888 bool SwPostItField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
1890 switch( nWhichId )
1892 case FIELD_PROP_PAR1:
1893 rAny >>= m_sAuthor;
1894 break;
1895 case FIELD_PROP_PAR2:
1896 rAny >>= m_sText;
1897 //#i100374# new string via api, delete complex text object so SwPostItNote picks up the new string
1898 mpText.reset();
1899 break;
1900 case FIELD_PROP_PAR3:
1901 rAny >>= m_sInitials;
1902 break;
1903 case FIELD_PROP_PAR4:
1904 rAny >>= m_sName;
1905 break;
1906 case FIELD_PROP_BOOL1:
1907 rAny >>= m_bResolved;
1908 break;
1909 case FIELD_PROP_TEXT:
1910 OSL_FAIL("Not implemented!");
1911 break;
1912 case FIELD_PROP_DATE:
1913 if( auto aSetDate = o3tl::tryAccess<util::Date>(rAny) )
1915 m_aDateTime = Date(aSetDate->Day, aSetDate->Month, aSetDate->Year);
1917 break;
1918 case FIELD_PROP_DATE_TIME:
1920 util::DateTime aDateTimeValue;
1921 if(!(rAny >>= aDateTimeValue))
1922 return false;
1923 m_aDateTime = DateTime(aDateTimeValue);
1925 break;
1926 default:
1927 assert(false);
1929 return true;
1932 void SwPostItField::dumpAsXml(xmlTextWriterPtr pWriter) const
1934 xmlTextWriterStartElement(pWriter, BAD_CAST("SwPostItField"));
1935 xmlTextWriterWriteAttribute(pWriter, BAD_CAST("name"), BAD_CAST(GetName().toUtf8().getStr()));
1937 SwField::dumpAsXml(pWriter);
1939 xmlTextWriterStartElement(pWriter, BAD_CAST("mpText"));
1940 xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("ptr"), "%p", mpText.get());
1941 if (mpText)
1942 mpText->dumpAsXml(pWriter);
1943 xmlTextWriterEndElement(pWriter);
1945 xmlTextWriterEndElement(pWriter);
1948 // extended user information field type
1950 SwExtUserFieldType::SwExtUserFieldType()
1951 : SwFieldType( SwFieldIds::ExtUser )
1955 std::unique_ptr<SwFieldType> SwExtUserFieldType::Copy() const
1957 return std::make_unique<SwExtUserFieldType>();
1960 OUString SwExtUserFieldType::Expand(sal_uInt16 nSub )
1962 UserOptToken nRet = static_cast<UserOptToken>(USHRT_MAX);
1963 switch(nSub)
1965 case EU_FIRSTNAME: nRet = UserOptToken::FirstName; break;
1966 case EU_NAME: nRet = UserOptToken::LastName; break;
1967 case EU_SHORTCUT: nRet = UserOptToken::ID; break;
1969 case EU_COMPANY: nRet = UserOptToken::Company; break;
1970 case EU_STREET: nRet = UserOptToken::Street; break;
1971 case EU_TITLE: nRet = UserOptToken::Title; break;
1972 case EU_POSITION: nRet = UserOptToken::Position; break;
1973 case EU_PHONE_PRIVATE: nRet = UserOptToken::TelephoneHome; break;
1974 case EU_PHONE_COMPANY: nRet = UserOptToken::TelephoneWork; break;
1975 case EU_FAX: nRet = UserOptToken::Fax; break;
1976 case EU_EMAIL: nRet = UserOptToken::Email; break;
1977 case EU_COUNTRY: nRet = UserOptToken::Country; break;
1978 case EU_ZIP: nRet = UserOptToken::Zip; break;
1979 case EU_CITY: nRet = UserOptToken::City; break;
1980 case EU_STATE: nRet = UserOptToken::State; break;
1981 case EU_FATHERSNAME: nRet = UserOptToken::FathersName; break;
1982 case EU_APARTMENT: nRet = UserOptToken::Apartment; break;
1983 default: OSL_ENSURE( false, "Field unknown");
1985 if( static_cast<UserOptToken>(USHRT_MAX) != nRet )
1987 SvtUserOptions& rUserOpt = SW_MOD()->GetUserOptions();
1988 return rUserOpt.GetToken( nRet );
1990 return OUString();
1993 // extended user information field
1995 SwExtUserField::SwExtUserField(SwExtUserFieldType* pTyp, sal_uInt16 nSubTyp, sal_uInt32 nFormat) :
1996 SwField(pTyp, nFormat), m_nType(nSubTyp)
1998 m_aContent = SwExtUserFieldType::Expand(m_nType);
2001 OUString SwExtUserField::ExpandImpl(SwRootFrame const*const) const
2003 if (!IsFixed())
2004 const_cast<SwExtUserField*>(this)->m_aContent = SwExtUserFieldType::Expand(m_nType);
2006 return m_aContent;
2009 std::unique_ptr<SwField> SwExtUserField::Copy() const
2011 std::unique_ptr<SwExtUserField> pField(new SwExtUserField(static_cast<SwExtUserFieldType*>(GetTyp()), m_nType, GetFormat()));
2012 pField->SetExpansion(m_aContent);
2014 return std::unique_ptr<SwField>(pField.release());
2017 sal_uInt16 SwExtUserField::GetSubType() const
2019 return m_nType;
2022 void SwExtUserField::SetSubType(sal_uInt16 nSub)
2024 m_nType = nSub;
2027 bool SwExtUserField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
2029 switch( nWhichId )
2031 case FIELD_PROP_PAR1:
2032 rAny <<= m_aContent;
2033 break;
2035 case FIELD_PROP_USHORT1:
2037 sal_Int16 nTmp = m_nType;
2038 rAny <<= nTmp;
2040 break;
2041 case FIELD_PROP_BOOL1:
2042 rAny <<= IsFixed();
2043 break;
2044 default:
2045 assert(false);
2047 return true;
2050 bool SwExtUserField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
2052 switch( nWhichId )
2054 case FIELD_PROP_PAR1:
2055 rAny >>= m_aContent;
2056 break;
2058 case FIELD_PROP_USHORT1:
2060 sal_Int16 nTmp = 0;
2061 rAny >>= nTmp;
2062 m_nType = nTmp;
2064 break;
2065 case FIELD_PROP_BOOL1:
2066 if( *o3tl::doAccess<bool>(rAny) )
2067 SetFormat(GetFormat() | AF_FIXED);
2068 else
2069 SetFormat(GetFormat() & ~AF_FIXED);
2070 break;
2071 default:
2072 assert(false);
2074 return true;
2077 // field type for relative page numbers
2079 SwRefPageSetFieldType::SwRefPageSetFieldType()
2080 : SwFieldType( SwFieldIds::RefPageSet )
2084 std::unique_ptr<SwFieldType> SwRefPageSetFieldType::Copy() const
2086 return std::make_unique<SwRefPageSetFieldType>();
2089 // overridden since there is nothing to update
2090 void SwRefPageSetFieldType::Modify( const SfxPoolItem*, const SfxPoolItem * )
2094 // field for relative page numbers
2096 SwRefPageSetField::SwRefPageSetField( SwRefPageSetFieldType* pTyp,
2097 short nOff, bool bFlag )
2098 : SwField( pTyp ), m_nOffset( nOff ), m_bOn( bFlag )
2102 OUString SwRefPageSetField::ExpandImpl(SwRootFrame const*const) const
2104 return OUString();
2107 std::unique_ptr<SwField> SwRefPageSetField::Copy() const
2109 return std::make_unique<SwRefPageSetField>( static_cast<SwRefPageSetFieldType*>(GetTyp()), m_nOffset, m_bOn );
2112 OUString SwRefPageSetField::GetPar2() const
2114 return OUString::number(GetOffset());
2117 void SwRefPageSetField::SetPar2(const OUString& rStr)
2119 SetOffset( static_cast<short>(rStr.toInt32()) );
2122 bool SwRefPageSetField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
2124 switch( nWhichId )
2126 case FIELD_PROP_BOOL1:
2127 rAny <<= m_bOn;
2128 break;
2129 case FIELD_PROP_USHORT1:
2130 rAny <<= static_cast<sal_Int16>(m_nOffset);
2131 break;
2132 default:
2133 assert(false);
2135 return true;
2138 bool SwRefPageSetField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
2140 switch( nWhichId )
2142 case FIELD_PROP_BOOL1:
2143 m_bOn = *o3tl::doAccess<bool>(rAny);
2144 break;
2145 case FIELD_PROP_USHORT1:
2146 rAny >>=m_nOffset;
2147 break;
2148 default:
2149 assert(false);
2151 return true;
2154 // relative page numbers - query field
2156 SwRefPageGetFieldType::SwRefPageGetFieldType( SwDoc& rDc )
2157 : SwFieldType( SwFieldIds::RefPageGet ), m_rDoc( rDc ), m_nNumberingType( SVX_NUM_ARABIC )
2161 std::unique_ptr<SwFieldType> SwRefPageGetFieldType::Copy() const
2163 std::unique_ptr<SwRefPageGetFieldType> pNew(new SwRefPageGetFieldType( m_rDoc ));
2164 pNew->m_nNumberingType = m_nNumberingType;
2165 return pNew;
2168 void SwRefPageGetFieldType::Modify( const SfxPoolItem* pOld, const SfxPoolItem* pNew )
2170 auto const ModifyImpl = [this](SwRootFrame const*const pLayout)
2172 // first collect all SetPageRefFields
2173 SetGetExpFields aTmpLst;
2174 if (MakeSetList(aTmpLst, pLayout))
2176 std::vector<SwFormatField*> vFields;
2177 GatherFields(vFields);
2178 for(auto pFormatField: vFields)
2179 UpdateField(pFormatField->GetTextField(), aTmpLst, pLayout);
2183 // update all GetReference fields
2184 if( !pNew && !pOld && HasWriterListeners() )
2186 SwRootFrame const* pLayout(nullptr);
2187 SwRootFrame const* pLayoutRLHidden(nullptr);
2188 for (SwRootFrame const*const pLay : m_rDoc.GetAllLayouts())
2190 if (pLay->IsHideRedlines())
2192 pLayoutRLHidden = pLay;
2194 else
2196 pLayout = pLay;
2199 ModifyImpl(pLayout);
2200 if (pLayoutRLHidden)
2202 ModifyImpl(pLayoutRLHidden);
2206 // forward to text fields, they "expand" the text
2207 NotifyClients( pOld, pNew );
2210 bool SwRefPageGetFieldType::MakeSetList(SetGetExpFields& rTmpLst,
2211 SwRootFrame const*const pLayout)
2213 IDocumentRedlineAccess const& rIDRA(m_rDoc.getIDocumentRedlineAccess());
2214 std::vector<SwFormatField*> vFields;
2215 GatherFields(vFields);
2216 for(auto pFormatField: vFields)
2218 // update only the GetRef fields
2219 const SwTextField* pTField = pFormatField->GetTextField();
2220 if (!pLayout || !pLayout->IsHideRedlines() || !sw::IsFieldDeletedInModel(rIDRA, *pTField))
2222 const SwTextNode& rTextNd = pTField->GetTextNode();
2224 // Always the first! (in Tab-Headline, header/footer )
2225 Point aPt;
2226 std::pair<Point, bool> const tmp(aPt, false);
2227 const SwContentFrame *const pFrame = rTextNd.getLayoutFrame(
2228 pLayout, nullptr, &tmp);
2230 std::unique_ptr<SetGetExpField> pNew;
2232 if( !pFrame ||
2233 pFrame->IsInDocBody() ||
2234 // #i31868#
2235 // Check if pFrame is not yet connected to the layout.
2236 !pFrame->FindPageFrame() )
2238 // create index for determination of the TextNode
2239 SwNodeIndex aIdx( rTextNd );
2240 pNew.reset( new SetGetExpField( aIdx, pTField ) );
2242 else
2244 // create index for determination of the TextNode
2245 SwPosition aPos( m_rDoc.GetNodes().GetEndOfPostIts() );
2246 bool const bResult = GetBodyTextNode( m_rDoc, aPos, *pFrame );
2247 OSL_ENSURE(bResult, "where is the Field?");
2248 pNew.reset( new SetGetExpField( aPos.nNode, pTField,
2249 &aPos.nContent ) );
2252 rTmpLst.insert( std::move(pNew) );
2255 return !rTmpLst.empty();
2258 void SwRefPageGetFieldType::UpdateField( SwTextField const * pTextField,
2259 SetGetExpFields const & rSetList,
2260 SwRootFrame const*const pLayout)
2262 SwRefPageGetField* pGetField = const_cast<SwRefPageGetField*>(static_cast<const SwRefPageGetField*>(pTextField->GetFormatField().GetField()));
2263 pGetField->SetText( OUString(), pLayout );
2265 // then search the correct RefPageSet field
2266 SwTextNode* pTextNode = &pTextField->GetTextNode();
2267 if( pTextNode->StartOfSectionIndex() >
2268 m_rDoc.GetNodes().GetEndOfExtras().GetIndex() )
2270 SwNodeIndex aIdx( *pTextNode );
2271 SetGetExpField aEndField( aIdx, pTextField );
2273 SetGetExpFields::const_iterator itLast = rSetList.lower_bound( &aEndField );
2275 if( itLast != rSetList.begin() )
2277 --itLast;
2278 const SwTextField* pRefTextField = (*itLast)->GetTextField();
2279 const SwRefPageSetField* pSetField =
2280 static_cast<const SwRefPageSetField*>(pRefTextField->GetFormatField().GetField());
2281 if( pSetField->IsOn() )
2283 // determine the correct offset
2284 Point aPt;
2285 std::pair<Point, bool> const tmp(aPt, false);
2286 const SwContentFrame *const pFrame = pTextNode->getLayoutFrame(
2287 pLayout, nullptr, &tmp);
2288 const SwContentFrame *const pRefFrame = pRefTextField->GetTextNode().getLayoutFrame(
2289 pLayout, nullptr, &tmp);
2290 const SwPageFrame* pPgFrame = nullptr;
2291 short nDiff = 1;
2292 if ( pFrame && pRefFrame )
2294 pPgFrame = pFrame->FindPageFrame();
2295 nDiff = pPgFrame->GetPhyPageNum() -
2296 pRefFrame->FindPageFrame()->GetPhyPageNum() + 1;
2299 SvxNumType nTmpFormat = SVX_NUM_PAGEDESC == static_cast<SvxNumType>(pGetField->GetFormat())
2300 ? ( !pPgFrame
2301 ? SVX_NUM_ARABIC
2302 : pPgFrame->GetPageDesc()->GetNumType().GetNumberingType() )
2303 : static_cast<SvxNumType>(pGetField->GetFormat());
2304 const short nPageNum = std::max<short>(0, pSetField->GetOffset() + nDiff);
2305 pGetField->SetText(FormatNumber(nPageNum, nTmpFormat), pLayout);
2309 // start formatting
2310 const_cast<SwFormatField&>(pTextField->GetFormatField()).UpdateTextNode(nullptr, nullptr);
2313 // queries for relative page numbering
2315 SwRefPageGetField::SwRefPageGetField( SwRefPageGetFieldType* pTyp,
2316 sal_uInt32 nFormat )
2317 : SwField( pTyp, nFormat )
2321 void SwRefPageGetField::SetText(const OUString& rText,
2322 SwRootFrame const*const pLayout)
2324 if (!pLayout || !pLayout->IsHideRedlines())
2326 m_sText = rText;
2328 if (!pLayout || pLayout->IsHideRedlines())
2330 m_sTextRLHidden = rText;
2334 OUString SwRefPageGetField::ExpandImpl(SwRootFrame const*const pLayout) const
2336 return pLayout && pLayout->IsHideRedlines() ? m_sTextRLHidden : m_sText;
2339 std::unique_ptr<SwField> SwRefPageGetField::Copy() const
2341 std::unique_ptr<SwRefPageGetField> pCpy(new SwRefPageGetField(
2342 static_cast<SwRefPageGetFieldType*>(GetTyp()), GetFormat() ));
2343 pCpy->m_sText = m_sText;
2344 pCpy->m_sTextRLHidden = m_sTextRLHidden;
2345 return std::unique_ptr<SwField>(pCpy.release());
2348 void SwRefPageGetField::ChangeExpansion(const SwFrame& rFrame,
2349 const SwTextField* pField )
2351 // only fields in Footer, Header, FootNote, Flys
2352 SwRefPageGetFieldType* pGetType = static_cast<SwRefPageGetFieldType*>(GetTyp());
2353 SwDoc& rDoc = pGetType->GetDoc();
2354 if( pField->GetTextNode().StartOfSectionIndex() >
2355 rDoc.GetNodes().GetEndOfExtras().GetIndex() )
2356 return;
2358 SwRootFrame const& rLayout(*rFrame.getRootFrame());
2359 OUString & rText(rLayout.IsHideRedlines() ? m_sTextRLHidden : m_sText);
2360 rText.clear();
2362 OSL_ENSURE(!rFrame.IsInDocBody(), "Flag incorrect, frame is in DocBody");
2364 // collect all SetPageRefFields
2365 SetGetExpFields aTmpLst;
2366 if (!pGetType->MakeSetList(aTmpLst, &rLayout))
2367 return ;
2369 // create index for determination of the TextNode
2370 SwPosition aPos( SwNodeIndex( rDoc.GetNodes() ) );
2371 SwTextNode* pTextNode = const_cast<SwTextNode*>(GetBodyTextNode(rDoc, aPos, rFrame));
2373 // If no layout exists, ChangeExpansion is called for header and
2374 // footer lines via layout formatting without existing TextNode.
2375 if(!pTextNode)
2376 return;
2378 SetGetExpField aEndField( aPos.nNode, pField, &aPos.nContent );
2380 SetGetExpFields::const_iterator itLast = aTmpLst.lower_bound( &aEndField );
2382 if( itLast == aTmpLst.begin() )
2383 return; // there is no corresponding set-field in front
2384 --itLast;
2386 const SwTextField* pRefTextField = (*itLast)->GetTextField();
2387 const SwRefPageSetField* pSetField =
2388 static_cast<const SwRefPageSetField*>(pRefTextField->GetFormatField().GetField());
2389 Point aPt;
2390 std::pair<Point, bool> const tmp(aPt, false);
2391 const SwContentFrame *const pRefFrame = pRefTextField->GetTextNode().getLayoutFrame(
2392 &rLayout, nullptr, &tmp);
2393 if( !(pSetField->IsOn() && pRefFrame) )
2394 return;
2396 // determine the correct offset
2397 const SwPageFrame* pPgFrame = rFrame.FindPageFrame();
2398 const short nDiff = pPgFrame->GetPhyPageNum() -
2399 pRefFrame->FindPageFrame()->GetPhyPageNum() + 1;
2401 SwRefPageGetField* pGetField = const_cast<SwRefPageGetField*>(static_cast<const SwRefPageGetField*>(pField->GetFormatField().GetField()));
2402 SvxNumType nTmpFormat = SVX_NUM_PAGEDESC == pGetField->GetFormat()
2403 ? pPgFrame->GetPageDesc()->GetNumType().GetNumberingType()
2404 : static_cast<SvxNumType>(pGetField->GetFormat());
2405 const short nPageNum = std::max<short>(0, pSetField->GetOffset() + nDiff);
2406 pGetField->SetText(FormatNumber(nPageNum, nTmpFormat), &rLayout);
2409 bool SwRefPageGetField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
2411 switch( nWhichId )
2413 case FIELD_PROP_USHORT1:
2414 rAny <<= static_cast<sal_Int16>(GetFormat());
2415 break;
2416 case FIELD_PROP_PAR1:
2417 rAny <<= m_sText;
2418 break;
2419 default:
2420 assert(false);
2422 return true;
2425 bool SwRefPageGetField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
2427 switch( nWhichId )
2429 case FIELD_PROP_USHORT1:
2431 sal_Int16 nSet = 0;
2432 rAny >>= nSet;
2433 if(nSet <= SVX_NUM_PAGEDESC )
2434 SetFormat(nSet);
2436 break;
2437 case FIELD_PROP_PAR1:
2438 rAny >>= m_sText;
2439 m_sTextRLHidden = m_sText;
2440 break;
2441 default:
2442 assert(false);
2444 return true;
2447 // field type to jump to and edit
2449 SwJumpEditFieldType::SwJumpEditFieldType( SwDoc& rD )
2450 : SwFieldType( SwFieldIds::JumpEdit ), m_rDoc( rD ), m_aDep( *this )
2454 std::unique_ptr<SwFieldType> SwJumpEditFieldType::Copy() const
2456 return std::make_unique<SwJumpEditFieldType>( m_rDoc );
2459 SwCharFormat* SwJumpEditFieldType::GetCharFormat()
2461 SwCharFormat* pFormat = m_rDoc.getIDocumentStylePoolAccess().GetCharFormatFromPool( RES_POOLCHR_JUMPEDIT );
2462 m_aDep.StartListening(pFormat);
2463 return pFormat;
2466 SwJumpEditField::SwJumpEditField( SwJumpEditFieldType* pTyp, sal_uInt32 nForm,
2467 const OUString& rText, const OUString& rHelp )
2468 : SwField( pTyp, nForm ), m_sText( rText ), m_sHelp( rHelp )
2472 OUString SwJumpEditField::ExpandImpl(SwRootFrame const*const) const
2474 return "<" + m_sText + ">";
2477 std::unique_ptr<SwField> SwJumpEditField::Copy() const
2479 return std::make_unique<SwJumpEditField>( static_cast<SwJumpEditFieldType*>(GetTyp()), GetFormat(),
2480 m_sText, m_sHelp );
2483 /// get place holder text
2484 OUString SwJumpEditField::GetPar1() const
2486 return m_sText;
2489 /// set place holder text
2490 void SwJumpEditField::SetPar1(const OUString& rStr)
2492 m_sText = rStr;
2495 /// get hint text
2496 OUString SwJumpEditField::GetPar2() const
2498 return m_sHelp;
2501 /// set hint text
2502 void SwJumpEditField::SetPar2(const OUString& rStr)
2504 m_sHelp = rStr;
2507 bool SwJumpEditField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
2509 switch( nWhichId )
2511 case FIELD_PROP_USHORT1:
2513 sal_Int16 nRet;
2514 switch( GetFormat() )
2516 case JE_FMT_TABLE: nRet = text::PlaceholderType::TABLE; break;
2517 case JE_FMT_FRAME: nRet = text::PlaceholderType::TEXTFRAME; break;
2518 case JE_FMT_GRAPHIC:nRet = text::PlaceholderType::GRAPHIC; break;
2519 case JE_FMT_OLE: nRet = text::PlaceholderType::OBJECT; break;
2520 default:
2521 nRet = text::PlaceholderType::TEXT; break;
2523 rAny <<= nRet;
2525 break;
2526 case FIELD_PROP_PAR1 :
2527 rAny <<= m_sHelp;
2528 break;
2529 case FIELD_PROP_PAR2 :
2530 rAny <<= m_sText;
2531 break;
2532 default:
2533 assert(false);
2535 return true;
2538 bool SwJumpEditField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
2540 switch( nWhichId )
2542 case FIELD_PROP_USHORT1:
2544 //JP 24.10.2001: int32 because in UnoField.cxx a putvalue is
2545 // called with a int32 value! But normally we need
2546 // here only a int16
2547 sal_Int32 nSet = 0;
2548 rAny >>= nSet;
2549 switch( nSet )
2551 case text::PlaceholderType::TEXT : SetFormat(JE_FMT_TEXT); break;
2552 case text::PlaceholderType::TABLE : SetFormat(JE_FMT_TABLE); break;
2553 case text::PlaceholderType::TEXTFRAME: SetFormat(JE_FMT_FRAME); break;
2554 case text::PlaceholderType::GRAPHIC : SetFormat(JE_FMT_GRAPHIC); break;
2555 case text::PlaceholderType::OBJECT : SetFormat(JE_FMT_OLE); break;
2558 break;
2559 case FIELD_PROP_PAR1 :
2560 rAny >>= m_sHelp;
2561 break;
2562 case FIELD_PROP_PAR2 :
2563 rAny >>= m_sText;
2564 break;
2565 default:
2566 assert(false);
2568 return true;
2571 // combined character field type
2573 SwCombinedCharFieldType::SwCombinedCharFieldType()
2574 : SwFieldType( SwFieldIds::CombinedChars )
2578 std::unique_ptr<SwFieldType> SwCombinedCharFieldType::Copy() const
2580 return std::make_unique<SwCombinedCharFieldType>();
2583 // combined character field
2585 SwCombinedCharField::SwCombinedCharField( SwCombinedCharFieldType* pFTyp,
2586 const OUString& rChars )
2587 : SwField( pFTyp, 0 ),
2588 m_sCharacters( rChars.copy( 0, std::min<sal_Int32>(rChars.getLength(), MAX_COMBINED_CHARACTERS) ))
2592 OUString SwCombinedCharField::ExpandImpl(SwRootFrame const*const) const
2594 return m_sCharacters;
2597 std::unique_ptr<SwField> SwCombinedCharField::Copy() const
2599 return std::make_unique<SwCombinedCharField>( static_cast<SwCombinedCharFieldType*>(GetTyp()),
2600 m_sCharacters );
2603 OUString SwCombinedCharField::GetPar1() const
2605 return m_sCharacters;
2608 void SwCombinedCharField::SetPar1(const OUString& rStr)
2610 m_sCharacters = rStr.copy(0, std::min<sal_Int32>(rStr.getLength(), MAX_COMBINED_CHARACTERS));
2613 bool SwCombinedCharField::QueryValue( uno::Any& rAny,
2614 sal_uInt16 nWhichId ) const
2616 switch( nWhichId )
2618 case FIELD_PROP_PAR1:
2619 rAny <<= m_sCharacters;
2620 break;
2621 default:
2622 assert(false);
2624 return true;
2627 bool SwCombinedCharField::PutValue( const uno::Any& rAny,
2628 sal_uInt16 nWhichId )
2630 switch( nWhichId )
2632 case FIELD_PROP_PAR1:
2634 OUString sTmp;
2635 rAny >>= sTmp;
2636 SetPar1(sTmp);
2638 break;
2639 default:
2640 assert(false);
2642 return true;
2645 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */