android: Update app-specific/MIME type icons
[LibreOffice.git] / sw / source / core / fields / fldbas.cxx
blobc528f2a0d65a5753c93de47276336dade1e91b70
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <fldbas.hxx>
22 #include <float.h>
24 #include <libxml/xmlwriter.h>
26 #include <rtl/math.hxx>
27 #include <comphelper/string.hxx>
28 #include <svl/numformat.hxx>
29 #include <svl/zforlist.hxx>
30 #include <svl/zformat.hxx>
31 #include <o3tl/enumarray.hxx>
32 #include <osl/diagnose.h>
33 #include <unofldmid.h>
34 #include <doc.hxx>
35 #include <fmtfld.hxx>
36 #include <docufld.hxx>
37 #include <expfld.hxx>
38 #include <shellres.hxx>
39 #include <calc.hxx>
40 #include <strings.hrc>
41 #include <docary.hxx>
42 #include <authfld.hxx>
43 #include <calbck.hxx>
44 #include <viewsh.hxx>
45 #include <hints.hxx>
46 #include <unofield.hxx>
48 using namespace ::com::sun::star;
49 using namespace nsSwDocInfoSubType;
51 static LanguageType lcl_GetLanguageOfFormat( LanguageType nLng, sal_uLong nFormat,
52 const SvNumberFormatter& rFormatter )
54 if( nLng == LANGUAGE_NONE ) // Bug #60010
55 nLng = LANGUAGE_SYSTEM;
56 else if( nLng == ::GetAppLanguage() )
57 switch( rFormatter.GetIndexTableOffset( nFormat ))
59 case NF_NUMBER_SYSTEM:
60 case NF_DATE_SYSTEM_SHORT:
61 case NF_DATE_SYSTEM_LONG:
62 case NF_DATETIME_SYSTEM_SHORT_HHMM:
63 nLng = LANGUAGE_SYSTEM;
64 break;
65 default: break;
67 return nLng;
70 // Globals
72 /// field names
73 std::vector<OUString>* SwFieldType::s_pFieldNames = nullptr;
75 namespace
78 const o3tl::enumarray<SwFieldIds,SwFieldTypesEnum> aTypeTab {
79 /* SwFieldIds::Database */ SwFieldTypesEnum::Database,
80 /* SwFieldIds::User */ SwFieldTypesEnum::User,
81 /* SwFieldIds::Filename */ SwFieldTypesEnum::Filename,
82 /* SwFieldIds::DatabaseName */ SwFieldTypesEnum::DatabaseName,
83 /* SwFieldIds::Date */ SwFieldTypesEnum::Date,
84 /* SwFieldIds::Time */ SwFieldTypesEnum::Time,
85 /* SwFieldIds::PageNumber */ SwFieldTypesEnum::PageNumber, // dynamic
86 /* SwFieldIds::Author */ SwFieldTypesEnum::Author,
87 /* SwFieldIds::Chapter */ SwFieldTypesEnum::Chapter,
88 /* SwFieldIds::DocStat */ SwFieldTypesEnum::DocumentStatistics,
89 /* SwFieldIds::GetExp */ SwFieldTypesEnum::Get, // dynamic
90 /* SwFieldIds::SetExp */ SwFieldTypesEnum::Set, // dynamic
91 /* SwFieldIds::GetRef */ SwFieldTypesEnum::GetRef,
92 /* SwFieldIds::HiddenText */ SwFieldTypesEnum::HiddenText,
93 /* SwFieldIds::Postit */ SwFieldTypesEnum::Postit,
94 /* SwFieldIds::FixDate */ SwFieldTypesEnum::FixedDate,
95 /* SwFieldIds::FixTime */ SwFieldTypesEnum::FixedTime,
96 /* SwFieldIds::Reg */ SwFieldTypesEnum::Begin, // old (no change since 2000)
97 /* SwFieldIds::VarReg */ SwFieldTypesEnum::Begin, // old (no change since 2000)
98 /* SwFieldIds::SetRef */ SwFieldTypesEnum::SetRef,
99 /* SwFieldIds::Input */ SwFieldTypesEnum::Input,
100 /* SwFieldIds::Macro */ SwFieldTypesEnum::Macro,
101 /* SwFieldIds::Dde */ SwFieldTypesEnum::DDE,
102 /* SwFieldIds::Table */ SwFieldTypesEnum::Formel,
103 /* SwFieldIds::HiddenPara */ SwFieldTypesEnum::HiddenParagraph,
104 /* SwFieldIds::DocInfo */ SwFieldTypesEnum::DocumentInfo,
105 /* SwFieldIds::TemplateName */ SwFieldTypesEnum::TemplateName,
106 /* SwFieldIds::DbNextSet */ SwFieldTypesEnum::DatabaseNextSet,
107 /* SwFieldIds::DbNumSet */ SwFieldTypesEnum::DatabaseNumberSet,
108 /* SwFieldIds::DbSetNumber */ SwFieldTypesEnum::DatabaseSetNumber,
109 /* SwFieldIds::ExtUser */ SwFieldTypesEnum::ExtendedUser,
110 /* SwFieldIds::RefPageSet */ SwFieldTypesEnum::SetRefPage,
111 /* SwFieldIds::RefPageGet */ SwFieldTypesEnum::GetRefPage,
112 /* SwFieldIds::Internet */ SwFieldTypesEnum::Internet,
113 /* SwFieldIds::JumpEdit */ SwFieldTypesEnum::JumpEdit,
114 /* SwFieldIds::Script */ SwFieldTypesEnum::Script,
115 /* SwFieldIds::DateTime */ SwFieldTypesEnum::Begin, // dynamic
116 /* SwFieldIds::TableOfAuthorities*/ SwFieldTypesEnum::Authority,
117 /* SwFieldIds::CombinedChars */ SwFieldTypesEnum::CombinedChars,
118 /* SwFieldIds::Dropdown */ SwFieldTypesEnum::Dropdown,
119 /* SwFieldIds::ParagraphSignature */ SwFieldTypesEnum::ParagraphSignature
124 const OUString & SwFieldType::GetTypeStr(SwFieldTypesEnum nTypeId)
126 if (!s_pFieldNames)
127 GetFieldName_();
129 return (*SwFieldType::s_pFieldNames)[static_cast<int>(nTypeId)];
132 // each field references a field type that is unique for each document
133 SwFieldType::SwFieldType( SwFieldIds nWhichId )
134 : sw::BroadcastingModify()
135 , m_nWhich(nWhichId)
139 OUString SwFieldType::GetName() const
141 return OUString();
144 void SwFieldType::QueryValue( uno::Any&, sal_uInt16 ) const
147 void SwFieldType::PutValue( const uno::Any& , sal_uInt16 )
151 void SwFieldType::PrintHiddenPara()
153 const SwMsgPoolItem aHint(RES_HIDDENPARA_PRINT);
154 SwClientNotify(*this, sw::LegacyModifyHint(&aHint, nullptr));
157 void SwFieldType::dumpAsXml(xmlTextWriterPtr pWriter) const
159 std::vector<SwFormatField*> vFields;
160 GatherFields(vFields);
161 if(!vFields.size())
162 return;
163 (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SwFieldType"));
164 (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("ptr"), "%p", this);
165 (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("symbol"), "%s", BAD_CAST(typeid(*this).name()));
166 for(const auto pFormatField: vFields)
167 pFormatField->dumpAsXml(pWriter);
168 (void)xmlTextWriterEndElement(pWriter);
171 SwFormatField* SwFieldType::FindFormatForField(const SwField* pField) const {
172 SwFormatField* pFormat = nullptr;
173 CallSwClientNotify(sw::FindFormatForFieldHint(pField, pFormat));
174 return pFormat;
177 SwFormatField* SwFieldType::FindFormatForPostItId(sal_uInt32 nPostItId) const {
178 SwFormatField* pFormat = nullptr;
179 CallSwClientNotify(sw::FindFormatForPostItIdHint(nPostItId, pFormat));
180 return pFormat;
183 void SwFieldType::CollectPostIts(std::vector<SwFormatField*>& rvFormatFields, IDocumentRedlineAccess const& rIDRA, const bool bHideRedlines)
185 CallSwClientNotify(sw::CollectPostItsHint(rvFormatFields, rIDRA, bHideRedlines));
188 bool SwFieldType::HasHiddenInformationNotes() const
190 bool bHasHiddenInformationNotes = false;
191 CallSwClientNotify(sw::HasHiddenInformationNotesHint(bHasHiddenInformationNotes));
192 return bHasHiddenInformationNotes;
195 void SwFieldType::GatherNodeIndex(std::vector<SwNodeOffset>& rvNodeIndex)
197 CallSwClientNotify(sw::GatherNodeIndexHint(rvNodeIndex));
200 void SwFieldType::GatherRefFields(std::vector<SwGetRefField*>& rvRFields, const sal_uInt16 nTyp)
202 CallSwClientNotify(sw::GatherRefFieldsHint(rvRFields, nTyp));
205 void SwFieldType::GatherFields(std::vector<SwFormatField*>& rvFields, bool bCollectOnlyInDocNodes) const
207 CallSwClientNotify(sw::GatherFieldsHint(rvFields, bCollectOnlyInDocNodes));
210 void SwFieldType::GatherDdeTables(std::vector<SwDDETable*>& rvTables) const
212 CallSwClientNotify(sw::GatherDdeTablesHint(rvTables));
215 void SwFieldType::UpdateDocPos(const SwTwips nDocPos)
217 CallSwClientNotify(sw::DocPosUpdate(nDocPos));
219 void SwFieldType::UpdateFields()
221 CallSwClientNotify(sw::LegacyModifyHint(nullptr, nullptr));
224 void SwFieldType::SetXObject(rtl::Reference<SwXFieldMaster> const& xFieldMaster)
226 m_wXFieldMaster = xFieldMaster.get();
229 void SwFieldTypes::dumpAsXml(xmlTextWriterPtr pWriter) const
231 (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SwFieldTypes"));
232 sal_uInt16 nCount = size();
233 for (sal_uInt16 nType = 0; nType < nCount; ++nType)
234 (*this)[nType]->dumpAsXml(pWriter);
235 (void)xmlTextWriterEndElement(pWriter);
240 // Base class for all fields.
241 // A field (multiple can exist) references a field type (can exists only once)
242 SwField::SwField(
243 SwFieldType* pType,
244 sal_uInt32 nFormat,
245 LanguageType nLang,
246 bool bUseFieldValueCache)
247 : m_pType( pType )
248 , m_nFormat( nFormat )
249 , m_nLang( nLang )
250 , m_bUseFieldValueCache( bUseFieldValueCache )
251 , m_bIsAutomaticLanguage( true )
253 assert(m_pType);
256 SwField::~SwField()
260 // instead of indirectly via the type
262 #ifdef DBG_UTIL
263 SwFieldIds SwField::Which() const
265 assert(m_pType);
266 return m_pType->Which();
268 #endif
270 SwFieldTypesEnum SwField::GetTypeId() const
273 SwFieldTypesEnum nRet;
274 switch (m_pType->Which())
276 case SwFieldIds::DateTime:
277 if (GetSubType() & FIXEDFLD)
278 nRet = GetSubType() & DATEFLD ? SwFieldTypesEnum::FixedDate : SwFieldTypesEnum::FixedTime;
279 else
280 nRet = GetSubType() & DATEFLD ? SwFieldTypesEnum::Date : SwFieldTypesEnum::Time;
281 break;
282 case SwFieldIds::GetExp:
283 nRet = nsSwGetSetExpType::GSE_FORMULA & GetSubType() ? SwFieldTypesEnum::Formel : SwFieldTypesEnum::Get;
284 break;
286 case SwFieldIds::HiddenText:
287 nRet = static_cast<SwFieldTypesEnum>(GetSubType());
288 break;
290 case SwFieldIds::SetExp:
291 if( nsSwGetSetExpType::GSE_SEQ & GetSubType() )
292 nRet = SwFieldTypesEnum::Sequence;
293 else if( static_cast<const SwSetExpField*>(this)->GetInputFlag() )
294 nRet = SwFieldTypesEnum::SetInput;
295 else
296 nRet = SwFieldTypesEnum::Set;
297 break;
299 case SwFieldIds::PageNumber:
301 auto nSubType = GetSubType();
302 if( PG_NEXT == nSubType )
303 nRet = SwFieldTypesEnum::NextPage;
304 else if( PG_PREV == nSubType )
305 nRet = SwFieldTypesEnum::PreviousPage;
306 else
307 nRet = SwFieldTypesEnum::PageNumber;
309 break;
311 default:
312 nRet = aTypeTab[ m_pType->Which() ];
314 return nRet;
317 /// get name or content
318 OUString SwField::GetFieldName() const
320 SwFieldTypesEnum nTypeId = GetTypeId();
321 if (SwFieldIds::DateTime == GetTyp()->Which())
323 nTypeId =
324 ((GetSubType() & DATEFLD) != 0) ? SwFieldTypesEnum::Date : SwFieldTypesEnum::Time;
326 OUString sRet = SwFieldType::GetTypeStr( nTypeId );
327 if (IsFixed())
329 sRet += " " + SwViewShell::GetShellRes()->aFixedStr;
331 return sRet;
334 OUString SwField::GetPar1() const
336 return OUString();
339 OUString SwField::GetPar2() const
341 return OUString();
344 OUString SwField::GetFormula() const
346 return GetPar2();
349 void SwField::SetPar1(const OUString& )
352 void SwField::SetPar2(const OUString& )
355 sal_uInt16 SwField::GetSubType() const
357 return 0;
360 void SwField::SetSubType(sal_uInt16 )
364 bool SwField::QueryValue( uno::Any& rVal, sal_uInt16 nWhichId ) const
366 switch( nWhichId )
368 case FIELD_PROP_BOOL4:
369 rVal <<= !m_bIsAutomaticLanguage;
370 break;
371 case FIELD_PROP_TITLE:
373 rVal <<= m_aTitle;
375 break;
376 default:
377 assert(false);
379 return true;
382 bool SwField::PutValue( const uno::Any& rVal, sal_uInt16 nWhichId )
384 switch( nWhichId )
386 case FIELD_PROP_BOOL4:
388 bool bFixed = false;
389 if(rVal >>= bFixed)
390 m_bIsAutomaticLanguage = !bFixed;
392 break;
393 case FIELD_PROP_TITLE:
395 OUString aTitle;
396 if (rVal >>= aTitle)
398 m_aTitle = aTitle;
401 break;
402 default:
403 assert(false);
405 return true;
408 /** Set a new type
410 * This is needed/used for copying between documents.
411 * Needs to be always of the same type.
412 * @param pNewType The new type.
413 * @return The old type.
415 SwFieldType* SwField::ChgTyp( SwFieldType* pNewType )
417 assert(pNewType && pNewType->Which() == m_pType->Which());
419 SwFieldType* pOld = m_pType;
420 m_pType = pNewType;
421 return pOld;
424 /// Does the field have an action on a ClickHandler? (E.g. INetFields,...)
425 bool SwField::HasClickHdl() const
427 bool bRet = false;
428 switch (m_pType->Which())
430 case SwFieldIds::Internet:
431 case SwFieldIds::JumpEdit:
432 case SwFieldIds::GetRef:
433 case SwFieldIds::Macro:
434 case SwFieldIds::Input:
435 case SwFieldIds::Dropdown:
436 case SwFieldIds::TableOfAuthorities:
437 bRet = true;
438 break;
440 case SwFieldIds::SetExp:
441 bRet = static_cast<const SwSetExpField*>(this)->GetInputFlag();
442 break;
444 default: break;
446 return bRet;
449 void SwField::SetLanguage(LanguageType const nLang)
451 m_nLang = nLang;
454 void SwField::ChangeFormat(sal_uInt32 const nFormat)
456 m_nFormat = nFormat;
459 bool SwField::IsFixed() const
461 bool bRet = false;
462 switch (m_pType->Which())
464 case SwFieldIds::FixDate:
465 case SwFieldIds::FixTime:
466 bRet = true;
467 break;
469 case SwFieldIds::DateTime:
470 bRet = 0 != (GetSubType() & FIXEDFLD);
471 break;
473 case SwFieldIds::ExtUser:
474 case SwFieldIds::Author:
475 bRet = 0 != (GetFormat() & AF_FIXED);
476 break;
478 case SwFieldIds::Filename:
479 bRet = 0 != (GetFormat() & FF_FIXED);
480 break;
482 case SwFieldIds::DocInfo:
483 bRet = 0 != (GetSubType() & DI_SUB_FIXED);
484 break;
485 default: break;
487 return bRet;
490 OUString
491 SwField::ExpandField(bool const bCached, SwRootFrame const*const pLayout) const
493 if ( m_bUseFieldValueCache )
495 if (!bCached) // #i85766# do not expand fields in clipboard documents
497 if (GetTypeId() == SwFieldTypesEnum::Authority)
499 const SwAuthorityField* pAuthorityField = static_cast<const SwAuthorityField*>(this);
500 m_Cache = pAuthorityField->ConditionalExpandAuthIdentifier(pLayout);
502 else
503 m_Cache = ExpandImpl(pLayout);
505 return m_Cache;
508 return ExpandImpl(pLayout);
511 std::unique_ptr<SwField> SwField::CopyField() const
513 std::unique_ptr<SwField> pNew = Copy();
514 // #i85766# cache expansion of source (for clipboard)
515 // use this->cache, not this->Expand(): only text formatting calls Expand()
516 pNew->m_Cache = m_Cache;
517 pNew->m_bUseFieldValueCache = m_bUseFieldValueCache;
519 return pNew;
522 /// expand numbering
523 OUString FormatNumber(sal_uInt32 nNum, SvxNumType nFormat, LanguageType nLang)
525 if(SVX_NUM_PAGEDESC == nFormat)
526 return OUString::number( nNum );
527 SvxNumberType aNumber;
529 OSL_ENSURE(nFormat != SVX_NUM_NUMBER_NONE, "wrong number format" );
531 aNumber.SetNumberingType(nFormat);
533 if (nLang == LANGUAGE_NONE)
534 return aNumber.GetNumStr(nNum);
535 else
536 return aNumber.GetNumStr(nNum, LanguageTag::convertToLocale(nLang));
539 SwFieldTypesEnum SwFieldTypeFromString(std::u16string_view rString)
541 if (rString == u"Date")
542 return SwFieldTypesEnum::Date;
543 if (rString == u"Time")
544 return SwFieldTypesEnum::Time;
545 if (rString == u"Filename")
546 return SwFieldTypesEnum::Filename;
547 if (rString == u"DatabaseName")
548 return SwFieldTypesEnum::DatabaseName;
549 if (rString == u"Chapter")
550 return SwFieldTypesEnum::Chapter;
551 if (rString == u"PageNumber")
552 return SwFieldTypesEnum::PageNumber;
553 if (rString == u"DocumentStatistics")
554 return SwFieldTypesEnum::DocumentStatistics;
555 if (rString == u"Author")
556 return SwFieldTypesEnum::Author;
557 if (rString == u"Set")
558 return SwFieldTypesEnum::Set;
559 if (rString == u"Get")
560 return SwFieldTypesEnum::Get;
561 if (rString == u"Formel")
562 return SwFieldTypesEnum::Formel;
563 if (rString == u"HiddenText")
564 return SwFieldTypesEnum::HiddenText;
565 if (rString == u"SetRef")
566 return SwFieldTypesEnum::SetRef;
567 return SwFieldTypesEnum::Unknown;
570 SwValueFieldType::SwValueFieldType(SwDoc *const pDoc, SwFieldIds const nWhichId)
571 : SwFieldType(nWhichId)
572 , m_pDoc(pDoc)
573 , m_bUseFormat(true)
577 SwValueFieldType::SwValueFieldType( const SwValueFieldType& rTyp )
578 : SwFieldType(rTyp.Which())
579 , m_pDoc(rTyp.GetDoc())
580 , m_bUseFormat(rTyp.UseFormat())
584 /// return value formatted as string
585 OUString SwValueFieldType::ExpandValue( const double& rVal,
586 sal_uInt32 nFormat, LanguageType nLng) const
588 if (rVal >= DBL_MAX) // error string for calculator
589 return SwViewShell::GetShellRes()->aCalc_Error;
591 OUString sExpand;
592 SvNumberFormatter* pFormatter = m_pDoc->GetNumberFormatter();
593 const Color* pCol = nullptr;
595 // Bug #60010
596 LanguageType nFormatLng = ::lcl_GetLanguageOfFormat( nLng, nFormat, *pFormatter );
598 if( nFormat < SV_COUNTRY_LANGUAGE_OFFSET && LANGUAGE_SYSTEM != nFormatLng )
600 const SvNumberformat* pEntry = pFormatter->GetEntry(nFormat);
602 if (pEntry && nLng != pEntry->GetLanguage())
604 sal_uInt32 nNewFormat = pFormatter->GetFormatForLanguageIfBuiltIn(nFormat,
605 nFormatLng);
606 if (nNewFormat == nFormat)
608 // probably user-defined format
609 OUString sFormat(pEntry->GetFormatstring());
610 sal_Int32 nDummy;
611 SvNumFormatType nType = SvNumFormatType::DEFINED;
613 pFormatter->PutandConvertEntry(sFormat, nDummy, nType, nFormat,
614 pEntry->GetLanguage(), nFormatLng, false);
616 else
617 nFormat = nNewFormat;
619 OSL_ENSURE(pEntry, "unknown number format!");
622 if( pFormatter->IsTextFormat( nFormat ) )
624 pFormatter->GetOutputString(DoubleToString(rVal, nFormatLng), nFormat,
625 sExpand, &pCol);
627 else
629 pFormatter->GetOutputString(rVal, nFormat, sExpand, &pCol);
631 return sExpand;
634 OUString SwValueFieldType::DoubleToString(const double &rVal,
635 sal_uInt32 nFormat) const
637 SvNumberFormatter* pFormatter = m_pDoc->GetNumberFormatter();
638 const SvNumberformat* pEntry = pFormatter->GetEntry(nFormat);
640 if (!pEntry)
641 return OUString();
643 return DoubleToString(rVal, pEntry->GetLanguage());
646 OUString SwValueFieldType::DoubleToString( const double &rVal,
647 LanguageType nLng ) const
649 SvNumberFormatter* pFormatter = m_pDoc->GetNumberFormatter();
651 // Bug #60010
652 if( nLng == LANGUAGE_NONE )
653 nLng = LANGUAGE_SYSTEM;
655 pFormatter->ChangeIntl( nLng ); // get separator in the correct language
656 return ::rtl::math::doubleToUString( rVal, rtl_math_StringFormat_F, 12,
657 pFormatter->GetNumDecimalSep()[0], true );
660 OUString SwValueFieldType::GetInputOrDateTime( const OUString& rInput, const double& rVal, sal_uInt32 nFormat ) const
662 if (nFormat && nFormat != SAL_MAX_UINT32 && UseFormat())
664 SvNumberFormatter* pFormatter = m_pDoc->GetNumberFormatter();
665 const SvNumberformat* pEntry = pFormatter->GetEntry(nFormat);
666 if (pEntry && (pEntry->GetType() & SvNumFormatType::DATETIME))
668 OUString aEdit;
669 pFormatter->GetInputLineString( rVal, nFormat, aEdit);
670 return aEdit;
673 return rInput;
676 SwValueField::SwValueField( SwValueFieldType* pFieldType, sal_uInt32 nFormat,
677 LanguageType nLng, const double fVal )
678 : SwField(pFieldType, nFormat, nLng)
679 , m_fValue(fVal)
683 SwValueField::SwValueField( const SwValueField& rField )
684 : SwField(rField)
685 , m_fValue(rField.GetValue())
689 SwValueField::~SwValueField()
693 /** Set a new type
695 * This is needed/used for copying between documents.
696 * Needs to be always of the same type.
697 * @param pNewType The new type.
698 * @return The old type.
700 SwFieldType* SwValueField::ChgTyp( SwFieldType* pNewType )
702 SwDoc* pNewDoc = static_cast<SwValueFieldType *>(pNewType)->GetDoc();
703 SwDoc* pDoc = GetDoc();
705 if( pNewDoc && pDoc && pDoc != pNewDoc)
707 SvNumberFormatter* pFormatter = pNewDoc->GetNumberFormatter();
709 if( pFormatter && pFormatter->HasMergeFormatTable() &&
710 static_cast<SwValueFieldType *>(GetTyp())->UseFormat() )
711 SetFormat(pFormatter->GetMergeFormatIndex( GetFormat() ));
714 return SwField::ChgTyp(pNewType);
717 /// get format in office language
718 sal_uInt32 SwValueField::GetSystemFormat(SvNumberFormatter* pFormatter, sal_uInt32 nFormat)
720 const SvNumberformat* pEntry = pFormatter->GetEntry(nFormat);
721 LanguageType nLng = SvtSysLocale().GetLanguageTag().getLanguageType();
723 if (pEntry && nLng != pEntry->GetLanguage())
725 sal_uInt32 nNewFormat = pFormatter->GetFormatForLanguageIfBuiltIn(nFormat,
726 nLng);
728 if (nNewFormat == nFormat)
730 // probably user-defined format
731 SvNumFormatType nType = SvNumFormatType::DEFINED;
732 sal_Int32 nDummy;
734 OUString sFormat(pEntry->GetFormatstring());
736 sal_uInt32 nTempFormat = nFormat;
737 pFormatter->PutandConvertEntry(sFormat, nDummy, nType,
738 nTempFormat, pEntry->GetLanguage(), nLng, true);
739 nFormat = nTempFormat;
741 else
742 nFormat = nNewFormat;
745 return nFormat;
748 void SwValueField::dumpAsXml(xmlTextWriterPtr pWriter) const
750 (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SwValueField"));
751 (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("m_fValue"), BAD_CAST(OString::number(m_fValue).getStr()));
752 SwField::dumpAsXml(pWriter);
753 (void)xmlTextWriterEndElement(pWriter);
756 /// set language of the format
757 void SwValueField::SetLanguage( LanguageType nLng )
759 if( IsAutomaticLanguage() &&
760 static_cast<SwValueFieldType *>(GetTyp())->UseFormat() &&
761 GetFormat() != SAL_MAX_UINT32 )
763 // Bug #60010
764 SvNumberFormatter* pFormatter = GetDoc()->GetNumberFormatter();
765 LanguageType nFormatLng = ::lcl_GetLanguageOfFormat( nLng, GetFormat(),
766 *pFormatter );
768 if( (GetFormat() >= SV_COUNTRY_LANGUAGE_OFFSET ||
769 LANGUAGE_SYSTEM != nFormatLng ) &&
770 !(Which() == SwFieldIds::User && (GetSubType()&nsSwExtendedSubType::SUB_CMD) ) )
772 const SvNumberformat* pEntry = pFormatter->GetEntry(GetFormat());
774 if( pEntry && nFormatLng != pEntry->GetLanguage() )
776 sal_uInt32 nNewFormat = pFormatter->GetFormatForLanguageIfBuiltIn(
777 GetFormat(), nFormatLng );
779 if( nNewFormat == GetFormat() )
781 // probably user-defined format
782 SvNumFormatType nType = SvNumFormatType::DEFINED;
783 sal_Int32 nDummy;
784 OUString sFormat( pEntry->GetFormatstring() );
785 pFormatter->PutandConvertEntry( sFormat, nDummy, nType,
786 nNewFormat,
787 pEntry->GetLanguage(),
788 nFormatLng, false);
790 SetFormat( nNewFormat );
792 OSL_ENSURE(pEntry, "unknown number format!");
796 SwField::SetLanguage(nLng);
799 double SwValueField::GetValue() const
801 return m_fValue;
804 void SwValueField::SetValue( const double& rVal )
806 m_fValue = rVal;
809 SwFormulaField::SwFormulaField( SwValueFieldType* pFieldType, sal_uInt32 nFormat, const double fVal)
810 : SwValueField(pFieldType, nFormat, LANGUAGE_SYSTEM, fVal)
814 SwFormulaField::SwFormulaField( const SwFormulaField& rField )
815 : SwValueField(static_cast<SwValueFieldType *>(rField.GetTyp()), rField.GetFormat(),
816 rField.GetLanguage(), rField.GetValue())
820 OUString SwFormulaField::GetFormula() const
822 return m_sFormula;
825 void SwFormulaField::SetFormula(const OUString& rStr)
827 m_sFormula = rStr;
829 sal_uLong nFormat(GetFormat());
831 if( nFormat && SAL_MAX_UINT32 != nFormat )
833 sal_Int32 nPos = 0;
834 double fTmpValue;
835 // Uses the SwCalc document locale.
836 if( SwCalc::Str2Double( rStr, nPos, fTmpValue, GetDoc() ) )
837 SwValueField::SetValue( fTmpValue );
841 void SwFormulaField::SetExpandedFormula( const OUString& rStr )
843 sal_uInt32 nFormat(GetFormat());
845 if (nFormat && nFormat != SAL_MAX_UINT32 && static_cast<SwValueFieldType *>(GetTyp())->UseFormat())
847 double fTmpValue;
849 if (GetDoc()->IsNumberFormat(rStr, nFormat, fTmpValue))
851 SwValueField::SetValue(fTmpValue);
853 // Will get reinterpreted by SwCalc when updating fields, so use
854 // the proper locale.
855 m_sFormula = static_cast<SwValueFieldType *>(GetTyp())->DoubleToString( fTmpValue,
856 SwCalc::GetDocAppScriptLang( *GetDoc()));
857 return;
860 m_sFormula = rStr;
863 OUString SwFormulaField::GetExpandedFormula() const
865 sal_uInt32 nFormat(GetFormat());
867 if (nFormat && nFormat != SAL_MAX_UINT32 && static_cast<SwValueFieldType *>(GetTyp())->UseFormat())
869 OUString sFormattedValue;
870 const Color* pCol = nullptr;
872 SvNumberFormatter* pFormatter = GetDoc()->GetNumberFormatter();
874 if (pFormatter->IsTextFormat(nFormat))
876 OUString sTempIn(static_cast<SwValueFieldType *>(GetTyp())->DoubleToString(GetValue(), nFormat));
877 pFormatter->GetOutputString(sTempIn, nFormat, sFormattedValue, &pCol);
879 else
881 pFormatter->GetOutputString(GetValue(), nFormat, sFormattedValue, &pCol);
883 return sFormattedValue;
885 else
886 return GetFormula();
889 OUString SwFormulaField::GetInputOrDateTime() const
891 // GetFormula() leads to problems with date formats because only the
892 // number string without formatting is returned (additionally that may or
893 // may not use a localized decimal separator due to the convoluted handling
894 // of "formula"). It must be used for expressions though because otherwise
895 // with GetPar2() only the value calculated by SwCalc would be displayed
896 // (instead of test2 = test + 1).
897 // Force a formatted edit value for date+time formats, assuming they are
898 // not editable calculated expressions if the formula doesn't contain
899 // arithmetic operators or assignment.
901 const OUString aFormula( GetFormula());
903 if (comphelper::string::indexOfAny( aFormula, u"=+-*/", 0) == -1)
904 return static_cast<SwValueFieldType*>(GetTyp())->GetInputOrDateTime( aFormula, GetValue(), GetFormat());
906 return aFormula;
909 OUString SwField::GetDescription() const
911 return SwResId(STR_FIELD);
914 bool SwField::IsClickable() const
916 switch (Which())
918 case SwFieldIds::JumpEdit:
919 case SwFieldIds::Macro:
920 case SwFieldIds::GetRef:
921 case SwFieldIds::Input:
922 case SwFieldIds::SetExp:
923 case SwFieldIds::Dropdown:
924 case SwFieldIds::TableOfAuthorities:
925 return true;
926 default: break;
928 return false;
931 void SwField::dumpAsXml(xmlTextWriterPtr pWriter) const
933 (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SwField"));
934 (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("symbol"), "%s", BAD_CAST(typeid(*this).name()));
935 (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("ptr"), "%p", this);
936 (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("m_nFormat"), BAD_CAST(OString::number(m_nFormat).getStr()));
937 (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("m_nLang"), BAD_CAST(OString::number(m_nLang.get()).getStr()));
938 (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("m_aTitle"), BAD_CAST(m_aTitle.toUtf8().getStr()));
940 (void)xmlTextWriterEndElement(pWriter);
943 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */