1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
20 #include <config_features.h>
21 
22 #include <textapi.hxx>
23 
24 #include <hintids.hxx>
25 #include <com/sun/star/text/XText.hpp>
26 #include <com/sun/star/script/Converter.hpp>
27 #include <com/sun/star/text/PlaceholderType.hpp>
28 #include <com/sun/star/text/TemplateDisplayFormat.hpp>
29 #include <com/sun/star/text/PageNumberType.hpp>
30 #include <com/sun/star/text/FilenameDisplayFormat.hpp>
31 #include <com/sun/star/text/DocumentStatistic.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 <editeng/unolingu.hxx>
39 #include <comphelper/processfactory.hxx>
40 #include <comphelper/string.hxx>
41 #include <tools/urlobj.hxx>
42 #include <vcl/svapp.hxx>
43 #include <svl/urihelper.hxx>
44 #include <unotools/useroptions.hxx>
45 #include <unotools/syslocale.hxx>
46 #include <svl/zforlist.hxx>
47 #include <libxml/xmlstring.h>
48 #include <libxml/xmlwriter.h>
49 
50 #include <tools/time.hxx>
51 #include <tools/datetime.hxx>
52 
53 #include <com/sun/star/util/DateTime.hpp>
54 #include <com/sun/star/util/Time.hpp>
55 
56 #include <swmodule.hxx>
57 #include <sfx2/app.hxx>
58 #include <sfx2/docfile.hxx>
59 #include <sfx2/doctempl.hxx>
60 #include <fmtfld.hxx>
61 #include <txtfld.hxx>
62 #include <charfmt.hxx>
63 #include <docstat.hxx>
64 #include <pagedesc.hxx>
65 #include <fmtpdsc.hxx>
66 #include <doc.hxx>
67 #include <IDocumentFieldsAccess.hxx>
68 #include <IDocumentStatistics.hxx>
69 #include <IDocumentStylePoolAccess.hxx>
70 #include <IDocumentLayoutAccess.hxx>
71 #include <rootfrm.hxx>
72 #include <pagefrm.hxx>
73 #include <cntfrm.hxx>
74 #include <pam.hxx>
75 #include <viewsh.hxx>
76 #include <dbmgr.hxx>
77 #include <shellres.hxx>
78 #include <docufld.hxx>
79 #include <flddat.hxx>
80 #include <docfld.hxx>
81 #include <ndtxt.hxx>
82 #include <expfld.hxx>
83 #include <poolfmt.hxx>
84 #include <docsh.hxx>
85 #include <unofldmid.h>
86 #include <swunohelper.hxx>
87 #include <strings.hrc>
88 
89 #include <editeng/outliner.hxx>
90 #include <editeng/outlobj.hxx>
91 #include <calbck.hxx>
92 #include <docary.hxx>
93 #include <hints.hxx>
94 
95 #define URL_DECODE  INetURLObject::DecodeMechanism::Unambiguous
96 
97 using namespace ::com::sun::star;
98 using namespace ::com::sun::star::uno;
99 using namespace nsSwDocInfoSubType;
100 
SwPageNumberFieldType()101 SwPageNumberFieldType::SwPageNumberFieldType()
102     : SwFieldType( SwFieldIds::PageNumber ),
103     m_nNumberingType( SVX_NUM_ARABIC ),
104     m_bVirtual( false )
105 {
106 }
107 
Expand(SvxNumType nFormat,short nOff,sal_uInt16 const nPageNumber,sal_uInt16 const nMaxPage,const OUString & rUserStr,LanguageType nLang) const108 OUString SwPageNumberFieldType::Expand( SvxNumType nFormat, short nOff,
109          sal_uInt16 const nPageNumber, sal_uInt16 const nMaxPage,
110          const OUString& rUserStr, LanguageType nLang ) const
111 {
112     SvxNumType nTmpFormat = (SVX_NUM_PAGEDESC == nFormat) ? m_nNumberingType : nFormat;
113     int const nTmp = nPageNumber + nOff;
114 
115     if (0 > nTmp || SVX_NUM_NUMBER_NONE == nTmpFormat || (!m_bVirtual && nTmp > nMaxPage))
116         return OUString();
117 
118     if( SVX_NUM_CHAR_SPECIAL == nTmpFormat )
119         return rUserStr;
120 
121     return FormatNumber( nTmp, nTmpFormat, nLang );
122 }
123 
Copy() const124 std::unique_ptr<SwFieldType> SwPageNumberFieldType::Copy() const
125 {
126     std::unique_ptr<SwPageNumberFieldType> pTmp(new SwPageNumberFieldType());
127 
128     pTmp->m_nNumberingType = m_nNumberingType;
129     pTmp->m_bVirtual  = m_bVirtual;
130 
131     return pTmp;
132 }
133 
ChangeExpansion(SwDoc * pDoc,bool bVirt,const SvxNumType * pNumFormat)134 void SwPageNumberFieldType::ChangeExpansion( SwDoc* pDoc,
135                                             bool bVirt,
136                                             const SvxNumType* pNumFormat )
137 {
138     if( pNumFormat )
139         m_nNumberingType = *pNumFormat;
140 
141     m_bVirtual = false;
142     if (bVirt && pDoc)
143     {
144         // check the flag since the layout NEVER sets it back
145         const SfxItemPool &rPool = pDoc->GetAttrPool();
146         for (const SfxPoolItem* pItem : rPool.GetItemSurrogates(RES_PAGEDESC))
147         {
148             auto pDesc = dynamic_cast<const SwFormatPageDesc*>(pItem);
149             if( pDesc && pDesc->GetNumOffset() && pDesc->GetDefinedIn() )
150             {
151                 const SwContentNode* pNd = dynamic_cast<const SwContentNode*>( pDesc->GetDefinedIn()  );
152                 if( pNd )
153                 {
154                     if (SwIterator<SwFrame, SwContentNode, sw::IteratorMode::UnwrapMulti>(*pNd).First())
155                     // sw_redlinehide: not sure if this should happen only if
156                     // it's the first node, because that's where RES_PAGEDESC
157                     // is effective?
158                         m_bVirtual = true;
159                 }
160                 else if( dynamic_cast< const SwFormat* >(pDesc->GetDefinedIn()) !=  nullptr)
161                 {
162                     SwAutoFormatGetDocNode aGetHt( &pDoc->GetNodes() );
163                     m_bVirtual = !pDesc->GetDefinedIn()->GetInfo( aGetHt );
164                     break;
165                 }
166             }
167         }
168     }
169 }
170 
SwPageNumberField(SwPageNumberFieldType * pTyp,sal_uInt16 nSub,sal_uInt32 nFormat,short nOff,sal_uInt16 const nPageNumber,sal_uInt16 const nMaxPage)171 SwPageNumberField::SwPageNumberField(SwPageNumberFieldType* pTyp,
172           sal_uInt16 nSub, sal_uInt32 nFormat, short nOff,
173           sal_uInt16 const nPageNumber, sal_uInt16 const nMaxPage)
174     : SwField(pTyp, nFormat), m_nSubType(nSub), m_nOffset(nOff)
175     , m_nPageNumber(nPageNumber)
176     , m_nMaxPage(nMaxPage)
177 {
178 }
179 
ChangeExpansion(sal_uInt16 const nPageNumber,sal_uInt16 const nMaxPage)180 void SwPageNumberField::ChangeExpansion(sal_uInt16 const nPageNumber,
181         sal_uInt16 const nMaxPage)
182 {
183     m_nPageNumber = nPageNumber;
184     m_nMaxPage = nMaxPage;
185 }
186 
ExpandImpl(SwRootFrame const * const) const187 OUString SwPageNumberField::ExpandImpl(SwRootFrame const*const) const
188 {
189     OUString sRet;
190     SwPageNumberFieldType* pFieldType = static_cast<SwPageNumberFieldType*>(GetTyp());
191 
192     if( PG_NEXT == m_nSubType && 1 != m_nOffset )
193     {
194         sRet = pFieldType->Expand(static_cast<SvxNumType>(GetFormat()), 1, m_nPageNumber, m_nMaxPage, m_sUserStr, GetLanguage());
195         if (!sRet.isEmpty())
196         {
197             sRet = pFieldType->Expand(static_cast<SvxNumType>(GetFormat()), m_nOffset, m_nPageNumber, m_nMaxPage, m_sUserStr, GetLanguage());
198         }
199     }
200     else if( PG_PREV == m_nSubType && -1 != m_nOffset )
201     {
202         sRet = pFieldType->Expand(static_cast<SvxNumType>(GetFormat()), -1, m_nPageNumber, m_nMaxPage, m_sUserStr, GetLanguage());
203         if (!sRet.isEmpty())
204         {
205             sRet = pFieldType->Expand(static_cast<SvxNumType>(GetFormat()), m_nOffset, m_nPageNumber, m_nMaxPage, m_sUserStr, GetLanguage());
206         }
207     }
208     else
209         sRet = pFieldType->Expand(static_cast<SvxNumType>(GetFormat()), m_nOffset, m_nPageNumber, m_nMaxPage, m_sUserStr, GetLanguage());
210     return sRet;
211 }
212 
Copy() const213 std::unique_ptr<SwField> SwPageNumberField::Copy() const
214 {
215     std::unique_ptr<SwPageNumberField> pTmp(new SwPageNumberField(
216                 static_cast<SwPageNumberFieldType*>(GetTyp()), m_nSubType,
217                 GetFormat(), m_nOffset, m_nPageNumber, m_nMaxPage));
218     pTmp->SetLanguage( GetLanguage() );
219     pTmp->SetUserString( m_sUserStr );
220     return std::unique_ptr<SwField>(pTmp.release());
221 }
222 
GetPar2() const223 OUString SwPageNumberField::GetPar2() const
224 {
225     return OUString::number(m_nOffset);
226 }
227 
SetPar2(const OUString & rStr)228 void SwPageNumberField::SetPar2(const OUString& rStr)
229 {
230     m_nOffset = static_cast<short>(rStr.toInt32());
231 }
232 
GetSubType() const233 sal_uInt16 SwPageNumberField::GetSubType() const
234 {
235     return m_nSubType;
236 }
237 
QueryValue(uno::Any & rAny,sal_uInt16 nWhichId) const238 bool SwPageNumberField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
239 {
240     switch( nWhichId )
241     {
242     case FIELD_PROP_FORMAT:
243         rAny <<= static_cast<sal_Int16>(GetFormat());
244         break;
245     case FIELD_PROP_USHORT1:
246         rAny <<= m_nOffset;
247         break;
248     case FIELD_PROP_SUBTYPE:
249         {
250             text::PageNumberType eType;
251             eType = text::PageNumberType_CURRENT;
252             if(m_nSubType == PG_PREV)
253                 eType = text::PageNumberType_PREV;
254             else if(m_nSubType == PG_NEXT)
255                 eType = text::PageNumberType_NEXT;
256             rAny <<= eType;
257         }
258         break;
259     case FIELD_PROP_PAR1:
260         rAny <<= m_sUserStr;
261         break;
262 
263     default:
264         assert(false);
265     }
266     return true;
267 }
268 
PutValue(const uno::Any & rAny,sal_uInt16 nWhichId)269 bool SwPageNumberField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
270 {
271     bool bRet = true;
272     sal_Int16 nSet = 0;
273     switch( nWhichId )
274     {
275     case FIELD_PROP_FORMAT:
276         rAny >>= nSet;
277 
278         // TODO: where do the defines come from?
279         if(nSet <= SVX_NUM_PAGEDESC )
280             SetFormat(nSet);
281         break;
282     case FIELD_PROP_USHORT1:
283         rAny >>= nSet;
284         m_nOffset = nSet;
285         break;
286     case FIELD_PROP_SUBTYPE:
287         switch( static_cast<text::PageNumberType>(SWUnoHelper::GetEnumAsInt32( rAny )) )
288         {
289             case text::PageNumberType_CURRENT:
290                 m_nSubType = PG_RANDOM;
291             break;
292             case text::PageNumberType_PREV:
293                 m_nSubType = PG_PREV;
294             break;
295             case text::PageNumberType_NEXT:
296                 m_nSubType = PG_NEXT;
297             break;
298             default:
299                 bRet = false;
300         }
301         break;
302     case FIELD_PROP_PAR1:
303         rAny >>= m_sUserStr;
304         break;
305 
306     default:
307         assert(false);
308     }
309     return bRet;
310 }
311 
SwAuthorFieldType()312 SwAuthorFieldType::SwAuthorFieldType()
313     : SwFieldType( SwFieldIds::Author )
314 {
315 }
316 
Expand(sal_uLong nFormat)317 OUString SwAuthorFieldType::Expand(sal_uLong nFormat)
318 {
319     SvtUserOptions&  rOpt = SW_MOD()->GetUserOptions();
320     if((nFormat & 0xff) == AF_NAME)
321         return rOpt.GetFullName();
322 
323     return rOpt.GetID();
324 }
325 
Copy() const326 std::unique_ptr<SwFieldType> SwAuthorFieldType::Copy() const
327 {
328     return std::make_unique<SwAuthorFieldType>();
329 }
330 
SwAuthorField(SwAuthorFieldType * pTyp,sal_uInt32 nFormat)331 SwAuthorField::SwAuthorField(SwAuthorFieldType* pTyp, sal_uInt32 nFormat)
332     : SwField(pTyp, nFormat)
333 {
334     m_aContent = SwAuthorFieldType::Expand(GetFormat());
335 }
336 
ExpandImpl(SwRootFrame const * const) const337 OUString SwAuthorField::ExpandImpl(SwRootFrame const*const) const
338 {
339     if (!IsFixed())
340         const_cast<SwAuthorField*>(this)->m_aContent =
341                     SwAuthorFieldType::Expand(GetFormat());
342 
343     return m_aContent;
344 }
345 
Copy() const346 std::unique_ptr<SwField> SwAuthorField::Copy() const
347 {
348     std::unique_ptr<SwAuthorField> pTmp(new SwAuthorField( static_cast<SwAuthorFieldType*>(GetTyp()),
349                                                 GetFormat()));
350     pTmp->SetExpansion(m_aContent);
351     return std::unique_ptr<SwField>(pTmp.release());
352 }
353 
QueryValue(uno::Any & rAny,sal_uInt16 nWhichId) const354 bool SwAuthorField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
355 {
356     switch( nWhichId )
357     {
358     case FIELD_PROP_BOOL1:
359         rAny <<= (GetFormat() & 0xff) == AF_NAME;
360         break;
361 
362     case FIELD_PROP_BOOL2:
363         rAny <<= IsFixed();
364         break;
365 
366     case FIELD_PROP_PAR1:
367         rAny <<= m_aContent;
368         break;
369 
370     default:
371         assert(false);
372     }
373     return true;
374 }
375 
PutValue(const uno::Any & rAny,sal_uInt16 nWhichId)376 bool SwAuthorField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
377 {
378     switch( nWhichId )
379     {
380     case FIELD_PROP_BOOL1:
381         SetFormat( *o3tl::doAccess<bool>(rAny) ? AF_NAME : AF_SHORTCUT );
382         break;
383 
384     case FIELD_PROP_BOOL2:
385         if( *o3tl::doAccess<bool>(rAny) )
386             SetFormat( GetFormat() | AF_FIXED);
387         else
388             SetFormat( GetFormat() & ~AF_FIXED);
389         break;
390 
391     case FIELD_PROP_PAR1:
392         rAny >>= m_aContent;
393         break;
394 
395     default:
396         assert(false);
397     }
398     return true;
399 }
400 
SwFileNameFieldType(SwDoc * pDocument)401 SwFileNameFieldType::SwFileNameFieldType(SwDoc *pDocument)
402     : SwFieldType( SwFieldIds::Filename )
403 {
404     m_pDoc = pDocument;
405 }
406 
Expand(sal_uLong nFormat) const407 OUString SwFileNameFieldType::Expand(sal_uLong nFormat) const
408 {
409     OUString aRet;
410     const SwDocShell* pDShell = m_pDoc->GetDocShell();
411     if( pDShell && pDShell->HasName() )
412     {
413         const INetURLObject& rURLObj = pDShell->GetMedium()->GetURLObject();
414         switch( nFormat & ~FF_FIXED )
415         {
416             case FF_PATH:
417                 {
418                     if( INetProtocol::File == rURLObj.GetProtocol() )
419                     {
420                         INetURLObject aTemp(rURLObj);
421                         aTemp.removeSegment();
422                         // last slash should belong to the pathname
423                         aRet = aTemp.PathToFileName();
424                     }
425                     else
426                     {
427                         aRet = URIHelper::removePassword(
428                                     rURLObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ),
429                                     INetURLObject::EncodeMechanism::WasEncoded, URL_DECODE );
430                         const sal_Int32 nPos = aRet.indexOf(rURLObj.GetLastName( URL_DECODE ));
431                         if (nPos>=0)
432                         {
433                             aRet = aRet.copy(0, nPos);
434                         }
435                     }
436                 }
437                 break;
438 
439             case FF_NAME:
440                 aRet = rURLObj.GetLastName( INetURLObject::DecodeMechanism::WithCharset );
441                 break;
442 
443             case FF_NAME_NOEXT:
444                 aRet = rURLObj.GetBase();
445                 break;
446 
447             default:
448                 if( INetProtocol::File == rURLObj.GetProtocol() )
449                     aRet = rURLObj.GetFull();
450                 else
451                     aRet = URIHelper::removePassword(
452                                     rURLObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ),
453                                     INetURLObject::EncodeMechanism::WasEncoded, URL_DECODE );
454         }
455     }
456     return aRet;
457 }
458 
Copy() const459 std::unique_ptr<SwFieldType> SwFileNameFieldType::Copy() const
460 {
461     return std::make_unique<SwFileNameFieldType>(m_pDoc);
462 }
463 
SwFileNameField(SwFileNameFieldType * pTyp,sal_uInt32 nFormat)464 SwFileNameField::SwFileNameField(SwFileNameFieldType* pTyp, sal_uInt32 nFormat)
465     : SwField(pTyp, nFormat)
466 {
467     m_aContent = static_cast<SwFileNameFieldType*>(GetTyp())->Expand(GetFormat());
468 }
469 
ExpandImpl(SwRootFrame const * const) const470 OUString SwFileNameField::ExpandImpl(SwRootFrame const*const) const
471 {
472     if (!IsFixed())
473         const_cast<SwFileNameField*>(this)->m_aContent = static_cast<SwFileNameFieldType*>(GetTyp())->Expand(GetFormat());
474 
475     return m_aContent;
476 }
477 
Copy() const478 std::unique_ptr<SwField> SwFileNameField::Copy() const
479 {
480     std::unique_ptr<SwFileNameField> pTmp(
481         new SwFileNameField(static_cast<SwFileNameFieldType*>(GetTyp()), GetFormat()));
482     pTmp->SetExpansion(m_aContent);
483 
484     return std::unique_ptr<SwField>(pTmp.release());
485 }
486 
QueryValue(uno::Any & rAny,sal_uInt16 nWhichId) const487 bool SwFileNameField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
488 {
489     switch( nWhichId )
490     {
491     case FIELD_PROP_FORMAT:
492         {
493             sal_Int16 nRet;
494             switch( GetFormat() &(~FF_FIXED) )
495             {
496                 case FF_PATH:
497                     nRet = text::FilenameDisplayFormat::PATH;
498                 break;
499                 case FF_NAME_NOEXT:
500                     nRet = text::FilenameDisplayFormat::NAME;
501                 break;
502                 case FF_NAME:
503                     nRet = text::FilenameDisplayFormat::NAME_AND_EXT;
504                 break;
505                 default:    nRet = text::FilenameDisplayFormat::FULL;
506             }
507             rAny <<= nRet;
508         }
509         break;
510 
511     case FIELD_PROP_BOOL2:
512         rAny <<= IsFixed();
513         break;
514 
515     case FIELD_PROP_PAR3:
516         rAny <<= m_aContent;
517         break;
518 
519     default:
520         assert(false);
521     }
522     return true;
523 }
524 
PutValue(const uno::Any & rAny,sal_uInt16 nWhichId)525 bool SwFileNameField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
526 {
527     switch( nWhichId )
528     {
529     case FIELD_PROP_FORMAT:
530         {
531             //JP 24.10.2001: int32 because in UnoField.cxx a putvalue is
532             //              called with a int32 value! But normally we need
533             //              here only a int16
534             sal_Int32 nType = 0;
535             rAny >>= nType;
536             bool bFixed = IsFixed();
537             switch( nType )
538             {
539                 case text::FilenameDisplayFormat::PATH:
540                     nType = FF_PATH;
541                 break;
542                 case text::FilenameDisplayFormat::NAME:
543                     nType = FF_NAME_NOEXT;
544                 break;
545                 case text::FilenameDisplayFormat::NAME_AND_EXT:
546                     nType = FF_NAME;
547                 break;
548                 default:    nType = FF_PATHNAME;
549             }
550             if(bFixed)
551                 nType |= FF_FIXED;
552             SetFormat(nType);
553         }
554         break;
555 
556     case FIELD_PROP_BOOL2:
557         if( *o3tl::doAccess<bool>(rAny) )
558             SetFormat( GetFormat() | FF_FIXED);
559         else
560             SetFormat( GetFormat() & ~FF_FIXED);
561         break;
562 
563     case FIELD_PROP_PAR3:
564         rAny >>= m_aContent;
565         break;
566 
567     default:
568         assert(false);
569     }
570     return true;
571 }
572 
SwTemplNameFieldType(SwDoc * pDocument)573 SwTemplNameFieldType::SwTemplNameFieldType(SwDoc *pDocument)
574     : SwFieldType( SwFieldIds::TemplateName )
575 {
576     m_pDoc = pDocument;
577 }
578 
Expand(sal_uLong nFormat) const579 OUString SwTemplNameFieldType::Expand(sal_uLong nFormat) const
580 {
581     OSL_ENSURE( nFormat < FF_END, "Expand: no valid Format!" );
582 
583     OUString aRet;
584     SwDocShell *pDocShell(m_pDoc->GetDocShell());
585     OSL_ENSURE(pDocShell, "no SwDocShell");
586     if (pDocShell) {
587         uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
588             pDocShell->GetModel(), uno::UNO_QUERY_THROW);
589         uno::Reference<document::XDocumentProperties> xDocProps(
590             xDPS->getDocumentProperties());
591         OSL_ENSURE(xDocProps.is(), "Doc has no DocumentProperties");
592 
593         if( FF_UI_NAME == nFormat )
594             aRet = xDocProps->getTemplateName();
595         else if( !xDocProps->getTemplateURL().isEmpty() )
596         {
597             if( FF_UI_RANGE == nFormat )
598             {
599                 // for getting region names!
600                 SfxDocumentTemplates aFac;
601                 OUString sTmp;
602                 OUString sRegion;
603                 aFac.GetLogicNames( xDocProps->getTemplateURL(), sRegion, sTmp );
604                 aRet = sRegion;
605             }
606             else
607             {
608                 INetURLObject aPathName( xDocProps->getTemplateURL() );
609                 if( FF_NAME == nFormat )
610                     aRet = aPathName.GetLastName(URL_DECODE);
611                 else if( FF_NAME_NOEXT == nFormat )
612                     aRet = aPathName.GetBase();
613                 else
614                 {
615                     if( FF_PATH == nFormat )
616                     {
617                         aPathName.removeSegment();
618                         aRet = aPathName.GetFull();
619                     }
620                     else
621                         aRet = aPathName.GetFull();
622                 }
623             }
624         }
625     }
626     return aRet;
627 }
628 
Copy() const629 std::unique_ptr<SwFieldType> SwTemplNameFieldType::Copy() const
630 {
631     return std::make_unique<SwTemplNameFieldType>(m_pDoc);
632 }
633 
SwTemplNameField(SwTemplNameFieldType * pTyp,sal_uInt32 nFormat)634 SwTemplNameField::SwTemplNameField(SwTemplNameFieldType* pTyp, sal_uInt32 nFormat)
635     : SwField(pTyp, nFormat)
636 {}
637 
ExpandImpl(SwRootFrame const * const) const638 OUString SwTemplNameField::ExpandImpl(SwRootFrame const*const) const
639 {
640     return static_cast<SwTemplNameFieldType*>(GetTyp())->Expand(GetFormat());
641 }
642 
Copy() const643 std::unique_ptr<SwField> SwTemplNameField::Copy() const
644 {
645     return std::make_unique<SwTemplNameField>(static_cast<SwTemplNameFieldType*>(GetTyp()), GetFormat());
646 }
647 
QueryValue(uno::Any & rAny,sal_uInt16 nWhichId) const648 bool SwTemplNameField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
649 {
650     switch ( nWhichId )
651     {
652     case FIELD_PROP_FORMAT:
653         {
654             sal_Int16 nRet;
655             switch( GetFormat() )
656             {
657                 case FF_PATH:       nRet = text::FilenameDisplayFormat::PATH; break;
658                 case FF_NAME_NOEXT: nRet = text::FilenameDisplayFormat::NAME; break;
659                 case FF_NAME:       nRet = text::FilenameDisplayFormat::NAME_AND_EXT; break;
660                 case FF_UI_RANGE:   nRet = text::TemplateDisplayFormat::AREA; break;
661                 case FF_UI_NAME:    nRet = text::TemplateDisplayFormat::TITLE;  break;
662                 default:    nRet = text::FilenameDisplayFormat::FULL;
663 
664             }
665             rAny <<= nRet;
666         }
667         break;
668 
669     default:
670         assert(false);
671     }
672     return true;
673 }
674 
PutValue(const uno::Any & rAny,sal_uInt16 nWhichId)675 bool SwTemplNameField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
676 {
677     switch ( nWhichId )
678     {
679     case FIELD_PROP_FORMAT:
680         {
681             //JP 24.10.2001: int32 because in UnoField.cxx a putvalue is
682             //              called with a int32 value! But normally we need
683             //              here only a int16
684             sal_Int32 nType = 0;
685             rAny >>= nType;
686             switch( nType )
687             {
688             case text::FilenameDisplayFormat::PATH:
689                 SetFormat(FF_PATH);
690             break;
691             case text::FilenameDisplayFormat::NAME:
692                 SetFormat(FF_NAME_NOEXT);
693             break;
694             case text::FilenameDisplayFormat::NAME_AND_EXT:
695                 SetFormat(FF_NAME);
696             break;
697             case text::TemplateDisplayFormat::AREA  :
698                 SetFormat(FF_UI_RANGE);
699             break;
700             case text::TemplateDisplayFormat::TITLE  :
701                 SetFormat(FF_UI_NAME);
702             break;
703             default:    SetFormat(FF_PATHNAME);
704             }
705         }
706         break;
707 
708     default:
709         assert(false);
710     }
711     return true;
712 }
713 
SwDocStatFieldType(SwDoc * pDocument)714 SwDocStatFieldType::SwDocStatFieldType(SwDoc* pDocument)
715     : SwFieldType( SwFieldIds::DocStat ), m_nNumberingType( SVX_NUM_ARABIC )
716 {
717     m_pDoc = pDocument;
718 }
719 
Expand(sal_uInt16 nSubType,SvxNumType nFormat) const720 OUString SwDocStatFieldType::Expand(sal_uInt16 nSubType, SvxNumType nFormat) const
721 {
722     sal_uInt32 nVal = 0;
723     const SwDocStat& rDStat = m_pDoc->getIDocumentStatistics().GetDocStat();
724     switch( nSubType )
725     {
726         case DS_TBL:  nVal = rDStat.nTable;   break;
727         case DS_GRF:  nVal = rDStat.nGrf;   break;
728         case DS_OLE:  nVal = rDStat.nOLE;   break;
729         case DS_PARA: nVal = rDStat.nPara;  break;
730         case DS_WORD: nVal = rDStat.nWord;  break;
731         case DS_CHAR: nVal = rDStat.nChar;  break;
732         case DS_PAGE:
733             if( m_pDoc->getIDocumentLayoutAccess().GetCurrentLayout() )
734                 const_cast<SwDocStat &>(rDStat).nPage = m_pDoc->getIDocumentLayoutAccess().GetCurrentLayout()->GetPageNum();
735             nVal = rDStat.nPage;
736             if( SVX_NUM_PAGEDESC == nFormat )
737                 nFormat = m_nNumberingType;
738             break;
739         default:
740             OSL_FAIL( "SwDocStatFieldType::Expand: unknown SubType" );
741     }
742 
743     if( nVal <= SHRT_MAX )
744         return FormatNumber( nVal, nFormat );
745 
746     return OUString::number( nVal );
747 }
748 
Copy() const749 std::unique_ptr<SwFieldType> SwDocStatFieldType::Copy() const
750 {
751     return std::make_unique<SwDocStatFieldType>(m_pDoc);
752 }
753 
754 /**
755  * @param pTyp
756  * @param nSub SubType
757  * @param nFormat
758  */
SwDocStatField(SwDocStatFieldType * pTyp,sal_uInt16 nSub,sal_uInt32 nFormat)759 SwDocStatField::SwDocStatField(SwDocStatFieldType* pTyp, sal_uInt16 nSub, sal_uInt32 nFormat)
760     : SwField(pTyp, nFormat),
761     m_nSubType(nSub)
762 {}
763 
ExpandImpl(SwRootFrame const * const) const764 OUString SwDocStatField::ExpandImpl(SwRootFrame const*const) const
765 {
766     return static_cast<SwDocStatFieldType*>(GetTyp())->Expand(m_nSubType, static_cast<SvxNumType>(GetFormat()));
767 }
768 
Copy() const769 std::unique_ptr<SwField> SwDocStatField::Copy() const
770 {
771     return std::make_unique<SwDocStatField>(
772                     static_cast<SwDocStatFieldType*>(GetTyp()), m_nSubType, GetFormat() );
773 }
774 
GetSubType() const775 sal_uInt16 SwDocStatField::GetSubType() const
776 {
777     return m_nSubType;
778 }
779 
SetSubType(sal_uInt16 nSub)780 void SwDocStatField::SetSubType(sal_uInt16 nSub)
781 {
782     m_nSubType = nSub;
783 }
784 
ChangeExpansion(const SwFrame * pFrame)785 void SwDocStatField::ChangeExpansion( const SwFrame* pFrame )
786 {
787     if( DS_PAGE == m_nSubType && SVX_NUM_PAGEDESC == GetFormat() )
788         static_cast<SwDocStatFieldType*>(GetTyp())->SetNumFormat(
789                 pFrame->FindPageFrame()->GetPageDesc()->GetNumType().GetNumberingType() );
790 }
791 
QueryValue(uno::Any & rAny,sal_uInt16 nWhichId) const792 bool SwDocStatField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
793 {
794     switch ( nWhichId )
795     {
796     case FIELD_PROP_USHORT2:
797         rAny <<= static_cast<sal_Int16>(GetFormat());
798         break;
799 
800     default:
801         assert(false);
802     }
803     return true;
804 }
805 
PutValue(const uno::Any & rAny,sal_uInt16 nWhichId)806 bool SwDocStatField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
807 {
808     bool bRet = false;
809     switch ( nWhichId )
810     {
811     case FIELD_PROP_USHORT2:
812         {
813             sal_Int16 nSet = 0;
814             rAny >>= nSet;
815             if(nSet <= SVX_NUM_CHARS_LOWER_LETTER_N &&
816                 nSet != SVX_NUM_CHAR_SPECIAL &&
817                     nSet != SVX_NUM_BITMAP)
818             {
819                 SetFormat(nSet);
820                 bRet = true;
821             }
822         }
823         break;
824 
825     default:
826         assert(false);
827     }
828     return bRet;
829 }
830 
831 // Document info field type
832 
SwDocInfoFieldType(SwDoc * pDc)833 SwDocInfoFieldType::SwDocInfoFieldType(SwDoc* pDc)
834     : SwValueFieldType( pDc, SwFieldIds::DocInfo )
835 {
836 }
837 
Copy() const838 std::unique_ptr<SwFieldType> SwDocInfoFieldType::Copy() const
839 {
840     return std::make_unique<SwDocInfoFieldType>(GetDoc());
841 }
842 
lcl_GetLocalDataWrapper(LanguageType nLang,const LocaleDataWrapper ** ppAppLocalData,const LocaleDataWrapper ** ppLocalData)843 static void lcl_GetLocalDataWrapper( LanguageType nLang,
844                               const LocaleDataWrapper **ppAppLocalData,
845                               const LocaleDataWrapper **ppLocalData )
846 {
847     SvtSysLocale aLocale;
848     *ppAppLocalData = &aLocale.GetLocaleData();
849     *ppLocalData = *ppAppLocalData;
850     if( nLang != (*ppLocalData)->getLanguageTag().getLanguageType() )
851         *ppLocalData = new LocaleDataWrapper(LanguageTag( nLang ));
852 }
853 
Expand(sal_uInt16 nSub,sal_uInt32 nFormat,LanguageType nLang,const OUString & rName) const854 OUString SwDocInfoFieldType::Expand( sal_uInt16 nSub, sal_uInt32 nFormat,
855                                     LanguageType nLang, const OUString& rName ) const
856 {
857     const LocaleDataWrapper *pAppLocalData = nullptr, *pLocalData = nullptr;
858     SwDocShell *pDocShell(GetDoc()->GetDocShell());
859     OSL_ENSURE(pDocShell, "no SwDocShell");
860     if (!pDocShell) { return OUString(); }
861 
862     uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
863         pDocShell->GetModel(), uno::UNO_QUERY_THROW);
864     uno::Reference<document::XDocumentProperties> xDocProps(
865         xDPS->getDocumentProperties());
866     OSL_ENSURE(xDocProps.is(), "Doc has no DocumentProperties");
867 
868     sal_uInt16 nExtSub = nSub & 0xff00;
869     nSub &= 0xff;   // do not consider extended SubTypes
870 
871     OUString aStr;
872     switch(nSub)
873     {
874     case DI_TITLE:  aStr = xDocProps->getTitle();       break;
875     case DI_THEMA:  aStr = xDocProps->getSubject();     break;
876     case DI_KEYS:   aStr = ::comphelper::string::convertCommaSeparated(
877                                 xDocProps->getKeywords());
878                     break;
879     case DI_COMMENT:aStr = xDocProps->getDescription(); break;
880     case DI_DOCNO:  aStr = OUString::number(
881                                         xDocProps->getEditingCycles() );
882                     break;
883     case DI_EDIT:
884         if ( !nFormat )
885         {
886             lcl_GetLocalDataWrapper( nLang, &pAppLocalData, &pLocalData );
887             sal_Int32 dur = xDocProps->getEditingDuration();
888             // If Seconds > 0 then bSec should be TRUE otherwise Seconds
889             // information will be lost if file has EditTime in Seconds format.
890             aStr = pLocalData->getTime( tools::Time(dur/3600, (dur%3600)/60, dur%60),
891                                         dur%60 > 0);
892         }
893         else
894         {
895             sal_Int32 dur = xDocProps->getEditingDuration();
896             double fVal = tools::Time(dur/3600, (dur%3600)/60, dur%60).GetTimeInDays();
897             aStr = ExpandValue(fVal, nFormat, nLang);
898         }
899         break;
900     case DI_CUSTOM:
901         {
902             OUString sVal;
903             try
904             {
905                 uno::Any aAny;
906                 uno::Reference < beans::XPropertySet > xSet(
907                     xDocProps->getUserDefinedProperties(),
908                     uno::UNO_QUERY_THROW);
909                 aAny = xSet->getPropertyValue( rName );
910 
911                 uno::Reference < script::XTypeConverter > xConverter( script::Converter::create(comphelper::getProcessComponentContext()) );
912                 uno::Any aNew = xConverter->convertToSimpleType( aAny, uno::TypeClass_STRING );
913                 aNew >>= sVal;
914             }
915             catch (uno::Exception&) {}
916             return sVal;
917         }
918 
919     default:
920         {
921             OUString aName( xDocProps->getAuthor() );
922             util::DateTime uDT( xDocProps->getCreationDate() );
923             DateTime aDate(uDT);
924             if( nSub == DI_CREATE )
925                 ;       // that's it !!
926             else if( nSub == DI_CHANGE )
927             {
928                 aName = xDocProps->getModifiedBy();
929                 uDT = xDocProps->getModificationDate();
930                 aDate = DateTime(uDT);
931             }
932             else if( nSub == DI_PRINT )
933             {
934                 aName = xDocProps->getPrintedBy();
935                 uDT = xDocProps->getPrintDate();
936                 aDate = DateTime(uDT);
937             }
938             else
939                 break;
940 
941             if (aDate.IsValidAndGregorian())
942             {
943                 switch (nExtSub & ~DI_SUB_FIXED)
944                 {
945                 case DI_SUB_AUTHOR:
946                     aStr = aName;
947                     break;
948 
949                 case DI_SUB_TIME:
950                     if (!nFormat)
951                     {
952                         lcl_GetLocalDataWrapper( nLang, &pAppLocalData,
953                                                         &pLocalData );
954                         aStr = pLocalData->getTime( aDate,
955                                                     false);
956                     }
957                     else
958                     {
959                         // start the number formatter
960                         double fVal = SwDateTimeField::GetDateTime( GetDoc(),
961                                                     aDate);
962                         aStr = ExpandValue(fVal, nFormat, nLang);
963                     }
964                     break;
965 
966                 case DI_SUB_DATE:
967                     if (!nFormat)
968                     {
969                         lcl_GetLocalDataWrapper( nLang, &pAppLocalData,
970                                                  &pLocalData );
971                         aStr = pLocalData->getDate( aDate );
972                     }
973                     else
974                     {
975                         // start the number formatter
976                         double fVal = SwDateTimeField::GetDateTime( GetDoc(),
977                                                     aDate);
978                         aStr = ExpandValue(fVal, nFormat, nLang);
979                     }
980                     break;
981                 }
982             }
983         }
984         break;
985     }
986 
987     if( pAppLocalData != pLocalData )
988         delete pLocalData;
989 
990     return aStr;
991 }
992 
993 // document info field
994 
SwDocInfoField(SwDocInfoFieldType * pTyp,sal_uInt16 nSub,const OUString & rName,sal_uInt32 nFormat)995 SwDocInfoField::SwDocInfoField(SwDocInfoFieldType* pTyp, sal_uInt16 nSub, const OUString& rName, sal_uInt32 nFormat) :
996     SwValueField(pTyp, nFormat), m_nSubType(nSub)
997 {
998     m_aName = rName;
999     m_aContent = static_cast<SwDocInfoFieldType*>(GetTyp())->Expand(m_nSubType, nFormat, GetLanguage(), m_aName);
1000 }
1001 
SwDocInfoField(SwDocInfoFieldType * pTyp,sal_uInt16 nSub,const OUString & rName,const OUString & rValue,sal_uInt32 nFormat)1002 SwDocInfoField::SwDocInfoField(SwDocInfoFieldType* pTyp, sal_uInt16 nSub, const OUString& rName, const OUString& rValue, sal_uInt32 nFormat) :
1003     SwValueField(pTyp, nFormat), m_nSubType(nSub)
1004 {
1005     m_aName = rName;
1006     m_aContent = rValue;
1007 }
1008 
1009 template<class T>
lcl_TimeToDouble(const T & rTime)1010 static double lcl_TimeToDouble( const T& rTime )
1011 {
1012     const double fNanoSecondsPerDay = 86400000000000.0;
1013     return (  (rTime.Hours   * SAL_CONST_INT64(3600000000000))
1014             + (rTime.Minutes * SAL_CONST_INT64(  60000000000))
1015             + (rTime.Seconds * SAL_CONST_INT64(   1000000000))
1016             + (rTime.NanoSeconds))
1017         / fNanoSecondsPerDay;
1018 }
1019 
1020 template<class D>
lcl_DateToDouble(const D & rDate,const Date & rNullDate)1021 static double lcl_DateToDouble( const D& rDate, const Date& rNullDate )
1022 {
1023     long nDate = Date::DateToDays( rDate.Day, rDate.Month, rDate.Year );
1024     long nNullDate = Date::DateToDays( rNullDate.GetDay(), rNullDate.GetMonth(), rNullDate.GetYear() );
1025     return double( nDate - nNullDate );
1026 }
1027 
ExpandImpl(SwRootFrame const * const) const1028 OUString SwDocInfoField::ExpandImpl(SwRootFrame const*const) const
1029 {
1030     if ( ( m_nSubType & 0xFF ) == DI_CUSTOM )
1031     {
1032         // custom properties currently need special treatment
1033         // We don't have a secure way to detect "real" custom properties in Word import of text
1034         // fields, so we treat *every* unknown property as a custom property, even the "built-in"
1035         // section in Word's document summary information stream as these properties have not been
1036         // inserted when the document summary information was imported, we do it here.
1037         // This approach is still a lot better than the old one to import such fields as
1038         // "user fields" and simple text
1039         SwDocShell* pDocShell = GetDoc()->GetDocShell();
1040         if( !pDocShell )
1041             return m_aContent;
1042         try
1043         {
1044             uno::Reference<document::XDocumentPropertiesSupplier> xDPS( pDocShell->GetModel(), uno::UNO_QUERY_THROW);
1045             uno::Reference<document::XDocumentProperties> xDocProps( xDPS->getDocumentProperties());
1046             uno::Reference < beans::XPropertySet > xSet( xDocProps->getUserDefinedProperties(), uno::UNO_QUERY_THROW);
1047             uno::Reference < beans::XPropertySetInfo > xSetInfo = xSet->getPropertySetInfo();
1048 
1049             uno::Any aAny;
1050             if( xSetInfo->hasPropertyByName( m_aName ) )
1051                 aAny = xSet->getPropertyValue( m_aName );
1052             if ( aAny.getValueType() != cppu::UnoType<void>::get() )
1053             {
1054                 // "void" type means that the property has not been inserted until now
1055                 if ( !IsFixed() )
1056                 {
1057                     // if the field is "fixed" we don't update it from the property
1058                     OUString sVal;
1059                     uno::Reference < script::XTypeConverter > xConverter( script::Converter::create(comphelper::getProcessComponentContext()) );
1060                     util::Date aDate;
1061                     util::DateTime aDateTime;
1062                     util::Duration aDuration;
1063                     if( aAny >>= aDate)
1064                     {
1065                         SvNumberFormatter* pFormatter = pDocShell->GetDoc()->GetNumberFormatter();
1066                         const Date& rNullDate = pFormatter->GetNullDate();
1067                         sVal = ExpandValue( lcl_DateToDouble<util::Date>( aDate, rNullDate ), GetFormat(), GetLanguage());
1068                     }
1069                     else if( aAny >>= aDateTime )
1070                     {
1071                         double fDateTime = lcl_TimeToDouble<util::DateTime>( aDateTime );
1072                         SvNumberFormatter* pFormatter = pDocShell->GetDoc()->GetNumberFormatter();
1073                         const Date& rNullDate = pFormatter->GetNullDate();
1074                         fDateTime += lcl_DateToDouble<util::DateTime>( aDateTime, rNullDate );
1075                         sVal = ExpandValue( fDateTime, GetFormat(), GetLanguage());
1076                     }
1077                     else if( aAny >>= aDuration )
1078                     {
1079                         sVal = OUStringChar(aDuration.Negative ? '-' : '+')
1080                              + SwViewShell::GetShellRes()->sDurationFormat;
1081                         sVal = sVal.replaceFirst("%1", OUString::number( aDuration.Years  ) );
1082                         sVal = sVal.replaceFirst("%2", OUString::number( aDuration.Months ) );
1083                         sVal = sVal.replaceFirst("%3", OUString::number( aDuration.Days   ) );
1084                         sVal = sVal.replaceFirst("%4", OUString::number( aDuration.Hours  ) );
1085                         sVal = sVal.replaceFirst("%5", OUString::number( aDuration.Minutes) );
1086                         sVal = sVal.replaceFirst("%6", OUString::number( aDuration.Seconds) );
1087                     }
1088                     else
1089                     {
1090                         uno::Any aNew = xConverter->convertToSimpleType( aAny, uno::TypeClass_STRING );
1091                         aNew >>= sVal;
1092                     }
1093                     const_cast<SwDocInfoField*>(this)->m_aContent = sVal;
1094                 }
1095             }
1096         }
1097         catch (uno::Exception&) {}
1098     }
1099     else if ( !IsFixed() )
1100         const_cast<SwDocInfoField*>(this)->m_aContent = static_cast<SwDocInfoFieldType*>(GetTyp())->Expand(m_nSubType, GetFormat(), GetLanguage(), m_aName);
1101 
1102     return m_aContent;
1103 }
1104 
GetFieldName() const1105 OUString SwDocInfoField::GetFieldName() const
1106 {
1107     OUString aStr(SwFieldType::GetTypeStr(GetTypeId()) + ":");
1108 
1109     sal_uInt16 const nSub = m_nSubType & 0xff;
1110 
1111     switch (nSub)
1112     {
1113         case DI_CUSTOM:
1114             aStr += m_aName;
1115             break;
1116 
1117         default:
1118             aStr += SwViewShell::GetShellRes()
1119                      ->aDocInfoLst[ nSub - DI_SUBTYPE_BEGIN ];
1120             break;
1121     }
1122     if (IsFixed())
1123     {
1124         aStr += " " + SwViewShell::GetShellRes()->aFixedStr;
1125     }
1126     return aStr;
1127 }
1128 
Copy() const1129 std::unique_ptr<SwField> SwDocInfoField::Copy() const
1130 {
1131     std::unique_ptr<SwDocInfoField> pField(new SwDocInfoField(static_cast<SwDocInfoFieldType*>(GetTyp()), m_nSubType, m_aName, GetFormat()));
1132     pField->SetAutomaticLanguage(IsAutomaticLanguage());
1133     pField->m_aContent = m_aContent;
1134 
1135     return std::unique_ptr<SwField>(pField.release());
1136 }
1137 
GetSubType() const1138 sal_uInt16 SwDocInfoField::GetSubType() const
1139 {
1140     return m_nSubType;
1141 }
1142 
SetSubType(sal_uInt16 nSub)1143 void SwDocInfoField::SetSubType(sal_uInt16 nSub)
1144 {
1145     m_nSubType = nSub;
1146 }
1147 
SetLanguage(LanguageType nLng)1148 void SwDocInfoField::SetLanguage(LanguageType nLng)
1149 {
1150     if (!GetFormat())
1151         SwField::SetLanguage(nLng);
1152     else
1153         SwValueField::SetLanguage(nLng);
1154 }
1155 
QueryValue(uno::Any & rAny,sal_uInt16 nWhichId) const1156 bool SwDocInfoField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
1157 {
1158     switch( nWhichId )
1159     {
1160     case FIELD_PROP_PAR1:
1161         rAny <<= m_aContent;
1162         break;
1163 
1164     case FIELD_PROP_PAR4:
1165         rAny <<= m_aName;
1166         break;
1167 
1168     case FIELD_PROP_USHORT1:
1169         rAny  <<= static_cast<sal_Int16>(m_aContent.toInt32());
1170         break;
1171 
1172     case FIELD_PROP_BOOL1:
1173         rAny <<= 0 != (m_nSubType & DI_SUB_FIXED);
1174         break;
1175 
1176     case FIELD_PROP_FORMAT:
1177         rAny  <<= static_cast<sal_Int32>(GetFormat());
1178         break;
1179 
1180     case FIELD_PROP_DOUBLE:
1181         {
1182             double fVal = GetValue();
1183             rAny <<= fVal;
1184         }
1185         break;
1186     case FIELD_PROP_PAR3:
1187         rAny <<= ExpandImpl(nullptr);
1188         break;
1189     case FIELD_PROP_BOOL2:
1190         {
1191             sal_uInt16 nExtSub = (m_nSubType & 0xff00) & ~DI_SUB_FIXED;
1192             rAny <<= nExtSub == DI_SUB_DATE;
1193         }
1194         break;
1195     default:
1196         return SwField::QueryValue(rAny, nWhichId);
1197     }
1198     return true;
1199 }
1200 
PutValue(const uno::Any & rAny,sal_uInt16 nWhichId)1201 bool SwDocInfoField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
1202 {
1203     sal_Int32 nValue = 0;
1204     switch( nWhichId )
1205     {
1206     case FIELD_PROP_PAR1:
1207         if( m_nSubType & DI_SUB_FIXED )
1208             rAny >>= m_aContent;
1209         break;
1210 
1211     case FIELD_PROP_USHORT1:
1212         if( m_nSubType & DI_SUB_FIXED )
1213         {
1214             rAny >>= nValue;
1215             m_aContent = OUString::number(nValue);
1216         }
1217         break;
1218 
1219     case FIELD_PROP_BOOL1:
1220         if(*o3tl::doAccess<bool>(rAny))
1221             m_nSubType |= DI_SUB_FIXED;
1222         else
1223             m_nSubType &= ~DI_SUB_FIXED;
1224         break;
1225     case FIELD_PROP_FORMAT:
1226         {
1227             rAny >>= nValue;
1228             if( nValue >= 0)
1229                 SetFormat(nValue);
1230         }
1231         break;
1232 
1233     case FIELD_PROP_PAR3:
1234         rAny >>= m_aContent;
1235         break;
1236     case FIELD_PROP_BOOL2:
1237         m_nSubType &= 0xf0ff;
1238         if(*o3tl::doAccess<bool>(rAny))
1239             m_nSubType |= DI_SUB_DATE;
1240         else
1241             m_nSubType |= DI_SUB_TIME;
1242         break;
1243     default:
1244         return SwField::PutValue(rAny, nWhichId);
1245     }
1246     return true;
1247 }
1248 
SwHiddenTextFieldType(bool bSetHidden)1249 SwHiddenTextFieldType::SwHiddenTextFieldType( bool bSetHidden )
1250     : SwFieldType( SwFieldIds::HiddenText ), m_bHidden( bSetHidden )
1251 {
1252 }
1253 
Copy() const1254 std::unique_ptr<SwFieldType> SwHiddenTextFieldType::Copy() const
1255 {
1256     return std::make_unique<SwHiddenTextFieldType>( m_bHidden );
1257 }
1258 
SetHiddenFlag(bool bSetHidden)1259 void SwHiddenTextFieldType::SetHiddenFlag( bool bSetHidden )
1260 {
1261     if( m_bHidden != bSetHidden )
1262     {
1263         m_bHidden = bSetHidden;
1264         UpdateFields();       // notify all HiddenTexts
1265     }
1266 }
1267 
SwHiddenTextField(SwHiddenTextFieldType * pFieldType,bool bConditional,const OUString & rCond,const OUString & rStr,bool bHidden,SwFieldTypesEnum nSub)1268 SwHiddenTextField::SwHiddenTextField( SwHiddenTextFieldType* pFieldType,
1269                                     bool    bConditional,
1270                                     const OUString& rCond,
1271                                     const OUString& rStr,
1272                                     bool    bHidden,
1273                                     SwFieldTypesEnum  nSub) :
1274     SwField( pFieldType ), m_aCond(rCond), m_nSubType(nSub),
1275     m_bCanToggle(bConditional), m_bIsHidden(bHidden), m_bValid(false)
1276 {
1277     if(m_nSubType == SwFieldTypesEnum::ConditionalText)
1278     {
1279         sal_Int32 nPos = 0;
1280         m_aTRUEText = rStr.getToken(0, '|', nPos);
1281 
1282         if(nPos != -1)
1283         {
1284             m_aFALSEText = rStr.getToken(0, '|', nPos);
1285             if(nPos != -1)
1286             {
1287                 m_aContent = rStr.getToken(0, '|', nPos);
1288                 m_bValid = true;
1289             }
1290         }
1291     }
1292     else
1293         m_aTRUEText = rStr;
1294 }
1295 
SwHiddenTextField(SwHiddenTextFieldType * pFieldType,const OUString & rCond,const OUString & rTrue,const OUString & rFalse,SwFieldTypesEnum nSub)1296 SwHiddenTextField::SwHiddenTextField( SwHiddenTextFieldType* pFieldType,
1297                                     const OUString& rCond,
1298                                     const OUString& rTrue,
1299                                     const OUString& rFalse,
1300                                     SwFieldTypesEnum nSub)
1301     : SwField( pFieldType ), m_aTRUEText(rTrue), m_aFALSEText(rFalse), m_aCond(rCond), m_nSubType(nSub),
1302       m_bIsHidden(true), m_bValid(false)
1303 {
1304     m_bCanToggle = !m_aCond.isEmpty();
1305 }
1306 
ExpandImpl(SwRootFrame const * const) const1307 OUString SwHiddenTextField::ExpandImpl(SwRootFrame const*const) const
1308 {
1309     // Type: !Hidden  -> show always
1310     //        Hide    -> evaluate condition
1311 
1312     if( SwFieldTypesEnum::ConditionalText == m_nSubType )
1313     {
1314         if( m_bValid )
1315             return m_aContent;
1316 
1317         if( m_bCanToggle && !m_bIsHidden )
1318             return m_aTRUEText;
1319     }
1320     else if( !static_cast<SwHiddenTextFieldType*>(GetTyp())->GetHiddenFlag() ||
1321         ( m_bCanToggle && m_bIsHidden ))
1322         return m_aTRUEText;
1323 
1324     return m_aFALSEText;
1325 }
1326 
1327 /// get current field value and cache it
Evaluate(SwDoc * pDoc)1328 void SwHiddenTextField::Evaluate(SwDoc* pDoc)
1329 {
1330     OSL_ENSURE(pDoc, "got no document");
1331 
1332     if( SwFieldTypesEnum::ConditionalText == m_nSubType )
1333     {
1334 #if !HAVE_FEATURE_DBCONNECTIVITY
1335         (void) pDoc;
1336 #else
1337         SwDBManager* pMgr = pDoc->GetDBManager();
1338 #endif
1339         m_bValid = false;
1340         OUString sTmpName = (m_bCanToggle && !m_bIsHidden) ? m_aTRUEText : m_aFALSEText;
1341 
1342         // Database expressions need to be different from normal text. Therefore, normal text is set
1343         // in quotes. If the latter exist they will be removed. If not, check if potential DB name.
1344         // Only if there are two or more dots and no quotes, we assume a database.
1345         if (sTmpName.getLength()>1 &&
1346             sTmpName.startsWith("\"") &&
1347             sTmpName.endsWith("\""))
1348         {
1349             m_aContent = sTmpName.copy(1, sTmpName.getLength() - 2);
1350             m_bValid = true;
1351         }
1352         else if(sTmpName.indexOf('\"')<0 &&
1353             comphelper::string::getTokenCount(sTmpName, '.') > 2)
1354         {
1355             sTmpName = ::ReplacePoint(sTmpName);
1356             if(sTmpName.startsWith("[") && sTmpName.endsWith("]"))
1357             {   // remove brackets
1358                 sTmpName = sTmpName.copy(1, sTmpName.getLength() - 2);
1359             }
1360 #if HAVE_FEATURE_DBCONNECTIVITY
1361             if( pMgr)
1362             {
1363                 sal_Int32 nIdx{ 0 };
1364                 OUString sDBName( GetDBName( sTmpName, pDoc ));
1365                 OUString sDataSource(sDBName.getToken(0, DB_DELIM, nIdx));
1366                 OUString sDataTableOrQuery(sDBName.getToken(0, DB_DELIM, nIdx));
1367                 if( pMgr->IsInMerge() && !sDBName.isEmpty() &&
1368                     pMgr->IsDataSourceOpen( sDataSource,
1369                                                 sDataTableOrQuery, false))
1370                 {
1371                     double fNumber;
1372                     pMgr->GetMergeColumnCnt(GetColumnName( sTmpName ),
1373                         GetLanguage(), m_aContent, &fNumber );
1374                     m_bValid = true;
1375                 }
1376                 else if( !sDBName.isEmpty() && !sDataSource.isEmpty() &&
1377                          !sDataTableOrQuery.isEmpty() )
1378                     m_bValid = true;
1379             }
1380 #endif
1381         }
1382     }
1383 }
1384 
GetFieldName() const1385 OUString SwHiddenTextField::GetFieldName() const
1386 {
1387     OUString aStr = SwFieldType::GetTypeStr(m_nSubType) +
1388         " " + m_aCond + " " + m_aTRUEText;
1389 
1390     if (m_nSubType == SwFieldTypesEnum::ConditionalText)
1391     {
1392         aStr += " : " + m_aFALSEText;
1393     }
1394     return aStr;
1395 }
1396 
Copy() const1397 std::unique_ptr<SwField> SwHiddenTextField::Copy() const
1398 {
1399     std::unique_ptr<SwHiddenTextField> pField(
1400         new SwHiddenTextField(static_cast<SwHiddenTextFieldType*>(GetTyp()), m_aCond,
1401                               m_aTRUEText, m_aFALSEText));
1402     pField->m_bIsHidden = m_bIsHidden;
1403     pField->m_bValid    = m_bValid;
1404     pField->m_aContent  = m_aContent;
1405     pField->SetFormat(GetFormat());
1406     pField->m_nSubType  = m_nSubType;
1407     return std::unique_ptr<SwField>(pField.release());
1408 }
1409 
1410 /// set condition
SetPar1(const OUString & rStr)1411 void SwHiddenTextField::SetPar1(const OUString& rStr)
1412 {
1413     m_aCond = rStr;
1414     m_bCanToggle = !m_aCond.isEmpty();
1415 }
1416 
GetPar1() const1417 OUString SwHiddenTextField::GetPar1() const
1418 {
1419     return m_aCond;
1420 }
1421 
1422 /// set True/False text
SetPar2(const OUString & rStr)1423 void SwHiddenTextField::SetPar2(const OUString& rStr)
1424 {
1425     if (m_nSubType == SwFieldTypesEnum::ConditionalText)
1426     {
1427         sal_Int32 nPos = rStr.indexOf('|');
1428         if (nPos == -1)
1429             m_aTRUEText = rStr;
1430         else
1431         {
1432             m_aTRUEText = rStr.copy(0, nPos);
1433             m_aFALSEText = rStr.copy(nPos + 1);
1434         }
1435     }
1436     else
1437         m_aTRUEText = rStr;
1438 }
1439 
1440 /// get True/False text
GetPar2() const1441 OUString SwHiddenTextField::GetPar2() const
1442 {
1443     if(m_nSubType != SwFieldTypesEnum::ConditionalText)
1444     {
1445         return m_aTRUEText;
1446     }
1447     return m_aTRUEText + "|" + m_aFALSEText;
1448 }
1449 
GetSubType() const1450 sal_uInt16 SwHiddenTextField::GetSubType() const
1451 {
1452     return static_cast<sal_uInt16>(m_nSubType);
1453 }
1454 
QueryValue(uno::Any & rAny,sal_uInt16 nWhichId) const1455 bool SwHiddenTextField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
1456 {
1457     switch( nWhichId )
1458     {
1459     case FIELD_PROP_PAR1:
1460         rAny <<= m_aCond;
1461         break;
1462     case FIELD_PROP_PAR2:
1463         rAny <<= m_aTRUEText;
1464         break;
1465     case FIELD_PROP_PAR3:
1466         rAny <<= m_aFALSEText;
1467         break;
1468     case FIELD_PROP_PAR4 :
1469         rAny <<= m_aContent;
1470         break;
1471     case FIELD_PROP_BOOL1:
1472         rAny <<= m_bIsHidden;
1473         break;
1474     default:
1475         assert(false);
1476     }
1477     return true;
1478 }
1479 
PutValue(const uno::Any & rAny,sal_uInt16 nWhichId)1480 bool SwHiddenTextField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
1481 {
1482     switch( nWhichId )
1483     {
1484     case FIELD_PROP_PAR1:
1485         {
1486             OUString sVal;
1487             rAny >>= sVal;
1488             SetPar1(sVal);
1489         }
1490         break;
1491     case FIELD_PROP_PAR2:
1492         rAny >>= m_aTRUEText;
1493         break;
1494     case FIELD_PROP_PAR3:
1495         rAny >>= m_aFALSEText;
1496         break;
1497     case FIELD_PROP_BOOL1:
1498         m_bIsHidden = *o3tl::doAccess<bool>(rAny);
1499         break;
1500     case FIELD_PROP_PAR4:
1501         rAny >>= m_aContent;
1502         m_bValid = true;
1503         break;
1504     default:
1505         assert(false);
1506     }
1507     return true;
1508 }
1509 
GetColumnName(const OUString & rName)1510 OUString SwHiddenTextField::GetColumnName(const OUString& rName)
1511 {
1512     sal_Int32 nPos = rName.indexOf(DB_DELIM);
1513     if( nPos>=0 )
1514     {
1515         nPos = rName.indexOf(DB_DELIM, nPos + 1);
1516 
1517         if( nPos>=0 )
1518             return rName.copy(nPos + 1);
1519     }
1520     return rName;
1521 }
1522 
GetDBName(const OUString & rName,SwDoc * pDoc)1523 OUString SwHiddenTextField::GetDBName(const OUString& rName, SwDoc *pDoc)
1524 {
1525     sal_Int32 nPos = rName.indexOf(DB_DELIM);
1526     if( nPos>=0 )
1527     {
1528         nPos = rName.indexOf(DB_DELIM, nPos + 1);
1529 
1530         if( nPos>=0 )
1531             return rName.copy(0, nPos);
1532     }
1533 
1534     SwDBData aData = pDoc->GetDBData();
1535     return aData.sDataSource + OUStringChar(DB_DELIM) + aData.sCommand;
1536 }
1537 
1538 // [aFieldDefinition] value sample : " IF A == B \"TrueText\" \"FalseText\""
ParseIfFieldDefinition(const OUString & aFieldDefinition,OUString & rCondition,OUString & rTrue,OUString & rFalse)1539 void SwHiddenTextField::ParseIfFieldDefinition(const OUString& aFieldDefinition,
1540                                                OUString& rCondition,
1541                                                OUString& rTrue,
1542                                                OUString& rFalse)
1543 {
1544     // get all positions inside the input string where words are started
1545     //
1546     // In: " IF A == B \"TrueText\" \"FalseText\""
1547     //      0         1           2          3
1548     //      01234567890 123456789 01 2345678901 2
1549     //
1550     // result:
1551     //      [1, 4, 6, 9, 11, 22]
1552     std::vector<sal_Int32> wordPosition;
1553     {
1554         bool quoted = false;
1555         bool insideWord = false;
1556         for (sal_Int32 i = 0; i < aFieldDefinition.getLength(); i++)
1557         {
1558             if (quoted)
1559             {
1560                 if (aFieldDefinition[i] == '\"')
1561                 {
1562                     quoted = false;
1563                     insideWord = false;
1564                 }
1565             }
1566             else
1567             {
1568                 if (aFieldDefinition[i] == ' ')
1569                 {
1570                     // word delimiter
1571                     insideWord = false;
1572                 }
1573                 else
1574                 {
1575                     if (insideWord)
1576                     {
1577                         quoted = (aFieldDefinition[i] == '\"');
1578                     }
1579                     else
1580                     {
1581                         insideWord = true;
1582                         wordPosition.push_back(i);
1583                         quoted = (aFieldDefinition[i] == '\"');
1584                     }
1585                 }
1586             }
1587         }
1588     }
1589 
1590     // first word is always "IF"
1591     // last two words are: true-case and false-case,
1592     // everything before is treated as condition expression
1593     // => we need at least 4 words to be inside the input string
1594     if (wordPosition.size() < 4)
1595     {
1596         return;
1597     }
1598 
1599 
1600     const sal_Int32 conditionBegin = wordPosition[1];
1601     const sal_Int32 trueBegin      = wordPosition[wordPosition.size() - 2];
1602     const sal_Int32 falseBegin     = wordPosition[wordPosition.size() - 1];
1603 
1604     const sal_Int32 conditionLength = trueBegin - conditionBegin;
1605     const sal_Int32 trueLength      = falseBegin - trueBegin;
1606 
1607     // Syntax
1608     // OUString::copy( sal_Int32 beginIndex, sal_Int32 count )
1609     rCondition = aFieldDefinition.copy(conditionBegin, conditionLength);
1610     rTrue = aFieldDefinition.copy(trueBegin, trueLength);
1611     rFalse = aFieldDefinition.copy(falseBegin);
1612 
1613     // trim
1614     rCondition = rCondition.trim();
1615     rTrue = rTrue.trim();
1616     rFalse = rFalse.trim();
1617 
1618     // remove quotes
1619     if (rCondition.getLength() >= 2)
1620     {
1621         if (rCondition[0] == '\"' && rCondition[rCondition.getLength() - 1] == '\"')
1622             rCondition = rCondition.copy(1, rCondition.getLength() - 2);
1623     }
1624     if (rTrue.getLength() >= 2)
1625     {
1626         if (rTrue[0] == '\"' && rTrue[rTrue.getLength() - 1] == '\"')
1627             rTrue = rTrue.copy(1, rTrue.getLength() - 2);
1628     }
1629     if (rFalse.getLength() >= 2)
1630     {
1631         if (rFalse[0] == '\"' && rFalse[rFalse.getLength() - 1] == '\"')
1632             rFalse = rFalse.copy(1, rFalse.getLength() - 2);
1633     }
1634 
1635     // Note: do not make trim once again, while this is a user defined data
1636 }
1637 
1638 // field type for line height 0
1639 
SwHiddenParaFieldType()1640 SwHiddenParaFieldType::SwHiddenParaFieldType()
1641     : SwFieldType( SwFieldIds::HiddenPara )
1642 {
1643 }
1644 
Copy() const1645 std::unique_ptr<SwFieldType> SwHiddenParaFieldType::Copy() const
1646 {
1647     return std::make_unique<SwHiddenParaFieldType>();
1648 }
1649 
1650 // field for line height 0
1651 
SwHiddenParaField(SwHiddenParaFieldType * pTyp,const OUString & rStr)1652 SwHiddenParaField::SwHiddenParaField(SwHiddenParaFieldType* pTyp, const OUString& rStr)
1653     : SwField(pTyp), m_aCond(rStr)
1654 {
1655     m_bIsHidden = false;
1656 }
1657 
ExpandImpl(SwRootFrame const * const) const1658 OUString SwHiddenParaField::ExpandImpl(SwRootFrame const*const) const
1659 {
1660     return OUString();
1661 }
1662 
Copy() const1663 std::unique_ptr<SwField> SwHiddenParaField::Copy() const
1664 {
1665     std::unique_ptr<SwHiddenParaField> pField(new SwHiddenParaField(static_cast<SwHiddenParaFieldType*>(GetTyp()), m_aCond));
1666     pField->m_bIsHidden = m_bIsHidden;
1667     return std::unique_ptr<SwField>(pField.release());
1668 }
1669 
QueryValue(uno::Any & rAny,sal_uInt16 nWhichId) const1670 bool SwHiddenParaField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
1671 {
1672     switch ( nWhichId )
1673     {
1674     case FIELD_PROP_PAR1:
1675         rAny <<= m_aCond;
1676         break;
1677     case  FIELD_PROP_BOOL1:
1678         rAny <<= m_bIsHidden;
1679         break;
1680 
1681     default:
1682         assert(false);
1683     }
1684     return true;
1685 }
1686 
PutValue(const uno::Any & rAny,sal_uInt16 nWhichId)1687 bool SwHiddenParaField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
1688 {
1689     switch ( nWhichId )
1690     {
1691     case FIELD_PROP_PAR1:
1692         rAny >>= m_aCond;
1693         break;
1694     case FIELD_PROP_BOOL1:
1695         m_bIsHidden = *o3tl::doAccess<bool>(rAny);
1696         break;
1697 
1698     default:
1699         assert(false);
1700     }
1701     return true;
1702 }
1703 
1704 /// set condition
SetPar1(const OUString & rStr)1705 void SwHiddenParaField::SetPar1(const OUString& rStr)
1706 {
1707     m_aCond = rStr;
1708 }
1709 
GetPar1() const1710 OUString SwHiddenParaField::GetPar1() const
1711 {
1712     return m_aCond;
1713 }
1714 
1715 // PostIt field type
1716 
SwPostItFieldType(SwDoc * pDoc)1717 SwPostItFieldType::SwPostItFieldType(SwDoc *pDoc)
1718     : SwFieldType( SwFieldIds::Postit )
1719     , mpDoc(pDoc)
1720 {}
1721 
Copy() const1722 std::unique_ptr<SwFieldType> SwPostItFieldType::Copy() const
1723 {
1724     return std::make_unique<SwPostItFieldType>(mpDoc);
1725 }
1726 
1727 // PostIt field
1728 
1729 sal_uInt32 SwPostItField::m_nLastPostItId = 1;
1730 
SwPostItField(SwPostItFieldType * pT,const OUString & rAuthor,const OUString & rText,const OUString & rInitials,const OUString & rName,const DateTime & rDateTime,const bool bResolved,const sal_uInt32 nPostItId)1731 SwPostItField::SwPostItField( SwPostItFieldType* pT,
1732         const OUString& rAuthor,
1733         const OUString& rText,
1734         const OUString& rInitials,
1735         const OUString& rName,
1736         const DateTime& rDateTime,
1737         const bool bResolved,
1738         const sal_uInt32 nPostItId
1739 )
1740     : SwField( pT )
1741     , m_sText( rText )
1742     , m_sAuthor( rAuthor )
1743     , m_sInitials( rInitials )
1744     , m_sName( rName )
1745     , m_aDateTime( rDateTime )
1746     , m_bResolved( bResolved )
1747 {
1748     m_nPostItId = nPostItId == 0 ? m_nLastPostItId++ : nPostItId;
1749 }
1750 
~SwPostItField()1751 SwPostItField::~SwPostItField()
1752 {
1753     if ( m_xTextObject.is() )
1754     {
1755         m_xTextObject->DisposeEditSource();
1756     }
1757 
1758     mpText.reset();
1759 }
1760 
ExpandImpl(SwRootFrame const * const) const1761 OUString SwPostItField::ExpandImpl(SwRootFrame const*const) const
1762 {
1763     return OUString();
1764 }
1765 
GetDescription() const1766 OUString SwPostItField::GetDescription() const
1767 {
1768     return SwResId(STR_NOTE);
1769 }
1770 
SetResolved(bool bNewState)1771 void SwPostItField::SetResolved(bool bNewState)
1772 {
1773     m_bResolved = bNewState;
1774 }
1775 
ToggleResolved()1776 void SwPostItField::ToggleResolved()
1777 {
1778     m_bResolved = !m_bResolved;
1779 }
1780 
GetResolved() const1781 bool SwPostItField::GetResolved() const
1782 {
1783     return m_bResolved;
1784 }
1785 
Copy() const1786 std::unique_ptr<SwField> SwPostItField::Copy() const
1787 {
1788     std::unique_ptr<SwPostItField> pRet(new SwPostItField( static_cast<SwPostItFieldType*>(GetTyp()), m_sAuthor, m_sText, m_sInitials, m_sName,
1789                                                            m_aDateTime, m_bResolved, m_nPostItId));
1790     if (mpText)
1791         pRet->SetTextObject( std::make_unique<OutlinerParaObject>(*mpText) );
1792 
1793     // Note: member <m_xTextObject> not copied.
1794 
1795     return std::unique_ptr<SwField>(pRet.release());
1796 }
1797 
1798 /// set author
SetPar1(const OUString & rStr)1799 void SwPostItField::SetPar1(const OUString& rStr)
1800 {
1801     m_sAuthor = rStr;
1802 }
1803 
1804 /// get author
GetPar1() const1805 OUString SwPostItField::GetPar1() const
1806 {
1807     return m_sAuthor;
1808 }
1809 
1810 /// set the PostIt's text
SetPar2(const OUString & rStr)1811 void SwPostItField::SetPar2(const OUString& rStr)
1812 {
1813     m_sText = rStr;
1814 }
1815 
1816 /// get the PostIt's text
GetPar2() const1817 OUString SwPostItField::GetPar2() const
1818 {
1819     return m_sText;
1820 }
1821 
1822 
SetName(const OUString & rName)1823 void SwPostItField::SetName(const OUString& rName)
1824 {
1825     m_sName = rName;
1826 }
1827 
1828 
SetTextObject(std::unique_ptr<OutlinerParaObject> pText)1829 void SwPostItField::SetTextObject( std::unique_ptr<OutlinerParaObject> pText )
1830 {
1831     mpText = std::move(pText);
1832 }
1833 
GetNumberOfParagraphs() const1834 sal_Int32 SwPostItField::GetNumberOfParagraphs() const
1835 {
1836     return mpText ? mpText->Count() : 1;
1837 }
1838 
QueryValue(uno::Any & rAny,sal_uInt16 nWhichId) const1839 bool SwPostItField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
1840 {
1841     switch( nWhichId )
1842     {
1843     case FIELD_PROP_PAR1:
1844         rAny <<= m_sAuthor;
1845         break;
1846     case FIELD_PROP_PAR2:
1847         {
1848         rAny <<= m_sText;
1849         break;
1850         }
1851     case FIELD_PROP_PAR3:
1852         rAny <<= m_sInitials;
1853         break;
1854     case FIELD_PROP_PAR4:
1855         rAny <<= m_sName;
1856         break;
1857     case FIELD_PROP_BOOL1:
1858         rAny <<= m_bResolved;
1859         break;
1860     case FIELD_PROP_TEXT:
1861         {
1862             if ( !m_xTextObject.is() )
1863             {
1864                 SwPostItFieldType* pGetType = static_cast<SwPostItFieldType*>(GetTyp());
1865                 SwDoc* pDoc = pGetType->GetDoc();
1866                 auto pObj = std::make_unique<SwTextAPIEditSource>( pDoc );
1867                 const_cast <SwPostItField*> (this)->m_xTextObject = new SwTextAPIObject( std::move(pObj) );
1868             }
1869 
1870             if ( mpText )
1871                 m_xTextObject->SetText( *mpText );
1872             else
1873                 m_xTextObject->SetString( m_sText );
1874 
1875             uno::Reference < text::XText > xText( m_xTextObject.get() );
1876             rAny <<= xText;
1877             break;
1878         }
1879     case FIELD_PROP_DATE:
1880         {
1881             rAny <<= m_aDateTime.GetUNODate();
1882         }
1883         break;
1884     case FIELD_PROP_DATE_TIME:
1885         {
1886             rAny <<= m_aDateTime.GetUNODateTime();
1887         }
1888         break;
1889     default:
1890         assert(false);
1891     }
1892     return true;
1893 }
1894 
PutValue(const uno::Any & rAny,sal_uInt16 nWhichId)1895 bool SwPostItField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
1896 {
1897     switch( nWhichId )
1898     {
1899     case FIELD_PROP_PAR1:
1900         rAny >>= m_sAuthor;
1901         break;
1902     case FIELD_PROP_PAR2:
1903         rAny >>= m_sText;
1904         //#i100374# new string via api, delete complex text object so SwPostItNote picks up the new string
1905         mpText.reset();
1906         break;
1907     case FIELD_PROP_PAR3:
1908         rAny >>= m_sInitials;
1909         break;
1910     case FIELD_PROP_PAR4:
1911         rAny >>= m_sName;
1912         break;
1913     case FIELD_PROP_BOOL1:
1914         rAny >>= m_bResolved;
1915         break;
1916     case FIELD_PROP_TEXT:
1917         OSL_FAIL("Not implemented!");
1918         break;
1919     case FIELD_PROP_DATE:
1920         if( auto aSetDate = o3tl::tryAccess<util::Date>(rAny) )
1921         {
1922             m_aDateTime = Date(aSetDate->Day, aSetDate->Month, aSetDate->Year);
1923         }
1924         break;
1925     case FIELD_PROP_DATE_TIME:
1926     {
1927         util::DateTime aDateTimeValue;
1928         if(!(rAny >>= aDateTimeValue))
1929             return false;
1930         m_aDateTime = DateTime(aDateTimeValue);
1931     }
1932     break;
1933     default:
1934         assert(false);
1935     }
1936     return true;
1937 }
1938 
dumpAsXml(xmlTextWriterPtr pWriter) const1939 void SwPostItField::dumpAsXml(xmlTextWriterPtr pWriter) const
1940 {
1941     xmlTextWriterStartElement(pWriter, BAD_CAST("SwPostItField"));
1942     xmlTextWriterWriteAttribute(pWriter, BAD_CAST("name"), BAD_CAST(GetName().toUtf8().getStr()));
1943 
1944     SwField::dumpAsXml(pWriter);
1945 
1946     xmlTextWriterStartElement(pWriter, BAD_CAST("mpText"));
1947     xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("ptr"), "%p", mpText.get());
1948     if (mpText)
1949         mpText->dumpAsXml(pWriter);
1950     xmlTextWriterEndElement(pWriter);
1951 
1952     xmlTextWriterEndElement(pWriter);
1953 }
1954 
1955 // extended user information field type
1956 
SwExtUserFieldType()1957 SwExtUserFieldType::SwExtUserFieldType()
1958     : SwFieldType( SwFieldIds::ExtUser )
1959 {
1960 }
1961 
Copy() const1962 std::unique_ptr<SwFieldType> SwExtUserFieldType::Copy() const
1963 {
1964     return std::make_unique<SwExtUserFieldType>();
1965 }
1966 
Expand(sal_uInt16 nSub)1967 OUString SwExtUserFieldType::Expand(sal_uInt16 nSub )
1968 {
1969     UserOptToken nRet = static_cast<UserOptToken>(USHRT_MAX);
1970     switch(nSub)
1971     {
1972     case EU_FIRSTNAME:      nRet = UserOptToken::FirstName; break;
1973     case EU_NAME:           nRet = UserOptToken::LastName;  break;
1974     case EU_SHORTCUT:       nRet = UserOptToken::ID; break;
1975 
1976     case EU_COMPANY:        nRet = UserOptToken::Company;        break;
1977     case EU_STREET:         nRet = UserOptToken::Street;         break;
1978     case EU_TITLE:          nRet = UserOptToken::Title;          break;
1979     case EU_POSITION:       nRet = UserOptToken::Position;       break;
1980     case EU_PHONE_PRIVATE:  nRet = UserOptToken::TelephoneHome;    break;
1981     case EU_PHONE_COMPANY:  nRet = UserOptToken::TelephoneWork;    break;
1982     case EU_FAX:            nRet = UserOptToken::Fax;            break;
1983     case EU_EMAIL:          nRet = UserOptToken::Email;          break;
1984     case EU_COUNTRY:        nRet = UserOptToken::Country;        break;
1985     case EU_ZIP:            nRet = UserOptToken::Zip;            break;
1986     case EU_CITY:           nRet = UserOptToken::City;           break;
1987     case EU_STATE:          nRet = UserOptToken::State;          break;
1988     case EU_FATHERSNAME:    nRet = UserOptToken::FathersName;    break;
1989     case EU_APARTMENT:      nRet = UserOptToken::Apartment;      break;
1990     default:             OSL_ENSURE( false, "Field unknown");
1991     }
1992     if( static_cast<UserOptToken>(USHRT_MAX) != nRet )
1993     {
1994         SvtUserOptions&  rUserOpt = SW_MOD()->GetUserOptions();
1995         return rUserOpt.GetToken( nRet );
1996     }
1997     return OUString();
1998 }
1999 
2000 // extended user information field
2001 
SwExtUserField(SwExtUserFieldType * pTyp,sal_uInt16 nSubTyp,sal_uInt32 nFormat)2002 SwExtUserField::SwExtUserField(SwExtUserFieldType* pTyp, sal_uInt16 nSubTyp, sal_uInt32 nFormat) :
2003     SwField(pTyp, nFormat), m_nType(nSubTyp)
2004 {
2005     m_aContent = SwExtUserFieldType::Expand(m_nType);
2006 }
2007 
ExpandImpl(SwRootFrame const * const) const2008 OUString SwExtUserField::ExpandImpl(SwRootFrame const*const) const
2009 {
2010     if (!IsFixed())
2011         const_cast<SwExtUserField*>(this)->m_aContent = SwExtUserFieldType::Expand(m_nType);
2012 
2013     return m_aContent;
2014 }
2015 
Copy() const2016 std::unique_ptr<SwField> SwExtUserField::Copy() const
2017 {
2018     std::unique_ptr<SwExtUserField> pField(new SwExtUserField(static_cast<SwExtUserFieldType*>(GetTyp()), m_nType, GetFormat()));
2019     pField->SetExpansion(m_aContent);
2020 
2021     return std::unique_ptr<SwField>(pField.release());
2022 }
2023 
GetSubType() const2024 sal_uInt16 SwExtUserField::GetSubType() const
2025 {
2026     return m_nType;
2027 }
2028 
SetSubType(sal_uInt16 nSub)2029 void SwExtUserField::SetSubType(sal_uInt16 nSub)
2030 {
2031     m_nType = nSub;
2032 }
2033 
QueryValue(uno::Any & rAny,sal_uInt16 nWhichId) const2034 bool SwExtUserField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
2035 {
2036     switch( nWhichId )
2037     {
2038     case FIELD_PROP_PAR1:
2039         rAny <<= m_aContent;
2040         break;
2041 
2042     case FIELD_PROP_USHORT1:
2043         {
2044             sal_Int16 nTmp = m_nType;
2045             rAny <<= nTmp;
2046         }
2047         break;
2048     case FIELD_PROP_BOOL1:
2049         rAny <<= IsFixed();
2050         break;
2051     default:
2052         assert(false);
2053     }
2054     return true;
2055 }
2056 
PutValue(const uno::Any & rAny,sal_uInt16 nWhichId)2057 bool SwExtUserField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
2058 {
2059     switch( nWhichId )
2060     {
2061     case FIELD_PROP_PAR1:
2062         rAny >>= m_aContent;
2063         break;
2064 
2065     case FIELD_PROP_USHORT1:
2066         {
2067             sal_Int16 nTmp = 0;
2068             rAny >>= nTmp;
2069             m_nType = nTmp;
2070         }
2071         break;
2072     case FIELD_PROP_BOOL1:
2073         if( *o3tl::doAccess<bool>(rAny) )
2074             SetFormat(GetFormat() | AF_FIXED);
2075         else
2076             SetFormat(GetFormat() & ~AF_FIXED);
2077         break;
2078     default:
2079         assert(false);
2080     }
2081     return true;
2082 }
2083 
2084 // field type for relative page numbers
2085 
SwRefPageSetFieldType()2086 SwRefPageSetFieldType::SwRefPageSetFieldType()
2087     : SwFieldType( SwFieldIds::RefPageSet )
2088 {
2089 }
2090 
Copy() const2091 std::unique_ptr<SwFieldType> SwRefPageSetFieldType::Copy() const
2092 {
2093     return std::make_unique<SwRefPageSetFieldType>();
2094 }
2095 
2096 // overridden since there is nothing to update
Modify(const SfxPoolItem *,const SfxPoolItem *)2097 void SwRefPageSetFieldType::Modify( const SfxPoolItem*, const SfxPoolItem * )
2098 {
2099 }
2100 
2101 // field for relative page numbers
2102 
SwRefPageSetField(SwRefPageSetFieldType * pTyp,short nOff,bool bFlag)2103 SwRefPageSetField::SwRefPageSetField( SwRefPageSetFieldType* pTyp,
2104                     short nOff, bool bFlag )
2105     : SwField( pTyp ), m_nOffset( nOff ), m_bOn( bFlag )
2106 {
2107 }
2108 
ExpandImpl(SwRootFrame const * const) const2109 OUString SwRefPageSetField::ExpandImpl(SwRootFrame const*const) const
2110 {
2111     return OUString();
2112 }
2113 
Copy() const2114 std::unique_ptr<SwField> SwRefPageSetField::Copy() const
2115 {
2116     return std::make_unique<SwRefPageSetField>( static_cast<SwRefPageSetFieldType*>(GetTyp()), m_nOffset, m_bOn );
2117 }
2118 
GetPar2() const2119 OUString SwRefPageSetField::GetPar2() const
2120 {
2121     return OUString::number(GetOffset());
2122 }
2123 
SetPar2(const OUString & rStr)2124 void SwRefPageSetField::SetPar2(const OUString& rStr)
2125 {
2126     SetOffset( static_cast<short>(rStr.toInt32()) );
2127 }
2128 
QueryValue(uno::Any & rAny,sal_uInt16 nWhichId) const2129 bool SwRefPageSetField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
2130 {
2131     switch( nWhichId )
2132     {
2133     case FIELD_PROP_BOOL1:
2134         rAny <<= m_bOn;
2135         break;
2136     case FIELD_PROP_USHORT1:
2137         rAny <<= static_cast<sal_Int16>(m_nOffset);
2138         break;
2139     default:
2140         assert(false);
2141     }
2142     return true;
2143 }
2144 
PutValue(const uno::Any & rAny,sal_uInt16 nWhichId)2145 bool SwRefPageSetField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
2146 {
2147     switch( nWhichId )
2148     {
2149     case FIELD_PROP_BOOL1:
2150         m_bOn = *o3tl::doAccess<bool>(rAny);
2151         break;
2152     case FIELD_PROP_USHORT1:
2153         rAny >>=m_nOffset;
2154         break;
2155     default:
2156         assert(false);
2157     }
2158     return true;
2159 }
2160 
2161 // relative page numbers - query field
2162 
SwRefPageGetFieldType(SwDoc * pDc)2163 SwRefPageGetFieldType::SwRefPageGetFieldType( SwDoc* pDc )
2164     : SwFieldType( SwFieldIds::RefPageGet ), m_pDoc( pDc ), m_nNumberingType( SVX_NUM_ARABIC )
2165 {
2166 }
2167 
Copy() const2168 std::unique_ptr<SwFieldType> SwRefPageGetFieldType::Copy() const
2169 {
2170     std::unique_ptr<SwRefPageGetFieldType> pNew(new SwRefPageGetFieldType( m_pDoc ));
2171     pNew->m_nNumberingType = m_nNumberingType;
2172     return pNew;
2173 }
2174 
Modify(const SfxPoolItem * pOld,const SfxPoolItem * pNew)2175 void SwRefPageGetFieldType::Modify( const SfxPoolItem* pOld, const SfxPoolItem* pNew )
2176 {
2177     auto const ModifyImpl = [this](SwRootFrame const*const pLayout)
2178     {
2179         // first collect all SetPageRefFields
2180         SetGetExpFields aTmpLst;
2181         if (MakeSetList(aTmpLst, pLayout))
2182         {
2183             SwIterator<SwFormatField,SwFieldType> aIter( *this );
2184             for ( SwFormatField* pFormatField = aIter.First(); pFormatField; pFormatField = aIter.Next() )
2185             {
2186                     // update only the GetRef fields
2187                     if( pFormatField->GetTextField() )
2188                         UpdateField(pFormatField->GetTextField(), aTmpLst, pLayout);
2189             }
2190         }
2191     };
2192 
2193     // update all GetReference fields
2194     if( !pNew && !pOld && HasWriterListeners() )
2195     {
2196         SwRootFrame const* pLayout(nullptr);
2197         SwRootFrame const* pLayoutRLHidden(nullptr);
2198         for (SwRootFrame const*const pLay : m_pDoc->GetAllLayouts())
2199         {
2200             if (pLay->IsHideRedlines())
2201             {
2202                 pLayoutRLHidden = pLay;
2203             }
2204             else
2205             {
2206                 pLayout = pLay;
2207             }
2208         }
2209         ModifyImpl(pLayout);
2210         if (pLayoutRLHidden)
2211         {
2212             ModifyImpl(pLayoutRLHidden);
2213         }
2214     }
2215 
2216     // forward to text fields, they "expand" the text
2217     NotifyClients( pOld, pNew );
2218 }
2219 
MakeSetList(SetGetExpFields & rTmpLst,SwRootFrame const * const pLayout)2220 bool SwRefPageGetFieldType::MakeSetList(SetGetExpFields& rTmpLst,
2221         SwRootFrame const*const pLayout)
2222 {
2223     IDocumentRedlineAccess const& rIDRA(m_pDoc->getIDocumentRedlineAccess());
2224     SwIterator<SwFormatField,SwFieldType> aIter(*m_pDoc->getIDocumentFieldsAccess().GetSysFieldType( SwFieldIds::RefPageSet));
2225     for ( SwFormatField* pFormatField = aIter.First(); pFormatField; pFormatField = aIter.Next() )
2226     {
2227         // update only the GetRef fields
2228         const SwTextField* pTField = pFormatField->GetTextField();
2229         if( pTField )
2230         {
2231             if (!pLayout || !pLayout->IsHideRedlines()
2232                 || !sw::IsFieldDeletedInModel(rIDRA, *pTField))
2233             {
2234                 const SwTextNode& rTextNd = pTField->GetTextNode();
2235 
2236                 // Always the first! (in Tab-Headline, header/footer )
2237                 Point aPt;
2238                 std::pair<Point, bool> const tmp(aPt, false);
2239                 const SwContentFrame *const pFrame = rTextNd.getLayoutFrame(
2240                     pLayout, nullptr, &tmp);
2241 
2242                 std::unique_ptr<SetGetExpField> pNew;
2243 
2244                 if( !pFrame ||
2245                      pFrame->IsInDocBody() ||
2246                     // #i31868#
2247                     // Check if pFrame is not yet connected to the layout.
2248                     !pFrame->FindPageFrame() )
2249                 {
2250                     //  create index for determination of the TextNode
2251                     SwNodeIndex aIdx( rTextNd );
2252                     pNew.reset( new SetGetExpField( aIdx, pTField ) );
2253                 }
2254                 else
2255                 {
2256                     //  create index for determination of the TextNode
2257                     SwPosition aPos( m_pDoc->GetNodes().GetEndOfPostIts() );
2258                     bool const bResult = GetBodyTextNode( *m_pDoc, aPos, *pFrame );
2259                     OSL_ENSURE(bResult, "where is the Field?");
2260                     pNew.reset( new SetGetExpField( aPos.nNode, pTField,
2261                                                 &aPos.nContent ) );
2262                 }
2263 
2264                 rTmpLst.insert( std::move(pNew) );
2265             }
2266         }
2267     }
2268 
2269     return !rTmpLst.empty();
2270 }
2271 
UpdateField(SwTextField const * pTextField,SetGetExpFields const & rSetList,SwRootFrame const * const pLayout)2272 void SwRefPageGetFieldType::UpdateField( SwTextField const * pTextField,
2273                                         SetGetExpFields const & rSetList,
2274                                         SwRootFrame const*const pLayout)
2275 {
2276     SwRefPageGetField* pGetField = const_cast<SwRefPageGetField*>(static_cast<const SwRefPageGetField*>(pTextField->GetFormatField().GetField()));
2277     pGetField->SetText( OUString(), pLayout );
2278 
2279     // then search the correct RefPageSet field
2280     SwTextNode* pTextNode = &pTextField->GetTextNode();
2281     if( pTextNode->StartOfSectionIndex() >
2282         m_pDoc->GetNodes().GetEndOfExtras().GetIndex() )
2283     {
2284         SwNodeIndex aIdx( *pTextNode );
2285         SetGetExpField aEndField( aIdx, pTextField );
2286 
2287         SetGetExpFields::const_iterator itLast = rSetList.lower_bound( &aEndField );
2288 
2289         if( itLast != rSetList.begin() )
2290         {
2291             --itLast;
2292             const SwTextField* pRefTextField = (*itLast)->GetTextField();
2293             const SwRefPageSetField* pSetField =
2294                         static_cast<const SwRefPageSetField*>(pRefTextField->GetFormatField().GetField());
2295             if( pSetField->IsOn() )
2296             {
2297                 // determine the correct offset
2298                 Point aPt;
2299                 std::pair<Point, bool> const tmp(aPt, false);
2300                 const SwContentFrame *const pFrame = pTextNode->getLayoutFrame(
2301                     pLayout, nullptr, &tmp);
2302                 const SwContentFrame *const pRefFrame = pRefTextField->GetTextNode().getLayoutFrame(
2303                     pLayout, nullptr, &tmp);
2304                 const SwPageFrame* pPgFrame = nullptr;
2305                 short nDiff = 1;
2306                 if ( pFrame && pRefFrame )
2307                 {
2308                     pPgFrame = pFrame->FindPageFrame();
2309                     nDiff = pPgFrame->GetPhyPageNum() -
2310                             pRefFrame->FindPageFrame()->GetPhyPageNum() + 1;
2311                 }
2312 
2313                 SvxNumType nTmpFormat = SVX_NUM_PAGEDESC == static_cast<SvxNumType>(pGetField->GetFormat())
2314                         ? ( !pPgFrame
2315                                 ? SVX_NUM_ARABIC
2316                                 : pPgFrame->GetPageDesc()->GetNumType().GetNumberingType() )
2317                         : static_cast<SvxNumType>(pGetField->GetFormat());
2318                 const short nPageNum = std::max<short>(0, pSetField->GetOffset() + nDiff);
2319                 pGetField->SetText(FormatNumber(nPageNum, nTmpFormat), pLayout);
2320             }
2321         }
2322     }
2323     // start formatting
2324     const_cast<SwFormatField&>(pTextField->GetFormatField()).ModifyNotification( nullptr, nullptr );
2325 }
2326 
2327 // queries for relative page numbering
2328 
SwRefPageGetField(SwRefPageGetFieldType * pTyp,sal_uInt32 nFormat)2329 SwRefPageGetField::SwRefPageGetField( SwRefPageGetFieldType* pTyp,
2330                                     sal_uInt32 nFormat )
2331     : SwField( pTyp, nFormat )
2332 {
2333 }
2334 
SetText(const OUString & rText,SwRootFrame const * const pLayout)2335 void SwRefPageGetField::SetText(const OUString& rText,
2336         SwRootFrame const*const pLayout)
2337 {
2338     if (!pLayout || !pLayout->IsHideRedlines())
2339     {
2340         m_sText = rText;
2341     }
2342     if (!pLayout || pLayout->IsHideRedlines())
2343     {
2344         m_sTextRLHidden = rText;
2345     }
2346 }
2347 
ExpandImpl(SwRootFrame const * const pLayout) const2348 OUString SwRefPageGetField::ExpandImpl(SwRootFrame const*const pLayout) const
2349 {
2350     return pLayout && pLayout->IsHideRedlines() ? m_sTextRLHidden : m_sText;
2351 }
2352 
Copy() const2353 std::unique_ptr<SwField> SwRefPageGetField::Copy() const
2354 {
2355     std::unique_ptr<SwRefPageGetField> pCpy(new SwRefPageGetField(
2356                         static_cast<SwRefPageGetFieldType*>(GetTyp()), GetFormat() ));
2357     pCpy->m_sText = m_sText;
2358     pCpy->m_sTextRLHidden = m_sTextRLHidden;
2359     return std::unique_ptr<SwField>(pCpy.release());
2360 }
2361 
ChangeExpansion(const SwFrame & rFrame,const SwTextField * pField)2362 void SwRefPageGetField::ChangeExpansion(const SwFrame& rFrame,
2363                                         const SwTextField* pField )
2364 {
2365     // only fields in Footer, Header, FootNote, Flys
2366     SwRefPageGetFieldType* pGetType = static_cast<SwRefPageGetFieldType*>(GetTyp());
2367     SwDoc* pDoc = pGetType->GetDoc();
2368     if( pField->GetTextNode().StartOfSectionIndex() >
2369         pDoc->GetNodes().GetEndOfExtras().GetIndex() )
2370         return;
2371 
2372     SwRootFrame const& rLayout(*rFrame.getRootFrame());
2373     OUString & rText(rLayout.IsHideRedlines() ? m_sTextRLHidden : m_sText);
2374     rText.clear();
2375 
2376     OSL_ENSURE(!rFrame.IsInDocBody(), "Flag incorrect, frame is in DocBody");
2377 
2378     // collect all SetPageRefFields
2379     SetGetExpFields aTmpLst;
2380     if (!pGetType->MakeSetList(aTmpLst, &rLayout))
2381         return ;
2382 
2383     //  create index for determination of the TextNode
2384     SwPosition aPos( SwNodeIndex( pDoc->GetNodes() ) );
2385     SwTextNode* pTextNode = const_cast<SwTextNode*>(GetBodyTextNode(*pDoc, aPos, rFrame));
2386 
2387     // If no layout exists, ChangeExpansion is called for header and
2388     // footer lines via layout formatting without existing TextNode.
2389     if(!pTextNode)
2390         return;
2391 
2392     SetGetExpField aEndField( aPos.nNode, pField, &aPos.nContent );
2393 
2394     SetGetExpFields::const_iterator itLast = aTmpLst.lower_bound( &aEndField );
2395 
2396     if( itLast == aTmpLst.begin() )
2397         return;        // there is no corresponding set-field in front
2398     --itLast;
2399 
2400     const SwTextField* pRefTextField = (*itLast)->GetTextField();
2401     const SwRefPageSetField* pSetField =
2402                         static_cast<const SwRefPageSetField*>(pRefTextField->GetFormatField().GetField());
2403     Point aPt;
2404     std::pair<Point, bool> const tmp(aPt, false);
2405     const SwContentFrame *const pRefFrame = pRefTextField->GetTextNode().getLayoutFrame(
2406             &rLayout, nullptr, &tmp);
2407     if( pSetField->IsOn() && pRefFrame )
2408     {
2409         // determine the correct offset
2410         const SwPageFrame* pPgFrame = rFrame.FindPageFrame();
2411         const short nDiff = pPgFrame->GetPhyPageNum() -
2412                             pRefFrame->FindPageFrame()->GetPhyPageNum() + 1;
2413 
2414         SwRefPageGetField* pGetField = const_cast<SwRefPageGetField*>(static_cast<const SwRefPageGetField*>(pField->GetFormatField().GetField()));
2415         SvxNumType nTmpFormat = SVX_NUM_PAGEDESC == pGetField->GetFormat()
2416                             ? pPgFrame->GetPageDesc()->GetNumType().GetNumberingType()
2417                             : static_cast<SvxNumType>(pGetField->GetFormat());
2418         const short nPageNum = std::max<short>(0, pSetField->GetOffset() + nDiff);
2419         pGetField->SetText(FormatNumber(nPageNum, nTmpFormat), &rLayout);
2420     }
2421 }
2422 
QueryValue(uno::Any & rAny,sal_uInt16 nWhichId) const2423 bool SwRefPageGetField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
2424 {
2425     switch( nWhichId )
2426     {
2427         case FIELD_PROP_USHORT1:
2428             rAny <<= static_cast<sal_Int16>(GetFormat());
2429         break;
2430         case FIELD_PROP_PAR1:
2431             rAny <<= m_sText;
2432         break;
2433         default:
2434             assert(false);
2435     }
2436     return true;
2437 }
2438 
PutValue(const uno::Any & rAny,sal_uInt16 nWhichId)2439 bool SwRefPageGetField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
2440 {
2441     switch( nWhichId )
2442     {
2443         case FIELD_PROP_USHORT1:
2444         {
2445             sal_Int16 nSet = 0;
2446             rAny >>= nSet;
2447             if(nSet <= SVX_NUM_PAGEDESC )
2448                 SetFormat(nSet);
2449         }
2450         break;
2451         case FIELD_PROP_PAR1:
2452             rAny >>= m_sText;
2453             m_sTextRLHidden = m_sText;
2454         break;
2455     default:
2456         assert(false);
2457     }
2458     return true;
2459 }
2460 
2461 // field type to jump to and edit
2462 
SwJumpEditFieldType(SwDoc * pD)2463 SwJumpEditFieldType::SwJumpEditFieldType( SwDoc* pD )
2464     : SwFieldType( SwFieldIds::JumpEdit ), m_pDoc( pD ), m_aDep( *this )
2465 {
2466 }
2467 
Copy() const2468 std::unique_ptr<SwFieldType> SwJumpEditFieldType::Copy() const
2469 {
2470     return std::make_unique<SwJumpEditFieldType>( m_pDoc );
2471 }
2472 
GetCharFormat()2473 SwCharFormat* SwJumpEditFieldType::GetCharFormat()
2474 {
2475     SwCharFormat* pFormat = m_pDoc->getIDocumentStylePoolAccess().GetCharFormatFromPool( RES_POOLCHR_JUMPEDIT );
2476     m_aDep.StartListening(pFormat);
2477     return pFormat;
2478 }
2479 
SwJumpEditField(SwJumpEditFieldType * pTyp,sal_uInt32 nForm,const OUString & rText,const OUString & rHelp)2480 SwJumpEditField::SwJumpEditField( SwJumpEditFieldType* pTyp, sal_uInt32 nForm,
2481                                 const OUString& rText, const OUString& rHelp )
2482     : SwField( pTyp, nForm ), m_sText( rText ), m_sHelp( rHelp )
2483 {
2484 }
2485 
ExpandImpl(SwRootFrame const * const) const2486 OUString SwJumpEditField::ExpandImpl(SwRootFrame const*const) const
2487 {
2488     return "<" + m_sText + ">";
2489 }
2490 
Copy() const2491 std::unique_ptr<SwField> SwJumpEditField::Copy() const
2492 {
2493     return std::make_unique<SwJumpEditField>( static_cast<SwJumpEditFieldType*>(GetTyp()), GetFormat(),
2494                                 m_sText, m_sHelp );
2495 }
2496 
2497 /// get place holder text
GetPar1() const2498 OUString SwJumpEditField::GetPar1() const
2499 {
2500     return m_sText;
2501 }
2502 
2503 /// set place holder text
SetPar1(const OUString & rStr)2504 void SwJumpEditField::SetPar1(const OUString& rStr)
2505 {
2506     m_sText = rStr;
2507 }
2508 
2509 /// get hint text
GetPar2() const2510 OUString SwJumpEditField::GetPar2() const
2511 {
2512     return m_sHelp;
2513 }
2514 
2515 /// set hint text
SetPar2(const OUString & rStr)2516 void SwJumpEditField::SetPar2(const OUString& rStr)
2517 {
2518     m_sHelp = rStr;
2519 }
2520 
QueryValue(uno::Any & rAny,sal_uInt16 nWhichId) const2521 bool SwJumpEditField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
2522 {
2523     switch( nWhichId )
2524     {
2525     case FIELD_PROP_USHORT1:
2526         {
2527             sal_Int16 nRet;
2528             switch( GetFormat() )
2529             {
2530             case JE_FMT_TABLE:  nRet = text::PlaceholderType::TABLE; break;
2531             case JE_FMT_FRAME:  nRet = text::PlaceholderType::TEXTFRAME; break;
2532             case JE_FMT_GRAPHIC:nRet = text::PlaceholderType::GRAPHIC; break;
2533             case JE_FMT_OLE:    nRet = text::PlaceholderType::OBJECT; break;
2534             default:
2535                 nRet = text::PlaceholderType::TEXT; break;
2536             }
2537             rAny <<= nRet;
2538         }
2539         break;
2540     case FIELD_PROP_PAR1 :
2541         rAny <<= m_sHelp;
2542         break;
2543     case FIELD_PROP_PAR2 :
2544          rAny <<= m_sText;
2545          break;
2546     default:
2547         assert(false);
2548     }
2549     return true;
2550 }
2551 
PutValue(const uno::Any & rAny,sal_uInt16 nWhichId)2552 bool SwJumpEditField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
2553 {
2554     switch( nWhichId )
2555     {
2556     case FIELD_PROP_USHORT1:
2557         {
2558             //JP 24.10.2001: int32 because in UnoField.cxx a putvalue is
2559             //              called with a int32 value! But normally we need
2560             //              here only a int16
2561             sal_Int32 nSet = 0;
2562             rAny >>= nSet;
2563             switch( nSet )
2564             {
2565                 case text::PlaceholderType::TEXT     : SetFormat(JE_FMT_TEXT); break;
2566                 case text::PlaceholderType::TABLE    : SetFormat(JE_FMT_TABLE); break;
2567                 case text::PlaceholderType::TEXTFRAME: SetFormat(JE_FMT_FRAME); break;
2568                 case text::PlaceholderType::GRAPHIC  : SetFormat(JE_FMT_GRAPHIC); break;
2569                 case text::PlaceholderType::OBJECT   : SetFormat(JE_FMT_OLE); break;
2570             }
2571         }
2572         break;
2573     case FIELD_PROP_PAR1 :
2574         rAny >>= m_sHelp;
2575         break;
2576     case FIELD_PROP_PAR2 :
2577          rAny >>= m_sText;
2578          break;
2579     default:
2580         assert(false);
2581     }
2582     return true;
2583 }
2584 
2585 // combined character field type
2586 
SwCombinedCharFieldType()2587 SwCombinedCharFieldType::SwCombinedCharFieldType()
2588     : SwFieldType( SwFieldIds::CombinedChars )
2589 {
2590 }
2591 
Copy() const2592 std::unique_ptr<SwFieldType> SwCombinedCharFieldType::Copy() const
2593 {
2594     return std::make_unique<SwCombinedCharFieldType>();
2595 }
2596 
2597 // combined character field
2598 
SwCombinedCharField(SwCombinedCharFieldType * pFTyp,const OUString & rChars)2599 SwCombinedCharField::SwCombinedCharField( SwCombinedCharFieldType* pFTyp,
2600                                             const OUString& rChars )
2601     : SwField( pFTyp, 0 ),
2602     m_sCharacters( rChars.copy( 0, std::min<sal_Int32>(rChars.getLength(), MAX_COMBINED_CHARACTERS) ))
2603 {
2604 }
2605 
ExpandImpl(SwRootFrame const * const) const2606 OUString SwCombinedCharField::ExpandImpl(SwRootFrame const*const) const
2607 {
2608     return m_sCharacters;
2609 }
2610 
Copy() const2611 std::unique_ptr<SwField> SwCombinedCharField::Copy() const
2612 {
2613     return std::make_unique<SwCombinedCharField>( static_cast<SwCombinedCharFieldType*>(GetTyp()),
2614                                         m_sCharacters );
2615 }
2616 
GetPar1() const2617 OUString SwCombinedCharField::GetPar1() const
2618 {
2619     return m_sCharacters;
2620 }
2621 
SetPar1(const OUString & rStr)2622 void SwCombinedCharField::SetPar1(const OUString& rStr)
2623 {
2624     m_sCharacters = rStr.copy(0, std::min<sal_Int32>(rStr.getLength(), MAX_COMBINED_CHARACTERS));
2625 }
2626 
QueryValue(uno::Any & rAny,sal_uInt16 nWhichId) const2627 bool SwCombinedCharField::QueryValue( uno::Any& rAny,
2628                                         sal_uInt16 nWhichId ) const
2629 {
2630     switch( nWhichId )
2631     {
2632     case FIELD_PROP_PAR1:
2633         rAny <<= m_sCharacters;
2634         break;
2635     default:
2636         assert(false);
2637     }
2638     return true;
2639 }
2640 
PutValue(const uno::Any & rAny,sal_uInt16 nWhichId)2641 bool SwCombinedCharField::PutValue( const uno::Any& rAny,
2642                                         sal_uInt16 nWhichId )
2643 {
2644     switch( nWhichId )
2645     {
2646         case FIELD_PROP_PAR1:
2647         {
2648             OUString sTmp;
2649             rAny >>= sTmp;
2650             SetPar1(sTmp);
2651         }
2652         break;
2653         default:
2654             assert(false);
2655     }
2656     return true;
2657 }
2658 
2659 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
2660