Add Marathi autocorrect
[LibreOffice.git] / sw / source / core / fields / fldbas.cxx
blob574e8a1ba79d3a36010b32c80e227c5fdcab94c4
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)
53 if( nLng == LANGUAGE_NONE ) // Bug #60010
54 nLng = LANGUAGE_SYSTEM;
55 else if( nLng == ::GetAppLanguage() )
56 switch( SvNumberFormatter::GetIndexTableOffset( nFormat ))
58 case NF_NUMBER_SYSTEM:
59 case NF_DATE_SYSTEM_SHORT:
60 case NF_DATE_SYSTEM_LONG:
61 case NF_DATETIME_SYSTEM_SHORT_HHMM:
62 nLng = LANGUAGE_SYSTEM;
63 break;
64 default: break;
66 return nLng;
69 // Globals
71 /// field names
72 std::vector<OUString>* SwFieldType::s_pFieldNames = nullptr;
74 namespace
77 const o3tl::enumarray<SwFieldIds,SwFieldTypesEnum> aTypeTab {
78 /* SwFieldIds::Database */ SwFieldTypesEnum::Database,
79 /* SwFieldIds::User */ SwFieldTypesEnum::User,
80 /* SwFieldIds::Filename */ SwFieldTypesEnum::Filename,
81 /* SwFieldIds::DatabaseName */ SwFieldTypesEnum::DatabaseName,
82 /* SwFieldIds::Date */ SwFieldTypesEnum::Date,
83 /* SwFieldIds::Time */ SwFieldTypesEnum::Time,
84 /* SwFieldIds::PageNumber */ SwFieldTypesEnum::PageNumber, // dynamic
85 /* SwFieldIds::Author */ SwFieldTypesEnum::Author,
86 /* SwFieldIds::Chapter */ SwFieldTypesEnum::Chapter,
87 /* SwFieldIds::DocStat */ SwFieldTypesEnum::DocumentStatistics,
88 /* SwFieldIds::GetExp */ SwFieldTypesEnum::Get, // dynamic
89 /* SwFieldIds::SetExp */ SwFieldTypesEnum::Set, // dynamic
90 /* SwFieldIds::GetRef */ SwFieldTypesEnum::GetRef,
91 /* SwFieldIds::HiddenText */ SwFieldTypesEnum::HiddenText,
92 /* SwFieldIds::Postit */ SwFieldTypesEnum::Postit,
93 /* SwFieldIds::FixDate */ SwFieldTypesEnum::FixedDate,
94 /* SwFieldIds::FixTime */ SwFieldTypesEnum::FixedTime,
95 /* SwFieldIds::Reg */ SwFieldTypesEnum::Begin, // old (no change since 2000)
96 /* SwFieldIds::VarReg */ SwFieldTypesEnum::Begin, // old (no change since 2000)
97 /* SwFieldIds::SetRef */ SwFieldTypesEnum::SetRef,
98 /* SwFieldIds::Input */ SwFieldTypesEnum::Input,
99 /* SwFieldIds::Macro */ SwFieldTypesEnum::Macro,
100 /* SwFieldIds::Dde */ SwFieldTypesEnum::DDE,
101 /* SwFieldIds::Table */ SwFieldTypesEnum::Formel,
102 /* SwFieldIds::HiddenPara */ SwFieldTypesEnum::HiddenParagraph,
103 /* SwFieldIds::DocInfo */ SwFieldTypesEnum::DocumentInfo,
104 /* SwFieldIds::TemplateName */ SwFieldTypesEnum::TemplateName,
105 /* SwFieldIds::DbNextSet */ SwFieldTypesEnum::DatabaseNextSet,
106 /* SwFieldIds::DbNumSet */ SwFieldTypesEnum::DatabaseNumberSet,
107 /* SwFieldIds::DbSetNumber */ SwFieldTypesEnum::DatabaseSetNumber,
108 /* SwFieldIds::ExtUser */ SwFieldTypesEnum::ExtendedUser,
109 /* SwFieldIds::RefPageSet */ SwFieldTypesEnum::SetRefPage,
110 /* SwFieldIds::RefPageGet */ SwFieldTypesEnum::GetRefPage,
111 /* SwFieldIds::Internet */ SwFieldTypesEnum::Internet,
112 /* SwFieldIds::JumpEdit */ SwFieldTypesEnum::JumpEdit,
113 /* SwFieldIds::Script */ SwFieldTypesEnum::Script,
114 /* SwFieldIds::DateTime */ SwFieldTypesEnum::Begin, // dynamic
115 /* SwFieldIds::TableOfAuthorities*/ SwFieldTypesEnum::Authority,
116 /* SwFieldIds::CombinedChars */ SwFieldTypesEnum::CombinedChars,
117 /* SwFieldIds::Dropdown */ SwFieldTypesEnum::Dropdown,
118 /* SwFieldIds::ParagraphSignature */ SwFieldTypesEnum::ParagraphSignature
123 const OUString & SwFieldType::GetTypeStr(SwFieldTypesEnum nTypeId)
125 if (!s_pFieldNames)
126 GetFieldName_();
128 return (*SwFieldType::s_pFieldNames)[static_cast<int>(nTypeId)];
131 // each field references a field type that is unique for each document
132 SwFieldType::SwFieldType( SwFieldIds nWhichId )
133 : sw::BroadcastingModify()
134 , m_nWhich(nWhichId)
138 OUString SwFieldType::GetName() const
140 return OUString();
143 void SwFieldType::QueryValue( uno::Any&, sal_uInt16 ) const
146 void SwFieldType::PutValue( const uno::Any& , sal_uInt16 )
150 void SwFieldType::PrintHiddenPara()
152 SwClientNotify(*this, sw::PrintHiddenParaHint());
155 void SwFieldType::dumpAsXml(xmlTextWriterPtr pWriter) const
157 std::vector<SwFormatField*> vFields;
158 GatherFields(vFields);
159 if(!vFields.size())
160 return;
161 (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SwFieldType"));
162 (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("ptr"), "%p", this);
163 (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("symbol"), "%s", BAD_CAST(typeid(*this).name()));
164 for(const auto pFormatField: vFields)
166 (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SwFormatField"));
167 (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("ptr"), "%p", pFormatField);
168 (void)xmlTextWriterEndElement(pWriter);
170 (void)xmlTextWriterEndElement(pWriter);
173 SwFormatField* SwFieldType::FindFormatForField(const SwField* pField) const {
174 SwFormatField* pFormat = nullptr;
175 CallSwClientNotify(sw::FindFormatForFieldHint(pField, pFormat));
176 return pFormat;
179 SwFormatField* SwFieldType::FindFormatForPostItId(sal_uInt32 nPostItId) const {
180 SwFormatField* pFormat = nullptr;
181 CallSwClientNotify(sw::FindFormatForPostItIdHint(nPostItId, pFormat));
182 return pFormat;
185 void SwFieldType::CollectPostIts(std::vector<SwFormatField*>& rvFormatFields, IDocumentRedlineAccess const& rIDRA, const bool bHideRedlines)
187 CallSwClientNotify(sw::CollectPostItsHint(rvFormatFields, rIDRA, bHideRedlines));
190 bool SwFieldType::HasHiddenInformationNotes() const
192 bool bHasHiddenInformationNotes = false;
193 CallSwClientNotify(sw::HasHiddenInformationNotesHint(bHasHiddenInformationNotes));
194 return bHasHiddenInformationNotes;
197 void SwFieldType::GatherNodeIndex(std::vector<SwNodeOffset>& rvNodeIndex)
199 CallSwClientNotify(sw::GatherNodeIndexHint(rvNodeIndex));
202 void SwFieldType::GatherRefFields(std::vector<SwGetRefField*>& rvRFields, const sal_uInt16 nTyp)
204 CallSwClientNotify(sw::GatherRefFieldsHint(rvRFields, nTyp));
207 void SwFieldType::GatherFields(std::vector<SwFormatField*>& rvFields, bool bCollectOnlyInDocNodes) const
209 CallSwClientNotify(sw::GatherFieldsHint(rvFields, bCollectOnlyInDocNodes));
212 void SwFieldType::GatherDdeTables(std::vector<SwDDETable*>& rvTables) const
214 CallSwClientNotify(sw::GatherDdeTablesHint(rvTables));
217 void SwFieldType::UpdateDocPos(const SwTwips nDocPos)
219 CallSwClientNotify(sw::DocPosUpdate(nDocPos));
221 void SwFieldType::UpdateFields()
223 CallSwClientNotify(sw::LegacyModifyHint(nullptr, nullptr));
226 void SwFieldType::SetXObject(rtl::Reference<SwXFieldMaster> const& xFieldMaster)
228 m_wXFieldMaster = xFieldMaster.get();
231 void SwFieldTypes::dumpAsXml(xmlTextWriterPtr pWriter) const
233 (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SwFieldTypes"));
234 sal_uInt16 nCount = size();
235 for (sal_uInt16 nType = 0; nType < nCount; ++nType)
236 (*this)[nType]->dumpAsXml(pWriter);
237 (void)xmlTextWriterEndElement(pWriter);
242 // Base class for all fields.
243 // A field (multiple can exist) references a field type (can exists only once)
244 SwField::SwField(
245 SwFieldType* pType,
246 sal_uInt32 nFormat,
247 LanguageType nLang,
248 bool bUseFieldValueCache)
249 : m_pType( pType )
250 , m_nFormat( nFormat )
251 , m_nLang( nLang )
252 , m_bUseFieldValueCache( bUseFieldValueCache )
253 , m_bIsAutomaticLanguage( true )
255 assert(m_pType);
258 SwField::~SwField()
262 SwFieldTypesEnum SwField::GetTypeId() const
265 SwFieldTypesEnum nRet;
266 switch (m_pType->Which())
268 case SwFieldIds::DateTime:
269 if (GetSubType() & FIXEDFLD)
270 nRet = GetSubType() & DATEFLD ? SwFieldTypesEnum::FixedDate : SwFieldTypesEnum::FixedTime;
271 else
272 nRet = GetSubType() & DATEFLD ? SwFieldTypesEnum::Date : SwFieldTypesEnum::Time;
273 break;
274 case SwFieldIds::GetExp:
275 nRet = nsSwGetSetExpType::GSE_FORMULA & GetSubType() ? SwFieldTypesEnum::Formel : SwFieldTypesEnum::Get;
276 break;
278 case SwFieldIds::HiddenText:
279 nRet = static_cast<SwFieldTypesEnum>(GetSubType());
280 break;
282 case SwFieldIds::SetExp:
283 if( nsSwGetSetExpType::GSE_SEQ & GetSubType() )
284 nRet = SwFieldTypesEnum::Sequence;
285 else if( static_cast<const SwSetExpField*>(this)->GetInputFlag() )
286 nRet = SwFieldTypesEnum::SetInput;
287 else
288 nRet = SwFieldTypesEnum::Set;
289 break;
291 case SwFieldIds::PageNumber:
293 auto nSubType = GetSubType();
294 if( PG_NEXT == nSubType )
295 nRet = SwFieldTypesEnum::NextPage;
296 else if( PG_PREV == nSubType )
297 nRet = SwFieldTypesEnum::PreviousPage;
298 else
299 nRet = SwFieldTypesEnum::PageNumber;
301 break;
303 default:
304 nRet = aTypeTab[ m_pType->Which() ];
306 return nRet;
309 /// get name or content
310 OUString SwField::GetFieldName() const
312 SwFieldTypesEnum nTypeId = GetTypeId();
313 if (SwFieldIds::DateTime == GetTyp()->Which())
315 nTypeId =
316 ((GetSubType() & DATEFLD) != 0) ? SwFieldTypesEnum::Date : SwFieldTypesEnum::Time;
318 OUString sRet = SwFieldType::GetTypeStr( nTypeId );
319 if (IsFixed())
321 sRet += " " + SwViewShell::GetShellRes()->aFixedStr;
323 return sRet;
326 OUString SwField::GetPar1() const
328 return OUString();
331 OUString SwField::GetPar2() const
333 return OUString();
336 OUString SwField::GetFormula() const
338 return GetPar2();
341 void SwField::SetPar1(const OUString& )
344 void SwField::SetPar2(const OUString& )
347 sal_uInt16 SwField::GetSubType() const
349 return 0;
352 void SwField::SetSubType(sal_uInt16 )
356 bool SwField::QueryValue( uno::Any& rVal, sal_uInt16 nWhichId ) const
358 switch( nWhichId )
360 case FIELD_PROP_BOOL4:
361 rVal <<= !m_bIsAutomaticLanguage;
362 break;
363 case FIELD_PROP_TITLE:
365 rVal <<= m_aTitle;
367 break;
368 default:
369 assert(false);
371 return true;
374 bool SwField::PutValue( const uno::Any& rVal, sal_uInt16 nWhichId )
376 switch( nWhichId )
378 case FIELD_PROP_BOOL4:
380 bool bFixed = false;
381 if(rVal >>= bFixed)
382 m_bIsAutomaticLanguage = !bFixed;
384 break;
385 case FIELD_PROP_TITLE:
387 OUString aTitle;
388 if (rVal >>= aTitle)
390 m_aTitle = aTitle;
393 break;
394 default:
395 assert(false);
397 return true;
400 /** Set a new type
402 * This is needed/used for copying between documents.
403 * Needs to be always of the same type.
404 * @param pNewType The new type.
405 * @return The old type.
407 SwFieldType* SwField::ChgTyp( SwFieldType* pNewType )
409 assert(pNewType && pNewType->Which() == m_pType->Which());
411 SwFieldType* pOld = m_pType;
412 m_pType = pNewType;
413 return pOld;
416 /// Does the field have an action on a ClickHandler? (E.g. INetFields,...)
417 bool SwField::HasClickHdl() const
419 bool bRet = false;
420 switch (m_pType->Which())
422 case SwFieldIds::Internet:
423 case SwFieldIds::JumpEdit:
424 case SwFieldIds::GetRef:
425 case SwFieldIds::Macro:
426 case SwFieldIds::Input:
427 case SwFieldIds::Dropdown:
428 case SwFieldIds::TableOfAuthorities:
429 bRet = true;
430 break;
432 case SwFieldIds::SetExp:
433 bRet = static_cast<const SwSetExpField*>(this)->GetInputFlag();
434 break;
436 default: break;
438 return bRet;
441 void SwField::SetLanguage(LanguageType const nLang)
443 m_nLang = nLang;
446 void SwField::ChangeFormat(sal_uInt32 const nFormat)
448 m_nFormat = nFormat;
451 bool SwField::IsFixed() const
453 bool bRet = false;
454 switch (m_pType->Which())
456 case SwFieldIds::FixDate:
457 case SwFieldIds::FixTime:
458 bRet = true;
459 break;
461 case SwFieldIds::DateTime:
462 bRet = 0 != (GetSubType() & FIXEDFLD);
463 break;
465 case SwFieldIds::ExtUser:
466 case SwFieldIds::Author:
467 bRet = 0 != (GetFormat() & AF_FIXED);
468 break;
470 case SwFieldIds::Filename:
471 bRet = 0 != (GetFormat() & FF_FIXED);
472 break;
474 case SwFieldIds::DocInfo:
475 bRet = 0 != (GetSubType() & DI_SUB_FIXED);
476 break;
477 default: break;
479 return bRet;
482 OUString
483 SwField::ExpandField(bool const bCached, SwRootFrame const*const pLayout) const
485 if ( m_bUseFieldValueCache )
487 if (!bCached) // #i85766# do not expand fields in clipboard documents
489 if (GetTypeId() == SwFieldTypesEnum::Authority)
491 const SwAuthorityField* pAuthorityField = static_cast<const SwAuthorityField*>(this);
492 m_Cache = pAuthorityField->ConditionalExpandAuthIdentifier(pLayout);
494 else
495 m_Cache = ExpandImpl(pLayout);
497 return m_Cache;
500 return ExpandImpl(pLayout);
503 std::unique_ptr<SwField> SwField::CopyField() const
505 std::unique_ptr<SwField> pNew = Copy();
506 // #i85766# cache expansion of source (for clipboard)
507 // use this->cache, not this->Expand(): only text formatting calls Expand()
508 pNew->m_Cache = m_Cache;
509 pNew->m_bUseFieldValueCache = m_bUseFieldValueCache;
511 return pNew;
514 /// expand numbering
515 OUString FormatNumber(sal_uInt32 nNum, SvxNumType nFormat, LanguageType nLang)
517 if(SVX_NUM_PAGEDESC == nFormat)
518 return OUString::number( nNum );
519 SvxNumberType aNumber;
521 OSL_ENSURE(nFormat != SVX_NUM_NUMBER_NONE, "wrong number format" );
523 aNumber.SetNumberingType(nFormat);
525 if (nLang == LANGUAGE_NONE)
526 return aNumber.GetNumStr(nNum);
527 else
528 return aNumber.GetNumStr(nNum, LanguageTag::convertToLocale(nLang));
531 SwFieldTypesEnum SwFieldTypeFromString(std::u16string_view rString)
533 if (rString == u"Date")
534 return SwFieldTypesEnum::Date;
535 if (rString == u"Time")
536 return SwFieldTypesEnum::Time;
537 if (rString == u"Filename")
538 return SwFieldTypesEnum::Filename;
539 if (rString == u"DatabaseName")
540 return SwFieldTypesEnum::DatabaseName;
541 if (rString == u"Chapter")
542 return SwFieldTypesEnum::Chapter;
543 if (rString == u"PageNumber")
544 return SwFieldTypesEnum::PageNumber;
545 if (rString == u"DocumentStatistics")
546 return SwFieldTypesEnum::DocumentStatistics;
547 if (rString == u"Author")
548 return SwFieldTypesEnum::Author;
549 if (rString == u"Set")
550 return SwFieldTypesEnum::Set;
551 if (rString == u"Get")
552 return SwFieldTypesEnum::Get;
553 if (rString == u"Formel")
554 return SwFieldTypesEnum::Formel;
555 if (rString == u"HiddenText")
556 return SwFieldTypesEnum::HiddenText;
557 if (rString == u"SetRef")
558 return SwFieldTypesEnum::SetRef;
559 return SwFieldTypesEnum::Unknown;
562 SwValueFieldType::SwValueFieldType(SwDoc *const pDoc, SwFieldIds const nWhichId)
563 : SwFieldType(nWhichId)
564 , m_pDoc(pDoc)
565 , m_bUseFormat(true)
569 SwValueFieldType::SwValueFieldType( const SwValueFieldType& rTyp )
570 : SwFieldType(rTyp.Which())
571 , m_pDoc(rTyp.GetDoc())
572 , m_bUseFormat(rTyp.UseFormat())
576 /// return value formatted as string
577 OUString SwValueFieldType::ExpandValue( const double& rVal,
578 sal_uInt32 nFormat, LanguageType nLng) const
580 if (rVal >= DBL_MAX) // error string for calculator
581 return SwViewShell::GetShellRes()->aCalc_Error;
583 OUString sExpand;
584 SvNumberFormatter* pFormatter = m_pDoc->GetNumberFormatter();
585 const Color* pCol = nullptr;
587 // Bug #60010
588 LanguageType nFormatLng = ::lcl_GetLanguageOfFormat( nLng, nFormat );
590 if( nFormat < SV_COUNTRY_LANGUAGE_OFFSET && LANGUAGE_SYSTEM != nFormatLng )
592 const SvNumberformat* pEntry = pFormatter->GetEntry(nFormat);
594 if (pEntry && nLng != pEntry->GetLanguage())
596 sal_uInt32 nNewFormat = pFormatter->GetFormatForLanguageIfBuiltIn(nFormat,
597 nFormatLng);
598 if (nNewFormat == nFormat)
600 // probably user-defined format
601 OUString sFormat(pEntry->GetFormatstring());
602 sal_Int32 nDummy;
603 SvNumFormatType nType = SvNumFormatType::DEFINED;
605 pFormatter->PutandConvertEntry(sFormat, nDummy, nType, nFormat,
606 pEntry->GetLanguage(), nFormatLng, false);
608 else
609 nFormat = nNewFormat;
611 OSL_ENSURE(pEntry, "unknown number format!");
614 if( pFormatter->IsTextFormat( nFormat ) )
616 pFormatter->GetOutputString(DoubleToString(rVal, nFormatLng), nFormat,
617 sExpand, &pCol);
619 else
621 pFormatter->GetOutputString(rVal, nFormat, sExpand, &pCol);
623 return sExpand;
626 OUString SwValueFieldType::DoubleToString(const double &rVal,
627 sal_uInt32 nFormat) const
629 SvNumberFormatter* pFormatter = m_pDoc->GetNumberFormatter();
630 const SvNumberformat* pEntry = pFormatter->GetEntry(nFormat);
632 if (!pEntry)
633 return OUString();
635 return DoubleToString(rVal, pEntry->GetLanguage());
638 OUString SwValueFieldType::DoubleToString( const double &rVal,
639 LanguageType nLng ) const
641 SvNumberFormatter* pFormatter = m_pDoc->GetNumberFormatter();
643 // Bug #60010
644 if( nLng == LANGUAGE_NONE )
645 nLng = LANGUAGE_SYSTEM;
647 pFormatter->ChangeIntl( nLng ); // get separator in the correct language
648 return ::rtl::math::doubleToUString( rVal, rtl_math_StringFormat_F, 12,
649 pFormatter->GetNumDecimalSep()[0], true );
652 OUString SwValueFieldType::GetInputOrDateTime( const OUString& rInput, const double& rVal, sal_uInt32 nFormat ) const
654 if (nFormat && nFormat != SAL_MAX_UINT32 && UseFormat())
656 SvNumberFormatter* pFormatter = m_pDoc->GetNumberFormatter();
657 const SvNumberformat* pEntry = pFormatter->GetEntry(nFormat);
658 if (pEntry && (pEntry->GetType() & SvNumFormatType::DATETIME))
659 return pFormatter->GetInputLineString( rVal, nFormat );
661 return rInput;
664 SwValueField::SwValueField( SwValueFieldType* pFieldType, sal_uInt32 nFormat,
665 LanguageType nLng, const double fVal )
666 : SwField(pFieldType, nFormat, nLng)
667 , m_fValue(fVal)
671 SwValueField::SwValueField( const SwValueField& rField )
672 : SwField(rField)
673 , m_fValue(rField.GetValue())
677 SwValueField::~SwValueField()
681 /** Set a new type
683 * This is needed/used for copying between documents.
684 * Needs to be always of the same type.
685 * @param pNewType The new type.
686 * @return The old type.
688 SwFieldType* SwValueField::ChgTyp( SwFieldType* pNewType )
690 SwDoc* pNewDoc = static_cast<SwValueFieldType *>(pNewType)->GetDoc();
691 SwDoc* pDoc = GetDoc();
693 if( pNewDoc && pDoc && pDoc != pNewDoc)
695 SvNumberFormatter* pFormatter = pNewDoc->GetNumberFormatter();
697 if( pFormatter && pFormatter->HasMergeFormatTable() &&
698 static_cast<SwValueFieldType *>(GetTyp())->UseFormat() )
699 SetFormat(pFormatter->GetMergeFormatIndex( GetFormat() ));
702 return SwField::ChgTyp(pNewType);
705 /// get format in office language
706 sal_uInt32 SwValueField::GetSystemFormat(SvNumberFormatter* pFormatter, sal_uInt32 nFormat)
708 const SvNumberformat* pEntry = pFormatter->GetEntry(nFormat);
709 LanguageType nLng = SvtSysLocale().GetLanguageTag().getLanguageType();
711 if (pEntry && nLng != pEntry->GetLanguage())
713 sal_uInt32 nNewFormat = pFormatter->GetFormatForLanguageIfBuiltIn(nFormat,
714 nLng);
716 if (nNewFormat == nFormat)
718 // probably user-defined format
719 SvNumFormatType nType = SvNumFormatType::DEFINED;
720 sal_Int32 nDummy;
722 OUString sFormat(pEntry->GetFormatstring());
724 sal_uInt32 nTempFormat = nFormat;
725 pFormatter->PutandConvertEntry(sFormat, nDummy, nType,
726 nTempFormat, pEntry->GetLanguage(), nLng, true);
727 nFormat = nTempFormat;
729 else
730 nFormat = nNewFormat;
733 return nFormat;
736 void SwValueField::dumpAsXml(xmlTextWriterPtr pWriter) const
738 (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SwValueField"));
739 (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("m_fValue"), BAD_CAST(OString::number(m_fValue).getStr()));
740 SwField::dumpAsXml(pWriter);
741 (void)xmlTextWriterEndElement(pWriter);
744 /// set language of the format
745 void SwValueField::SetLanguage( LanguageType nLng )
747 if( IsAutomaticLanguage() &&
748 static_cast<SwValueFieldType *>(GetTyp())->UseFormat() &&
749 GetFormat() != SAL_MAX_UINT32 )
751 // Bug #60010
752 SvNumberFormatter* pFormatter = GetDoc()->GetNumberFormatter();
753 LanguageType nFormatLng = ::lcl_GetLanguageOfFormat( nLng, GetFormat() );
755 if( (GetFormat() >= SV_COUNTRY_LANGUAGE_OFFSET ||
756 LANGUAGE_SYSTEM != nFormatLng ) &&
757 !(Which() == SwFieldIds::User && (GetSubType()&nsSwExtendedSubType::SUB_CMD) ) )
759 const SvNumberformat* pEntry = pFormatter->GetEntry(GetFormat());
761 if( pEntry && nFormatLng != pEntry->GetLanguage() )
763 sal_uInt32 nNewFormat = pFormatter->GetFormatForLanguageIfBuiltIn(
764 GetFormat(), nFormatLng );
766 if( nNewFormat == GetFormat() )
768 // probably user-defined format
769 SvNumFormatType nType = SvNumFormatType::DEFINED;
770 sal_Int32 nDummy;
771 OUString sFormat( pEntry->GetFormatstring() );
772 pFormatter->PutandConvertEntry( sFormat, nDummy, nType,
773 nNewFormat,
774 pEntry->GetLanguage(),
775 nFormatLng, false);
777 SetFormat( nNewFormat );
779 OSL_ENSURE(pEntry, "unknown number format!");
783 SwField::SetLanguage(nLng);
786 double SwValueField::GetValue() const
788 return m_fValue;
791 void SwValueField::SetValue( const double& rVal )
793 m_fValue = rVal;
796 SwFormulaField::SwFormulaField( SwValueFieldType* pFieldType, sal_uInt32 nFormat, const double fVal)
797 : SwValueField(pFieldType, nFormat, LANGUAGE_SYSTEM, fVal)
801 SwFormulaField::SwFormulaField( const SwFormulaField& rField )
802 : SwValueField(static_cast<SwValueFieldType *>(rField.GetTyp()), rField.GetFormat(),
803 rField.GetLanguage(), rField.GetValue())
807 OUString SwFormulaField::GetFormula() const
809 return m_sFormula;
812 void SwFormulaField::SetFormula(const OUString& rStr)
814 m_sFormula = rStr;
816 sal_uLong nFormat(GetFormat());
818 if( nFormat && SAL_MAX_UINT32 != nFormat )
820 sal_Int32 nPos = 0;
821 double fTmpValue;
822 // Uses the SwCalc document locale.
823 if( SwCalc::Str2Double( rStr, nPos, fTmpValue, GetDoc() ) )
824 SwValueField::SetValue( fTmpValue );
828 void SwFormulaField::SetExpandedFormula( const OUString& rStr )
830 sal_uInt32 nFormat(GetFormat());
832 if (nFormat && nFormat != SAL_MAX_UINT32 && static_cast<SwValueFieldType *>(GetTyp())->UseFormat())
834 double fTmpValue;
836 if (GetDoc()->IsNumberFormat(rStr, nFormat, fTmpValue))
838 SwValueField::SetValue(fTmpValue);
840 // Will get reinterpreted by SwCalc when updating fields, so use
841 // the proper locale.
842 m_sFormula = static_cast<SwValueFieldType *>(GetTyp())->DoubleToString( fTmpValue,
843 SwCalc::GetDocAppScriptLang( *GetDoc()));
844 return;
847 m_sFormula = rStr;
850 OUString SwFormulaField::GetExpandedFormula() const
852 sal_uInt32 nFormat(GetFormat());
854 if (nFormat && nFormat != SAL_MAX_UINT32 && static_cast<SwValueFieldType *>(GetTyp())->UseFormat())
856 OUString sFormattedValue;
857 const Color* pCol = nullptr;
859 SvNumberFormatter* pFormatter = GetDoc()->GetNumberFormatter();
861 if (pFormatter->IsTextFormat(nFormat))
863 OUString sTempIn(static_cast<SwValueFieldType *>(GetTyp())->DoubleToString(GetValue(), nFormat));
864 pFormatter->GetOutputString(sTempIn, nFormat, sFormattedValue, &pCol);
866 else
868 pFormatter->GetOutputString(GetValue(), nFormat, sFormattedValue, &pCol);
870 return sFormattedValue;
872 else
873 return GetFormula();
876 OUString SwFormulaField::GetInputOrDateTime() const
878 // GetFormula() leads to problems with date formats because only the
879 // number string without formatting is returned (additionally that may or
880 // may not use a localized decimal separator due to the convoluted handling
881 // of "formula"). It must be used for expressions though because otherwise
882 // with GetPar2() only the value calculated by SwCalc would be displayed
883 // (instead of test2 = test + 1).
884 // Force a formatted edit value for date+time formats, assuming they are
885 // not editable calculated expressions if the formula doesn't contain
886 // arithmetic operators or assignment.
888 const OUString aFormula( GetFormula());
890 if (comphelper::string::indexOfAny( aFormula, u"=+-*/", 0) == -1)
891 return static_cast<SwValueFieldType*>(GetTyp())->GetInputOrDateTime( aFormula, GetValue(), GetFormat());
893 return aFormula;
896 OUString SwField::GetDescription() const
898 return SwResId(STR_FIELD);
901 bool SwField::IsClickable() const
903 switch (Which())
905 case SwFieldIds::JumpEdit:
906 case SwFieldIds::Macro:
907 case SwFieldIds::GetRef:
908 case SwFieldIds::Input:
909 case SwFieldIds::SetExp:
910 case SwFieldIds::Dropdown:
911 case SwFieldIds::TableOfAuthorities:
912 return true;
913 default: break;
915 return false;
918 void SwField::dumpAsXml(xmlTextWriterPtr pWriter) const
920 (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SwField"));
921 (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("symbol"), "%s", BAD_CAST(typeid(*this).name()));
922 (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("ptr"), "%p", this);
923 (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("m_nFormat"), BAD_CAST(OString::number(m_nFormat).getStr()));
924 (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("m_nLang"), BAD_CAST(OString::number(m_nLang.get()).getStr()));
925 (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("m_aTitle"), BAD_CAST(m_aTitle.toUtf8().getStr()));
927 (void)xmlTextWriterEndElement(pWriter);
930 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */