tdf#154285 Check upper bound of arguments in SbRtl_Minute function
[LibreOffice.git] / xmloff / source / text / txtvfldi.cxx
blob2280c2912371e3cdbe2226740e0fed312911b3c1
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 .
21 /** @#file
23 * export of all variable related text fields (and database display field)
25 #include <txtvfldi.hxx>
26 #include <xmloff/xmltoken.hxx>
27 #include <xmloff/txtimp.hxx>
28 #include <xmloff/xmlnamespace.hxx>
29 #include <xmloff/namespacemap.hxx>
30 #include <xmloff/i18nmap.hxx>
31 #include <xmloff/xmlimp.hxx>
32 #include <xmloff/xmluconv.hxx>
33 #include <xmloff/xmlement.hxx>
34 #include <com/sun/star/frame/XModel.hpp>
35 #include <com/sun/star/text/SetVariableType.hpp>
36 #include <com/sun/star/text/XDependentTextField.hpp>
37 #include <com/sun/star/text/XTextFieldsSupplier.hpp>
38 #include <com/sun/star/beans/XPropertySet.hpp>
39 #include <com/sun/star/beans/XPropertySetInfo.hpp>
40 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
41 #include <com/sun/star/style/NumberingType.hpp>
42 #include <com/sun/star/container/XIndexReplace.hpp>
44 #include <sax/tools/converter.hxx>
46 #include <rtl/ustring.hxx>
47 #include <osl/diagnose.h>
48 #include <sal/log.hxx>
50 #include <tools/debug.hxx>
51 #include <comphelper/diagnose_ex.hxx>
54 // service names
55 constexpr char16_t sAPI_fieldmaster_prefix[] = u"com.sun.star.text.FieldMaster.";
56 constexpr OUString sAPI_get_expression = u"GetExpression"_ustr;
57 constexpr OUString sAPI_set_expression = u"SetExpression"_ustr;
58 constexpr OUString sAPI_user = u"User"_ustr;
59 constexpr OUString sAPI_database = u"com.sun.star.text.TextField.Database"_ustr;
61 // property names
62 constexpr OUString sAPI_content = u"Content"_ustr;
63 constexpr OUString sAPI_sub_type = u"SubType"_ustr;
64 constexpr OUString sAPI_number_format = u"NumberFormat"_ustr;
65 constexpr OUString sAPI_is_visible = u"IsVisible"_ustr;
66 constexpr OUString sAPI_current_presentation = u"CurrentPresentation"_ustr;
69 using namespace ::com::sun::star;
70 using namespace ::com::sun::star::uno;
71 using namespace ::com::sun::star::beans;
72 using namespace ::com::sun::star::text;
73 using namespace ::com::sun::star::style;
74 using namespace ::xmloff::token;
77 // XMLVarFieldImportContext: superclass for all variable related fields
80 XMLVarFieldImportContext::XMLVarFieldImportContext(
81 SvXMLImport& rImport, XMLTextImportHelper& rHlp,
82 const OUString& pServiceName,
83 bool bFormula, bool bFormulaDefault,
84 bool bDescription, bool bHelp, bool bHint, bool bVisible,
85 bool bIsDisplayFormula,
86 bool bType, bool bStyle, bool bValue,
87 bool bPresentation) :
88 XMLTextFieldImportContext(rImport, rHlp, pServiceName),
89 aValueHelper(rImport, rHlp, bType, bStyle, bValue, false),
90 bDisplayFormula(false),
91 bDisplayNone(false),
92 bFormulaOK(false),
93 bDescriptionOK(false),
94 bHelpOK(false),
95 bHintOK(false),
96 bDisplayOK(false),
97 bSetFormula(bFormula),
98 bSetFormulaDefault(bFormulaDefault),
99 bSetDescription(bDescription),
100 bSetHelp(bHelp),
101 bSetHint(bHint),
102 bSetVisible(bVisible),
103 bSetDisplayFormula(bIsDisplayFormula),
104 bSetPresentation(bPresentation)
108 void XMLVarFieldImportContext::ProcessAttribute(
109 sal_Int32 nAttrToken,
110 std::string_view sAttrValue )
112 switch (nAttrToken)
114 case XML_ELEMENT(TEXT, XML_NAME):
115 sName = OUString::fromUtf8(sAttrValue);
116 bValid = true; // we assume: field with name is valid!
117 break;
118 case XML_ELEMENT(TEXT, XML_DESCRIPTION):
119 sDescription = OUString::fromUtf8(sAttrValue);
120 bDescriptionOK = true;
121 break;
122 case XML_ELEMENT(TEXT, XML_HELP):
123 sHelp = OUString::fromUtf8(sAttrValue);
124 bHelpOK = true;
125 break;
126 case XML_ELEMENT(TEXT, XML_HINT):
127 sHint = OUString::fromUtf8(sAttrValue);
128 bHintOK = true;
129 break;
130 case XML_ELEMENT(TEXT, XML_FORMULA):
132 OUString sTmp;
133 sal_uInt16 nPrefix = GetImport().GetNamespaceMap().
134 GetKeyByAttrValueQName(OUString::fromUtf8(sAttrValue), &sTmp);
135 if( XML_NAMESPACE_OOOW == nPrefix )
137 sFormula = sTmp;
138 bFormulaOK = true;
140 else
141 sFormula = OUString::fromUtf8(sAttrValue);
143 break;
144 case XML_ELEMENT(TEXT, XML_DISPLAY):
145 if (IsXMLToken(sAttrValue, XML_FORMULA))
147 bDisplayFormula = true;
148 bDisplayNone = false;
149 bDisplayOK = true;
151 else if (IsXMLToken(sAttrValue, XML_VALUE))
153 bDisplayFormula = false;
154 bDisplayNone = false;
155 bDisplayOK = true;
157 else if (IsXMLToken(sAttrValue, XML_NONE))
159 bDisplayFormula = false;
160 bDisplayNone = true;
161 bDisplayOK = true;
162 } // else: no change
163 DBG_ASSERT(!(bDisplayFormula && bDisplayNone),
164 "illegal display values");
165 break;
166 default:
167 // delegate all others to value helper
168 aValueHelper.ProcessAttribute(nAttrToken, sAttrValue);
169 break;
173 void XMLVarFieldImportContext::PrepareField(
174 const Reference<XPropertySet> & xPropertySet)
176 // bSetName: not implemented
178 if (bSetFormula)
180 if (!bFormulaOK && bSetFormulaDefault)
182 sFormula = GetContent();
183 bFormulaOK = true;
186 if (bFormulaOK)
188 xPropertySet->setPropertyValue(sAPI_content, Any(sFormula));
192 if (bSetDescription && bDescriptionOK)
194 xPropertySet->setPropertyValue(u"Hint"_ustr, Any(sDescription));
197 if (bSetHelp && bHelpOK)
199 xPropertySet->setPropertyValue(u"Help"_ustr, Any(sHelp));
202 if (bSetHint && bHintOK)
204 xPropertySet->setPropertyValue(u"Tooltip"_ustr, Any(sHint));
207 if (bSetVisible && bDisplayOK)
209 bool bTmp = !bDisplayNone;
210 xPropertySet->setPropertyValue(sAPI_is_visible, Any(bTmp));
213 // workaround for #no-bug#: display formula by default
214 if (xPropertySet->getPropertySetInfo()->
215 hasPropertyByName(u"IsShowFormula"_ustr) &&
216 !bSetDisplayFormula)
218 bDisplayFormula = false;
219 bSetDisplayFormula = true;
223 if (bSetDisplayFormula)
225 bool bTmp = bDisplayFormula && bDisplayOK;
226 xPropertySet->setPropertyValue(u"IsShowFormula"_ustr, Any(bTmp));
229 // delegate to value helper
230 aValueHelper.SetDefault(GetContent());
231 aValueHelper.PrepareField(xPropertySet);
233 // finally, set the current presentation
234 if (bSetPresentation)
236 Any aAny;
237 aAny <<= GetContent();
238 xPropertySet->setPropertyValue(sAPI_current_presentation, aAny);
243 // variable set fields
246 XMLSetVarFieldImportContext::XMLSetVarFieldImportContext(
247 SvXMLImport& rImport, XMLTextImportHelper& rHlp,
248 const OUString& pServiceName, VarType eVarType,
249 bool bFormula, bool bFormulaDefault,
250 bool bDescription, bool bHelp, bool bHint, bool bVisible, bool bIsDisplayFormula,
251 bool bType, bool bStyle, bool bValue, bool bPresentation) :
252 XMLVarFieldImportContext(rImport, rHlp, pServiceName,
253 bFormula, bFormulaDefault,
254 bDescription, bHelp, bHint, bVisible, bIsDisplayFormula,
255 bType, bStyle, bValue, bPresentation),
256 eFieldType(eVarType)
260 void XMLSetVarFieldImportContext::endFastElement(sal_Int32 )
262 // should we call PrepareField on the field, or rather on it's master?
263 // currently: call on field (just like superclass)
264 // possible alternatives: call on master
265 // call field or master depending on variable
266 // PrepareMaster() in addition to PrepareField()
268 DBG_ASSERT(!GetServiceName().isEmpty(), "no service name for element!");
270 if (bValid)
272 DBG_ASSERT(!GetName().isEmpty(), "variable name needed!");
274 // find field master
275 Reference<XPropertySet> xMaster;
276 if (FindFieldMaster(xMaster))
278 // create field/Service
279 Reference<XPropertySet> xPropSet;
280 if (CreateField(xPropSet, "com.sun.star.text.TextField." + GetServiceName()))
282 Reference<XDependentTextField> xDepTextField(xPropSet, UNO_QUERY);
283 if (xDepTextField.is())
285 // attach field to field master
286 xDepTextField->attachTextFieldMaster(xMaster);
288 // attach field to document
289 Reference<XTextContent> xTextContent(xPropSet, UNO_QUERY);
290 if (xTextContent.is())
292 try {
293 // insert, set field properties and exit!
294 GetImportHelper().InsertTextContent(xTextContent);
295 PrepareField(xPropSet);
296 } catch (lang::IllegalArgumentException & /*e*/)
298 // ignore e: #i54023#
300 return;
307 // above: exit on success; so for all error cases we end up here!
308 // write element content
309 GetImportHelper().InsertString(GetContent());
312 bool XMLSetVarFieldImportContext::FindFieldMaster(
313 Reference<XPropertySet> & xMaster)
315 // currently: delegate to XMLVariableDeclImportContext;
316 // should eventually go here
317 return XMLVariableDeclImportContext::FindFieldMaster(xMaster,
318 GetImport(),
319 GetImportHelper(),
320 GetName(),
321 eFieldType);
325 // sequence field
328 XMLSequenceFieldImportContext::XMLSequenceFieldImportContext(
329 SvXMLImport& rImport, XMLTextImportHelper& rHlp) :
330 XMLSetVarFieldImportContext(rImport, rHlp, sAPI_set_expression,
331 VarTypeSequence,
332 // formula
333 true, true,
334 false, false, false, false,
335 false,
336 false, false, false, true),
338 sNumFormat(OUString('1')),
339 sNumFormatSync(GetXMLToken(XML_FALSE)),
340 bRefNameOK(false)
344 void XMLSequenceFieldImportContext::ProcessAttribute(
345 sal_Int32 nAttrToken, std::string_view sAttrValue )
347 switch (nAttrToken)
349 case XML_ELEMENT(STYLE, XML_NUM_FORMAT):
350 sNumFormat = OUString::fromUtf8(sAttrValue);
351 break;
352 case XML_ELEMENT(STYLE, XML_NUM_LETTER_SYNC):
353 sNumFormatSync = OUString::fromUtf8(sAttrValue);
354 break;
355 case XML_ELEMENT(TEXT, XML_REF_NAME):
356 sRefName = OUString::fromUtf8(sAttrValue);
357 bRefNameOK = true;
358 break;
359 default:
360 // delegate to super class (name, formula)
361 XMLSetVarFieldImportContext::ProcessAttribute(nAttrToken,
362 sAttrValue);
363 break;
364 } // switch
367 void XMLSequenceFieldImportContext::PrepareField(
368 const Reference<XPropertySet> & xPropertySet)
370 // delegate to super class (formula)
371 XMLSetVarFieldImportContext::PrepareField(xPropertySet);
373 // set format
374 sal_Int16 nNumType = NumberingType::ARABIC;
375 GetImport().GetMM100UnitConverter().convertNumFormat( nNumType, sNumFormat, sNumFormatSync );
376 xPropertySet->setPropertyValue(sAPI_number_format, Any(nNumType));
378 // handle reference name
379 if (bRefNameOK)
381 Any aAny = xPropertySet->getPropertyValue(u"SequenceValue"_ustr);
382 sal_Int16 nValue = 0;
383 aAny >>= nValue;
384 GetImportHelper().InsertSequenceID(sRefName, GetName(), nValue);
389 // variable set field
392 XMLVariableSetFieldImportContext::XMLVariableSetFieldImportContext(
393 SvXMLImport& rImport, XMLTextImportHelper& rHlp) :
394 XMLSetVarFieldImportContext(rImport, rHlp, sAPI_set_expression,
395 VarTypeSimple,
396 // formula, value&type, style,
397 // display none
398 true, true,
399 false, false, false,
400 true, false,
401 true, true, true,
402 true)
406 void XMLVariableSetFieldImportContext::PrepareField(
407 const Reference<XPropertySet> & xPropertySet)
409 // set type
410 Any aAny;
411 aAny <<= (IsStringValue()? SetVariableType::STRING : SetVariableType::VAR);
412 xPropertySet->setPropertyValue(sAPI_sub_type, aAny);
414 // the remainder is handled by super class
415 XMLSetVarFieldImportContext::PrepareField(xPropertySet);
419 // variable input field
422 XMLVariableInputFieldImportContext::XMLVariableInputFieldImportContext(
423 SvXMLImport& rImport, XMLTextImportHelper& rHlp) :
424 XMLSetVarFieldImportContext(rImport, rHlp, sAPI_set_expression,
425 VarTypeSimple,
426 // description, display none/formula,
427 // value&type, style, formula
428 true, true,
429 true, true, true,
430 true, false,
431 true, true, true,
432 true)
436 void XMLVariableInputFieldImportContext::PrepareField(
437 const Reference<XPropertySet> & xPropertySet)
439 // set type (input field)
440 Any aAny;
441 xPropertySet->setPropertyValue(u"Input"_ustr, Any(true));
443 // set type
444 aAny <<= (IsStringValue()? SetVariableType::STRING : SetVariableType::VAR);
445 xPropertySet->setPropertyValue(sAPI_sub_type, aAny);
447 // the remainder is handled by super class
448 XMLSetVarFieldImportContext::PrepareField(xPropertySet);
452 // user field
455 XMLUserFieldImportContext::XMLUserFieldImportContext(
456 SvXMLImport& rImport, XMLTextImportHelper& rHlp) :
457 XMLSetVarFieldImportContext(rImport, rHlp, sAPI_user,
458 VarTypeUserField,
459 // display none/formula, style
460 false, false,
461 false, false, false, true,
462 true,
463 false, true, false,
464 false)
469 // user input field
472 // bug: doesn't work (SO API lacking)
473 XMLUserFieldInputImportContext::XMLUserFieldInputImportContext(
474 SvXMLImport& rImport, XMLTextImportHelper& rHlp) :
475 XMLVarFieldImportContext(rImport, rHlp, u"InputUser"_ustr,
476 // description, style
477 false, false,
478 true, false, false,
479 false, false,
480 false /*???*/, true, false,
481 false)
485 void XMLUserFieldInputImportContext::PrepareField(
486 const Reference<XPropertySet> & xPropertySet)
488 xPropertySet->setPropertyValue(sAPI_content, Any(GetName()));
490 // delegate to super class
491 XMLVarFieldImportContext::PrepareField(xPropertySet);
495 // variable get field
498 XMLVariableGetFieldImportContext::XMLVariableGetFieldImportContext(
499 SvXMLImport& rImport, XMLTextImportHelper& rHlp) :
500 XMLVarFieldImportContext(rImport, rHlp, sAPI_get_expression,
501 // style, display formula
502 false, false,
503 false, false, false,
504 false, true,
505 true, true, false,
506 true)
510 void XMLVariableGetFieldImportContext::PrepareField(
511 const Reference<XPropertySet> & xPropertySet)
513 // set name
514 xPropertySet->setPropertyValue(sAPI_content, Any(GetName()));
516 // the remainder is handled by super class
517 XMLVarFieldImportContext::PrepareField(xPropertySet);
521 // expression field
524 XMLExpressionFieldImportContext::XMLExpressionFieldImportContext(
525 SvXMLImport& rImport, XMLTextImportHelper& rHlp) :
526 XMLVarFieldImportContext(rImport, rHlp, sAPI_get_expression,
527 // formula, type, style, display formula
528 true, true,
529 false, false, false,
530 false, true,
531 true, true, false,
532 true)
534 bValid = true; // always valid
538 void XMLExpressionFieldImportContext::PrepareField(
539 const Reference<XPropertySet> & xPropertySet)
541 xPropertySet->setPropertyValue(sAPI_sub_type, Any(sal_Int16(SetVariableType::FORMULA)));
543 // delegate to super class
544 XMLVarFieldImportContext::PrepareField(xPropertySet);
548 // text input field
551 XMLTextInputFieldImportContext::XMLTextInputFieldImportContext(
552 SvXMLImport& rImport, XMLTextImportHelper& rHlp) :
553 XMLVarFieldImportContext(rImport, rHlp, u"Input"_ustr,
554 // description
555 false, false,
556 true, true, true,
557 false, false,
558 false, false, false,
559 false)
561 bValid = true; // always valid
564 void XMLTextInputFieldImportContext::PrepareField(
565 const Reference<XPropertySet> & xPropertySet)
567 XMLVarFieldImportContext::PrepareField(xPropertySet);
569 xPropertySet->setPropertyValue(sAPI_content, Any(GetContent()));
573 // table formula field
576 XMLTableFormulaImportContext::XMLTableFormulaImportContext(
577 SvXMLImport& rImport,
578 XMLTextImportHelper& rHlp) :
579 XMLTextFieldImportContext(rImport, rHlp, u"TableFormula"_ustr),
580 aValueHelper(rImport, rHlp, false, true, false, true),
581 bIsShowFormula(false)
585 void XMLTableFormulaImportContext::ProcessAttribute(
586 sal_Int32 nAttrToken,
587 std::string_view sAttrValue )
589 switch (nAttrToken)
591 case XML_ELEMENT(TEXT, XML_FORMULA):
592 aValueHelper.ProcessAttribute( nAttrToken, sAttrValue );
593 bValid = true; // we need a formula!
594 break;
596 case XML_ELEMENT(STYLE, XML_DATA_STYLE_NAME):
597 aValueHelper.ProcessAttribute( nAttrToken, sAttrValue );
598 break;
599 case XML_ELEMENT(TEXT, XML_DISPLAY):
600 if ( sAttrValue == "formula" )
601 bIsShowFormula = true;
602 break;
603 default:
604 // unknown attribute -> ignore
605 XMLOFF_WARN_UNKNOWN_ATTR("xmloff", nAttrToken, sAttrValue);
606 break;
610 void XMLTableFormulaImportContext::PrepareField(
611 const Reference<XPropertySet> & xPropertySet)
613 // set format and formula
614 aValueHelper.PrepareField( xPropertySet );
616 Any aAny;
618 // set 'show formula' and presentation
619 xPropertySet->setPropertyValue( u"IsShowFormula"_ustr, Any(bIsShowFormula) );
621 aAny <<= GetContent();
622 xPropertySet->setPropertyValue( u"CurrentPresentation"_ustr, aAny );
626 // variable declarations
628 // Should be adapted to XMLVarField-/XMLSetVarFieldImportContext scheme!
631 // declaration container import (<variable/user-field/sequence-decls>)
634 XMLVariableDeclsImportContext::XMLVariableDeclsImportContext(
635 SvXMLImport& rImport, XMLTextImportHelper& rHlp, enum VarType eVarType) :
636 SvXMLImportContext(rImport),
637 eVarDeclsContextType(eVarType),
638 rImportHelper(rHlp)
642 css::uno::Reference< css::xml::sax::XFastContextHandler > XMLVariableDeclsImportContext::createFastChildContext(
643 sal_Int32 nElement,
644 const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
646 if( IsTokenInNamespace(nElement, XML_NAMESPACE_TEXT) )
648 enum XMLTokenEnum eElementName;
649 switch (eVarDeclsContextType)
651 case VarTypeSequence:
652 eElementName = XML_SEQUENCE_DECL;
653 break;
654 case VarTypeSimple:
655 eElementName = XML_VARIABLE_DECL;
656 break;
657 case VarTypeUserField:
658 eElementName = XML_USER_FIELD_DECL;
659 break;
660 default:
661 OSL_FAIL("unknown field type!");
662 eElementName = XML_SEQUENCE_DECL;
663 break;
666 if( nElement == XML_ELEMENT(TEXT, eElementName) )
668 return new XMLVariableDeclImportContext(
669 GetImport(), rImportHelper, nElement, xAttrList,
670 eVarDeclsContextType);
674 // if no context was created, use default context
675 return nullptr;
679 // declaration import (<variable/user-field/sequence-decl> elements)
682 XMLVariableDeclImportContext::XMLVariableDeclImportContext(
683 SvXMLImport& rImport, XMLTextImportHelper& rHlp,
684 sal_Int32 nElement,
685 const Reference<xml::sax::XFastAttributeList> & xAttrList,
686 enum VarType eVarType) :
687 SvXMLImportContext(rImport)
689 // bug?? which properties for userfield/userfieldmaster
690 XMLValueImportHelper aValueHelper(rImport, rHlp, true, false, true, false);
691 sal_Unicode cSeparationChar('.');
693 sal_Int8 nNumLevel(-1);
694 OUString sName;
696 if (nElement != XML_ELEMENT(TEXT, XML_SEQUENCE_DECL) &&
697 nElement != XML_ELEMENT(TEXT, XML_VARIABLE_DECL) &&
698 nElement != XML_ELEMENT(TEXT, XML_USER_FIELD_DECL) )
699 return;
701 // TODO: check validity (need name!)
703 // parse attributes
704 for (auto &aIter : sax_fastparser::castToFastAttributeList( xAttrList ))
706 switch (aIter.getToken())
708 case XML_ELEMENT(TEXT, XML_NAME):
709 sName = aIter.toString();
710 break;
711 case XML_ELEMENT(TEXT, XML_DISPLAY_OUTLINE_LEVEL):
713 sal_Int32 nLevel;
714 bool const bRet = ::sax::Converter::convertNumber(
715 nLevel, aIter.toView(), 0,
716 GetImport().GetTextImport()->GetChapterNumbering()->
717 getCount());
718 if (bRet)
720 nNumLevel = static_cast< sal_Int8 >( nLevel-1 ); // API numbers -1..9
722 break;
724 case XML_ELEMENT(TEXT, XML_SEPARATION_CHARACTER):
725 cSeparationChar =
726 static_cast<char>(aIter.toString().toChar());
727 break;
729 default:
730 // delegate to value helper
731 aValueHelper.ProcessAttribute(aIter.getToken(), aIter.toView());
732 break;
736 Reference<XPropertySet> xFieldMaster;
737 if (!FindFieldMaster(xFieldMaster, GetImport(), rHlp,
738 sName, eVarType))
739 return;
741 // now we have a field master: process attributes!
742 Any aAny;
744 switch (eVarType)
746 case VarTypeSequence:
747 xFieldMaster->setPropertyValue(u"ChapterNumberingLevel"_ustr, Any(nNumLevel));
749 if (nNumLevel >= 0)
751 OUString sStr(&cSeparationChar, 1);
752 xFieldMaster->setPropertyValue(
753 u"NumberingSeparator"_ustr, Any(sStr));
755 break;
756 case VarTypeSimple:
758 // set string or non-string SubType (#93192#)
759 // The SubType was already set in the FindFieldMaster
760 // method, but it needs to be adjusted if it's a string.
761 aAny <<= aValueHelper.IsStringValue()
762 ? SetVariableType::STRING : SetVariableType::VAR;
763 xFieldMaster->setPropertyValue(sAPI_sub_type, aAny);
765 break;
766 case VarTypeUserField:
768 bool bTmp = !aValueHelper.IsStringValue();
769 xFieldMaster->setPropertyValue(u"IsExpression"_ustr, Any(bTmp));
770 aValueHelper.PrepareField(xFieldMaster);
771 break;
773 default:
774 OSL_FAIL("unknown varfield type");
775 } // switch
779 bool XMLVariableDeclImportContext::FindFieldMaster(
780 Reference<XPropertySet> & xMaster, SvXMLImport& rImport,
781 XMLTextImportHelper& rImportHelper,
782 const OUString& sVarName, enum VarType eVarType)
784 static sal_Int32 nCollisionCount = 0;
786 // rename field
787 // currently: no family in use! Use 0.
788 OUString sName = rImportHelper.GetRenameMap().Get(
789 sal::static_int_cast< sal_uInt16 >(eVarType), sVarName);
791 // get text fields supplier and field masters
792 Reference<XTextFieldsSupplier> xTextFieldsSupp(rImport.GetModel(),
793 UNO_QUERY);
794 Reference<container::XNameAccess> xFieldMasterNameAccess =
795 xTextFieldsSupp->getTextFieldMasters();
797 OUString sVarServiceName =
798 OUString::Concat(sAPI_fieldmaster_prefix) +
799 sAPI_set_expression +
800 "." +
801 sName;
803 OUString sUserServiceName =
804 OUString::Concat(sAPI_fieldmaster_prefix) +
805 sAPI_user +
806 "." +
807 sName;
809 if (xFieldMasterNameAccess->hasByName(sVarServiceName)) {
810 // variable field master already in document
812 Any aAny = xFieldMasterNameAccess->getByName(sVarServiceName);
813 aAny >>= xMaster;
815 aAny = xMaster->getPropertyValue(sAPI_sub_type);
816 sal_Int16 nType = 0;
817 aAny >>= nType;
819 enum VarType eFMVarType =
820 (SetVariableType::SEQUENCE == nType) ?
821 VarTypeSequence : VarTypeSimple;
823 if (eFMVarType != eVarType)
825 ++nCollisionCount;
826 OUString sNew(sName + "_renamed_" + OUString::number(nCollisionCount));
828 // FIXME! can't find if name is taken already!!!!
830 rImportHelper.GetRenameMap().Add(
831 sal::static_int_cast< sal_uInt16 >(eVarType), sName, sNew);
833 // call FindFieldMaster recursively to create new master
834 return FindFieldMaster(xMaster, rImport, rImportHelper,
835 sNew, eVarType);
837 } else if (xFieldMasterNameAccess->hasByName(sUserServiceName)) {
838 // user field: get field master
839 Any aAny = xFieldMasterNameAccess->getByName(sUserServiceName);
840 aAny >>= xMaster;
842 if (VarTypeUserField != eVarType) {
843 ++nCollisionCount;
844 // find new name that is not taken
845 OUString sNew(sName + "_renamed_" + OUString::number(nCollisionCount));
847 // FIXME! can't find if name is taken already!!!!
849 rImportHelper.GetRenameMap().Add(
850 sal::static_int_cast< sal_uInt16 >(eVarType), sName, sNew);
852 // call FindFieldMaster recursively to create new master
853 return FindFieldMaster(xMaster, rImport, rImportHelper,
854 sNew, eVarType);
856 } else {
857 // field name not used: create field master
859 // import -> model is MultiServiceFactory -> createInstance
860 Reference<lang::XMultiServiceFactory>
861 xFactory(rImport.GetModel(),UNO_QUERY);
862 if( xFactory.is() ) {
864 OUString sService = sAPI_fieldmaster_prefix
865 + ((eVarType==VarTypeUserField) ?
866 sAPI_user : sAPI_set_expression);
867 Reference<XInterface> xIfc =
868 xFactory->createInstance( sService );
869 if (xIfc.is()) {
870 xMaster.set(xIfc, UNO_QUERY);
872 // set name
873 xMaster->setPropertyValue(u"Name"_ustr, Any(sName));
875 if (eVarType != VarTypeUserField) {
876 // set subtype for setexp field
877 Any aAny;
878 aAny <<= ((eVarType == VarTypeSimple) ?
879 SetVariableType::VAR :
880 SetVariableType::SEQUENCE);
881 xMaster->setPropertyValue(sAPI_sub_type, aAny);
882 } // else : user field: no subtype
884 } else {
885 return false;
887 } else {
888 return false;
892 DBG_ASSERT(xMaster.is(), "no field master found!?!");
893 return true;
897 // Database Display field import
900 XMLDatabaseDisplayImportContext::XMLDatabaseDisplayImportContext(
901 SvXMLImport& rImport, XMLTextImportHelper& rHlp) :
902 XMLDatabaseFieldImportContext(rImport, rHlp, sAPI_database, false),
903 aValueHelper(rImport, rHlp, false, true, false, false),
904 bColumnOK(false),
905 bDisplay( true ),
906 bDisplayOK( false )
910 void XMLDatabaseDisplayImportContext::ProcessAttribute(
911 sal_Int32 nAttrToken, std::string_view sAttrValue )
913 switch (nAttrToken)
915 case XML_ELEMENT(TEXT, XML_COLUMN_NAME):
916 sColumnName = OUString::fromUtf8(sAttrValue);
917 bColumnOK = true;
918 break;
919 case XML_ELEMENT(TEXT, XML_DISPLAY):
921 bool bNone = IsXMLToken( sAttrValue, XML_NONE );
922 bool bValue = IsXMLToken( sAttrValue, XML_VALUE );
923 bDisplay = bValue;
924 bDisplayOK = bNone || bValue;
926 break;
927 case XML_ELEMENT(TEXT, XML_DATABASE_NAME):
928 case XML_ELEMENT(TEXT, XML_TABLE_NAME):
929 case XML_ELEMENT(TEXT, XML_TABLE_TYPE):
930 // handled by super class
931 XMLDatabaseFieldImportContext::ProcessAttribute(nAttrToken,
932 sAttrValue);
933 break;
934 default:
935 // remainder handled by value helper
936 aValueHelper.ProcessAttribute(nAttrToken, sAttrValue);
937 break;
940 bValid = m_bTableOK && m_bDatabaseOK && bColumnOK;
943 void XMLDatabaseDisplayImportContext::endFastElement(sal_Int32 )
945 // we have an EndElement of our own, because database fields need
946 // to be attached to a field master before they can be inserted into
947 // the document. Database stuff (database, table, column) all goes
948 // to the field master, value & style go to the field.
950 if (bValid)
953 // so here goes: we start with the master
954 Reference<XPropertySet> xMaster;
956 // create and prepare field master first
957 if (CreateField(xMaster,
958 u"com.sun.star.text.FieldMaster.Database"_ustr))
960 Any aAny;
961 xMaster->setPropertyValue(u"DataColumnName"_ustr, Any(sColumnName));
963 // fieldmaster takes database, table and column name
964 XMLDatabaseFieldImportContext::PrepareField(xMaster);
966 // create field
967 Reference<XPropertySet> xField;
968 if (CreateField(xField,
969 sAPI_database))
971 // attach field master
972 Reference<XDependentTextField> xDepField(xField, UNO_QUERY);
973 if (xDepField.is())
975 // attach field to field master
976 xDepField->attachTextFieldMaster(xMaster);
978 // attach field to document
979 Reference<XTextContent> xTextContent(xField, UNO_QUERY);
980 if (xTextContent.is())
982 // insert, set field properties and exit!
985 GetImportHelper().InsertTextContent(xTextContent);
987 // prepare field: format from database?
988 bool bTmp = !aValueHelper.IsFormatOK();
989 xField->setPropertyValue(u"DataBaseFormat"_ustr, Any(bTmp));
991 // value, value-type and format done by value helper
992 aValueHelper.PrepareField(xField);
994 // visibility
995 if( bDisplayOK )
997 xField->setPropertyValue(sAPI_is_visible, Any(bDisplay));
1000 // set presentation
1001 aAny <<= GetContent();
1002 xField->setPropertyValue(sAPI_current_presentation, aAny);
1004 // success!
1005 return;
1007 catch (const lang::IllegalArgumentException&)
1009 TOOLS_WARN_EXCEPTION("xmloff.text", "Failed to insert text content");
1017 // above: exit on success; so for all error cases we end up here!
1018 // write element content
1019 GetImportHelper().InsertString(GetContent());
1023 // value import helper
1025 namespace {
1027 enum ValueType
1029 XML_VALUE_TYPE_STRING,
1030 XML_VALUE_TYPE_FLOAT,
1031 XML_VALUE_TYPE_CURRENCY,
1032 XML_VALUE_TYPE_PERCENTAGE,
1033 XML_VALUE_TYPE_DATE,
1034 XML_VALUE_TYPE_TIME,
1035 XML_VALUE_TYPE_BOOLEAN
1040 SvXMLEnumMapEntry<ValueType> const aValueTypeMap[] =
1042 { XML_FLOAT, XML_VALUE_TYPE_FLOAT },
1043 { XML_CURRENCY, XML_VALUE_TYPE_CURRENCY },
1044 { XML_PERCENTAGE, XML_VALUE_TYPE_PERCENTAGE },
1045 { XML_DATE, XML_VALUE_TYPE_DATE },
1046 { XML_TIME, XML_VALUE_TYPE_TIME },
1047 { XML_BOOLEAN, XML_VALUE_TYPE_BOOLEAN },
1048 { XML_STRING, XML_VALUE_TYPE_STRING },
1049 { XML_TOKEN_INVALID, ValueType(0) }
1052 XMLValueImportHelper::XMLValueImportHelper(
1053 SvXMLImport& rImprt,
1054 XMLTextImportHelper& rHlp,
1055 bool bType, bool bStyle, bool bValue, bool bFormula) :
1057 rImport(rImprt),
1058 rHelper(rHlp),
1060 fValue(0.0),
1061 nFormatKey(0),
1062 bIsDefaultLanguage(true),
1064 bStringType(false),
1065 bFormatOK(false),
1066 bStringValueOK(false),
1067 bFormulaOK(false),
1069 bSetType(bType),
1070 bSetValue(bValue),
1071 bSetStyle(bStyle),
1072 bSetFormula(bFormula)
1076 void XMLValueImportHelper::ProcessAttribute(
1077 sal_Int32 nAttrToken, std::string_view sAttrValue )
1079 switch (nAttrToken)
1081 case XML_ELEMENT(TEXT, XML_VALUE_TYPE): // #i32362#: src680m48++ saves text:value-type
1082 case XML_ELEMENT(OFFICE, XML_VALUE_TYPE):
1084 // convert enum
1085 ValueType eValueType = XML_VALUE_TYPE_STRING;
1086 bool bRet = SvXMLUnitConverter::convertEnum(
1087 eValueType, sAttrValue, aValueTypeMap);
1089 if (bRet) {
1090 switch (eValueType)
1092 case XML_VALUE_TYPE_STRING:
1093 bStringType = true;
1094 break;
1095 case XML_VALUE_TYPE_FLOAT:
1096 case XML_VALUE_TYPE_CURRENCY:
1097 case XML_VALUE_TYPE_PERCENTAGE:
1098 case XML_VALUE_TYPE_DATE:
1099 case XML_VALUE_TYPE_TIME:
1100 case XML_VALUE_TYPE_BOOLEAN:
1101 bStringType = false;
1102 break;
1104 default:
1105 OSL_FAIL("unknown value type");
1108 break;
1111 case XML_ELEMENT(TEXT, XML_VALUE):
1112 case XML_ELEMENT(OFFICE, XML_VALUE):
1114 double fTmp;
1115 bool const bRet = ::sax::Converter::convertDouble(fTmp,sAttrValue);
1116 if (bRet) {
1117 fValue = fTmp;
1119 break;
1122 case XML_ELEMENT(TEXT, XML_TIME_VALUE):
1123 case XML_ELEMENT(OFFICE, XML_TIME_VALUE):
1125 double fTmp;
1126 bool const bRet =
1127 ::sax::Converter::convertDuration(fTmp, sAttrValue);
1128 if (bRet) {
1129 fValue = fTmp;
1131 break;
1134 case XML_ELEMENT(TEXT, XML_DATE_VALUE):
1135 case XML_ELEMENT(OFFICE, XML_DATE_VALUE):
1137 double fTmp;
1138 bool bRet = rImport.GetMM100UnitConverter().
1139 convertDateTime(fTmp,sAttrValue);
1140 if (bRet) {
1141 fValue = fTmp;
1143 break;
1146 case XML_ELEMENT(OFFICE, XML_BOOLEAN_VALUE):
1148 bool bTmp(false);
1149 bool bRet = ::sax::Converter::convertBool(bTmp, sAttrValue);
1150 if (bRet) {
1151 fValue = (bTmp ? 1.0 : 0.0);
1153 else
1155 double fTmp;
1156 bRet = ::sax::Converter::convertDouble(fTmp, sAttrValue);
1157 if (bRet) {
1158 fValue = fTmp;
1161 break;
1164 case XML_ELEMENT(TEXT, XML_STRING_VALUE):
1165 case XML_ELEMENT(OFFICE, XML_STRING_VALUE):
1166 sValue = OUString::fromUtf8(sAttrValue);
1167 bStringValueOK = true;
1168 break;
1170 case XML_ELEMENT(TEXT, XML_FORMULA):
1172 OUString sTmp;
1173 sal_uInt16 nPrefix = rImport.GetNamespaceMap().
1174 GetKeyByAttrValueQName(OUString::fromUtf8(sAttrValue), &sTmp);
1175 if( XML_NAMESPACE_OOOW == nPrefix )
1177 sFormula = sTmp;
1178 bFormulaOK = true;
1180 else
1181 sFormula = OUString::fromUtf8(sAttrValue);
1183 break;
1185 case XML_ELEMENT(STYLE, XML_DATA_STYLE_NAME):
1187 sal_Int32 nKey = rHelper.GetDataStyleKey(
1188 OUString::fromUtf8(sAttrValue), &bIsDefaultLanguage);
1189 if (-1 != nKey)
1191 nFormatKey = nKey;
1192 bFormatOK = true;
1194 break;
1196 default:
1197 XMLOFF_WARN_UNKNOWN_ATTR("xmloff", nAttrToken, sAttrValue);
1198 } // switch
1201 void XMLValueImportHelper::PrepareField(
1202 const Reference<XPropertySet> & xPropertySet)
1204 Any aAny;
1206 if (bSetType)
1208 // ??? how to set type?
1211 if (bSetFormula)
1213 aAny <<= !bFormulaOK ? sDefault : sFormula;
1214 xPropertySet->setPropertyValue(sAPI_content, aAny);
1217 // format/style
1218 if (bSetStyle && bFormatOK)
1220 xPropertySet->setPropertyValue(sAPI_number_format, Any(nFormatKey));
1222 if( xPropertySet->getPropertySetInfo()->
1223 hasPropertyByName( u"IsFixedLanguage"_ustr ) )
1225 bool bIsFixedLanguage = ! bIsDefaultLanguage;
1226 xPropertySet->setPropertyValue( u"IsFixedLanguage"_ustr, Any(bIsFixedLanguage) );
1230 // value: string or float
1231 if (bSetValue)
1233 if (bStringType)
1235 aAny <<= !bStringValueOK ? sDefault : sValue;
1236 xPropertySet->setPropertyValue(sAPI_content, aAny);
1238 else
1240 xPropertySet->setPropertyValue(u"Value"_ustr, Any(fValue));
1245 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */