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