Mark some visible strings in ui files as translatable
[LibreOffice.git] / sw / source / core / fields / docufld.cxx
blob7ea308f576cd4c1ed7a12b90c34afdb00b2e7ff6
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 for (SwRootFrame* pRootFrame : pDoc->GetAllLayouts())
145 const SwPageFrame* pPageFrameIter = pRootFrame->GetLastPage();
146 while (pPageFrameIter)
148 const SwContentFrame* pContentFrame = pPageFrameIter->FindFirstBodyContent();
149 if (pContentFrame)
151 const SwFormatPageDesc& rFormatPageDesc = pContentFrame->GetPageDescItem();
152 if ( rFormatPageDesc.GetNumOffset() && rFormatPageDesc.GetDefinedIn() )
154 const SwContentNode* pNd = dynamic_cast<const SwContentNode*>( rFormatPageDesc.GetDefinedIn() );
155 if( pNd )
157 if (SwIterator<SwFrame, SwContentNode, sw::IteratorMode::UnwrapMulti>(*pNd).First())
158 // sw_redlinehide: not sure if this should happen only if
159 // it's the first node, because that's where RES_PAGEDESC
160 // is effective?
161 m_bVirtual = true;
163 else if( dynamic_cast< const SwFormat* >(rFormatPageDesc.GetDefinedIn()) != nullptr)
165 m_bVirtual = false;
166 sw::AutoFormatUsedHint aHint(m_bVirtual, pDoc->GetNodes());
167 rFormatPageDesc.GetDefinedIn()->CallSwClientNotify(aHint);
168 break;
172 pPageFrameIter = static_cast<const SwPageFrame*>(pPageFrameIter->GetPrev());
177 SwPageNumberField::SwPageNumberField(SwPageNumberFieldType* pTyp,
178 sal_uInt16 nSub, sal_uInt32 nFormat, short nOff,
179 sal_uInt16 const nPageNumber, sal_uInt16 const nMaxPage)
180 : SwField(pTyp, nFormat), m_nSubType(nSub), m_nOffset(nOff)
181 , m_nPageNumber(nPageNumber)
182 , m_nMaxPage(nMaxPage)
186 void SwPageNumberField::ChangeExpansion(sal_uInt16 const nPageNumber,
187 sal_uInt16 const nMaxPage)
189 m_nPageNumber = nPageNumber;
190 m_nMaxPage = nMaxPage;
193 OUString SwPageNumberField::ExpandImpl(SwRootFrame const*const) const
195 OUString sRet;
196 SwPageNumberFieldType* pFieldType = static_cast<SwPageNumberFieldType*>(GetTyp());
198 if( PG_NEXT == m_nSubType && 1 != m_nOffset )
200 sRet = pFieldType->Expand(static_cast<SvxNumType>(GetFormat()), 1, m_nPageNumber, m_nMaxPage, m_sUserStr, GetLanguage());
201 if (!sRet.isEmpty())
203 sRet = pFieldType->Expand(static_cast<SvxNumType>(GetFormat()), m_nOffset, m_nPageNumber, m_nMaxPage, m_sUserStr, GetLanguage());
206 else if( PG_PREV == m_nSubType && -1 != m_nOffset )
208 sRet = pFieldType->Expand(static_cast<SvxNumType>(GetFormat()), -1, m_nPageNumber, m_nMaxPage, m_sUserStr, GetLanguage());
209 if (!sRet.isEmpty())
211 sRet = pFieldType->Expand(static_cast<SvxNumType>(GetFormat()), m_nOffset, m_nPageNumber, m_nMaxPage, m_sUserStr, GetLanguage());
214 else
215 sRet = pFieldType->Expand(static_cast<SvxNumType>(GetFormat()), m_nOffset, m_nPageNumber, m_nMaxPage, m_sUserStr, GetLanguage());
216 return sRet;
219 std::unique_ptr<SwField> SwPageNumberField::Copy() const
221 std::unique_ptr<SwPageNumberField> pTmp(new SwPageNumberField(
222 static_cast<SwPageNumberFieldType*>(GetTyp()), m_nSubType,
223 GetFormat(), m_nOffset, m_nPageNumber, m_nMaxPage));
224 pTmp->SetLanguage( GetLanguage() );
225 pTmp->SetUserString( m_sUserStr );
226 return std::unique_ptr<SwField>(pTmp.release());
229 OUString SwPageNumberField::GetPar2() const
231 return OUString::number(m_nOffset);
234 void SwPageNumberField::SetPar2(const OUString& rStr)
236 m_nOffset = static_cast<short>(rStr.toInt32());
239 sal_uInt16 SwPageNumberField::GetSubType() const
241 return m_nSubType;
244 bool SwPageNumberField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
246 switch( nWhichId )
248 case FIELD_PROP_FORMAT:
249 rAny <<= static_cast<sal_Int16>(GetFormat());
250 break;
251 case FIELD_PROP_USHORT1:
252 rAny <<= m_nOffset;
253 break;
254 case FIELD_PROP_SUBTYPE:
256 text::PageNumberType eType;
257 eType = text::PageNumberType_CURRENT;
258 if(m_nSubType == PG_PREV)
259 eType = text::PageNumberType_PREV;
260 else if(m_nSubType == PG_NEXT)
261 eType = text::PageNumberType_NEXT;
262 rAny <<= eType;
264 break;
265 case FIELD_PROP_PAR1:
266 rAny <<= m_sUserStr;
267 break;
269 default:
270 assert(false);
272 return true;
275 bool SwPageNumberField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
277 bool bRet = true;
278 sal_Int16 nSet = 0;
279 switch( nWhichId )
281 case FIELD_PROP_FORMAT:
282 rAny >>= nSet;
284 // TODO: where do the defines come from?
285 if(nSet <= SVX_NUM_PAGEDESC )
286 SetFormat(nSet);
287 break;
288 case FIELD_PROP_USHORT1:
289 rAny >>= nSet;
290 m_nOffset = nSet;
291 break;
292 case FIELD_PROP_SUBTYPE:
293 switch( static_cast<text::PageNumberType>(SWUnoHelper::GetEnumAsInt32( rAny )) )
295 case text::PageNumberType_CURRENT:
296 m_nSubType = PG_RANDOM;
297 break;
298 case text::PageNumberType_PREV:
299 m_nSubType = PG_PREV;
300 break;
301 case text::PageNumberType_NEXT:
302 m_nSubType = PG_NEXT;
303 break;
304 default:
305 bRet = false;
307 break;
308 case FIELD_PROP_PAR1:
309 rAny >>= m_sUserStr;
310 break;
312 default:
313 assert(false);
315 return bRet;
318 SwAuthorFieldType::SwAuthorFieldType()
319 : SwFieldType( SwFieldIds::Author )
323 OUString SwAuthorFieldType::Expand(sal_uLong nFormat)
325 SwModule* mod = SwModule::get();
326 SvtUserOptions& rOpt = mod->GetUserOptions();
327 if((nFormat & 0xff) == AF_NAME)
329 // Prefer the view's redline author name.
330 // (set in SwXTextDocument::initializeForTiledRendering)
331 std::size_t nAuthor = mod->GetRedlineAuthor();
332 OUString sAuthor = mod->GetRedlineAuthor(nAuthor);
333 if (sAuthor.isEmpty())
334 return rOpt.GetFullName();
336 return sAuthor;
339 return rOpt.GetID();
342 std::unique_ptr<SwFieldType> SwAuthorFieldType::Copy() const
344 return std::make_unique<SwAuthorFieldType>();
347 SwAuthorField::SwAuthorField(SwAuthorFieldType* pTyp, sal_uInt32 nFormat)
348 : SwField(pTyp, nFormat)
350 m_aContent = SwAuthorFieldType::Expand(GetFormat());
353 OUString SwAuthorField::ExpandImpl(SwRootFrame const*const) const
355 if (!IsFixed())
356 const_cast<SwAuthorField*>(this)->m_aContent =
357 SwAuthorFieldType::Expand(GetFormat());
359 return m_aContent;
362 std::unique_ptr<SwField> SwAuthorField::Copy() const
364 std::unique_ptr<SwAuthorField> pTmp(new SwAuthorField( static_cast<SwAuthorFieldType*>(GetTyp()),
365 GetFormat()));
366 pTmp->SetExpansion(m_aContent);
367 return std::unique_ptr<SwField>(pTmp.release());
370 bool SwAuthorField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
372 switch( nWhichId )
374 case FIELD_PROP_BOOL1:
375 rAny <<= (GetFormat() & 0xff) == AF_NAME;
376 break;
378 case FIELD_PROP_BOOL2:
379 rAny <<= IsFixed();
380 break;
382 case FIELD_PROP_PAR1:
383 rAny <<= m_aContent;
384 break;
386 case FIELD_PROP_TITLE:
387 break;
389 default:
390 assert(false);
392 return true;
395 bool SwAuthorField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
397 switch( nWhichId )
399 case FIELD_PROP_BOOL1:
400 SetFormat( *o3tl::doAccess<bool>(rAny) ? AF_NAME : AF_SHORTCUT );
401 break;
403 case FIELD_PROP_BOOL2:
404 if( *o3tl::doAccess<bool>(rAny) )
405 SetFormat( GetFormat() | AF_FIXED);
406 else
407 SetFormat( GetFormat() & ~AF_FIXED);
408 break;
410 case FIELD_PROP_PAR1:
411 rAny >>= m_aContent;
412 break;
414 case FIELD_PROP_TITLE:
415 break;
417 default:
418 assert(false);
420 return true;
423 SwFileNameFieldType::SwFileNameFieldType(SwDoc& rDocument)
424 : SwFieldType( SwFieldIds::Filename )
425 , m_rDoc(rDocument)
429 OUString SwFileNameFieldType::Expand(sal_uLong nFormat) const
431 OUString aRet;
432 const SwDocShell* pDShell = m_rDoc.GetDocShell();
433 if( pDShell && pDShell->HasName() )
435 const INetURLObject& rURLObj = pDShell->GetMedium()->GetURLObject();
436 switch( nFormat & ~FF_FIXED )
438 case FF_PATH:
440 if( INetProtocol::File == rURLObj.GetProtocol() )
442 INetURLObject aTemp(rURLObj);
443 aTemp.removeSegment();
444 // last slash should belong to the pathname
445 aRet = aTemp.PathToFileName();
447 else
449 aRet = URIHelper::removePassword(
450 rURLObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ),
451 INetURLObject::EncodeMechanism::WasEncoded, URL_DECODE );
452 const sal_Int32 nPos = aRet.indexOf(rURLObj.GetLastName( URL_DECODE ));
453 if (nPos>=0)
455 aRet = aRet.copy(0, nPos);
459 break;
461 case FF_NAME:
462 aRet = rURLObj.GetLastName( INetURLObject::DecodeMechanism::WithCharset );
463 break;
465 case FF_NAME_NOEXT:
466 aRet = rURLObj.GetBase();
467 break;
469 default:
470 if( INetProtocol::File == rURLObj.GetProtocol() )
471 aRet = rURLObj.GetFull();
472 else
473 aRet = URIHelper::removePassword(
474 rURLObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ),
475 INetURLObject::EncodeMechanism::WasEncoded, URL_DECODE );
478 return aRet;
481 std::unique_ptr<SwFieldType> SwFileNameFieldType::Copy() const
483 return std::make_unique<SwFileNameFieldType>(m_rDoc);
486 SwFileNameField::SwFileNameField(SwFileNameFieldType* pTyp, sal_uInt32 nFormat)
487 : SwField(pTyp, nFormat)
489 m_aContent = static_cast<SwFileNameFieldType*>(GetTyp())->Expand(GetFormat());
492 OUString SwFileNameField::ExpandImpl(SwRootFrame const*const) const
494 if (!IsFixed())
495 const_cast<SwFileNameField*>(this)->m_aContent = static_cast<SwFileNameFieldType*>(GetTyp())->Expand(GetFormat());
497 return m_aContent;
500 std::unique_ptr<SwField> SwFileNameField::Copy() const
502 std::unique_ptr<SwFileNameField> pTmp(
503 new SwFileNameField(static_cast<SwFileNameFieldType*>(GetTyp()), GetFormat()));
504 pTmp->SetExpansion(m_aContent);
506 return std::unique_ptr<SwField>(pTmp.release());
509 bool SwFileNameField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
511 switch( nWhichId )
513 case FIELD_PROP_FORMAT:
515 sal_Int16 nRet;
516 switch( GetFormat() &(~FF_FIXED) )
518 case FF_PATH:
519 nRet = text::FilenameDisplayFormat::PATH;
520 break;
521 case FF_NAME_NOEXT:
522 nRet = text::FilenameDisplayFormat::NAME;
523 break;
524 case FF_NAME:
525 nRet = text::FilenameDisplayFormat::NAME_AND_EXT;
526 break;
527 default: nRet = text::FilenameDisplayFormat::FULL;
529 rAny <<= nRet;
531 break;
533 case FIELD_PROP_BOOL2:
534 rAny <<= IsFixed();
535 break;
537 case FIELD_PROP_PAR3:
538 rAny <<= m_aContent;
539 break;
541 default:
542 assert(false);
544 return true;
547 bool SwFileNameField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
549 switch( nWhichId )
551 case FIELD_PROP_FORMAT:
553 //JP 24.10.2001: int32 because in UnoField.cxx a putvalue is
554 // called with a int32 value! But normally we need
555 // here only a int16
556 sal_Int32 nType = 0;
557 rAny >>= nType;
558 bool bFixed = IsFixed();
559 switch( nType )
561 case text::FilenameDisplayFormat::PATH:
562 nType = FF_PATH;
563 break;
564 case text::FilenameDisplayFormat::NAME:
565 nType = FF_NAME_NOEXT;
566 break;
567 case text::FilenameDisplayFormat::NAME_AND_EXT:
568 nType = FF_NAME;
569 break;
570 default: nType = FF_PATHNAME;
572 if(bFixed)
573 nType |= FF_FIXED;
574 SetFormat(nType);
576 break;
578 case FIELD_PROP_BOOL2:
579 if( *o3tl::doAccess<bool>(rAny) )
580 SetFormat( GetFormat() | FF_FIXED);
581 else
582 SetFormat( GetFormat() & ~FF_FIXED);
583 break;
585 case FIELD_PROP_PAR3:
586 rAny >>= m_aContent;
587 break;
589 default:
590 assert(false);
592 return true;
595 SwTemplNameFieldType::SwTemplNameFieldType(SwDoc& rDocument)
596 : SwFieldType( SwFieldIds::TemplateName )
597 , m_rDoc(rDocument)
601 OUString SwTemplNameFieldType::Expand(sal_uLong nFormat) const
603 OSL_ENSURE( nFormat < FF_END, "Expand: no valid Format!" );
605 OUString aRet;
606 SwDocShell *pDocShell(m_rDoc.GetDocShell());
607 OSL_ENSURE(pDocShell, "no SwDocShell");
608 if (pDocShell) {
609 uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
610 pDocShell->GetModel(), uno::UNO_QUERY_THROW);
611 uno::Reference<document::XDocumentProperties> xDocProps(
612 xDPS->getDocumentProperties());
613 OSL_ENSURE(xDocProps.is(), "Doc has no DocumentProperties");
615 if( FF_UI_NAME == nFormat )
616 aRet = xDocProps->getTemplateName();
617 else if( !xDocProps->getTemplateURL().isEmpty() )
619 if( FF_UI_RANGE == nFormat )
621 // for getting region names!
622 SfxDocumentTemplates aFac;
623 OUString sTmp;
624 OUString sRegion;
625 aFac.GetLogicNames( xDocProps->getTemplateURL(), sRegion, sTmp );
626 aRet = sRegion;
628 else
630 INetURLObject aPathName( xDocProps->getTemplateURL() );
631 if( FF_NAME == nFormat )
632 aRet = aPathName.GetLastName(URL_DECODE);
633 else if( FF_NAME_NOEXT == nFormat )
634 aRet = aPathName.GetBase();
635 else
637 if( FF_PATH == nFormat )
639 aPathName.removeSegment();
640 aRet = aPathName.GetFull();
642 else
643 aRet = aPathName.GetFull();
648 return aRet;
651 std::unique_ptr<SwFieldType> SwTemplNameFieldType::Copy() const
653 return std::make_unique<SwTemplNameFieldType>(m_rDoc);
656 SwTemplNameField::SwTemplNameField(SwTemplNameFieldType* pTyp, sal_uInt32 nFormat)
657 : SwField(pTyp, nFormat)
660 OUString SwTemplNameField::ExpandImpl(SwRootFrame const*const) const
662 return static_cast<SwTemplNameFieldType*>(GetTyp())->Expand(GetFormat());
665 std::unique_ptr<SwField> SwTemplNameField::Copy() const
667 return std::make_unique<SwTemplNameField>(static_cast<SwTemplNameFieldType*>(GetTyp()), GetFormat());
670 bool SwTemplNameField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
672 switch ( nWhichId )
674 case FIELD_PROP_FORMAT:
676 sal_Int16 nRet;
677 switch( GetFormat() )
679 case FF_PATH: nRet = text::FilenameDisplayFormat::PATH; break;
680 case FF_NAME_NOEXT: nRet = text::FilenameDisplayFormat::NAME; break;
681 case FF_NAME: nRet = text::FilenameDisplayFormat::NAME_AND_EXT; break;
682 case FF_UI_RANGE: nRet = text::TemplateDisplayFormat::AREA; break;
683 case FF_UI_NAME: nRet = text::TemplateDisplayFormat::TITLE; break;
684 default: nRet = text::FilenameDisplayFormat::FULL;
687 rAny <<= nRet;
689 break;
691 default:
692 assert(false);
694 return true;
697 bool SwTemplNameField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
699 switch ( nWhichId )
701 case FIELD_PROP_FORMAT:
703 //JP 24.10.2001: int32 because in UnoField.cxx a putvalue is
704 // called with a int32 value! But normally we need
705 // here only a int16
706 sal_Int32 nType = 0;
707 rAny >>= nType;
708 switch( nType )
710 case text::FilenameDisplayFormat::PATH:
711 SetFormat(FF_PATH);
712 break;
713 case text::FilenameDisplayFormat::NAME:
714 SetFormat(FF_NAME_NOEXT);
715 break;
716 case text::FilenameDisplayFormat::NAME_AND_EXT:
717 SetFormat(FF_NAME);
718 break;
719 case text::TemplateDisplayFormat::AREA :
720 SetFormat(FF_UI_RANGE);
721 break;
722 case text::TemplateDisplayFormat::TITLE :
723 SetFormat(FF_UI_NAME);
724 break;
725 default: SetFormat(FF_PATHNAME);
728 break;
730 default:
731 assert(false);
733 return true;
736 SwDocStatFieldType::SwDocStatFieldType(SwDoc& rDocument)
737 : SwFieldType(SwFieldIds::DocStat)
738 , m_rDoc(rDocument)
739 , m_nNumberingType(SVX_NUM_ARABIC)
743 OUString SwDocStatFieldType::Expand(sal_uInt16 nSubType, SvxNumType nFormat) const
745 sal_uInt32 nVal = 0;
746 const SwDocStat& rDStat = m_rDoc.getIDocumentStatistics().GetDocStat();
747 switch( nSubType )
749 case DS_TBL: nVal = rDStat.nTable; break;
750 case DS_GRF: nVal = rDStat.nGrf; break;
751 case DS_OLE: nVal = rDStat.nOLE; break;
752 case DS_PARA: nVal = rDStat.nPara; break;
753 case DS_WORD: nVal = rDStat.nWord; break;
754 case DS_CHAR: nVal = rDStat.nChar; break;
755 case DS_PAGE:
756 if( m_rDoc.getIDocumentLayoutAccess().GetCurrentLayout() )
757 const_cast<SwDocStat &>(rDStat).nPage = m_rDoc.getIDocumentLayoutAccess().GetCurrentLayout()->GetPageNum();
758 nVal = rDStat.nPage;
759 if( SVX_NUM_PAGEDESC == nFormat )
760 nFormat = m_nNumberingType;
761 break;
762 default:
763 OSL_FAIL( "SwDocStatFieldType::Expand: unknown SubType" );
766 if( nVal <= SHRT_MAX )
767 return FormatNumber( nVal, nFormat );
769 return OUString::number( nVal );
772 std::unique_ptr<SwFieldType> SwDocStatFieldType::Copy() const
774 return std::make_unique<SwDocStatFieldType>(m_rDoc);
778 * @param pTyp
779 * @param nSub SubType
780 * @param nFormat
782 SwDocStatField::SwDocStatField(SwDocStatFieldType* pTyp, sal_uInt16 nSub, sal_uInt32 nFormat)
783 : SwField(pTyp, nFormat),
784 m_nSubType(nSub)
787 OUString SwDocStatField::ExpandImpl(SwRootFrame const*const) const
789 return static_cast<SwDocStatFieldType*>(GetTyp())->Expand(m_nSubType, static_cast<SvxNumType>(GetFormat()));
792 std::unique_ptr<SwField> SwDocStatField::Copy() const
794 return std::make_unique<SwDocStatField>(
795 static_cast<SwDocStatFieldType*>(GetTyp()), m_nSubType, GetFormat() );
798 sal_uInt16 SwDocStatField::GetSubType() const
800 return m_nSubType;
803 void SwDocStatField::SetSubType(sal_uInt16 nSub)
805 m_nSubType = nSub;
808 void SwDocStatField::ChangeExpansion( const SwFrame* pFrame )
810 if( DS_PAGE == m_nSubType && SVX_NUM_PAGEDESC == GetFormat() )
811 static_cast<SwDocStatFieldType*>(GetTyp())->SetNumFormat(
812 pFrame->FindPageFrame()->GetPageDesc()->GetNumType().GetNumberingType() );
815 bool SwDocStatField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
817 switch ( nWhichId )
819 case FIELD_PROP_USHORT2:
820 rAny <<= static_cast<sal_Int16>(GetFormat());
821 break;
823 default:
824 assert(false);
826 return true;
829 bool SwDocStatField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
831 bool bRet = false;
832 switch ( nWhichId )
834 case FIELD_PROP_USHORT2:
836 sal_Int16 nSet = 0;
837 rAny >>= nSet;
838 if(nSet <= SVX_NUM_CHARS_LOWER_LETTER_N &&
839 nSet != SVX_NUM_CHAR_SPECIAL &&
840 nSet != SVX_NUM_BITMAP)
842 SetFormat(nSet);
843 bRet = true;
846 break;
848 default:
849 assert(false);
851 return bRet;
854 // Document info field type
856 SwDocInfoFieldType::SwDocInfoFieldType(SwDoc* pDc)
857 : SwValueFieldType( pDc, SwFieldIds::DocInfo )
861 std::unique_ptr<SwFieldType> SwDocInfoFieldType::Copy() const
863 return std::make_unique<SwDocInfoFieldType>(GetDoc());
866 static void lcl_GetLocalDataWrapper( LanguageType nLang,
867 const LocaleDataWrapper **ppAppLocalData,
868 const LocaleDataWrapper **ppLocalData )
870 SvtSysLocale aLocale;
871 *ppAppLocalData = &aLocale.GetLocaleData();
872 *ppLocalData = *ppAppLocalData;
873 if( nLang != (*ppLocalData)->getLanguageTag().getLanguageType() )
874 *ppLocalData = new LocaleDataWrapper(LanguageTag( nLang ));
877 OUString SwDocInfoFieldType::Expand( sal_uInt16 nSub, sal_uInt32 nFormat,
878 LanguageType nLang, const OUString& rName ) const
880 const LocaleDataWrapper *pAppLocalData = nullptr, *pLocalData = nullptr;
881 SwDocShell *pDocShell(GetDoc()->GetDocShell());
882 OSL_ENSURE(pDocShell, "no SwDocShell");
883 if (!pDocShell) { return OUString(); }
885 uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
886 pDocShell->GetModel(), uno::UNO_QUERY_THROW);
887 uno::Reference<document::XDocumentProperties> xDocProps(
888 xDPS->getDocumentProperties());
889 OSL_ENSURE(xDocProps.is(), "Doc has no DocumentProperties");
891 sal_uInt16 nExtSub = nSub & 0xff00;
892 nSub &= 0xff; // do not consider extended SubTypes
894 OUString aStr;
895 switch(nSub)
897 case DI_TITLE: aStr = xDocProps->getTitle(); break;
898 case DI_SUBJECT:aStr = xDocProps->getSubject(); break;
899 case DI_KEYS: aStr = ::comphelper::string::convertCommaSeparated(
900 xDocProps->getKeywords());
901 break;
902 case DI_COMMENT:aStr = xDocProps->getDescription(); break;
903 case DI_DOCNO: aStr = OUString::number(
904 xDocProps->getEditingCycles() );
905 break;
906 case DI_EDIT:
907 if ( !nFormat )
909 lcl_GetLocalDataWrapper( nLang, &pAppLocalData, &pLocalData );
910 sal_Int32 dur = xDocProps->getEditingDuration();
911 // If Seconds > 0 then bSec should be TRUE otherwise Seconds
912 // information will be lost if file has EditTime in Seconds format.
913 aStr = pLocalData->getTime( tools::Time(dur/3600, (dur%3600)/60, dur%60),
914 dur%60 > 0);
916 else
918 sal_Int32 dur = xDocProps->getEditingDuration();
919 double fVal = tools::Time(dur/3600, (dur%3600)/60, dur%60).GetTimeInDays();
920 aStr = ExpandValue(fVal, nFormat, nLang);
922 break;
923 case DI_CUSTOM:
925 OUString sVal;
928 uno::Any aAny;
929 uno::Reference < beans::XPropertySet > xSet(
930 xDocProps->getUserDefinedProperties(),
931 uno::UNO_QUERY_THROW);
932 aAny = xSet->getPropertyValue( rName );
934 uno::Reference < script::XTypeConverter > xConverter( script::Converter::create(comphelper::getProcessComponentContext()) );
935 uno::Any aNew = xConverter->convertToSimpleType( aAny, uno::TypeClass_STRING );
936 aNew >>= sVal;
938 catch (uno::Exception&) {}
939 return sVal;
942 default:
944 OUString aName( xDocProps->getAuthor() );
945 util::DateTime uDT( xDocProps->getCreationDate() );
946 DateTime aDate(uDT);
947 if( nSub == DI_CREATE )
948 ; // that's it !!
949 else if( nSub == DI_CHANGE )
951 aName = xDocProps->getModifiedBy();
952 uDT = xDocProps->getModificationDate();
953 aDate = DateTime(uDT);
955 else if( nSub == DI_PRINT )
957 aName = xDocProps->getPrintedBy();
958 if ( !std::getenv("STABLE_FIELDS_HACK") )
960 uDT = xDocProps->getPrintDate();
961 aDate = DateTime(uDT);
964 else
965 break;
967 if (aDate.IsValidAndGregorian())
969 switch (nExtSub & ~DI_SUB_FIXED)
971 case DI_SUB_AUTHOR:
972 aStr = aName;
973 break;
975 case DI_SUB_TIME:
976 if (!nFormat)
978 lcl_GetLocalDataWrapper( nLang, &pAppLocalData,
979 &pLocalData );
980 aStr = pLocalData->getTime( aDate,
981 false);
983 else
985 // start the number formatter
986 double fVal = SwDateTimeField::GetDateTime( *GetDoc(),
987 aDate);
988 aStr = ExpandValue(fVal, nFormat, nLang);
990 break;
992 case DI_SUB_DATE:
993 if (!nFormat)
995 lcl_GetLocalDataWrapper( nLang, &pAppLocalData,
996 &pLocalData );
997 aStr = pLocalData->getDate( aDate );
999 else
1001 // start the number formatter
1002 double fVal = SwDateTimeField::GetDateTime( *GetDoc(),
1003 aDate);
1004 aStr = ExpandValue(fVal, nFormat, nLang);
1006 break;
1010 break;
1013 if( pAppLocalData != pLocalData )
1014 delete pLocalData;
1016 return aStr;
1019 // document info field
1021 SwDocInfoField::SwDocInfoField(SwDocInfoFieldType* pTyp, sal_uInt16 nSub, const OUString& rName, sal_uInt32 nFormat) :
1022 SwValueField(pTyp, nFormat), m_nSubType(nSub)
1024 m_aName = rName;
1025 m_aContent = static_cast<SwDocInfoFieldType*>(GetTyp())->Expand(m_nSubType, nFormat, GetLanguage(), m_aName);
1028 SwDocInfoField::SwDocInfoField(SwDocInfoFieldType* pTyp, sal_uInt16 nSub, const OUString& rName, const OUString& rValue, sal_uInt32 nFormat) :
1029 SwValueField(pTyp, nFormat), m_nSubType(nSub)
1031 m_aName = rName;
1032 m_aContent = rValue;
1035 template<class T>
1036 static double lcl_TimeToDouble( const T& rTime )
1038 const double fNanoSecondsPerDay = 86400000000000.0;
1039 return ( (rTime.Hours * SAL_CONST_INT64(3600000000000))
1040 + (rTime.Minutes * SAL_CONST_INT64( 60000000000))
1041 + (rTime.Seconds * SAL_CONST_INT64( 1000000000))
1042 + (rTime.NanoSeconds))
1043 / fNanoSecondsPerDay;
1046 template<class D>
1047 static double lcl_DateToDouble( const D& rDate, const Date& rNullDate )
1049 tools::Long nDate = Date::DateToDays( rDate.Day, rDate.Month, rDate.Year );
1050 tools::Long nNullDate = Date::DateToDays( rNullDate.GetDay(), rNullDate.GetMonth(), rNullDate.GetYear() );
1051 return double( nDate - nNullDate );
1054 OUString SwDocInfoField::ExpandImpl(SwRootFrame const*const) const
1056 if ( ( m_nSubType & 0xFF ) == DI_CUSTOM )
1058 // custom properties currently need special treatment
1059 // We don't have a secure way to detect "real" custom properties in Word import of text
1060 // fields, so we treat *every* unknown property as a custom property, even the "built-in"
1061 // section in Word's document summary information stream as these properties have not been
1062 // inserted when the document summary information was imported, we do it here.
1063 // This approach is still a lot better than the old one to import such fields as
1064 // "user fields" and simple text
1065 SwDocShell* pDocShell = GetDoc()->GetDocShell();
1066 if( !pDocShell )
1067 return m_aContent;
1070 uno::Reference<document::XDocumentPropertiesSupplier> xDPS( pDocShell->GetModel(), uno::UNO_QUERY_THROW);
1071 uno::Reference<document::XDocumentProperties> xDocProps( xDPS->getDocumentProperties());
1072 uno::Reference < beans::XPropertySet > xSet( xDocProps->getUserDefinedProperties(), uno::UNO_QUERY_THROW);
1073 uno::Reference < beans::XPropertySetInfo > xSetInfo = xSet->getPropertySetInfo();
1075 uno::Any aAny;
1076 if( xSetInfo->hasPropertyByName( m_aName ) )
1077 aAny = xSet->getPropertyValue( m_aName );
1078 if ( aAny.getValueType() != cppu::UnoType<void>::get() )
1080 // "void" type means that the property has not been inserted until now
1081 if ( !IsFixed() )
1083 // if the field is "fixed" we don't update it from the property
1084 OUString sVal;
1085 uno::Reference < script::XTypeConverter > xConverter( script::Converter::create(comphelper::getProcessComponentContext()) );
1086 util::Date aDate;
1087 util::DateTime aDateTime;
1088 util::Duration aDuration;
1089 if( aAny >>= aDate)
1091 SvNumberFormatter* pFormatter = pDocShell->GetDoc()->GetNumberFormatter();
1092 const Date& rNullDate = pFormatter->GetNullDate();
1093 sVal = ExpandValue( lcl_DateToDouble<util::Date>( aDate, rNullDate ), GetFormat(), GetLanguage());
1095 else if( aAny >>= aDateTime )
1097 double fDateTime = lcl_TimeToDouble<util::DateTime>( aDateTime );
1098 SvNumberFormatter* pFormatter = pDocShell->GetDoc()->GetNumberFormatter();
1099 const Date& rNullDate = pFormatter->GetNullDate();
1100 fDateTime += lcl_DateToDouble<util::DateTime>( aDateTime, rNullDate );
1101 sVal = ExpandValue( fDateTime, GetFormat(), GetLanguage());
1103 else if( aAny >>= aDuration )
1105 sVal = OUStringChar(aDuration.Negative ? '-' : '+')
1106 + SwViewShell::GetShellRes()->sDurationFormat;
1107 sVal = sVal.replaceFirst("%1", OUString::number( aDuration.Years ) );
1108 sVal = sVal.replaceFirst("%2", OUString::number( aDuration.Months ) );
1109 sVal = sVal.replaceFirst("%3", OUString::number( aDuration.Days ) );
1110 sVal = sVal.replaceFirst("%4", OUString::number( aDuration.Hours ) );
1111 sVal = sVal.replaceFirst("%5", OUString::number( aDuration.Minutes) );
1112 sVal = sVal.replaceFirst("%6", OUString::number( aDuration.Seconds) );
1114 else
1116 uno::Any aNew = xConverter->convertToSimpleType( aAny, uno::TypeClass_STRING );
1117 aNew >>= sVal;
1119 const_cast<SwDocInfoField*>(this)->m_aContent = sVal;
1123 catch (uno::Exception&) {}
1125 else if ( !IsFixed() )
1126 const_cast<SwDocInfoField*>(this)->m_aContent = static_cast<SwDocInfoFieldType*>(GetTyp())->Expand(m_nSubType, GetFormat(), GetLanguage(), m_aName);
1128 return m_aContent;
1131 OUString SwDocInfoField::GetFieldName() const
1133 OUString aStr(SwFieldType::GetTypeStr(GetTypeId()) + ":");
1135 sal_uInt16 const nSub = m_nSubType & 0xff;
1137 switch (nSub)
1139 case DI_CUSTOM:
1140 aStr += m_aName;
1141 break;
1143 default:
1144 aStr += SwViewShell::GetShellRes()
1145 ->aDocInfoLst[ nSub - DI_SUBTYPE_BEGIN ];
1146 break;
1148 if (IsFixed())
1150 aStr += " " + SwViewShell::GetShellRes()->aFixedStr;
1152 return aStr;
1155 std::unique_ptr<SwField> SwDocInfoField::Copy() const
1157 std::unique_ptr<SwDocInfoField> pField(new SwDocInfoField(static_cast<SwDocInfoFieldType*>(GetTyp()), m_nSubType, m_aName, GetFormat()));
1158 pField->SetAutomaticLanguage(IsAutomaticLanguage());
1159 pField->m_aContent = m_aContent;
1161 return std::unique_ptr<SwField>(pField.release());
1164 sal_uInt16 SwDocInfoField::GetSubType() const
1166 return m_nSubType;
1169 void SwDocInfoField::SetSubType(sal_uInt16 nSub)
1171 m_nSubType = nSub;
1174 void SwDocInfoField::SetLanguage(LanguageType nLng)
1176 if (!GetFormat())
1177 SwField::SetLanguage(nLng);
1178 else
1179 SwValueField::SetLanguage(nLng);
1182 bool SwDocInfoField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
1184 switch( nWhichId )
1186 case FIELD_PROP_PAR1:
1187 rAny <<= m_aContent;
1188 break;
1190 case FIELD_PROP_PAR4:
1191 rAny <<= m_aName;
1192 break;
1194 case FIELD_PROP_USHORT1:
1195 rAny <<= static_cast<sal_Int16>(m_aContent.toInt32());
1196 break;
1198 case FIELD_PROP_BOOL1:
1199 rAny <<= 0 != (m_nSubType & DI_SUB_FIXED);
1200 break;
1202 case FIELD_PROP_FORMAT:
1203 rAny <<= static_cast<sal_Int32>(GetFormat());
1204 break;
1206 case FIELD_PROP_DOUBLE:
1208 double fVal = GetValue();
1209 rAny <<= fVal;
1211 break;
1212 case FIELD_PROP_PAR3:
1213 rAny <<= ExpandImpl(nullptr);
1214 break;
1215 case FIELD_PROP_BOOL2:
1217 sal_uInt16 nExtSub = (m_nSubType & 0xff00) & ~DI_SUB_FIXED;
1218 rAny <<= nExtSub == DI_SUB_DATE;
1220 break;
1221 default:
1222 return SwField::QueryValue(rAny, nWhichId);
1224 return true;
1227 bool SwDocInfoField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
1229 sal_Int32 nValue = 0;
1230 switch( nWhichId )
1232 case FIELD_PROP_PAR1:
1233 if( m_nSubType & DI_SUB_FIXED )
1234 rAny >>= m_aContent;
1235 break;
1237 case FIELD_PROP_USHORT1:
1238 if( m_nSubType & DI_SUB_FIXED )
1240 rAny >>= nValue;
1241 m_aContent = OUString::number(nValue);
1243 break;
1245 case FIELD_PROP_BOOL1:
1246 if(*o3tl::doAccess<bool>(rAny))
1247 m_nSubType |= DI_SUB_FIXED;
1248 else
1249 m_nSubType &= ~DI_SUB_FIXED;
1250 break;
1251 case FIELD_PROP_FORMAT:
1253 rAny >>= nValue;
1254 if( nValue >= 0)
1255 SetFormat(nValue);
1257 break;
1259 case FIELD_PROP_PAR3:
1260 rAny >>= m_aContent;
1261 break;
1262 case FIELD_PROP_BOOL2:
1263 m_nSubType &= 0xf0ff;
1264 if(*o3tl::doAccess<bool>(rAny))
1265 m_nSubType |= DI_SUB_DATE;
1266 else
1267 m_nSubType |= DI_SUB_TIME;
1268 break;
1269 default:
1270 return SwField::PutValue(rAny, nWhichId);
1272 return true;
1275 SwHiddenTextFieldType::SwHiddenTextFieldType( bool bSetHidden )
1276 : SwFieldType( SwFieldIds::HiddenText ), m_bHidden( bSetHidden )
1280 std::unique_ptr<SwFieldType> SwHiddenTextFieldType::Copy() const
1282 return std::make_unique<SwHiddenTextFieldType>( m_bHidden );
1285 void SwHiddenTextFieldType::SetHiddenFlag( bool bSetHidden )
1287 if( m_bHidden != bSetHidden )
1289 m_bHidden = bSetHidden;
1290 UpdateFields(); // notify all HiddenTexts
1294 SwHiddenTextField::SwHiddenTextField( SwHiddenTextFieldType* pFieldType,
1295 bool bConditional,
1296 OUString aCond,
1297 const OUString& rStr,
1298 bool bHidden,
1299 SwFieldTypesEnum nSub) :
1300 SwField( pFieldType ), m_aCond(std::move(aCond)), m_nSubType(nSub),
1301 m_bCanToggle(bConditional), m_bIsHidden(bHidden), m_bValid(false)
1303 if(m_nSubType == SwFieldTypesEnum::ConditionalText)
1305 sal_Int32 nPos = 0;
1306 m_aTRUEText = rStr.getToken(0, '|', nPos);
1308 if(nPos != -1)
1310 m_aFALSEText = rStr.getToken(0, '|', nPos);
1311 if(nPos != -1)
1313 m_aContent = rStr.getToken(0, '|', nPos);
1314 m_bValid = true;
1318 else
1319 m_aTRUEText = rStr;
1322 SwHiddenTextField::SwHiddenTextField( SwHiddenTextFieldType* pFieldType,
1323 OUString aCond,
1324 OUString aTrue,
1325 OUString aFalse,
1326 SwFieldTypesEnum nSub)
1327 : SwField( pFieldType ), m_aTRUEText(std::move(aTrue)), m_aFALSEText(std::move(aFalse)), m_aCond(std::move(aCond)), m_nSubType(nSub),
1328 m_bIsHidden(true), m_bValid(false)
1330 m_bCanToggle = !m_aCond.isEmpty();
1333 OUString SwHiddenTextField::ExpandImpl(SwRootFrame const*const) const
1335 // Type: !Hidden -> show always
1336 // Hide -> evaluate condition
1338 if( SwFieldTypesEnum::ConditionalText == m_nSubType )
1340 if( m_bValid )
1341 return m_aContent;
1343 if( m_bCanToggle && !m_bIsHidden )
1344 return m_aTRUEText;
1346 else if( !static_cast<SwHiddenTextFieldType*>(GetTyp())->GetHiddenFlag() ||
1347 ( m_bCanToggle && m_bIsHidden ))
1348 return m_aTRUEText;
1350 return m_aFALSEText;
1353 /// get current field value and cache it
1354 void SwHiddenTextField::Evaluate(SwDoc& rDoc)
1356 if( SwFieldTypesEnum::ConditionalText != m_nSubType )
1357 return;
1359 #if !HAVE_FEATURE_DBCONNECTIVITY || ENABLE_FUZZERS
1360 (void) rDoc;
1361 #else
1362 SwDBManager* pMgr = rDoc.GetDBManager();
1363 #endif
1364 m_bValid = false;
1365 OUString sTmpName = (m_bCanToggle && !m_bIsHidden) ? m_aTRUEText : m_aFALSEText;
1367 // Database expressions need to be different from normal text. Therefore, normal text is set
1368 // in quotes. If the latter exist they will be removed. If not, check if potential DB name.
1369 // Only if there are two or more dots and no quotes, we assume a database.
1370 if (sTmpName.getLength()>1 &&
1371 sTmpName.startsWith("\"") &&
1372 sTmpName.endsWith("\""))
1374 m_aContent = sTmpName.copy(1, sTmpName.getLength() - 2);
1375 m_bValid = true;
1377 else if(sTmpName.indexOf('\"')<0 &&
1378 comphelper::string::getTokenCount(sTmpName, '.') > 2)
1380 sTmpName = ::ReplacePoint(sTmpName);
1381 if(sTmpName.startsWith("[") && sTmpName.endsWith("]"))
1382 { // remove brackets
1383 sTmpName = sTmpName.copy(1, sTmpName.getLength() - 2);
1385 #if HAVE_FEATURE_DBCONNECTIVITY && !ENABLE_FUZZERS
1386 if( pMgr)
1388 sal_Int32 nIdx{ 0 };
1389 OUString sDBName( GetDBName( sTmpName, rDoc ));
1390 OUString sDataSource(sDBName.getToken(0, DB_DELIM, nIdx));
1391 OUString sDataTableOrQuery(sDBName.getToken(0, DB_DELIM, nIdx));
1392 if( pMgr->IsInMerge() && !sDBName.isEmpty() &&
1393 pMgr->IsDataSourceOpen( sDataSource,
1394 sDataTableOrQuery, false))
1396 double fNumber;
1397 pMgr->GetMergeColumnCnt(GetColumnName( sTmpName ),
1398 GetLanguage(), m_aContent, &fNumber );
1399 m_bValid = true;
1402 #endif
1406 OUString SwHiddenTextField::GetFieldName() const
1408 OUString aStr = SwFieldType::GetTypeStr(m_nSubType) +
1409 " " + m_aCond + " " + m_aTRUEText;
1411 if (m_nSubType == SwFieldTypesEnum::ConditionalText)
1413 aStr += " : " + m_aFALSEText;
1415 return aStr;
1418 std::unique_ptr<SwField> SwHiddenTextField::Copy() const
1420 std::unique_ptr<SwHiddenTextField> pField(
1421 new SwHiddenTextField(static_cast<SwHiddenTextFieldType*>(GetTyp()), m_aCond,
1422 m_aTRUEText, m_aFALSEText));
1423 pField->m_bIsHidden = m_bIsHidden;
1424 pField->m_bValid = m_bValid;
1425 pField->m_aContent = m_aContent;
1426 pField->SetFormat(GetFormat());
1427 pField->m_nSubType = m_nSubType;
1428 return std::unique_ptr<SwField>(pField.release());
1431 /// set condition
1432 void SwHiddenTextField::SetPar1(const OUString& rStr)
1434 m_aCond = rStr;
1435 m_bCanToggle = !m_aCond.isEmpty();
1438 OUString SwHiddenTextField::GetPar1() const
1440 return m_aCond;
1443 /// set True/False text
1444 void SwHiddenTextField::SetPar2(const OUString& rStr)
1446 if (m_nSubType == SwFieldTypesEnum::ConditionalText)
1448 sal_Int32 nPos = rStr.indexOf('|');
1449 if (nPos == -1)
1450 m_aTRUEText = rStr;
1451 else
1453 m_aTRUEText = rStr.copy(0, nPos);
1454 m_aFALSEText = rStr.copy(nPos + 1);
1457 else
1458 m_aTRUEText = rStr;
1461 /// get True/False text
1462 OUString SwHiddenTextField::GetPar2() const
1464 if(m_nSubType != SwFieldTypesEnum::ConditionalText)
1466 return m_aTRUEText;
1468 return m_aTRUEText + "|" + m_aFALSEText;
1471 sal_uInt16 SwHiddenTextField::GetSubType() const
1473 return static_cast<sal_uInt16>(m_nSubType);
1476 bool SwHiddenTextField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
1478 switch( nWhichId )
1480 case FIELD_PROP_PAR1:
1481 rAny <<= m_aCond;
1482 break;
1483 case FIELD_PROP_PAR2:
1484 rAny <<= m_aTRUEText;
1485 break;
1486 case FIELD_PROP_PAR3:
1487 rAny <<= m_aFALSEText;
1488 break;
1489 case FIELD_PROP_PAR4 :
1490 rAny <<= m_aContent;
1491 break;
1492 case FIELD_PROP_BOOL1:
1493 rAny <<= m_bIsHidden;
1494 break;
1495 default:
1496 assert(false);
1498 return true;
1501 bool SwHiddenTextField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
1503 switch( nWhichId )
1505 case FIELD_PROP_PAR1:
1507 OUString sVal;
1508 rAny >>= sVal;
1509 SetPar1(sVal);
1511 break;
1512 case FIELD_PROP_PAR2:
1513 rAny >>= m_aTRUEText;
1514 break;
1515 case FIELD_PROP_PAR3:
1516 rAny >>= m_aFALSEText;
1517 break;
1518 case FIELD_PROP_BOOL1:
1519 m_bIsHidden = *o3tl::doAccess<bool>(rAny);
1520 break;
1521 case FIELD_PROP_PAR4:
1522 rAny >>= m_aContent;
1523 m_bValid = true;
1524 break;
1525 default:
1526 assert(false);
1528 return true;
1531 OUString SwHiddenTextField::GetColumnName(const OUString& rName)
1533 sal_Int32 nPos = rName.indexOf(DB_DELIM);
1534 if( nPos>=0 )
1536 nPos = rName.indexOf(DB_DELIM, nPos + 1);
1538 if( nPos>=0 )
1539 return rName.copy(nPos + 1);
1541 return rName;
1544 OUString SwHiddenTextField::GetDBName(std::u16string_view rName, SwDoc& rDoc)
1546 size_t nPos = rName.find(DB_DELIM);
1547 if( nPos != std::u16string_view::npos )
1549 nPos = rName.find(DB_DELIM, nPos + 1);
1551 if( nPos != std::u16string_view::npos )
1552 return OUString(rName.substr(0, nPos));
1555 SwDBData aData = rDoc.GetDBData();
1556 return aData.sDataSource + OUStringChar(DB_DELIM) + aData.sCommand;
1559 // [aFieldDefinition] value sample : " IF A == B \"TrueText\" \"FalseText\""
1560 void SwHiddenTextField::ParseIfFieldDefinition(std::u16string_view aFieldDefinition,
1561 OUString& rCondition,
1562 OUString& rTrue,
1563 OUString& rFalse)
1565 // get all positions inside the input string where words are started
1567 // In: " IF A == B \"TrueText\" \"FalseText\""
1568 // 0 1 2 3
1569 // 01234567890 123456789 01 2345678901 2
1571 // result:
1572 // [1, 4, 6, 9, 11, 22]
1573 std::vector<sal_Int32> wordPosition;
1575 bool quoted = false;
1576 bool insideWord = false;
1577 for (size_t i = 0; i < aFieldDefinition.size(); i++)
1579 if (quoted)
1581 if (aFieldDefinition[i] == '\"')
1583 quoted = false;
1584 insideWord = false;
1587 else
1589 if (aFieldDefinition[i] == ' ')
1591 // word delimiter
1592 insideWord = false;
1594 else
1596 if (insideWord)
1598 quoted = (aFieldDefinition[i] == '\"');
1600 else
1602 insideWord = true;
1603 wordPosition.push_back(i);
1604 quoted = (aFieldDefinition[i] == '\"');
1611 // first word is always "IF"
1612 // last two words are: true-case and false-case,
1613 // everything before is treated as condition expression
1614 // => we need at least 4 words to be inside the input string
1615 if (wordPosition.size() < 4)
1617 return;
1621 const sal_Int32 conditionBegin = wordPosition[1];
1622 const sal_Int32 trueBegin = wordPosition[wordPosition.size() - 2];
1623 const sal_Int32 falseBegin = wordPosition[wordPosition.size() - 1];
1625 const sal_Int32 conditionLength = trueBegin - conditionBegin;
1626 const sal_Int32 trueLength = falseBegin - trueBegin;
1628 // Syntax
1629 // OUString::copy( sal_Int32 beginIndex, sal_Int32 count )
1630 rCondition = o3tl::trim(aFieldDefinition.substr(conditionBegin, conditionLength));
1631 rTrue = o3tl::trim(aFieldDefinition.substr(trueBegin, trueLength));
1632 rFalse = o3tl::trim(aFieldDefinition.substr(falseBegin));
1634 // remove quotes
1635 if (rCondition.getLength() >= 2)
1637 if (rCondition[0] == '\"' && rCondition[rCondition.getLength() - 1] == '\"')
1638 rCondition = rCondition.copy(1, rCondition.getLength() - 2);
1640 if (rTrue.getLength() >= 2)
1642 if (rTrue[0] == '\"' && rTrue[rTrue.getLength() - 1] == '\"')
1643 rTrue = rTrue.copy(1, rTrue.getLength() - 2);
1645 if (rFalse.getLength() >= 2)
1647 if (rFalse[0] == '\"' && rFalse[rFalse.getLength() - 1] == '\"')
1648 rFalse = rFalse.copy(1, rFalse.getLength() - 2);
1651 // Note: do not make trim once again, while this is a user defined data
1654 // field type for line height 0
1656 SwHiddenParaFieldType::SwHiddenParaFieldType()
1657 : SwFieldType( SwFieldIds::HiddenPara )
1661 std::unique_ptr<SwFieldType> SwHiddenParaFieldType::Copy() const
1663 return std::make_unique<SwHiddenParaFieldType>();
1666 // field for line height 0
1668 SwHiddenParaField::SwHiddenParaField(SwHiddenParaFieldType* pTyp, OUString aStr)
1669 : SwField(pTyp), m_aCond(std::move(aStr))
1671 m_bIsHidden = false;
1674 OUString SwHiddenParaField::ExpandImpl(SwRootFrame const*const) const
1676 return OUString();
1679 std::unique_ptr<SwField> SwHiddenParaField::Copy() const
1681 std::unique_ptr<SwHiddenParaField> pField(new SwHiddenParaField(static_cast<SwHiddenParaFieldType*>(GetTyp()), m_aCond));
1682 pField->m_bIsHidden = m_bIsHidden;
1683 return std::unique_ptr<SwField>(pField.release());
1686 bool SwHiddenParaField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
1688 switch ( nWhichId )
1690 case FIELD_PROP_PAR1:
1691 rAny <<= m_aCond;
1692 break;
1693 case FIELD_PROP_BOOL1:
1694 rAny <<= m_bIsHidden;
1695 break;
1697 default:
1698 assert(false);
1700 return true;
1703 bool SwHiddenParaField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
1705 switch ( nWhichId )
1707 case FIELD_PROP_PAR1:
1708 rAny >>= m_aCond;
1709 break;
1710 case FIELD_PROP_BOOL1:
1711 m_bIsHidden = *o3tl::doAccess<bool>(rAny);
1712 break;
1714 default:
1715 assert(false);
1717 return true;
1720 /// set condition
1721 void SwHiddenParaField::SetPar1(const OUString& rStr)
1723 m_aCond = rStr;
1726 OUString SwHiddenParaField::GetPar1() const
1728 return m_aCond;
1731 // PostIt field type
1733 SwPostItFieldType::SwPostItFieldType(SwDoc& rDoc)
1734 : SwFieldType( SwFieldIds::Postit )
1735 , mrDoc(rDoc)
1738 std::unique_ptr<SwFieldType> SwPostItFieldType::Copy() const
1740 return std::make_unique<SwPostItFieldType>(mrDoc);
1743 // PostIt field
1745 sal_uInt32 SwPostItField::s_nLastPostItId = 1;
1747 SwPostItField::SwPostItField( SwPostItFieldType* pT,
1748 OUString aAuthor,
1749 OUString aText,
1750 OUString aInitials,
1751 OUString aName,
1752 const DateTime& rDateTime,
1753 const bool bResolved,
1754 const sal_uInt32 nPostItId,
1755 const sal_uInt32 nParentId,
1756 const sal_uInt32 nParaId,
1757 const sal_uInt32 nParentPostItId,
1758 OUString aParentName
1760 : SwField( pT )
1761 , m_sText( std::move(aText) )
1762 , m_sAuthor( std::move(aAuthor) )
1763 , m_sInitials( std::move(aInitials) )
1764 , m_sName( std::move(aName) )
1765 , m_aDateTime( rDateTime )
1766 , m_bResolved( bResolved )
1767 , m_nParentId( nParentId )
1768 , m_nParaId( nParaId )
1769 , m_nParentPostItId ( nParentPostItId )
1770 , m_sParentName( std::move(aParentName) )
1772 m_nPostItId = nPostItId == 0 ? s_nLastPostItId++ : nPostItId;
1775 SwPostItField::~SwPostItField()
1777 if ( m_xTextObject.is() )
1779 m_xTextObject->DisposeEditSource();
1782 mpText.reset();
1785 OUString SwPostItField::ExpandImpl(SwRootFrame const*const) const
1787 return OUString();
1790 OUString SwPostItField::GetDescription() const
1792 return SwResId(STR_NOTE);
1795 void SwPostItField::SetResolved(bool bNewState)
1797 m_bResolved = bNewState;
1800 void SwPostItField::ToggleResolved()
1802 m_bResolved = !m_bResolved;
1805 bool SwPostItField::GetResolved() const
1807 return m_bResolved;
1810 std::unique_ptr<SwField> SwPostItField::Copy() const
1812 std::unique_ptr<SwPostItField> pRet(new SwPostItField( static_cast<SwPostItFieldType*>(GetTyp()), m_sAuthor, m_sText, m_sInitials, m_sName,
1813 m_aDateTime, m_bResolved, m_nPostItId, m_nParentId, m_nParaId, m_nParentPostItId, m_sParentName));
1814 if (mpText)
1815 pRet->SetTextObject( *mpText );
1817 // Note: member <m_xTextObject> not copied.
1819 return std::unique_ptr<SwField>(pRet.release());
1822 /// set author
1823 void SwPostItField::SetPar1(const OUString& rStr)
1825 m_sAuthor = rStr;
1828 /// get author
1829 OUString SwPostItField::GetPar1() const
1831 return m_sAuthor;
1834 /// set the PostIt's text
1835 void SwPostItField::SetPar2(const OUString& rStr)
1837 m_sText = rStr;
1840 /// get the PostIt's text
1841 OUString SwPostItField::GetPar2() const
1843 return m_sText;
1847 void SwPostItField::SetName(const OUString& rName)
1849 m_sName = rName;
1852 void SwPostItField::SetParentName(const OUString& rName)
1854 m_sParentName = rName;
1857 void SwPostItField::SetTextObject( std::optional<OutlinerParaObject> pText )
1859 mpText = std::move(pText);
1862 sal_Int32 SwPostItField::GetNumberOfParagraphs() const
1864 return mpText ? mpText->Count() : 1;
1867 void SwPostItField::ChangeStyleSheetName(std::u16string_view rOldName, const SfxStyleSheetBase* pStyleSheet)
1869 if (mpText && pStyleSheet)
1870 mpText->ChangeStyleSheetName(pStyleSheet->GetFamily(), rOldName, pStyleSheet->GetName());
1873 void SwPostItField::SetPostItId(const sal_uInt32 nPostItId)
1875 m_nPostItId = nPostItId == 0 ? s_nLastPostItId++ : nPostItId;
1878 void SwPostItField::SetParentPostItId(const sal_uInt32 nParentPostItId)
1880 m_nParentPostItId = nParentPostItId;
1883 void SwPostItField::SetParentId(const sal_uInt32 nParentId)
1885 m_nParentId = nParentId;
1888 void SwPostItField::SetParaId(const sal_uInt32 nParaId)
1890 m_nParaId = nParaId;
1893 bool SwPostItField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
1895 switch( nWhichId )
1897 case FIELD_PROP_PAR1:
1898 rAny <<= m_sAuthor;
1899 break;
1900 case FIELD_PROP_PAR2:
1902 rAny <<= m_sText;
1903 break;
1905 case FIELD_PROP_PAR3:
1906 rAny <<= m_sInitials;
1907 break;
1908 case FIELD_PROP_PAR4:
1909 rAny <<= m_sName;
1910 break;
1911 case FIELD_PROP_PAR7: // PAR5 (Parent Para Id) and PAR6 (Para Id) are skipped - they are not written into xml. Used for file conversion.
1912 rAny <<= m_sParentName;
1913 break;
1914 case FIELD_PROP_BOOL1:
1915 rAny <<= m_bResolved;
1916 break;
1917 case FIELD_PROP_TEXT:
1919 if ( !m_xTextObject.is() )
1921 SwPostItFieldType* pGetType = static_cast<SwPostItFieldType*>(GetTyp());
1922 SwDoc& rDoc = pGetType->GetDoc();
1923 auto pObj = std::make_unique<SwTextAPIEditSource>( &rDoc );
1924 const_cast <SwPostItField*> (this)->m_xTextObject = new SwTextAPIObject( std::move(pObj) );
1927 if ( mpText )
1928 m_xTextObject->SetText( *mpText );
1929 else
1930 m_xTextObject->SetString( m_sText );
1932 uno::Reference < text::XText > xText( m_xTextObject );
1933 rAny <<= xText;
1934 break;
1936 case FIELD_PROP_DATE:
1938 rAny <<= m_aDateTime.GetUNODate();
1940 break;
1941 case FIELD_PROP_DATE_TIME:
1943 rAny <<= m_aDateTime.GetUNODateTime();
1945 break;
1946 case FIELD_PROP_PAR5:
1948 rAny <<= OUString(OUString::number(m_nParentId, 16).toAsciiUpperCase());
1950 break;
1951 case FIELD_PROP_PAR6:
1953 rAny <<= OUString(OUString::number(m_nPostItId, 16).toAsciiUpperCase());
1955 break;
1956 case FIELD_PROP_TITLE:
1957 break;
1958 default:
1959 assert(false);
1961 return true;
1964 bool SwPostItField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
1966 switch( nWhichId )
1968 case FIELD_PROP_PAR1:
1969 rAny >>= m_sAuthor;
1970 break;
1971 case FIELD_PROP_PAR2:
1972 rAny >>= m_sText;
1973 //#i100374# new string via api, delete complex text object so SwPostItNote picks up the new string
1974 mpText.reset();
1975 break;
1976 case FIELD_PROP_PAR3:
1977 rAny >>= m_sInitials;
1978 break;
1979 case FIELD_PROP_PAR4:
1980 rAny >>= m_sName;
1981 break;
1982 case FIELD_PROP_PAR7: // PAR5 (Parent Para Id) and PAR6 (Para Id) are skipped - they are not written into xml. Used for file conversion.
1983 rAny >>= m_sParentName;
1984 break;
1985 case FIELD_PROP_BOOL1:
1986 rAny >>= m_bResolved;
1987 break;
1988 case FIELD_PROP_TEXT:
1989 OSL_FAIL("Not implemented!");
1990 break;
1991 case FIELD_PROP_DATE:
1992 if( auto aSetDate = o3tl::tryAccess<util::Date>(rAny) )
1994 m_aDateTime = DateTime( Date(aSetDate->Day, aSetDate->Month, aSetDate->Year) );
1996 break;
1997 case FIELD_PROP_DATE_TIME:
1999 util::DateTime aDateTimeValue;
2000 if(!(rAny >>= aDateTimeValue))
2001 return false;
2002 m_aDateTime = DateTime(aDateTimeValue);
2004 break;
2005 case FIELD_PROP_PAR5:
2007 OUString sTemp;
2008 rAny >>= sTemp;
2009 m_nParentId = sTemp.toInt32(16);
2011 break;
2012 case FIELD_PROP_PAR6:
2014 OUString sTemp;
2015 rAny >>= sTemp;
2016 m_nPostItId = sTemp.toInt32(16);
2018 break;
2019 default:
2020 assert(false);
2022 return true;
2025 void SwPostItField::dumpAsXml(xmlTextWriterPtr pWriter) const
2027 (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SwPostItField"));
2028 (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("name"), BAD_CAST(GetName().toUtf8().getStr()));
2030 SwField::dumpAsXml(pWriter);
2032 (void)xmlTextWriterStartElement(pWriter, BAD_CAST("mpText"));
2033 (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("ptr"), "%p", mpText ? &*mpText : nullptr);
2034 if (mpText)
2035 mpText->dumpAsXml(pWriter);
2036 (void)xmlTextWriterEndElement(pWriter);
2038 (void)xmlTextWriterEndElement(pWriter);
2041 // extended user information field type
2043 SwExtUserFieldType::SwExtUserFieldType()
2044 : SwFieldType( SwFieldIds::ExtUser )
2048 std::unique_ptr<SwFieldType> SwExtUserFieldType::Copy() const
2050 return std::make_unique<SwExtUserFieldType>();
2053 OUString SwExtUserFieldType::Expand(sal_uInt16 nSub )
2055 UserOptToken nRet = static_cast<UserOptToken>(USHRT_MAX);
2056 switch(nSub)
2058 case EU_FIRSTNAME: nRet = UserOptToken::FirstName; break;
2059 case EU_NAME: nRet = UserOptToken::LastName; break;
2060 case EU_SHORTCUT: nRet = UserOptToken::ID; break;
2062 case EU_COMPANY: nRet = UserOptToken::Company; break;
2063 case EU_STREET: nRet = UserOptToken::Street; break;
2064 case EU_TITLE: nRet = UserOptToken::Title; break;
2065 case EU_POSITION: nRet = UserOptToken::Position; break;
2066 case EU_PHONE_PRIVATE: nRet = UserOptToken::TelephoneHome; break;
2067 case EU_PHONE_COMPANY: nRet = UserOptToken::TelephoneWork; break;
2068 case EU_FAX: nRet = UserOptToken::Fax; break;
2069 case EU_EMAIL: nRet = UserOptToken::Email; break;
2070 case EU_COUNTRY: nRet = UserOptToken::Country; break;
2071 case EU_ZIP: nRet = UserOptToken::Zip; break;
2072 case EU_CITY: nRet = UserOptToken::City; break;
2073 case EU_STATE: nRet = UserOptToken::State; break;
2074 case EU_FATHERSNAME: nRet = UserOptToken::FathersName; break;
2075 case EU_APARTMENT: nRet = UserOptToken::Apartment; break;
2076 default: OSL_ENSURE( false, "Field unknown");
2078 if( static_cast<UserOptToken>(USHRT_MAX) != nRet )
2080 SvtUserOptions& rUserOpt = SwModule::get()->GetUserOptions();
2081 return rUserOpt.GetToken( nRet );
2083 return OUString();
2086 // extended user information field
2088 SwExtUserField::SwExtUserField(SwExtUserFieldType* pTyp, sal_uInt16 nSubTyp, sal_uInt32 nFormat) :
2089 SwField(pTyp, nFormat), m_nType(nSubTyp)
2091 m_aContent = SwExtUserFieldType::Expand(m_nType);
2094 OUString SwExtUserField::ExpandImpl(SwRootFrame const*const) const
2096 if (!IsFixed())
2097 const_cast<SwExtUserField*>(this)->m_aContent = SwExtUserFieldType::Expand(m_nType);
2099 return m_aContent;
2102 std::unique_ptr<SwField> SwExtUserField::Copy() const
2104 std::unique_ptr<SwExtUserField> pField(new SwExtUserField(static_cast<SwExtUserFieldType*>(GetTyp()), m_nType, GetFormat()));
2105 pField->SetExpansion(m_aContent);
2107 return std::unique_ptr<SwField>(pField.release());
2110 sal_uInt16 SwExtUserField::GetSubType() const
2112 return m_nType;
2115 void SwExtUserField::SetSubType(sal_uInt16 nSub)
2117 m_nType = nSub;
2120 bool SwExtUserField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
2122 switch( nWhichId )
2124 case FIELD_PROP_PAR1:
2125 rAny <<= m_aContent;
2126 break;
2128 case FIELD_PROP_USHORT1:
2130 sal_Int16 nTmp = m_nType;
2131 rAny <<= nTmp;
2133 break;
2134 case FIELD_PROP_BOOL1:
2135 rAny <<= IsFixed();
2136 break;
2137 default:
2138 assert(false);
2140 return true;
2143 bool SwExtUserField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
2145 switch( nWhichId )
2147 case FIELD_PROP_PAR1:
2148 rAny >>= m_aContent;
2149 break;
2151 case FIELD_PROP_USHORT1:
2153 sal_Int16 nTmp = 0;
2154 rAny >>= nTmp;
2155 m_nType = nTmp;
2157 break;
2158 case FIELD_PROP_BOOL1:
2159 if( *o3tl::doAccess<bool>(rAny) )
2160 SetFormat(GetFormat() | AF_FIXED);
2161 else
2162 SetFormat(GetFormat() & ~AF_FIXED);
2163 break;
2164 default:
2165 assert(false);
2167 return true;
2170 // field type for relative page numbers
2172 SwRefPageSetFieldType::SwRefPageSetFieldType()
2173 : SwFieldType( SwFieldIds::RefPageSet )
2177 std::unique_ptr<SwFieldType> SwRefPageSetFieldType::Copy() const
2179 return std::make_unique<SwRefPageSetFieldType>();
2182 // overridden since there is nothing to update
2183 void SwRefPageSetFieldType::SwClientNotify(const SwModify&, const SfxHint&)
2187 // field for relative page numbers
2189 SwRefPageSetField::SwRefPageSetField( SwRefPageSetFieldType* pTyp,
2190 short nOff, bool bFlag )
2191 : SwField( pTyp ), m_nOffset( nOff ), m_bOn( bFlag )
2195 OUString SwRefPageSetField::ExpandImpl(SwRootFrame const*const) const
2197 return OUString();
2200 std::unique_ptr<SwField> SwRefPageSetField::Copy() const
2202 return std::make_unique<SwRefPageSetField>( static_cast<SwRefPageSetFieldType*>(GetTyp()), m_nOffset, m_bOn );
2205 OUString SwRefPageSetField::GetPar2() const
2207 return OUString::number(GetOffset());
2210 void SwRefPageSetField::SetPar2(const OUString& rStr)
2212 SetOffset( static_cast<short>(rStr.toInt32()) );
2215 bool SwRefPageSetField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
2217 switch( nWhichId )
2219 case FIELD_PROP_BOOL1:
2220 rAny <<= m_bOn;
2221 break;
2222 case FIELD_PROP_USHORT1:
2223 rAny <<= static_cast<sal_Int16>(m_nOffset);
2224 break;
2225 default:
2226 assert(false);
2228 return true;
2231 bool SwRefPageSetField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
2233 switch( nWhichId )
2235 case FIELD_PROP_BOOL1:
2236 m_bOn = *o3tl::doAccess<bool>(rAny);
2237 break;
2238 case FIELD_PROP_USHORT1:
2239 rAny >>=m_nOffset;
2240 break;
2241 default:
2242 assert(false);
2244 return true;
2247 // relative page numbers - query field
2249 SwRefPageGetFieldType::SwRefPageGetFieldType( SwDoc& rDc )
2250 : SwFieldType( SwFieldIds::RefPageGet ), m_rDoc( rDc ), m_nNumberingType( SVX_NUM_ARABIC )
2254 std::unique_ptr<SwFieldType> SwRefPageGetFieldType::Copy() const
2256 std::unique_ptr<SwRefPageGetFieldType> pNew(new SwRefPageGetFieldType( m_rDoc ));
2257 pNew->m_nNumberingType = m_nNumberingType;
2258 return pNew;
2261 void SwRefPageGetFieldType::SwClientNotify(const SwModify&, const SfxHint& rHint)
2263 if (rHint.GetId() == SfxHintId::SwFormatChange
2264 || rHint.GetId() == SfxHintId::SwObjectDying
2265 || rHint.GetId() == SfxHintId::SwUpdateAttr)
2267 // forward to text fields, they "expand" the text
2268 CallSwClientNotify(rHint);
2269 return;
2271 if (rHint.GetId() != SfxHintId::SwLegacyModify && rHint.GetId() != SfxHintId::SwAttrSetChange)
2272 return;
2273 const sw::LegacyModifyHint* pLegacy = nullptr;
2274 const sw::AttrSetChangeHint* pChangeHint = nullptr;
2275 if (rHint.GetId() == SfxHintId::SwLegacyModify)
2276 pLegacy = static_cast<const sw::LegacyModifyHint*>(&rHint);
2277 else // rHint.GetId() == SfxHintId::SwAttrSetChange
2278 pChangeHint = static_cast<const sw::AttrSetChangeHint*>(&rHint);
2279 auto const ModifyImpl = [this](SwRootFrame const*const pLayout)
2281 // first collect all SetPageRefFields
2282 SetGetExpFields aTmpLst;
2283 if (MakeSetList(aTmpLst, pLayout))
2285 std::vector<SwFormatField*> vFields;
2286 GatherFields(vFields);
2287 for(auto pFormatField: vFields)
2288 UpdateField(pFormatField->GetTextField(), aTmpLst, pLayout);
2292 // update all GetReference fields
2293 if( (pLegacy && !pLegacy->m_pNew && !pLegacy->m_pOld && HasWriterListeners())
2294 || (pChangeHint && !pChangeHint->m_pNew && !pChangeHint->m_pOld && HasWriterListeners()))
2296 SwRootFrame const* pLayout(nullptr);
2297 SwRootFrame const* pLayoutRLHidden(nullptr);
2298 for (SwRootFrame const*const pLay : m_rDoc.GetAllLayouts())
2300 if (pLay->IsHideRedlines())
2302 pLayoutRLHidden = pLay;
2304 else
2306 pLayout = pLay;
2309 ModifyImpl(pLayout);
2310 if (pLayoutRLHidden)
2312 ModifyImpl(pLayoutRLHidden);
2316 // forward to text fields, they "expand" the text
2317 CallSwClientNotify(rHint);
2320 bool SwRefPageGetFieldType::MakeSetList(SetGetExpFields& rTmpLst,
2321 SwRootFrame const*const pLayout)
2323 IDocumentRedlineAccess const& rIDRA(m_rDoc.getIDocumentRedlineAccess());
2324 std::vector<SwFormatField*> vFields;
2325 m_rDoc.getIDocumentFieldsAccess().GetSysFieldType(SwFieldIds::RefPageSet)->GatherFields(vFields);
2326 for(auto pFormatField: vFields)
2328 // update only the GetRef fields
2329 const SwTextField* pTField = pFormatField->GetTextField();
2330 if (!pLayout || !pLayout->IsHideRedlines() || !sw::IsFieldDeletedInModel(rIDRA, *pTField))
2332 const SwTextNode& rTextNd = pTField->GetTextNode();
2334 // Always the first! (in Tab-Headline, header/footer )
2335 Point aPt;
2336 std::pair<Point, bool> const tmp(aPt, false);
2337 const SwContentFrame *const pFrame = rTextNd.getLayoutFrame(
2338 pLayout, nullptr, &tmp);
2340 std::unique_ptr<SetGetExpField> pNew;
2342 if( !pFrame ||
2343 pFrame->IsInDocBody() ||
2344 // #i31868#
2345 // Check if pFrame is not yet connected to the layout.
2346 !pFrame->FindPageFrame() )
2348 pNew.reset( new SetGetExpField( rTextNd, pTField ) );
2350 else
2352 // create index for determination of the TextNode
2353 SwPosition aPos( m_rDoc.GetNodes().GetEndOfPostIts() );
2354 bool const bResult = GetBodyTextNode( m_rDoc, aPos, *pFrame );
2355 OSL_ENSURE(bResult, "where is the Field?");
2356 pNew.reset( new SetGetExpField( aPos.GetNode(), pTField,
2357 aPos.GetContentIndex() ) );
2360 rTmpLst.insert( std::move(pNew) );
2363 return !rTmpLst.empty();
2366 void SwRefPageGetFieldType::UpdateField( SwTextField const * pTextField,
2367 SetGetExpFields const & rSetList,
2368 SwRootFrame const*const pLayout)
2370 SwRefPageGetField* pGetField = const_cast<SwRefPageGetField*>(static_cast<const SwRefPageGetField*>(pTextField->GetFormatField().GetField()));
2371 pGetField->SetText( OUString(), pLayout );
2373 // then search the correct RefPageSet field
2374 SwTextNode* pTextNode = &pTextField->GetTextNode();
2375 if( pTextNode->StartOfSectionIndex() >
2376 m_rDoc.GetNodes().GetEndOfExtras().GetIndex() )
2378 SetGetExpField aEndField( *pTextNode, pTextField );
2380 SetGetExpFields::const_iterator itLast = rSetList.lower_bound( &aEndField );
2382 if( itLast != rSetList.begin() )
2384 --itLast;
2385 const SwTextField* pRefTextField = (*itLast)->GetTextField();
2386 const SwRefPageSetField* pSetField =
2387 static_cast<const SwRefPageSetField*>(pRefTextField->GetFormatField().GetField());
2388 if( pSetField->IsOn() )
2390 // determine the correct offset
2391 Point aPt;
2392 std::pair<Point, bool> const tmp(aPt, false);
2393 const SwContentFrame *const pFrame = pTextNode->getLayoutFrame(
2394 pLayout, nullptr, &tmp);
2395 const SwContentFrame *const pRefFrame = pRefTextField->GetTextNode().getLayoutFrame(
2396 pLayout, nullptr, &tmp);
2397 const SwPageFrame* pPgFrame = nullptr;
2398 short nDiff = 1;
2399 if ( pFrame && pRefFrame )
2401 pPgFrame = pFrame->FindPageFrame();
2402 nDiff = pPgFrame->GetPhyPageNum() -
2403 pRefFrame->FindPageFrame()->GetPhyPageNum() + 1;
2406 SvxNumType nTmpFormat = SVX_NUM_PAGEDESC == static_cast<SvxNumType>(pGetField->GetFormat())
2407 ? ( !pPgFrame
2408 ? SVX_NUM_ARABIC
2409 : pPgFrame->GetPageDesc()->GetNumType().GetNumberingType() )
2410 : static_cast<SvxNumType>(pGetField->GetFormat());
2411 const short nPageNum = std::max<short>(0, pSetField->GetOffset() + nDiff);
2412 pGetField->SetText(FormatNumber(nPageNum, nTmpFormat), pLayout);
2416 // start formatting
2417 const_cast<SwFormatField&>(pTextField->GetFormatField()).ForceUpdateTextNode();
2420 // queries for relative page numbering
2422 SwRefPageGetField::SwRefPageGetField( SwRefPageGetFieldType* pTyp,
2423 sal_uInt32 nFormat )
2424 : SwField( pTyp, nFormat )
2428 void SwRefPageGetField::SetText(const OUString& rText,
2429 SwRootFrame const*const pLayout)
2431 if (!pLayout || !pLayout->IsHideRedlines())
2433 m_sText = rText;
2435 if (!pLayout || pLayout->IsHideRedlines())
2437 m_sTextRLHidden = rText;
2441 OUString SwRefPageGetField::ExpandImpl(SwRootFrame const*const pLayout) const
2443 return pLayout && pLayout->IsHideRedlines() ? m_sTextRLHidden : m_sText;
2446 std::unique_ptr<SwField> SwRefPageGetField::Copy() const
2448 std::unique_ptr<SwRefPageGetField> pCpy(new SwRefPageGetField(
2449 static_cast<SwRefPageGetFieldType*>(GetTyp()), GetFormat() ));
2450 pCpy->m_sText = m_sText;
2451 pCpy->m_sTextRLHidden = m_sTextRLHidden;
2452 return std::unique_ptr<SwField>(pCpy.release());
2455 void SwRefPageGetField::ChangeExpansion(const SwFrame& rFrame,
2456 const SwTextField* pField )
2458 // only fields in Footer, Header, FootNote, Flys
2459 SwRefPageGetFieldType* pGetType = static_cast<SwRefPageGetFieldType*>(GetTyp());
2460 SwDoc& rDoc = pGetType->GetDoc();
2461 if( pField->GetTextNode().StartOfSectionIndex() >
2462 rDoc.GetNodes().GetEndOfExtras().GetIndex() )
2463 return;
2465 SwRootFrame const& rLayout(*rFrame.getRootFrame());
2466 OUString & rText(rLayout.IsHideRedlines() ? m_sTextRLHidden : m_sText);
2467 rText.clear();
2469 OSL_ENSURE(!rFrame.IsInDocBody(), "Flag incorrect, frame is in DocBody");
2471 // collect all SetPageRefFields
2472 SetGetExpFields aTmpLst;
2473 if (!pGetType->MakeSetList(aTmpLst, &rLayout))
2474 return ;
2476 // create index for determination of the TextNode
2477 SwPosition aPos( rDoc.GetNodes() );
2478 SwTextNode* pTextNode = const_cast<SwTextNode*>(GetBodyTextNode(rDoc, aPos, rFrame));
2480 // If no layout exists, ChangeExpansion is called for header and
2481 // footer lines via layout formatting without existing TextNode.
2482 if(!pTextNode)
2483 return;
2485 SetGetExpField aEndField( aPos.GetNode(), pField, aPos.GetContentIndex() );
2487 SetGetExpFields::const_iterator itLast = aTmpLst.lower_bound( &aEndField );
2489 if( itLast == aTmpLst.begin() )
2490 return; // there is no corresponding set-field in front
2491 --itLast;
2493 const SwTextField* pRefTextField = (*itLast)->GetTextField();
2494 const SwRefPageSetField* pSetField =
2495 static_cast<const SwRefPageSetField*>(pRefTextField->GetFormatField().GetField());
2496 Point aPt;
2497 std::pair<Point, bool> const tmp(aPt, false);
2498 const SwContentFrame *const pRefFrame = pRefTextField->GetTextNode().getLayoutFrame(
2499 &rLayout, nullptr, &tmp);
2500 if( !(pSetField->IsOn() && pRefFrame) )
2501 return;
2503 // determine the correct offset
2504 const SwPageFrame* pPgFrame = rFrame.FindPageFrame();
2505 const short nDiff = pPgFrame->GetPhyPageNum() -
2506 pRefFrame->FindPageFrame()->GetPhyPageNum() + 1;
2508 SwRefPageGetField* pGetField = const_cast<SwRefPageGetField*>(static_cast<const SwRefPageGetField*>(pField->GetFormatField().GetField()));
2509 SvxNumType nTmpFormat = SVX_NUM_PAGEDESC == pGetField->GetFormat()
2510 ? pPgFrame->GetPageDesc()->GetNumType().GetNumberingType()
2511 : static_cast<SvxNumType>(pGetField->GetFormat());
2512 const short nPageNum = std::max<short>(0, pSetField->GetOffset() + nDiff);
2513 pGetField->SetText(FormatNumber(nPageNum, nTmpFormat), &rLayout);
2516 bool SwRefPageGetField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
2518 switch( nWhichId )
2520 case FIELD_PROP_USHORT1:
2521 rAny <<= static_cast<sal_Int16>(GetFormat());
2522 break;
2523 case FIELD_PROP_PAR1:
2524 rAny <<= m_sText;
2525 break;
2526 default:
2527 assert(false);
2529 return true;
2532 bool SwRefPageGetField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
2534 switch( nWhichId )
2536 case FIELD_PROP_USHORT1:
2538 sal_Int16 nSet = 0;
2539 rAny >>= nSet;
2540 if(nSet <= SVX_NUM_PAGEDESC )
2541 SetFormat(nSet);
2543 break;
2544 case FIELD_PROP_PAR1:
2545 rAny >>= m_sText;
2546 m_sTextRLHidden = m_sText;
2547 break;
2548 default:
2549 assert(false);
2551 return true;
2554 // field type to jump to and edit
2556 SwJumpEditFieldType::SwJumpEditFieldType( SwDoc& rD )
2557 : SwFieldType( SwFieldIds::JumpEdit ), m_rDoc( rD ), m_aDep( *this )
2561 std::unique_ptr<SwFieldType> SwJumpEditFieldType::Copy() const
2563 return std::make_unique<SwJumpEditFieldType>( m_rDoc );
2566 SwCharFormat* SwJumpEditFieldType::GetCharFormat()
2568 SwCharFormat* pFormat = m_rDoc.getIDocumentStylePoolAccess().GetCharFormatFromPool( RES_POOLCHR_JUMPEDIT );
2569 m_aDep.StartListening(pFormat);
2570 return pFormat;
2573 SwJumpEditField::SwJumpEditField( SwJumpEditFieldType* pTyp, sal_uInt32 nForm,
2574 OUString aText, OUString aHelp )
2575 : SwField( pTyp, nForm ), m_sText( std::move(aText) ), m_sHelp( std::move(aHelp) )
2579 OUString SwJumpEditField::ExpandImpl(SwRootFrame const*const) const
2581 return "<" + m_sText + ">";
2584 std::unique_ptr<SwField> SwJumpEditField::Copy() const
2586 return std::make_unique<SwJumpEditField>( static_cast<SwJumpEditFieldType*>(GetTyp()), GetFormat(),
2587 m_sText, m_sHelp );
2590 /// get place holder text
2591 OUString SwJumpEditField::GetPar1() const
2593 return m_sText;
2596 /// set place holder text
2597 void SwJumpEditField::SetPar1(const OUString& rStr)
2599 m_sText = rStr;
2602 /// get hint text
2603 OUString SwJumpEditField::GetPar2() const
2605 return m_sHelp;
2608 /// set hint text
2609 void SwJumpEditField::SetPar2(const OUString& rStr)
2611 m_sHelp = rStr;
2614 bool SwJumpEditField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
2616 switch( nWhichId )
2618 case FIELD_PROP_USHORT1:
2620 sal_Int16 nRet;
2621 switch( GetFormat() )
2623 case JE_FMT_TABLE: nRet = text::PlaceholderType::TABLE; break;
2624 case JE_FMT_FRAME: nRet = text::PlaceholderType::TEXTFRAME; break;
2625 case JE_FMT_GRAPHIC:nRet = text::PlaceholderType::GRAPHIC; break;
2626 case JE_FMT_OLE: nRet = text::PlaceholderType::OBJECT; break;
2627 default:
2628 nRet = text::PlaceholderType::TEXT; break;
2630 rAny <<= nRet;
2632 break;
2633 case FIELD_PROP_PAR1 :
2634 rAny <<= m_sHelp;
2635 break;
2636 case FIELD_PROP_PAR2 :
2637 rAny <<= m_sText;
2638 break;
2639 default:
2640 assert(false);
2642 return true;
2645 bool SwJumpEditField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
2647 switch( nWhichId )
2649 case FIELD_PROP_USHORT1:
2651 //JP 24.10.2001: int32 because in UnoField.cxx a putvalue is
2652 // called with a int32 value! But normally we need
2653 // here only a int16
2654 sal_Int32 nSet = 0;
2655 rAny >>= nSet;
2656 switch( nSet )
2658 case text::PlaceholderType::TEXT : SetFormat(JE_FMT_TEXT); break;
2659 case text::PlaceholderType::TABLE : SetFormat(JE_FMT_TABLE); break;
2660 case text::PlaceholderType::TEXTFRAME: SetFormat(JE_FMT_FRAME); break;
2661 case text::PlaceholderType::GRAPHIC : SetFormat(JE_FMT_GRAPHIC); break;
2662 case text::PlaceholderType::OBJECT : SetFormat(JE_FMT_OLE); break;
2665 break;
2666 case FIELD_PROP_PAR1 :
2667 rAny >>= m_sHelp;
2668 break;
2669 case FIELD_PROP_PAR2 :
2670 rAny >>= m_sText;
2671 break;
2672 default:
2673 assert(false);
2675 return true;
2678 // combined character field type
2680 SwCombinedCharFieldType::SwCombinedCharFieldType()
2681 : SwFieldType( SwFieldIds::CombinedChars )
2685 std::unique_ptr<SwFieldType> SwCombinedCharFieldType::Copy() const
2687 return std::make_unique<SwCombinedCharFieldType>();
2690 // combined character field
2692 SwCombinedCharField::SwCombinedCharField( SwCombinedCharFieldType* pFTyp,
2693 const OUString& rChars )
2694 : SwField( pFTyp, 0 ),
2695 m_sCharacters( rChars.copy( 0, std::min<sal_Int32>(rChars.getLength(), MAX_COMBINED_CHARACTERS) ))
2699 OUString SwCombinedCharField::ExpandImpl(SwRootFrame const*const) const
2701 return m_sCharacters;
2704 std::unique_ptr<SwField> SwCombinedCharField::Copy() const
2706 return std::make_unique<SwCombinedCharField>( static_cast<SwCombinedCharFieldType*>(GetTyp()),
2707 m_sCharacters );
2710 OUString SwCombinedCharField::GetPar1() const
2712 return m_sCharacters;
2715 void SwCombinedCharField::SetPar1(const OUString& rStr)
2717 m_sCharacters = rStr.copy(0, std::min<sal_Int32>(rStr.getLength(), MAX_COMBINED_CHARACTERS));
2720 bool SwCombinedCharField::QueryValue( uno::Any& rAny,
2721 sal_uInt16 nWhichId ) const
2723 switch( nWhichId )
2725 case FIELD_PROP_PAR1:
2726 rAny <<= m_sCharacters;
2727 break;
2728 default:
2729 assert(false);
2731 return true;
2734 bool SwCombinedCharField::PutValue( const uno::Any& rAny,
2735 sal_uInt16 nWhichId )
2737 switch( nWhichId )
2739 case FIELD_PROP_PAR1:
2741 OUString sTmp;
2742 rAny >>= sTmp;
2743 SetPar1(sTmp);
2745 break;
2746 default:
2747 assert(false);
2749 return true;
2752 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */