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 <fldbas.hxx>
21 
22 #include <float.h>
23 
24 #include <libxml/xmlwriter.h>
25 
26 #include <rtl/math.hxx>
27 #include <svl/zforlist.hxx>
28 #include <svl/zformat.hxx>
29 #include <o3tl/enumarray.hxx>
30 #include <osl/diagnose.h>
31 #include <unofldmid.h>
32 #include <doc.hxx>
33 #include <fmtfld.hxx>
34 #include <docufld.hxx>
35 #include <expfld.hxx>
36 #include <shellres.hxx>
37 #include <calc.hxx>
38 #include <strings.hrc>
39 #include <docary.hxx>
40 #include <authfld.hxx>
41 #include <calbck.hxx>
42 #include <viewsh.hxx>
43 #include <hints.hxx>
44 
45 using namespace ::com::sun::star;
46 using namespace nsSwDocInfoSubType;
47 
lcl_GetLanguageOfFormat(LanguageType nLng,sal_uLong nFormat,const SvNumberFormatter & rFormatter)48 static LanguageType lcl_GetLanguageOfFormat( LanguageType nLng, sal_uLong nFormat,
49                                 const SvNumberFormatter& rFormatter )
50 {
51     if( nLng == LANGUAGE_NONE ) // Bug #60010
52         nLng = LANGUAGE_SYSTEM;
53     else if( nLng == ::GetAppLanguage() )
54         switch( rFormatter.GetIndexTableOffset( nFormat ))
55         {
56         case NF_NUMBER_SYSTEM:
57         case NF_DATE_SYSTEM_SHORT:
58         case NF_DATE_SYSTEM_LONG:
59         case NF_DATETIME_SYSTEM_SHORT_HHMM:
60             nLng = LANGUAGE_SYSTEM;
61             break;
62         default: break;
63         }
64     return nLng;
65 }
66 
67 // Globals
68 
69 /// field names
70 std::vector<OUString>* SwFieldType::s_pFieldNames = nullptr;
71 
72 namespace
73 {
74 
75     const o3tl::enumarray<SwFieldIds,SwFieldTypesEnum> aTypeTab {
76     /* SwFieldIds::Database      */      SwFieldTypesEnum::Database,
77     /* SwFieldIds::User          */      SwFieldTypesEnum::User,
78     /* SwFieldIds::Filename      */      SwFieldTypesEnum::Filename,
79     /* SwFieldIds::DatabaseName  */      SwFieldTypesEnum::DatabaseName,
80     /* SwFieldIds::Date          */      SwFieldTypesEnum::Date,
81     /* SwFieldIds::Time          */      SwFieldTypesEnum::Time,
82     /* SwFieldIds::PageNumber    */      SwFieldTypesEnum::PageNumber,  // dynamic
83     /* SwFieldIds::Author        */      SwFieldTypesEnum::Author,
84     /* SwFieldIds::Chapter       */      SwFieldTypesEnum::Chapter,
85     /* SwFieldIds::DocStat       */      SwFieldTypesEnum::DocumentStatistics,
86     /* SwFieldIds::GetExp        */      SwFieldTypesEnum::Get,         // dynamic
87     /* SwFieldIds::SetExp        */      SwFieldTypesEnum::Set,         // dynamic
88     /* SwFieldIds::GetRef        */      SwFieldTypesEnum::GetRef,
89     /* SwFieldIds::HiddenText    */      SwFieldTypesEnum::HiddenText,
90     /* SwFieldIds::Postit        */      SwFieldTypesEnum::Postit,
91     /* SwFieldIds::FixDate       */      SwFieldTypesEnum::FixedDate,
92     /* SwFieldIds::FixTime       */      SwFieldTypesEnum::FixedTime,
93     /* SwFieldIds::Reg           */      SwFieldTypesEnum::Begin,         // old (no change since 2000)
94     /* SwFieldIds::VarReg        */      SwFieldTypesEnum::Begin,         // old (no change since 2000)
95     /* SwFieldIds::SetRef        */      SwFieldTypesEnum::SetRef,
96     /* SwFieldIds::Input         */      SwFieldTypesEnum::Input,
97     /* SwFieldIds::Macro         */      SwFieldTypesEnum::Macro,
98     /* SwFieldIds::Dde           */      SwFieldTypesEnum::DDE,
99     /* SwFieldIds::Table         */      SwFieldTypesEnum::Formel,
100     /* SwFieldIds::HiddenPara    */      SwFieldTypesEnum::HiddenParagraph,
101     /* SwFieldIds::DocInfo       */      SwFieldTypesEnum::DocumentInfo,
102     /* SwFieldIds::TemplateName  */      SwFieldTypesEnum::TemplateName,
103     /* SwFieldIds::DbNextSet     */      SwFieldTypesEnum::DatabaseNextSet,
104     /* SwFieldIds::DbNumSet      */      SwFieldTypesEnum::DatabaseNumberSet,
105     /* SwFieldIds::DbSetNumber   */      SwFieldTypesEnum::DatabaseSetNumber,
106     /* SwFieldIds::ExtUser       */      SwFieldTypesEnum::ExtendedUser,
107     /* SwFieldIds::RefPageSet    */      SwFieldTypesEnum::SetRefPage,
108     /* SwFieldIds::RefPageGet    */      SwFieldTypesEnum::GetRefPage,
109     /* SwFieldIds::Internet      */      SwFieldTypesEnum::Internet,
110     /* SwFieldIds::JumpEdit      */      SwFieldTypesEnum::JumpEdit,
111     /* SwFieldIds::Script        */      SwFieldTypesEnum::Script,
112     /* SwFieldIds::DateTime      */      SwFieldTypesEnum::Begin,         // dynamic
113     /* SwFieldIds::TableOfAuthorities*/  SwFieldTypesEnum::Authority,
114     /* SwFieldIds::CombinedChars */      SwFieldTypesEnum::CombinedChars,
115     /* SwFieldIds::Dropdown      */      SwFieldTypesEnum::Dropdown,
116     /* SwFieldIds::ParagraphSignature */ SwFieldTypesEnum::ParagraphSignature
117     };
118 
119 }
120 
GetTypeStr(SwFieldTypesEnum nTypeId)121 const OUString & SwFieldType::GetTypeStr(SwFieldTypesEnum nTypeId)
122 {
123     if (!s_pFieldNames)
124         GetFieldName_();
125 
126     return (*SwFieldType::s_pFieldNames)[static_cast<int>(nTypeId)];
127 }
128 
129 // each field references a field type that is unique for each document
SwFieldType(SwFieldIds nWhichId)130 SwFieldType::SwFieldType( SwFieldIds nWhichId )
131     : sw::BroadcastingModify()
132     , m_nWhich(nWhichId)
133 {
134 }
135 
GetName() const136 OUString SwFieldType::GetName() const
137 {
138     return OUString();
139 }
140 
QueryValue(uno::Any &,sal_uInt16) const141 void SwFieldType::QueryValue( uno::Any&, sal_uInt16 ) const
142 {
143 }
PutValue(const uno::Any &,sal_uInt16)144 void SwFieldType::PutValue( const uno::Any& , sal_uInt16 )
145 {
146 }
147 
UpdateFields() const148 void SwFieldType::UpdateFields() const
149 {
150     const_cast<SwFieldType*>(this)->SwClientNotify(*this, sw::LegacyModifyHint(nullptr, nullptr));
151 }
152 
PrintHiddenPara()153 void SwFieldType::PrintHiddenPara()
154 {
155     const SwMsgPoolItem aHint(RES_HIDDENPARA_PRINT);
156     SwClientNotify(*this, sw::LegacyModifyHint(&aHint, nullptr));
157 }
158 
dumpAsXml(xmlTextWriterPtr pWriter) const159 void SwFieldType::dumpAsXml(xmlTextWriterPtr pWriter) const
160 {
161     std::vector<SwFormatField*> vFields;
162     GatherFields(vFields);
163     if(!vFields.size())
164         return;
165     (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SwFieldType"));
166     (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("ptr"), "%p", this);
167     (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("symbol"), "%s", BAD_CAST(typeid(*this).name()));
168     for(const auto pFormatField: vFields)
169         pFormatField->dumpAsXml(pWriter);
170     (void)xmlTextWriterEndElement(pWriter);
171 }
172 
FindFormatForField(const SwField * pField) const173 SwFormatField* SwFieldType::FindFormatForField(const SwField* pField) const {
174     SwFormatField* pFormat = nullptr;
175     CallSwClientNotify(sw::FindFormatForFieldHint(pField, pFormat));
176     return pFormat;
177 }
178 
FindFormatForPostItId(sal_uInt32 nPostItId) const179 SwFormatField* SwFieldType::FindFormatForPostItId(sal_uInt32 nPostItId) const {
180     SwFormatField* pFormat = nullptr;
181     CallSwClientNotify(sw::FindFormatForPostItIdHint(nPostItId, pFormat));
182     return pFormat;
183 }
184 
CollectPostIts(std::vector<SwFormatField * > & rvFormatFields,IDocumentRedlineAccess const & rIDRA,const bool bHideRedlines)185 void SwFieldType::CollectPostIts(std::vector<SwFormatField*>& rvFormatFields, IDocumentRedlineAccess const& rIDRA, const bool bHideRedlines)
186 {
187     CallSwClientNotify(sw::CollectPostItsHint(rvFormatFields, rIDRA, bHideRedlines));
188 }
189 
HasHiddenInformationNotes() const190 bool SwFieldType::HasHiddenInformationNotes() const
191 {
192     bool bHasHiddenInformationNotes = false;
193     CallSwClientNotify(sw::HasHiddenInformationNotesHint(bHasHiddenInformationNotes));
194     return bHasHiddenInformationNotes;
195 }
196 
GatherNodeIndex(std::vector<sal_uLong> & rvNodeIndex)197 void SwFieldType::GatherNodeIndex(std::vector<sal_uLong>& rvNodeIndex)
198 {
199     CallSwClientNotify(sw::GatherNodeIndexHint(rvNodeIndex));
200 }
201 
GatherRefFields(std::vector<SwGetRefField * > & rvRFields,const sal_uInt16 nTyp)202 void SwFieldType::GatherRefFields(std::vector<SwGetRefField*>& rvRFields, const sal_uInt16 nTyp)
203 {
204     CallSwClientNotify(sw::GatherRefFieldsHint(rvRFields, nTyp));
205 }
206 
GatherFields(std::vector<SwFormatField * > & rvFields,bool bCollectOnlyInDocNodes) const207 void SwFieldType::GatherFields(std::vector<SwFormatField*>& rvFields, bool bCollectOnlyInDocNodes) const
208 {
209     CallSwClientNotify(sw::GatherFieldsHint(rvFields, bCollectOnlyInDocNodes));
210 }
211 
GatherDdeTables(std::vector<SwDDETable * > & rvTables) const212 void SwFieldType::GatherDdeTables(std::vector<SwDDETable*>& rvTables) const
213 {
214     CallSwClientNotify(sw::GatherDdeTablesHint(rvTables));
215 }
216 
dumpAsXml(xmlTextWriterPtr pWriter) const217 void SwFieldTypes::dumpAsXml(xmlTextWriterPtr pWriter) const
218 {
219     (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SwFieldTypes"));
220     sal_uInt16 nCount = size();
221     for (sal_uInt16 nType = 0; nType < nCount; ++nType)
222         (*this)[nType]->dumpAsXml(pWriter);
223     (void)xmlTextWriterEndElement(pWriter);
224 }
225 
226 // Base class for all fields.
227 // A field (multiple can exist) references a field type (can exists only once)
SwField(SwFieldType * pType,sal_uInt32 nFormat,LanguageType nLang,bool bUseFieldValueCache)228 SwField::SwField(
229         SwFieldType* pType,
230         sal_uInt32 nFormat,
231         LanguageType nLang,
232         bool bUseFieldValueCache)
233     : m_Cache()
234     , m_pType( pType )
235     , m_nFormat( nFormat )
236     , m_nLang( nLang )
237     , m_bUseFieldValueCache( bUseFieldValueCache )
238     , m_bIsAutomaticLanguage( true )
239 {
240     assert(m_pType);
241 }
242 
~SwField()243 SwField::~SwField()
244 {
245 }
246 
247 // instead of indirectly via the type
248 
249 #ifdef DBG_UTIL
Which() const250 SwFieldIds SwField::Which() const
251 {
252     assert(m_pType);
253     return m_pType->Which();
254 }
255 #endif
256 
GetTypeId() const257 SwFieldTypesEnum SwField::GetTypeId() const
258 {
259 
260     SwFieldTypesEnum nRet;
261     switch (m_pType->Which())
262     {
263     case SwFieldIds::DateTime:
264         if (GetSubType() & FIXEDFLD)
265             nRet = GetSubType() & DATEFLD ? SwFieldTypesEnum::FixedDate : SwFieldTypesEnum::FixedTime;
266         else
267             nRet = GetSubType() & DATEFLD ? SwFieldTypesEnum::Date : SwFieldTypesEnum::Time;
268         break;
269     case SwFieldIds::GetExp:
270         nRet = nsSwGetSetExpType::GSE_FORMULA & GetSubType() ? SwFieldTypesEnum::Formel : SwFieldTypesEnum::Get;
271         break;
272 
273     case SwFieldIds::HiddenText:
274         nRet = static_cast<SwFieldTypesEnum>(GetSubType());
275         break;
276 
277     case SwFieldIds::SetExp:
278         if( nsSwGetSetExpType::GSE_SEQ & GetSubType() )
279             nRet = SwFieldTypesEnum::Sequence;
280         else if( static_cast<const SwSetExpField*>(this)->GetInputFlag() )
281             nRet = SwFieldTypesEnum::SetInput;
282         else
283             nRet = SwFieldTypesEnum::Set;
284         break;
285 
286     case SwFieldIds::PageNumber:
287         {
288             auto nSubType = GetSubType();
289             if( PG_NEXT == nSubType )
290                 nRet = SwFieldTypesEnum::NextPage;
291             else if( PG_PREV == nSubType )
292                 nRet = SwFieldTypesEnum::PreviousPage;
293             else
294                 nRet = SwFieldTypesEnum::PageNumber;
295         }
296         break;
297 
298     default:
299         nRet = aTypeTab[ m_pType->Which() ];
300     }
301     return nRet;
302 }
303 
304 /// get name or content
GetFieldName() const305 OUString SwField::GetFieldName() const
306 {
307     SwFieldTypesEnum nTypeId = GetTypeId();
308     if (SwFieldIds::DateTime == GetTyp()->Which())
309     {
310         nTypeId =
311             ((GetSubType() & DATEFLD) != 0) ? SwFieldTypesEnum::Date : SwFieldTypesEnum::Time;
312     }
313     OUString sRet = SwFieldType::GetTypeStr( nTypeId );
314     if (IsFixed())
315     {
316         sRet += " " + SwViewShell::GetShellRes()->aFixedStr;
317     }
318     return sRet;
319 }
320 
GetPar1() const321 OUString SwField::GetPar1() const
322 {
323     return OUString();
324 }
325 
GetPar2() const326 OUString SwField::GetPar2() const
327 {
328     return OUString();
329 }
330 
GetFormula() const331 OUString SwField::GetFormula() const
332 {
333     return GetPar2();
334 }
335 
SetPar1(const OUString &)336 void SwField::SetPar1(const OUString& )
337 {}
338 
SetPar2(const OUString &)339 void SwField::SetPar2(const OUString& )
340 {}
341 
GetSubType() const342 sal_uInt16 SwField::GetSubType() const
343 {
344     return 0;
345 }
346 
SetSubType(sal_uInt16)347 void SwField::SetSubType(sal_uInt16 )
348 {
349 }
350 
QueryValue(uno::Any & rVal,sal_uInt16 nWhichId) const351 bool  SwField::QueryValue( uno::Any& rVal, sal_uInt16 nWhichId ) const
352 {
353     switch( nWhichId )
354     {
355         case FIELD_PROP_BOOL4:
356             rVal <<= !m_bIsAutomaticLanguage;
357         break;
358         default:
359             assert(false);
360     }
361     return true;
362 }
363 
PutValue(const uno::Any & rVal,sal_uInt16 nWhichId)364 bool SwField::PutValue( const uno::Any& rVal, sal_uInt16 nWhichId )
365 {
366     switch( nWhichId )
367     {
368         case FIELD_PROP_BOOL4:
369         {
370             bool bFixed = false;
371             if(rVal >>= bFixed)
372                 m_bIsAutomaticLanguage = !bFixed;
373         }
374         break;
375         default:
376             assert(false);
377     }
378     return true;
379 }
380 
381 /** Set a new type
382  *
383  * This is needed/used for copying between documents.
384  * Needs to be always of the same type.
385  * @param pNewType The new type.
386  * @return The old type.
387  */
ChgTyp(SwFieldType * pNewType)388 SwFieldType* SwField::ChgTyp( SwFieldType* pNewType )
389 {
390     assert(pNewType && pNewType->Which() == m_pType->Which());
391 
392     SwFieldType* pOld = m_pType;
393     m_pType = pNewType;
394     return pOld;
395 }
396 
397 /// Does the field have an action on a ClickHandler? (E.g. INetFields,...)
HasClickHdl() const398 bool SwField::HasClickHdl() const
399 {
400     bool bRet = false;
401     switch (m_pType->Which())
402     {
403     case SwFieldIds::Internet:
404     case SwFieldIds::JumpEdit:
405     case SwFieldIds::GetRef:
406     case SwFieldIds::Macro:
407     case SwFieldIds::Input:
408     case SwFieldIds::Dropdown :
409         bRet = true;
410         break;
411 
412     case SwFieldIds::SetExp:
413         bRet = static_cast<const SwSetExpField*>(this)->GetInputFlag();
414         break;
415 
416     case SwFieldIds::TableOfAuthorities:
417     {
418         const auto pAuthorityField = static_cast<const SwAuthorityField*>(this);
419         bRet = pAuthorityField->HasURL();
420         break;
421     }
422 
423     default: break;
424     }
425     return bRet;
426 }
427 
SetLanguage(LanguageType const nLang)428 void SwField::SetLanguage(LanguageType const nLang)
429 {
430     m_nLang = nLang;
431 }
432 
ChangeFormat(sal_uInt32 const nFormat)433 void SwField::ChangeFormat(sal_uInt32 const nFormat)
434 {
435     m_nFormat = nFormat;
436 }
437 
IsFixed() const438 bool SwField::IsFixed() const
439 {
440     bool bRet = false;
441     switch (m_pType->Which())
442     {
443     case SwFieldIds::FixDate:
444     case SwFieldIds::FixTime:
445         bRet = true;
446         break;
447 
448     case SwFieldIds::DateTime:
449         bRet = 0 != (GetSubType() & FIXEDFLD);
450         break;
451 
452     case SwFieldIds::ExtUser:
453     case SwFieldIds::Author:
454         bRet = 0 != (GetFormat() & AF_FIXED);
455         break;
456 
457     case SwFieldIds::Filename:
458         bRet = 0 != (GetFormat() & FF_FIXED);
459         break;
460 
461     case SwFieldIds::DocInfo:
462         bRet = 0 != (GetSubType() & DI_SUB_FIXED);
463         break;
464     default: break;
465     }
466     return bRet;
467 }
468 
469 OUString
ExpandField(bool const bCached,SwRootFrame const * const pLayout) const470 SwField::ExpandField(bool const bCached, SwRootFrame const*const pLayout) const
471 {
472     if ( m_bUseFieldValueCache )
473     {
474         if (!bCached) // #i85766# do not expand fields in clipboard documents
475         {
476             if (GetTypeId() == SwFieldTypesEnum::Authority)
477             {
478                 const SwAuthorityField* pAuthorityField = static_cast<const SwAuthorityField*>(this);
479                 m_Cache = pAuthorityField->ConditionalExpandAuthIdentifier(pLayout);
480             }
481             else
482                 m_Cache = ExpandImpl(pLayout);
483         }
484         return m_Cache;
485     }
486 
487     return ExpandImpl(pLayout);
488 }
489 
CopyField() const490 std::unique_ptr<SwField> SwField::CopyField() const
491 {
492     std::unique_ptr<SwField> pNew = Copy();
493     // #i85766# cache expansion of source (for clipboard)
494     // use this->cache, not this->Expand(): only text formatting calls Expand()
495     pNew->m_Cache = m_Cache;
496     pNew->m_bUseFieldValueCache = m_bUseFieldValueCache;
497 
498     return pNew;
499 }
500 
501 /// expand numbering
FormatNumber(sal_uInt32 nNum,SvxNumType nFormat,LanguageType nLang)502 OUString FormatNumber(sal_uInt32 nNum, SvxNumType nFormat, LanguageType nLang)
503 {
504     if(SVX_NUM_PAGEDESC == nFormat)
505         return  OUString::number( nNum );
506     SvxNumberType aNumber;
507 
508     OSL_ENSURE(nFormat != SVX_NUM_NUMBER_NONE, "wrong number format" );
509 
510     aNumber.SetNumberingType(nFormat);
511 
512     if (nLang == LANGUAGE_NONE)
513         return aNumber.GetNumStr(nNum);
514     else
515         return aNumber.GetNumStr(nNum, LanguageTag::convertToLocale(nLang));
516 }
517 
SwValueFieldType(SwDoc * const pDoc,SwFieldIds const nWhichId)518 SwValueFieldType::SwValueFieldType(SwDoc *const pDoc, SwFieldIds const nWhichId)
519     : SwFieldType(nWhichId)
520     , m_pDoc(pDoc)
521     , m_bUseFormat(true)
522 {
523 }
524 
SwValueFieldType(const SwValueFieldType & rTyp)525 SwValueFieldType::SwValueFieldType( const SwValueFieldType& rTyp )
526     : SwFieldType(rTyp.Which())
527     , m_pDoc(rTyp.GetDoc())
528     , m_bUseFormat(rTyp.UseFormat())
529 {
530 }
531 
532 /// return value formatted as string
ExpandValue(const double & rVal,sal_uInt32 nFormat,LanguageType nLng) const533 OUString SwValueFieldType::ExpandValue( const double& rVal,
534                                         sal_uInt32 nFormat, LanguageType nLng) const
535 {
536     if (rVal >= DBL_MAX) // error string for calculator
537         return SwViewShell::GetShellRes()->aCalc_Error;
538 
539     OUString sExpand;
540     SvNumberFormatter* pFormatter = m_pDoc->GetNumberFormatter();
541     const Color* pCol = nullptr;
542 
543     // Bug #60010
544     LanguageType nFormatLng = ::lcl_GetLanguageOfFormat( nLng, nFormat, *pFormatter );
545 
546     if( nFormat < SV_COUNTRY_LANGUAGE_OFFSET && LANGUAGE_SYSTEM != nFormatLng )
547     {
548         const SvNumberformat* pEntry = pFormatter->GetEntry(nFormat);
549 
550         if (pEntry && nLng != pEntry->GetLanguage())
551         {
552             sal_uInt32 nNewFormat = pFormatter->GetFormatForLanguageIfBuiltIn(nFormat,
553                                                     nFormatLng);
554             if (nNewFormat == nFormat)
555             {
556                 // probably user-defined format
557                 OUString sFormat(pEntry->GetFormatstring());
558                 sal_Int32 nDummy;
559                 SvNumFormatType nType = SvNumFormatType::DEFINED;
560 
561                 pFormatter->PutandConvertEntry(sFormat, nDummy, nType, nFormat,
562                                         pEntry->GetLanguage(), nFormatLng, false);
563             }
564             else
565                 nFormat = nNewFormat;
566         }
567         OSL_ENSURE(pEntry, "unknown number format!");
568     }
569 
570     if( pFormatter->IsTextFormat( nFormat ) )
571     {
572         pFormatter->GetOutputString(DoubleToString(rVal, nFormatLng), nFormat,
573                                     sExpand, &pCol);
574     }
575     else
576     {
577         pFormatter->GetOutputString(rVal, nFormat, sExpand, &pCol);
578     }
579     return sExpand;
580 }
581 
DoubleToString(const double & rVal,sal_uInt32 nFormat) const582 OUString SwValueFieldType::DoubleToString(const double &rVal,
583                                         sal_uInt32 nFormat) const
584 {
585     SvNumberFormatter* pFormatter = m_pDoc->GetNumberFormatter();
586     const SvNumberformat* pEntry = pFormatter->GetEntry(nFormat);
587 
588     if (!pEntry)
589         return OUString();
590 
591     return DoubleToString(rVal, pEntry->GetLanguage());
592 }
593 
DoubleToString(const double & rVal,LanguageType nLng) const594 OUString SwValueFieldType::DoubleToString( const double &rVal,
595                                         LanguageType nLng ) const
596 {
597     SvNumberFormatter* pFormatter = m_pDoc->GetNumberFormatter();
598 
599     // Bug #60010
600     if( nLng == LANGUAGE_NONE )
601         nLng = LANGUAGE_SYSTEM;
602 
603     pFormatter->ChangeIntl( nLng ); // get separator in the correct language
604     return ::rtl::math::doubleToUString( rVal, rtl_math_StringFormat_F, 12,
605                                     pFormatter->GetNumDecimalSep()[0], true );
606 }
607 
SwValueField(SwValueFieldType * pFieldType,sal_uInt32 nFormat,LanguageType nLng,const double fVal)608 SwValueField::SwValueField( SwValueFieldType* pFieldType, sal_uInt32 nFormat,
609                             LanguageType nLng, const double fVal )
610     : SwField(pFieldType, nFormat, nLng)
611     , m_fValue(fVal)
612 {
613 }
614 
SwValueField(const SwValueField & rField)615 SwValueField::SwValueField( const SwValueField& rField )
616     : SwField(rField)
617     , m_fValue(rField.GetValue())
618 {
619 }
620 
~SwValueField()621 SwValueField::~SwValueField()
622 {
623 }
624 
625 /** Set a new type
626  *
627  * This is needed/used for copying between documents.
628  * Needs to be always of the same type.
629  * @param pNewType The new type.
630  * @return The old type.
631  */
ChgTyp(SwFieldType * pNewType)632 SwFieldType* SwValueField::ChgTyp( SwFieldType* pNewType )
633 {
634     SwDoc* pNewDoc = static_cast<SwValueFieldType *>(pNewType)->GetDoc();
635     SwDoc* pDoc    = GetDoc();
636 
637     if( pNewDoc && pDoc && pDoc != pNewDoc)
638     {
639         SvNumberFormatter* pFormatter = pNewDoc->GetNumberFormatter();
640 
641         if( pFormatter && pFormatter->HasMergeFormatTable() &&
642             static_cast<SwValueFieldType *>(GetTyp())->UseFormat() )
643             SetFormat(pFormatter->GetMergeFormatIndex( GetFormat() ));
644     }
645 
646     return SwField::ChgTyp(pNewType);
647 }
648 
649 /// get format in office language
GetSystemFormat(SvNumberFormatter * pFormatter,sal_uInt32 nFormat)650 sal_uInt32 SwValueField::GetSystemFormat(SvNumberFormatter* pFormatter, sal_uInt32 nFormat)
651 {
652     const SvNumberformat* pEntry = pFormatter->GetEntry(nFormat);
653     LanguageType nLng = SvtSysLocale().GetLanguageTag().getLanguageType();
654 
655     if (pEntry && nLng != pEntry->GetLanguage())
656     {
657         sal_uInt32 nNewFormat = pFormatter->GetFormatForLanguageIfBuiltIn(nFormat,
658                                                         nLng);
659 
660         if (nNewFormat == nFormat)
661         {
662             // probably user-defined format
663             SvNumFormatType nType = SvNumFormatType::DEFINED;
664             sal_Int32 nDummy;
665 
666             OUString sFormat(pEntry->GetFormatstring());
667 
668             sal_uInt32 nTempFormat = nFormat;
669             pFormatter->PutandConvertEntry(sFormat, nDummy, nType,
670                                            nTempFormat, pEntry->GetLanguage(), nLng, true);
671             nFormat = nTempFormat;
672         }
673         else
674             nFormat = nNewFormat;
675     }
676 
677     return nFormat;
678 }
679 
dumpAsXml(xmlTextWriterPtr pWriter) const680 void SwValueField::dumpAsXml(xmlTextWriterPtr pWriter) const
681 {
682     (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SwValueField"));
683     (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("m_fValue"), BAD_CAST(OString::number(m_fValue).getStr()));
684     SwField::dumpAsXml(pWriter);
685     (void)xmlTextWriterEndElement(pWriter);
686 }
687 
688 /// set language of the format
SetLanguage(LanguageType nLng)689 void SwValueField::SetLanguage( LanguageType nLng )
690 {
691     if( IsAutomaticLanguage() &&
692             static_cast<SwValueFieldType *>(GetTyp())->UseFormat() &&
693         GetFormat() != SAL_MAX_UINT32 )
694     {
695         // Bug #60010
696         SvNumberFormatter* pFormatter = GetDoc()->GetNumberFormatter();
697         LanguageType nFormatLng = ::lcl_GetLanguageOfFormat( nLng, GetFormat(),
698                                                     *pFormatter );
699 
700         if( (GetFormat() >= SV_COUNTRY_LANGUAGE_OFFSET ||
701              LANGUAGE_SYSTEM != nFormatLng ) &&
702             !(Which() == SwFieldIds::User && (GetSubType()&nsSwExtendedSubType::SUB_CMD) ) )
703         {
704             const SvNumberformat* pEntry = pFormatter->GetEntry(GetFormat());
705 
706             if( pEntry && nFormatLng != pEntry->GetLanguage() )
707             {
708                 sal_uInt32 nNewFormat = pFormatter->GetFormatForLanguageIfBuiltIn(
709                                         GetFormat(), nFormatLng );
710 
711                 if( nNewFormat == GetFormat() )
712                 {
713                     // probably user-defined format
714                     SvNumFormatType nType = SvNumFormatType::DEFINED;
715                     sal_Int32 nDummy;
716                     OUString sFormat( pEntry->GetFormatstring() );
717                     pFormatter->PutandConvertEntry( sFormat, nDummy, nType,
718                                                     nNewFormat,
719                                                     pEntry->GetLanguage(),
720                                                     nFormatLng, false);
721                 }
722                 SetFormat( nNewFormat );
723             }
724             OSL_ENSURE(pEntry, "unknown number format!");
725         }
726     }
727 
728     SwField::SetLanguage(nLng);
729 }
730 
GetValue() const731 double SwValueField::GetValue() const
732 {
733     return m_fValue;
734 }
735 
SetValue(const double & rVal)736 void SwValueField::SetValue( const double& rVal )
737 {
738     m_fValue = rVal;
739 }
740 
SwFormulaField(SwValueFieldType * pFieldType,sal_uInt32 nFormat,const double fVal)741 SwFormulaField::SwFormulaField( SwValueFieldType* pFieldType, sal_uInt32 nFormat, const double fVal)
742     : SwValueField(pFieldType, nFormat, LANGUAGE_SYSTEM, fVal)
743 {
744 }
745 
SwFormulaField(const SwFormulaField & rField)746 SwFormulaField::SwFormulaField( const SwFormulaField& rField )
747     : SwValueField(static_cast<SwValueFieldType *>(rField.GetTyp()), rField.GetFormat(),
748                     rField.GetLanguage(), rField.GetValue())
749 {
750 }
751 
GetFormula() const752 OUString SwFormulaField::GetFormula() const
753 {
754     return m_sFormula;
755 }
756 
SetFormula(const OUString & rStr)757 void SwFormulaField::SetFormula(const OUString& rStr)
758 {
759     m_sFormula = rStr;
760 
761     sal_uLong nFormat(GetFormat());
762 
763     if( nFormat && SAL_MAX_UINT32 != nFormat )
764     {
765         sal_Int32 nPos = 0;
766         double fTmpValue;
767         if( SwCalc::Str2Double( rStr, nPos, fTmpValue, GetDoc() ) )
768             SwValueField::SetValue( fTmpValue );
769     }
770 }
771 
SetExpandedFormula(const OUString & rStr)772 void SwFormulaField::SetExpandedFormula( const OUString& rStr )
773 {
774     sal_uInt32 nFormat(GetFormat());
775 
776     if (nFormat && nFormat != SAL_MAX_UINT32 && static_cast<SwValueFieldType *>(GetTyp())->UseFormat())
777     {
778         double fTmpValue;
779 
780         if (GetDoc()->IsNumberFormat(rStr, nFormat, fTmpValue))
781         {
782             SwValueField::SetValue(fTmpValue);
783 
784             m_sFormula = static_cast<SwValueFieldType *>(GetTyp())->DoubleToString(fTmpValue, nFormat);
785             return;
786         }
787     }
788     m_sFormula = rStr;
789 }
790 
GetExpandedFormula() const791 OUString SwFormulaField::GetExpandedFormula() const
792 {
793     sal_uInt32 nFormat(GetFormat());
794 
795     if (nFormat && nFormat != SAL_MAX_UINT32 && static_cast<SwValueFieldType *>(GetTyp())->UseFormat())
796     {
797         OUString sFormattedValue;
798         const Color* pCol = nullptr;
799 
800         SvNumberFormatter* pFormatter = GetDoc()->GetNumberFormatter();
801 
802         if (pFormatter->IsTextFormat(nFormat))
803         {
804             OUString sTempIn(static_cast<SwValueFieldType *>(GetTyp())->DoubleToString(GetValue(), nFormat));
805             pFormatter->GetOutputString(sTempIn, nFormat, sFormattedValue, &pCol);
806         }
807         else
808         {
809             pFormatter->GetOutputString(GetValue(), nFormat, sFormattedValue, &pCol);
810         }
811         return sFormattedValue;
812     }
813     else
814         return GetFormula();
815 }
816 
GetDescription() const817 OUString SwField::GetDescription() const
818 {
819     return SwResId(STR_FIELD);
820 }
821 
IsClickable() const822 bool SwField::IsClickable() const
823 {
824     switch (Which())
825     {
826     case SwFieldIds::JumpEdit:
827     case SwFieldIds::Macro:
828     case SwFieldIds::GetRef:
829     case SwFieldIds::Input:
830     case SwFieldIds::SetExp:
831     case SwFieldIds::Dropdown:
832     case SwFieldIds::TableOfAuthorities:
833         return true;
834     default: break;
835     }
836     return false;
837 }
838 
dumpAsXml(xmlTextWriterPtr pWriter) const839 void SwField::dumpAsXml(xmlTextWriterPtr pWriter) const
840 {
841     (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SwField"));
842     (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("symbol"), "%s", BAD_CAST(typeid(*this).name()));
843     (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("ptr"), "%p", this);
844     (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("m_nFormat"), BAD_CAST(OString::number(m_nFormat).getStr()));
845     (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("m_nLang"), BAD_CAST(OString::number(m_nLang.get()).getStr()));
846 
847     (void)xmlTextWriterEndElement(pWriter);
848 }
849 
850 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
851