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