• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2016 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6 
7 #include "xfa/fxfa/parser/cxfa_widgetdata.h"
8 
9 #include "core/fxcrt/fx_ext.h"
10 #include "third_party/base/stl_util.h"
11 #include "xfa/fxbarcode/BC_Library.h"
12 #include "xfa/fxfa/app/xfa_ffnotify.h"
13 #include "xfa/fxfa/parser/cxfa_document.h"
14 #include "xfa/fxfa/parser/cxfa_event.h"
15 #include "xfa/fxfa/parser/cxfa_measurement.h"
16 #include "xfa/fxfa/parser/xfa_localevalue.h"
17 #include "xfa/fxfa/parser/xfa_object.h"
18 
19 namespace {
20 
GetEdgeThickness(const std::vector<CXFA_Stroke> & strokes,bool b3DStyle,int32_t nIndex)21 FX_FLOAT GetEdgeThickness(const std::vector<CXFA_Stroke>& strokes,
22                           bool b3DStyle,
23                           int32_t nIndex) {
24   FX_FLOAT fThickness = 0;
25 
26   if (strokes[nIndex * 2 + 1].GetPresence() == XFA_ATTRIBUTEENUM_Visible) {
27     if (nIndex == 0)
28       fThickness += 2.5f;
29 
30     fThickness += strokes[nIndex * 2 + 1].GetThickness() * (b3DStyle ? 4 : 2);
31   }
32   return fThickness;
33 }
34 
SplitDateTime(const CFX_WideString & wsDateTime,CFX_WideString & wsDate,CFX_WideString & wsTime)35 bool SplitDateTime(const CFX_WideString& wsDateTime,
36                    CFX_WideString& wsDate,
37                    CFX_WideString& wsTime) {
38   wsDate = L"";
39   wsTime = L"";
40   if (wsDateTime.IsEmpty())
41     return false;
42 
43   int nSplitIndex = -1;
44   nSplitIndex = wsDateTime.Find('T');
45   if (nSplitIndex < 0)
46     nSplitIndex = wsDateTime.Find(' ');
47   if (nSplitIndex < 0)
48     return false;
49 
50   wsDate = wsDateTime.Left(nSplitIndex);
51   if (!wsDate.IsEmpty()) {
52     int32_t iCount = wsDate.GetLength();
53     int32_t i = 0;
54     for (i = 0; i < iCount; i++) {
55       if (wsDate[i] >= '0' && wsDate[i] <= '9')
56         break;
57     }
58     if (i == iCount)
59       return false;
60   }
61   wsTime = wsDateTime.Right(wsDateTime.GetLength() - nSplitIndex - 1);
62   if (!wsTime.IsEmpty()) {
63     int32_t iCount = wsTime.GetLength();
64     int32_t i = 0;
65     for (i = 0; i < iCount; i++) {
66       if (wsTime[i] >= '0' && wsTime[i] <= '9')
67         break;
68     }
69     if (i == iCount)
70       return false;
71   }
72   return true;
73 }
74 
CreateUIChild(CXFA_Node * pNode,XFA_Element & eWidgetType)75 CXFA_Node* CreateUIChild(CXFA_Node* pNode, XFA_Element& eWidgetType) {
76   XFA_Element eType = pNode->GetElementType();
77   eWidgetType = eType;
78   if (eType != XFA_Element::Field && eType != XFA_Element::Draw)
79     return nullptr;
80 
81   eWidgetType = XFA_Element::Unknown;
82   XFA_Element eUIType = XFA_Element::Unknown;
83   CXFA_Value defValue(pNode->GetProperty(0, XFA_Element::Value, true));
84   XFA_Element eValueType = defValue.GetChildValueClassID();
85   switch (eValueType) {
86     case XFA_Element::Boolean:
87       eUIType = XFA_Element::CheckButton;
88       break;
89     case XFA_Element::Integer:
90     case XFA_Element::Decimal:
91     case XFA_Element::Float:
92       eUIType = XFA_Element::NumericEdit;
93       break;
94     case XFA_Element::ExData:
95     case XFA_Element::Text:
96       eUIType = XFA_Element::TextEdit;
97       eWidgetType = XFA_Element::Text;
98       break;
99     case XFA_Element::Date:
100     case XFA_Element::Time:
101     case XFA_Element::DateTime:
102       eUIType = XFA_Element::DateTimeEdit;
103       break;
104     case XFA_Element::Image:
105       eUIType = XFA_Element::ImageEdit;
106       eWidgetType = XFA_Element::Image;
107       break;
108     case XFA_Element::Arc:
109     case XFA_Element::Line:
110     case XFA_Element::Rectangle:
111       eUIType = XFA_Element::DefaultUi;
112       eWidgetType = eValueType;
113       break;
114     default:
115       break;
116   }
117 
118   CXFA_Node* pUIChild = nullptr;
119   CXFA_Node* pUI = pNode->GetProperty(0, XFA_Element::Ui, true);
120   CXFA_Node* pChild = pUI->GetNodeItem(XFA_NODEITEM_FirstChild);
121   for (; pChild; pChild = pChild->GetNodeItem(XFA_NODEITEM_NextSibling)) {
122     XFA_Element eChildType = pChild->GetElementType();
123     if (eChildType == XFA_Element::Extras ||
124         eChildType == XFA_Element::Picture) {
125       continue;
126     }
127     const XFA_PROPERTY* pProperty = XFA_GetPropertyOfElement(
128         XFA_Element::Ui, eChildType, XFA_XDPPACKET_Form);
129     if (pProperty && (pProperty->uFlags & XFA_PROPERTYFLAG_OneOf)) {
130       pUIChild = pChild;
131       break;
132     }
133   }
134 
135   if (eType == XFA_Element::Draw) {
136     XFA_Element eDraw =
137         pUIChild ? pUIChild->GetElementType() : XFA_Element::Unknown;
138     switch (eDraw) {
139       case XFA_Element::TextEdit:
140         eWidgetType = XFA_Element::Text;
141         break;
142       case XFA_Element::ImageEdit:
143         eWidgetType = XFA_Element::Image;
144         break;
145       default:
146         eWidgetType = eWidgetType == XFA_Element::Unknown ? XFA_Element::Text
147                                                           : eWidgetType;
148         break;
149     }
150   } else {
151     if (pUIChild && pUIChild->GetElementType() == XFA_Element::DefaultUi) {
152       eWidgetType = XFA_Element::TextEdit;
153     } else {
154       eWidgetType =
155           pUIChild ? pUIChild->GetElementType()
156                    : (eUIType == XFA_Element::Unknown ? XFA_Element::TextEdit
157                                                       : eUIType);
158     }
159   }
160 
161   if (!pUIChild) {
162     if (eUIType == XFA_Element::Unknown) {
163       eUIType = XFA_Element::TextEdit;
164       defValue.GetNode()->GetProperty(0, XFA_Element::Text, true);
165     }
166     return pUI->GetProperty(0, eUIType, true);
167   }
168 
169   if (eUIType != XFA_Element::Unknown)
170     return pUIChild;
171 
172   switch (pUIChild->GetElementType()) {
173     case XFA_Element::CheckButton: {
174       eValueType = XFA_Element::Text;
175       if (CXFA_Node* pItems = pNode->GetChild(0, XFA_Element::Items)) {
176         if (CXFA_Node* pItem = pItems->GetChild(0, XFA_Element::Unknown))
177           eValueType = pItem->GetElementType();
178       }
179       break;
180     }
181     case XFA_Element::DateTimeEdit:
182       eValueType = XFA_Element::DateTime;
183       break;
184     case XFA_Element::ImageEdit:
185       eValueType = XFA_Element::Image;
186       break;
187     case XFA_Element::NumericEdit:
188       eValueType = XFA_Element::Float;
189       break;
190     case XFA_Element::ChoiceList: {
191       eValueType = (pUIChild->GetEnum(XFA_ATTRIBUTE_Open) ==
192                     XFA_ATTRIBUTEENUM_MultiSelect)
193                        ? XFA_Element::ExData
194                        : XFA_Element::Text;
195       break;
196     }
197     case XFA_Element::Barcode:
198     case XFA_Element::Button:
199     case XFA_Element::PasswordEdit:
200     case XFA_Element::Signature:
201     case XFA_Element::TextEdit:
202     default:
203       eValueType = XFA_Element::Text;
204       break;
205   }
206   defValue.GetNode()->GetProperty(0, eValueType, true);
207 
208   return pUIChild;
209 }
210 
GetAttributeDefaultValue_Enum(XFA_Element eElement,XFA_ATTRIBUTE eAttribute,uint32_t dwPacket)211 XFA_ATTRIBUTEENUM GetAttributeDefaultValue_Enum(XFA_Element eElement,
212                                                 XFA_ATTRIBUTE eAttribute,
213                                                 uint32_t dwPacket) {
214   void* pValue;
215   if (XFA_GetAttributeDefaultValue(pValue, eElement, eAttribute,
216                                    XFA_ATTRIBUTETYPE_Enum, dwPacket)) {
217     return (XFA_ATTRIBUTEENUM)(uintptr_t)pValue;
218   }
219   return XFA_ATTRIBUTEENUM_Unknown;
220 }
221 
GetAttributeDefaultValue_Cdata(XFA_Element eElement,XFA_ATTRIBUTE eAttribute,uint32_t dwPacket)222 CFX_WideStringC GetAttributeDefaultValue_Cdata(XFA_Element eElement,
223                                                XFA_ATTRIBUTE eAttribute,
224                                                uint32_t dwPacket) {
225   void* pValue;
226   if (XFA_GetAttributeDefaultValue(pValue, eElement, eAttribute,
227                                    XFA_ATTRIBUTETYPE_Cdata, dwPacket)) {
228     return (const FX_WCHAR*)pValue;
229   }
230   return nullptr;
231 }
232 
GetAttributeDefaultValue_Boolean(XFA_Element eElement,XFA_ATTRIBUTE eAttribute,uint32_t dwPacket)233 bool GetAttributeDefaultValue_Boolean(XFA_Element eElement,
234                                       XFA_ATTRIBUTE eAttribute,
235                                       uint32_t dwPacket) {
236   void* pValue;
237   if (XFA_GetAttributeDefaultValue(pValue, eElement, eAttribute,
238                                    XFA_ATTRIBUTETYPE_Boolean, dwPacket)) {
239     return !!pValue;
240   }
241   return false;
242 }
243 
244 }  // namespace
245 
CXFA_WidgetData(CXFA_Node * pNode)246 CXFA_WidgetData::CXFA_WidgetData(CXFA_Node* pNode)
247     : CXFA_Data(pNode),
248       m_bIsNull(true),
249       m_bPreNull(true),
250       m_pUiChildNode(nullptr),
251       m_eUIType(XFA_Element::Unknown) {}
252 
GetUIChild()253 CXFA_Node* CXFA_WidgetData::GetUIChild() {
254   if (m_eUIType == XFA_Element::Unknown)
255     m_pUiChildNode = CreateUIChild(m_pNode, m_eUIType);
256 
257   return m_pUiChildNode;
258 }
259 
GetUIType()260 XFA_Element CXFA_WidgetData::GetUIType() {
261   GetUIChild();
262   return m_eUIType;
263 }
264 
GetRawValue()265 CFX_WideString CXFA_WidgetData::GetRawValue() {
266   return m_pNode->GetContent();
267 }
268 
GetAccess(bool bTemplate)269 int32_t CXFA_WidgetData::GetAccess(bool bTemplate) {
270   if (bTemplate) {
271     CXFA_Node* pNode = m_pNode->GetTemplateNode();
272     if (pNode)
273       return pNode->GetEnum(XFA_ATTRIBUTE_Access);
274     return XFA_ATTRIBUTEENUM_Open;
275   }
276   CXFA_Node* pNode = m_pNode;
277   while (pNode) {
278     int32_t iAcc = pNode->GetEnum(XFA_ATTRIBUTE_Access);
279     if (iAcc != XFA_ATTRIBUTEENUM_Open)
280       return iAcc;
281 
282     pNode =
283         pNode->GetNodeItem(XFA_NODEITEM_Parent, XFA_ObjectType::ContainerNode);
284   }
285   return XFA_ATTRIBUTEENUM_Open;
286 }
287 
GetRotate()288 int32_t CXFA_WidgetData::GetRotate() {
289   CXFA_Measurement ms;
290   if (!m_pNode->TryMeasure(XFA_ATTRIBUTE_Rotate, ms, false))
291     return 0;
292 
293   int32_t iRotate = FXSYS_round(ms.GetValue());
294   iRotate = XFA_MapRotation(iRotate);
295   return iRotate / 90 * 90;
296 }
297 
GetBorder(bool bModified)298 CXFA_Border CXFA_WidgetData::GetBorder(bool bModified) {
299   return CXFA_Border(m_pNode->GetProperty(0, XFA_Element::Border, bModified));
300 }
301 
GetCaption(bool bModified)302 CXFA_Caption CXFA_WidgetData::GetCaption(bool bModified) {
303   return CXFA_Caption(m_pNode->GetProperty(0, XFA_Element::Caption, bModified));
304 }
305 
GetFont(bool bModified)306 CXFA_Font CXFA_WidgetData::GetFont(bool bModified) {
307   return CXFA_Font(m_pNode->GetProperty(0, XFA_Element::Font, bModified));
308 }
309 
GetMargin(bool bModified)310 CXFA_Margin CXFA_WidgetData::GetMargin(bool bModified) {
311   return CXFA_Margin(m_pNode->GetProperty(0, XFA_Element::Margin, bModified));
312 }
313 
GetPara(bool bModified)314 CXFA_Para CXFA_WidgetData::GetPara(bool bModified) {
315   return CXFA_Para(m_pNode->GetProperty(0, XFA_Element::Para, bModified));
316 }
317 
GetEventList(CXFA_NodeArray & events)318 void CXFA_WidgetData::GetEventList(CXFA_NodeArray& events) {
319   m_pNode->GetNodeList(events, 0, XFA_Element::Event);
320 }
321 
GetEventByActivity(int32_t iActivity,CXFA_NodeArray & events,bool bIsFormReady)322 int32_t CXFA_WidgetData::GetEventByActivity(int32_t iActivity,
323                                             CXFA_NodeArray& events,
324                                             bool bIsFormReady) {
325   CXFA_NodeArray allEvents;
326   GetEventList(allEvents);
327   int32_t iCount = allEvents.GetSize();
328   for (int32_t i = 0; i < iCount; i++) {
329     CXFA_Event event(allEvents[i]);
330     if (event.GetActivity() == iActivity) {
331       if (iActivity == XFA_ATTRIBUTEENUM_Ready) {
332         CFX_WideStringC wsRef;
333         event.GetRef(wsRef);
334         if (bIsFormReady) {
335           if (wsRef == CFX_WideStringC(L"$form"))
336             events.Add(allEvents[i]);
337         } else {
338           if (wsRef == CFX_WideStringC(L"$layout"))
339             events.Add(allEvents[i]);
340         }
341       } else {
342         events.Add(allEvents[i]);
343       }
344     }
345   }
346   return events.GetSize();
347 }
348 
GetDefaultValue(bool bModified)349 CXFA_Value CXFA_WidgetData::GetDefaultValue(bool bModified) {
350   CXFA_Node* pTemNode = m_pNode->GetTemplateNode();
351   return CXFA_Value(
352       pTemNode ? pTemNode->GetProperty(0, XFA_Element::Value, bModified)
353                : nullptr);
354 }
355 
GetFormValue(bool bModified)356 CXFA_Value CXFA_WidgetData::GetFormValue(bool bModified) {
357   return CXFA_Value(m_pNode->GetProperty(0, XFA_Element::Value, bModified));
358 }
359 
GetCalculate(bool bModified)360 CXFA_Calculate CXFA_WidgetData::GetCalculate(bool bModified) {
361   return CXFA_Calculate(
362       m_pNode->GetProperty(0, XFA_Element::Calculate, bModified));
363 }
364 
GetValidate(bool bModified)365 CXFA_Validate CXFA_WidgetData::GetValidate(bool bModified) {
366   return CXFA_Validate(
367       m_pNode->GetProperty(0, XFA_Element::Validate, bModified));
368 }
369 
GetBind(bool bModified)370 CXFA_Bind CXFA_WidgetData::GetBind(bool bModified) {
371   return CXFA_Bind(m_pNode->GetProperty(0, XFA_Element::Bind, bModified));
372 }
373 
GetAssist(bool bModified)374 CXFA_Assist CXFA_WidgetData::GetAssist(bool bModified) {
375   return CXFA_Assist(m_pNode->GetProperty(0, XFA_Element::Assist, bModified));
376 }
377 
GetWidth(FX_FLOAT & fWidth)378 bool CXFA_WidgetData::GetWidth(FX_FLOAT& fWidth) {
379   return TryMeasure(XFA_ATTRIBUTE_W, fWidth);
380 }
381 
GetHeight(FX_FLOAT & fHeight)382 bool CXFA_WidgetData::GetHeight(FX_FLOAT& fHeight) {
383   return TryMeasure(XFA_ATTRIBUTE_H, fHeight);
384 }
385 
GetMinWidth(FX_FLOAT & fMinWidth)386 bool CXFA_WidgetData::GetMinWidth(FX_FLOAT& fMinWidth) {
387   return TryMeasure(XFA_ATTRIBUTE_MinW, fMinWidth);
388 }
389 
GetMinHeight(FX_FLOAT & fMinHeight)390 bool CXFA_WidgetData::GetMinHeight(FX_FLOAT& fMinHeight) {
391   return TryMeasure(XFA_ATTRIBUTE_MinH, fMinHeight);
392 }
393 
GetMaxWidth(FX_FLOAT & fMaxWidth)394 bool CXFA_WidgetData::GetMaxWidth(FX_FLOAT& fMaxWidth) {
395   return TryMeasure(XFA_ATTRIBUTE_MaxW, fMaxWidth);
396 }
397 
GetMaxHeight(FX_FLOAT & fMaxHeight)398 bool CXFA_WidgetData::GetMaxHeight(FX_FLOAT& fMaxHeight) {
399   return TryMeasure(XFA_ATTRIBUTE_MaxH, fMaxHeight);
400 }
401 
GetUIBorder()402 CXFA_Border CXFA_WidgetData::GetUIBorder() {
403   CXFA_Node* pUIChild = GetUIChild();
404   return CXFA_Border(pUIChild
405                          ? pUIChild->GetProperty(0, XFA_Element::Border, false)
406                          : nullptr);
407 }
408 
GetUIMargin()409 CFX_RectF CXFA_WidgetData::GetUIMargin() {
410   CXFA_Node* pUIChild = GetUIChild();
411   CXFA_Margin mgUI = CXFA_Margin(
412       pUIChild ? pUIChild->GetProperty(0, XFA_Element::Margin, false)
413                : nullptr);
414 
415   if (!mgUI)
416     return CFX_RectF();
417 
418   CXFA_Border border = GetUIBorder();
419   if (border && border.GetPresence() != XFA_ATTRIBUTEENUM_Visible)
420     return CFX_RectF();
421 
422   FX_FLOAT fLeftInset, fTopInset, fRightInset, fBottomInset;
423   bool bLeft = mgUI.GetLeftInset(fLeftInset);
424   bool bTop = mgUI.GetTopInset(fTopInset);
425   bool bRight = mgUI.GetRightInset(fRightInset);
426   bool bBottom = mgUI.GetBottomInset(fBottomInset);
427   if (border) {
428     bool bVisible = false;
429     FX_FLOAT fThickness = 0;
430     border.Get3DStyle(bVisible, fThickness);
431     if (!bLeft || !bTop || !bRight || !bBottom) {
432       std::vector<CXFA_Stroke> strokes;
433       border.GetStrokes(&strokes);
434       if (!bTop)
435         fTopInset = GetEdgeThickness(strokes, bVisible, 0);
436       if (!bRight)
437         fRightInset = GetEdgeThickness(strokes, bVisible, 1);
438       if (!bBottom)
439         fBottomInset = GetEdgeThickness(strokes, bVisible, 2);
440       if (!bLeft)
441         fLeftInset = GetEdgeThickness(strokes, bVisible, 3);
442     }
443   }
444   return CFX_RectF(fLeftInset, fTopInset, fRightInset, fBottomInset);
445 }
446 
GetButtonHighlight()447 int32_t CXFA_WidgetData::GetButtonHighlight() {
448   CXFA_Node* pUIChild = GetUIChild();
449   if (pUIChild)
450     return pUIChild->GetEnum(XFA_ATTRIBUTE_Highlight);
451   return GetAttributeDefaultValue_Enum(
452       XFA_Element::Button, XFA_ATTRIBUTE_Highlight, XFA_XDPPACKET_Form);
453 }
454 
GetButtonRollover(CFX_WideString & wsRollover,bool & bRichText)455 bool CXFA_WidgetData::GetButtonRollover(CFX_WideString& wsRollover,
456                                         bool& bRichText) {
457   if (CXFA_Node* pItems = m_pNode->GetChild(0, XFA_Element::Items)) {
458     CXFA_Node* pText = pItems->GetNodeItem(XFA_NODEITEM_FirstChild);
459     while (pText) {
460       CFX_WideStringC wsName;
461       pText->TryCData(XFA_ATTRIBUTE_Name, wsName);
462       if (wsName == L"rollover") {
463         pText->TryContent(wsRollover);
464         bRichText = pText->GetElementType() == XFA_Element::ExData;
465         return !wsRollover.IsEmpty();
466       }
467       pText = pText->GetNodeItem(XFA_NODEITEM_NextSibling);
468     }
469   }
470   return false;
471 }
472 
GetButtonDown(CFX_WideString & wsDown,bool & bRichText)473 bool CXFA_WidgetData::GetButtonDown(CFX_WideString& wsDown, bool& bRichText) {
474   if (CXFA_Node* pItems = m_pNode->GetChild(0, XFA_Element::Items)) {
475     CXFA_Node* pText = pItems->GetNodeItem(XFA_NODEITEM_FirstChild);
476     while (pText) {
477       CFX_WideStringC wsName;
478       pText->TryCData(XFA_ATTRIBUTE_Name, wsName);
479       if (wsName == L"down") {
480         pText->TryContent(wsDown);
481         bRichText = pText->GetElementType() == XFA_Element::ExData;
482         return !wsDown.IsEmpty();
483       }
484       pText = pText->GetNodeItem(XFA_NODEITEM_NextSibling);
485     }
486   }
487   return false;
488 }
489 
GetCheckButtonShape()490 int32_t CXFA_WidgetData::GetCheckButtonShape() {
491   CXFA_Node* pUIChild = GetUIChild();
492   if (pUIChild)
493     return pUIChild->GetEnum(XFA_ATTRIBUTE_Shape);
494   return GetAttributeDefaultValue_Enum(XFA_Element::CheckButton,
495                                        XFA_ATTRIBUTE_Shape, XFA_XDPPACKET_Form);
496 }
497 
GetCheckButtonMark()498 int32_t CXFA_WidgetData::GetCheckButtonMark() {
499   CXFA_Node* pUIChild = GetUIChild();
500   if (pUIChild)
501     return pUIChild->GetEnum(XFA_ATTRIBUTE_Mark);
502   return GetAttributeDefaultValue_Enum(XFA_Element::CheckButton,
503                                        XFA_ATTRIBUTE_Mark, XFA_XDPPACKET_Form);
504 }
505 
IsRadioButton()506 bool CXFA_WidgetData::IsRadioButton() {
507   if (CXFA_Node* pParent = m_pNode->GetNodeItem(XFA_NODEITEM_Parent))
508     return pParent->GetElementType() == XFA_Element::ExclGroup;
509   return false;
510 }
511 
GetCheckButtonSize()512 FX_FLOAT CXFA_WidgetData::GetCheckButtonSize() {
513   CXFA_Node* pUIChild = GetUIChild();
514   if (pUIChild)
515     return pUIChild->GetMeasure(XFA_ATTRIBUTE_Size).ToUnit(XFA_UNIT_Pt);
516   return XFA_GetAttributeDefaultValue_Measure(
517              XFA_Element::CheckButton, XFA_ATTRIBUTE_Size, XFA_XDPPACKET_Form)
518       .ToUnit(XFA_UNIT_Pt);
519 }
520 
IsAllowNeutral()521 bool CXFA_WidgetData::IsAllowNeutral() {
522   CXFA_Node* pUIChild = GetUIChild();
523   if (pUIChild)
524     return pUIChild->GetBoolean(XFA_ATTRIBUTE_AllowNeutral);
525   return GetAttributeDefaultValue_Boolean(
526       XFA_Element::CheckButton, XFA_ATTRIBUTE_AllowNeutral, XFA_XDPPACKET_Form);
527 }
528 
GetCheckState()529 XFA_CHECKSTATE CXFA_WidgetData::GetCheckState() {
530   CFX_WideString wsValue = GetRawValue();
531   if (wsValue.IsEmpty())
532     return XFA_CHECKSTATE_Off;
533 
534   if (CXFA_Node* pItems = m_pNode->GetChild(0, XFA_Element::Items)) {
535     CXFA_Node* pText = pItems->GetNodeItem(XFA_NODEITEM_FirstChild);
536     int32_t i = 0;
537     while (pText) {
538       CFX_WideString wsContent;
539       if (pText->TryContent(wsContent) && (wsContent == wsValue))
540         return (XFA_CHECKSTATE)i;
541 
542       i++;
543       pText = pText->GetNodeItem(XFA_NODEITEM_NextSibling);
544     }
545   }
546   return XFA_CHECKSTATE_Off;
547 }
548 
SetCheckState(XFA_CHECKSTATE eCheckState,bool bNotify)549 void CXFA_WidgetData::SetCheckState(XFA_CHECKSTATE eCheckState, bool bNotify) {
550   CXFA_WidgetData exclGroup(GetExclGroupNode());
551   if (exclGroup) {
552     CFX_WideString wsValue;
553     if (eCheckState != XFA_CHECKSTATE_Off) {
554       if (CXFA_Node* pItems = m_pNode->GetChild(0, XFA_Element::Items)) {
555         CXFA_Node* pText = pItems->GetNodeItem(XFA_NODEITEM_FirstChild);
556         if (pText)
557           pText->TryContent(wsValue);
558       }
559     }
560     CXFA_Node* pChild =
561         exclGroup.GetNode()->GetNodeItem(XFA_NODEITEM_FirstChild);
562     for (; pChild; pChild = pChild->GetNodeItem(XFA_NODEITEM_NextSibling)) {
563       if (pChild->GetElementType() != XFA_Element::Field)
564         continue;
565 
566       CXFA_Node* pItem = pChild->GetChild(0, XFA_Element::Items);
567       if (!pItem)
568         continue;
569 
570       CXFA_Node* pItemchild = pItem->GetNodeItem(XFA_NODEITEM_FirstChild);
571       if (!pItemchild)
572         continue;
573 
574       CFX_WideString text = pItemchild->GetContent();
575       CFX_WideString wsChildValue = text;
576       if (wsValue != text) {
577         pItemchild = pItemchild->GetNodeItem(XFA_NODEITEM_NextSibling);
578         if (pItemchild)
579           wsChildValue = pItemchild->GetContent();
580         else
581           wsChildValue.clear();
582       }
583       CXFA_WidgetData ch(pChild);
584       ch.SyncValue(wsChildValue, bNotify);
585     }
586     exclGroup.SyncValue(wsValue, bNotify);
587   } else {
588     CXFA_Node* pItems = m_pNode->GetChild(0, XFA_Element::Items);
589     if (!pItems)
590       return;
591 
592     int32_t i = -1;
593     CXFA_Node* pText = pItems->GetNodeItem(XFA_NODEITEM_FirstChild);
594     CFX_WideString wsContent;
595     while (pText) {
596       i++;
597       if (i == eCheckState) {
598         pText->TryContent(wsContent);
599         break;
600       }
601       pText = pText->GetNodeItem(XFA_NODEITEM_NextSibling);
602     }
603     SyncValue(wsContent, bNotify);
604   }
605 }
606 
GetExclGroupNode()607 CXFA_Node* CXFA_WidgetData::GetExclGroupNode() {
608   CXFA_Node* pExcl = ToNode(m_pNode->GetNodeItem(XFA_NODEITEM_Parent));
609   if (!pExcl || pExcl->GetElementType() != XFA_Element::ExclGroup)
610     return nullptr;
611   return pExcl;
612 }
613 
GetSelectedMember()614 CXFA_Node* CXFA_WidgetData::GetSelectedMember() {
615   CXFA_Node* pSelectedMember = nullptr;
616   CFX_WideString wsState = GetRawValue();
617   if (wsState.IsEmpty())
618     return pSelectedMember;
619 
620   for (CXFA_Node* pNode = ToNode(m_pNode->GetNodeItem(XFA_NODEITEM_FirstChild));
621        pNode; pNode = pNode->GetNodeItem(XFA_NODEITEM_NextSibling)) {
622     CXFA_WidgetData widgetData(pNode);
623     if (widgetData.GetCheckState() == XFA_CHECKSTATE_On) {
624       pSelectedMember = pNode;
625       break;
626     }
627   }
628   return pSelectedMember;
629 }
630 
SetSelectedMember(const CFX_WideStringC & wsName,bool bNotify)631 CXFA_Node* CXFA_WidgetData::SetSelectedMember(const CFX_WideStringC& wsName,
632                                               bool bNotify) {
633   uint32_t nameHash = FX_HashCode_GetW(wsName, false);
634   for (CXFA_Node* pNode = ToNode(m_pNode->GetNodeItem(XFA_NODEITEM_FirstChild));
635        pNode; pNode = pNode->GetNodeItem(XFA_NODEITEM_NextSibling)) {
636     if (pNode->GetNameHash() == nameHash) {
637       CXFA_WidgetData widgetData(pNode);
638       widgetData.SetCheckState(XFA_CHECKSTATE_On, bNotify);
639       return pNode;
640     }
641   }
642   return nullptr;
643 }
644 
SetSelectedMemberByValue(const CFX_WideStringC & wsValue,bool bNotify,bool bScriptModify,bool bSyncData)645 void CXFA_WidgetData::SetSelectedMemberByValue(const CFX_WideStringC& wsValue,
646                                                bool bNotify,
647                                                bool bScriptModify,
648                                                bool bSyncData) {
649   CFX_WideString wsExclGroup;
650   for (CXFA_Node* pNode = m_pNode->GetNodeItem(XFA_NODEITEM_FirstChild); pNode;
651        pNode = pNode->GetNodeItem(XFA_NODEITEM_NextSibling)) {
652     if (pNode->GetElementType() != XFA_Element::Field)
653       continue;
654 
655     CXFA_Node* pItem = pNode->GetChild(0, XFA_Element::Items);
656     if (!pItem)
657       continue;
658 
659     CXFA_Node* pItemchild = pItem->GetNodeItem(XFA_NODEITEM_FirstChild);
660     if (!pItemchild)
661       continue;
662 
663     CFX_WideString wsChildValue = pItemchild->GetContent();
664     if (wsValue != wsChildValue) {
665       pItemchild = pItemchild->GetNodeItem(XFA_NODEITEM_NextSibling);
666       if (pItemchild)
667         wsChildValue = pItemchild->GetContent();
668       else
669         wsChildValue.clear();
670     } else {
671       wsExclGroup = wsValue;
672     }
673     pNode->SetContent(wsChildValue, wsChildValue, bNotify, bScriptModify,
674                       false);
675   }
676   if (m_pNode) {
677     m_pNode->SetContent(wsExclGroup, wsExclGroup, bNotify, bScriptModify,
678                         bSyncData);
679   }
680 }
681 
GetExclGroupFirstMember()682 CXFA_Node* CXFA_WidgetData::GetExclGroupFirstMember() {
683   CXFA_Node* pExcl = GetNode();
684   if (!pExcl)
685     return nullptr;
686 
687   CXFA_Node* pNode = pExcl->GetNodeItem(XFA_NODEITEM_FirstChild);
688   while (pNode) {
689     if (pNode->GetElementType() == XFA_Element::Field)
690       return pNode;
691 
692     pNode = pNode->GetNodeItem(XFA_NODEITEM_NextSibling);
693   }
694   return nullptr;
695 }
GetExclGroupNextMember(CXFA_Node * pNode)696 CXFA_Node* CXFA_WidgetData::GetExclGroupNextMember(CXFA_Node* pNode) {
697   if (!pNode)
698     return nullptr;
699 
700   CXFA_Node* pNodeField = pNode->GetNodeItem(XFA_NODEITEM_NextSibling);
701   while (pNodeField) {
702     if (pNodeField->GetElementType() == XFA_Element::Field)
703       return pNodeField;
704 
705     pNodeField = pNodeField->GetNodeItem(XFA_NODEITEM_NextSibling);
706   }
707   return nullptr;
708 }
709 
GetChoiceListCommitOn()710 int32_t CXFA_WidgetData::GetChoiceListCommitOn() {
711   CXFA_Node* pUIChild = GetUIChild();
712   if (pUIChild)
713     return pUIChild->GetEnum(XFA_ATTRIBUTE_CommitOn);
714   return GetAttributeDefaultValue_Enum(
715       XFA_Element::ChoiceList, XFA_ATTRIBUTE_CommitOn, XFA_XDPPACKET_Form);
716 }
717 
IsChoiceListAllowTextEntry()718 bool CXFA_WidgetData::IsChoiceListAllowTextEntry() {
719   CXFA_Node* pUIChild = GetUIChild();
720   if (pUIChild)
721     return pUIChild->GetBoolean(XFA_ATTRIBUTE_TextEntry);
722   return GetAttributeDefaultValue_Boolean(
723       XFA_Element::ChoiceList, XFA_ATTRIBUTE_TextEntry, XFA_XDPPACKET_Form);
724 }
725 
GetChoiceListOpen()726 int32_t CXFA_WidgetData::GetChoiceListOpen() {
727   CXFA_Node* pUIChild = GetUIChild();
728   if (pUIChild)
729     return pUIChild->GetEnum(XFA_ATTRIBUTE_Open);
730   return GetAttributeDefaultValue_Enum(XFA_Element::ChoiceList,
731                                        XFA_ATTRIBUTE_Open, XFA_XDPPACKET_Form);
732 }
733 
IsListBox()734 bool CXFA_WidgetData::IsListBox() {
735   int32_t iOpenMode = GetChoiceListOpen();
736   return (iOpenMode == XFA_ATTRIBUTEENUM_Always ||
737           iOpenMode == XFA_ATTRIBUTEENUM_MultiSelect);
738 }
739 
CountChoiceListItems(bool bSaveValue)740 int32_t CXFA_WidgetData::CountChoiceListItems(bool bSaveValue) {
741   CXFA_NodeArray pItems;
742   CXFA_Node* pItem = nullptr;
743   int32_t iCount = 0;
744   CXFA_Node* pNode = m_pNode->GetNodeItem(XFA_NODEITEM_FirstChild);
745   for (; pNode; pNode = pNode->GetNodeItem(XFA_NODEITEM_NextSibling)) {
746     if (pNode->GetElementType() != XFA_Element::Items)
747       continue;
748 
749     iCount++;
750     pItems.Add(pNode);
751     if (iCount == 2)
752       break;
753   }
754   if (iCount == 0)
755     return 0;
756 
757   pItem = pItems[0];
758   if (iCount > 1) {
759     bool bItemOneHasSave = pItems[0]->GetBoolean(XFA_ATTRIBUTE_Save);
760     bool bItemTwoHasSave = pItems[1]->GetBoolean(XFA_ATTRIBUTE_Save);
761     if (bItemOneHasSave != bItemTwoHasSave && bSaveValue == bItemTwoHasSave)
762       pItem = pItems[1];
763   }
764   pItems.RemoveAll();
765   return pItem->CountChildren(XFA_Element::Unknown);
766 }
767 
GetChoiceListItem(CFX_WideString & wsText,int32_t nIndex,bool bSaveValue)768 bool CXFA_WidgetData::GetChoiceListItem(CFX_WideString& wsText,
769                                         int32_t nIndex,
770                                         bool bSaveValue) {
771   wsText.clear();
772   CXFA_NodeArray pItemsArray;
773   CXFA_Node* pItems = nullptr;
774   int32_t iCount = 0;
775   CXFA_Node* pNode = m_pNode->GetNodeItem(XFA_NODEITEM_FirstChild);
776   for (; pNode; pNode = pNode->GetNodeItem(XFA_NODEITEM_NextSibling)) {
777     if (pNode->GetElementType() != XFA_Element::Items)
778       continue;
779 
780     iCount++;
781     pItemsArray.Add(pNode);
782     if (iCount == 2)
783       break;
784   }
785   if (iCount == 0)
786     return false;
787 
788   pItems = pItemsArray[0];
789   if (iCount > 1) {
790     bool bItemOneHasSave = pItemsArray[0]->GetBoolean(XFA_ATTRIBUTE_Save);
791     bool bItemTwoHasSave = pItemsArray[1]->GetBoolean(XFA_ATTRIBUTE_Save);
792     if (bItemOneHasSave != bItemTwoHasSave && bSaveValue == bItemTwoHasSave)
793       pItems = pItemsArray[1];
794   }
795   if (pItems) {
796     CXFA_Node* pItem = pItems->GetChild(nIndex, XFA_Element::Unknown);
797     if (pItem) {
798       pItem->TryContent(wsText);
799       return true;
800     }
801   }
802   return false;
803 }
804 
GetChoiceListItems(std::vector<CFX_WideString> & wsTextArray,bool bSaveValue)805 void CXFA_WidgetData::GetChoiceListItems(
806     std::vector<CFX_WideString>& wsTextArray,
807     bool bSaveValue) {
808   CXFA_NodeArray pItems;
809   CXFA_Node* pItem = nullptr;
810   int32_t iCount = 0;
811   CXFA_Node* pNode = m_pNode->GetNodeItem(XFA_NODEITEM_FirstChild);
812   for (; pNode; pNode = pNode->GetNodeItem(XFA_NODEITEM_NextSibling)) {
813     if (pNode->GetElementType() != XFA_Element::Items)
814       continue;
815 
816     iCount++;
817     pItems.Add(pNode);
818     if (iCount == 2)
819       break;
820   }
821   if (iCount == 0)
822     return;
823 
824   pItem = pItems[0];
825   if (iCount > 1) {
826     bool bItemOneHasSave = pItems[0]->GetBoolean(XFA_ATTRIBUTE_Save);
827     bool bItemTwoHasSave = pItems[1]->GetBoolean(XFA_ATTRIBUTE_Save);
828     if (bItemOneHasSave != bItemTwoHasSave && bSaveValue == bItemTwoHasSave)
829       pItem = pItems[1];
830   }
831   pItems.RemoveAll();
832   pNode = pItem->GetNodeItem(XFA_NODEITEM_FirstChild);
833   for (; pNode; pNode = pNode->GetNodeItem(XFA_NODEITEM_NextSibling)) {
834     wsTextArray.emplace_back();
835     pNode->TryContent(wsTextArray.back());
836   }
837 }
838 
CountSelectedItems()839 int32_t CXFA_WidgetData::CountSelectedItems() {
840   std::vector<CFX_WideString> wsValueArray;
841   GetSelectedItemsValue(wsValueArray);
842   if (IsListBox() || !IsChoiceListAllowTextEntry())
843     return pdfium::CollectionSize<int32_t>(wsValueArray);
844 
845   int32_t iSelected = 0;
846   std::vector<CFX_WideString> wsSaveTextArray;
847   GetChoiceListItems(wsSaveTextArray, true);
848   int32_t iValues = pdfium::CollectionSize<int32_t>(wsValueArray);
849   for (int32_t i = 0; i < iValues; i++) {
850     int32_t iSaves = pdfium::CollectionSize<int32_t>(wsSaveTextArray);
851     for (int32_t j = 0; j < iSaves; j++) {
852       if (wsValueArray[i] == wsSaveTextArray[j]) {
853         iSelected++;
854         break;
855       }
856     }
857   }
858   return iSelected;
859 }
860 
GetSelectedItem(int32_t nIndex)861 int32_t CXFA_WidgetData::GetSelectedItem(int32_t nIndex) {
862   std::vector<CFX_WideString> wsValueArray;
863   GetSelectedItemsValue(wsValueArray);
864   std::vector<CFX_WideString> wsSaveTextArray;
865   GetChoiceListItems(wsSaveTextArray, true);
866   int32_t iSaves = pdfium::CollectionSize<int32_t>(wsSaveTextArray);
867   for (int32_t j = 0; j < iSaves; j++) {
868     if (wsValueArray[nIndex] == wsSaveTextArray[j])
869       return j;
870   }
871   return -1;
872 }
873 
GetSelectedItems(CFX_ArrayTemplate<int32_t> & iSelArray)874 void CXFA_WidgetData::GetSelectedItems(CFX_ArrayTemplate<int32_t>& iSelArray) {
875   std::vector<CFX_WideString> wsValueArray;
876   GetSelectedItemsValue(wsValueArray);
877   int32_t iValues = pdfium::CollectionSize<int32_t>(wsValueArray);
878   if (iValues < 1)
879     return;
880 
881   std::vector<CFX_WideString> wsSaveTextArray;
882   GetChoiceListItems(wsSaveTextArray, true);
883   int32_t iSaves = pdfium::CollectionSize<int32_t>(wsSaveTextArray);
884   for (int32_t i = 0; i < iValues; i++) {
885     for (int32_t j = 0; j < iSaves; j++) {
886       if (wsValueArray[i] == wsSaveTextArray[j]) {
887         iSelArray.Add(j);
888         break;
889       }
890     }
891   }
892 }
893 
GetSelectedItemsValue(std::vector<CFX_WideString> & wsSelTextArray)894 void CXFA_WidgetData::GetSelectedItemsValue(
895     std::vector<CFX_WideString>& wsSelTextArray) {
896   CFX_WideString wsValue = GetRawValue();
897   if (GetChoiceListOpen() == XFA_ATTRIBUTEENUM_MultiSelect) {
898     if (!wsValue.IsEmpty()) {
899       int32_t iStart = 0;
900       int32_t iLength = wsValue.GetLength();
901       int32_t iEnd = wsValue.Find(L'\n', iStart);
902       iEnd = (iEnd == -1) ? iLength : iEnd;
903       while (iEnd >= iStart) {
904         wsSelTextArray.push_back(wsValue.Mid(iStart, iEnd - iStart));
905         iStart = iEnd + 1;
906         if (iStart >= iLength)
907           break;
908 
909         iEnd = wsValue.Find(L'\n', iStart);
910         if (iEnd < 0)
911           wsSelTextArray.push_back(wsValue.Mid(iStart, iLength - iStart));
912       }
913     }
914   } else {
915     wsSelTextArray.push_back(wsValue);
916   }
917 }
918 
GetItemState(int32_t nIndex)919 bool CXFA_WidgetData::GetItemState(int32_t nIndex) {
920   if (nIndex < 0)
921     return false;
922 
923   std::vector<CFX_WideString> wsSaveTextArray;
924   GetChoiceListItems(wsSaveTextArray, true);
925   if (pdfium::CollectionSize<int32_t>(wsSaveTextArray) <= nIndex)
926     return false;
927 
928   std::vector<CFX_WideString> wsValueArray;
929   GetSelectedItemsValue(wsValueArray);
930   int32_t iValues = pdfium::CollectionSize<int32_t>(wsValueArray);
931   for (int32_t j = 0; j < iValues; j++) {
932     if (wsValueArray[j] == wsSaveTextArray[nIndex])
933       return true;
934   }
935   return false;
936 }
937 
SetItemState(int32_t nIndex,bool bSelected,bool bNotify,bool bScriptModify,bool bSyncData)938 void CXFA_WidgetData::SetItemState(int32_t nIndex,
939                                    bool bSelected,
940                                    bool bNotify,
941                                    bool bScriptModify,
942                                    bool bSyncData) {
943   if (nIndex < 0)
944     return;
945 
946   std::vector<CFX_WideString> wsSaveTextArray;
947   GetChoiceListItems(wsSaveTextArray, true);
948   if (pdfium::CollectionSize<int32_t>(wsSaveTextArray) <= nIndex)
949     return;
950 
951   int32_t iSel = -1;
952   std::vector<CFX_WideString> wsValueArray;
953   GetSelectedItemsValue(wsValueArray);
954   int32_t iValues = pdfium::CollectionSize<int32_t>(wsValueArray);
955   for (int32_t j = 0; j < iValues; j++) {
956     if (wsValueArray[j] == wsSaveTextArray[nIndex]) {
957       iSel = j;
958       break;
959     }
960   }
961   if (GetChoiceListOpen() == XFA_ATTRIBUTEENUM_MultiSelect) {
962     if (bSelected) {
963       if (iSel < 0) {
964         CFX_WideString wsValue = GetRawValue();
965         if (!wsValue.IsEmpty()) {
966           wsValue += L"\n";
967         }
968         wsValue += wsSaveTextArray[nIndex];
969         m_pNode->SetContent(wsValue, wsValue, bNotify, bScriptModify,
970                             bSyncData);
971       }
972     } else if (iSel >= 0) {
973       CFX_ArrayTemplate<int32_t> iSelArray;
974       GetSelectedItems(iSelArray);
975       for (int32_t i = 0; i < iSelArray.GetSize(); i++) {
976         if (iSelArray[i] == nIndex) {
977           iSelArray.RemoveAt(i);
978           break;
979         }
980       }
981       SetSelectedItems(iSelArray, bNotify, bScriptModify, bSyncData);
982     }
983   } else {
984     if (bSelected) {
985       if (iSel < 0) {
986         CFX_WideString wsSaveText = wsSaveTextArray[nIndex];
987         CFX_WideString wsFormatText(wsSaveText);
988         GetFormatDataValue(wsSaveText, wsFormatText);
989         m_pNode->SetContent(wsSaveText, wsFormatText, bNotify, bScriptModify,
990                             bSyncData);
991       }
992     } else if (iSel >= 0) {
993       m_pNode->SetContent(CFX_WideString(), CFX_WideString(), bNotify,
994                           bScriptModify, bSyncData);
995     }
996   }
997 }
998 
SetSelectedItems(CFX_ArrayTemplate<int32_t> & iSelArray,bool bNotify,bool bScriptModify,bool bSyncData)999 void CXFA_WidgetData::SetSelectedItems(CFX_ArrayTemplate<int32_t>& iSelArray,
1000                                        bool bNotify,
1001                                        bool bScriptModify,
1002                                        bool bSyncData) {
1003   CFX_WideString wsValue;
1004   int32_t iSize = iSelArray.GetSize();
1005   if (iSize >= 1) {
1006     std::vector<CFX_WideString> wsSaveTextArray;
1007     GetChoiceListItems(wsSaveTextArray, true);
1008     CFX_WideString wsItemValue;
1009     for (int32_t i = 0; i < iSize; i++) {
1010       wsItemValue = (iSize == 1) ? wsSaveTextArray[iSelArray[i]]
1011                                  : wsSaveTextArray[iSelArray[i]] + L"\n";
1012       wsValue += wsItemValue;
1013     }
1014   }
1015   CFX_WideString wsFormat(wsValue);
1016   if (GetChoiceListOpen() != XFA_ATTRIBUTEENUM_MultiSelect)
1017     GetFormatDataValue(wsValue, wsFormat);
1018 
1019   m_pNode->SetContent(wsValue, wsFormat, bNotify, bScriptModify, bSyncData);
1020 }
1021 
ClearAllSelections()1022 void CXFA_WidgetData::ClearAllSelections() {
1023   CXFA_Node* pBind = m_pNode->GetBindData();
1024   if (!pBind || GetChoiceListOpen() != XFA_ATTRIBUTEENUM_MultiSelect) {
1025     SyncValue(CFX_WideString(), false);
1026     return;
1027   }
1028 
1029   while (CXFA_Node* pChildNode = pBind->GetNodeItem(XFA_NODEITEM_FirstChild))
1030     pBind->RemoveChild(pChildNode);
1031 }
1032 
InsertItem(const CFX_WideString & wsLabel,const CFX_WideString & wsValue,int32_t nIndex,bool bNotify)1033 void CXFA_WidgetData::InsertItem(const CFX_WideString& wsLabel,
1034                                  const CFX_WideString& wsValue,
1035                                  int32_t nIndex,
1036                                  bool bNotify) {
1037   CFX_WideString wsNewValue(wsValue);
1038   if (wsNewValue.IsEmpty())
1039     wsNewValue = wsLabel;
1040 
1041   CXFA_NodeArray listitems;
1042   int32_t iCount = 0;
1043   CXFA_Node* pItemNode = m_pNode->GetNodeItem(XFA_NODEITEM_FirstChild);
1044   for (; pItemNode;
1045        pItemNode = pItemNode->GetNodeItem(XFA_NODEITEM_NextSibling)) {
1046     if (pItemNode->GetElementType() != XFA_Element::Items)
1047       continue;
1048 
1049     listitems.Add(pItemNode);
1050     iCount++;
1051   }
1052   if (iCount < 1) {
1053     CXFA_Node* pItems = m_pNode->CreateSamePacketNode(XFA_Element::Items);
1054     m_pNode->InsertChild(-1, pItems);
1055     InsertListTextItem(pItems, wsLabel, nIndex);
1056     CXFA_Node* pSaveItems = m_pNode->CreateSamePacketNode(XFA_Element::Items);
1057     m_pNode->InsertChild(-1, pSaveItems);
1058     pSaveItems->SetBoolean(XFA_ATTRIBUTE_Save, true);
1059     InsertListTextItem(pSaveItems, wsNewValue, nIndex);
1060   } else if (iCount > 1) {
1061     for (int32_t i = 0; i < 2; i++) {
1062       CXFA_Node* pNode = listitems[i];
1063       bool bHasSave = pNode->GetBoolean(XFA_ATTRIBUTE_Save);
1064       if (bHasSave)
1065         InsertListTextItem(pNode, wsNewValue, nIndex);
1066       else
1067         InsertListTextItem(pNode, wsLabel, nIndex);
1068     }
1069   } else {
1070     CXFA_Node* pNode = listitems[0];
1071     pNode->SetBoolean(XFA_ATTRIBUTE_Save, false);
1072     pNode->SetEnum(XFA_ATTRIBUTE_Presence, XFA_ATTRIBUTEENUM_Visible);
1073     CXFA_Node* pSaveItems = m_pNode->CreateSamePacketNode(XFA_Element::Items);
1074     m_pNode->InsertChild(-1, pSaveItems);
1075     pSaveItems->SetBoolean(XFA_ATTRIBUTE_Save, true);
1076     pSaveItems->SetEnum(XFA_ATTRIBUTE_Presence, XFA_ATTRIBUTEENUM_Hidden);
1077     listitems.RemoveAll();
1078     CXFA_Node* pListNode = pNode->GetNodeItem(XFA_NODEITEM_FirstChild);
1079     int32_t i = 0;
1080     while (pListNode) {
1081       CFX_WideString wsOldValue;
1082       pListNode->TryContent(wsOldValue);
1083       InsertListTextItem(pSaveItems, wsOldValue, i);
1084       i++;
1085       pListNode = pListNode->GetNodeItem(XFA_NODEITEM_NextSibling);
1086     }
1087     InsertListTextItem(pNode, wsLabel, nIndex);
1088     InsertListTextItem(pSaveItems, wsNewValue, nIndex);
1089   }
1090   if (!bNotify)
1091     return;
1092 
1093   m_pNode->GetDocument()->GetNotify()->OnWidgetListItemAdded(
1094       this, wsLabel.c_str(), wsValue.c_str(), nIndex);
1095 }
1096 
GetItemLabel(const CFX_WideStringC & wsValue,CFX_WideString & wsLabel)1097 void CXFA_WidgetData::GetItemLabel(const CFX_WideStringC& wsValue,
1098                                    CFX_WideString& wsLabel) {
1099   int32_t iCount = 0;
1100   CXFA_NodeArray listitems;
1101   CXFA_Node* pItems = m_pNode->GetNodeItem(XFA_NODEITEM_FirstChild);
1102   for (; pItems; pItems = pItems->GetNodeItem(XFA_NODEITEM_NextSibling)) {
1103     if (pItems->GetElementType() != XFA_Element::Items)
1104       continue;
1105 
1106     iCount++;
1107     listitems.Add(pItems);
1108   }
1109   if (iCount <= 1) {
1110     wsLabel = wsValue;
1111   } else {
1112     CXFA_Node* pLabelItems = listitems[0];
1113     bool bSave = pLabelItems->GetBoolean(XFA_ATTRIBUTE_Save);
1114     CXFA_Node* pSaveItems = nullptr;
1115     if (bSave) {
1116       pSaveItems = pLabelItems;
1117       pLabelItems = listitems[1];
1118     } else {
1119       pSaveItems = listitems[1];
1120     }
1121     iCount = 0;
1122     int32_t iSearch = -1;
1123     CFX_WideString wsContent;
1124     CXFA_Node* pChildItem = pSaveItems->GetNodeItem(XFA_NODEITEM_FirstChild);
1125     for (; pChildItem;
1126          pChildItem = pChildItem->GetNodeItem(XFA_NODEITEM_NextSibling)) {
1127       pChildItem->TryContent(wsContent);
1128       if (wsContent == wsValue) {
1129         iSearch = iCount;
1130         break;
1131       }
1132       iCount++;
1133     }
1134     if (iSearch < 0)
1135       return;
1136     if (CXFA_Node* pText =
1137             pLabelItems->GetChild(iSearch, XFA_Element::Unknown)) {
1138       pText->TryContent(wsLabel);
1139     }
1140   }
1141 }
1142 
GetItemValue(const CFX_WideStringC & wsLabel,CFX_WideString & wsValue)1143 void CXFA_WidgetData::GetItemValue(const CFX_WideStringC& wsLabel,
1144                                    CFX_WideString& wsValue) {
1145   int32_t iCount = 0;
1146   CXFA_NodeArray listitems;
1147   CXFA_Node* pItems = m_pNode->GetNodeItem(XFA_NODEITEM_FirstChild);
1148   for (; pItems; pItems = pItems->GetNodeItem(XFA_NODEITEM_NextSibling)) {
1149     if (pItems->GetElementType() != XFA_Element::Items)
1150       continue;
1151 
1152     iCount++;
1153     listitems.Add(pItems);
1154   }
1155   if (iCount <= 1) {
1156     wsValue = wsLabel;
1157   } else {
1158     CXFA_Node* pLabelItems = listitems[0];
1159     bool bSave = pLabelItems->GetBoolean(XFA_ATTRIBUTE_Save);
1160     CXFA_Node* pSaveItems = nullptr;
1161     if (bSave) {
1162       pSaveItems = pLabelItems;
1163       pLabelItems = listitems[1];
1164     } else {
1165       pSaveItems = listitems[1];
1166     }
1167     iCount = 0;
1168     int32_t iSearch = -1;
1169     CFX_WideString wsContent;
1170     CXFA_Node* pChildItem = pLabelItems->GetNodeItem(XFA_NODEITEM_FirstChild);
1171     for (; pChildItem;
1172          pChildItem = pChildItem->GetNodeItem(XFA_NODEITEM_NextSibling)) {
1173       pChildItem->TryContent(wsContent);
1174       if (wsContent == wsLabel) {
1175         iSearch = iCount;
1176         break;
1177       }
1178       iCount++;
1179     }
1180     if (iSearch < 0)
1181       return;
1182     if (CXFA_Node* pText = pSaveItems->GetChild(iSearch, XFA_Element::Unknown))
1183       pText->TryContent(wsValue);
1184   }
1185 }
1186 
DeleteItem(int32_t nIndex,bool bNotify,bool bScriptModify,bool bSyncData)1187 bool CXFA_WidgetData::DeleteItem(int32_t nIndex,
1188                                  bool bNotify,
1189                                  bool bScriptModify,
1190                                  bool bSyncData) {
1191   bool bSetValue = false;
1192   CXFA_Node* pItems = m_pNode->GetNodeItem(XFA_NODEITEM_FirstChild);
1193   for (; pItems; pItems = pItems->GetNodeItem(XFA_NODEITEM_NextSibling)) {
1194     if (pItems->GetElementType() != XFA_Element::Items)
1195       continue;
1196 
1197     if (nIndex < 0) {
1198       while (CXFA_Node* pNode = pItems->GetNodeItem(XFA_NODEITEM_FirstChild)) {
1199         pItems->RemoveChild(pNode);
1200       }
1201     } else {
1202       if (!bSetValue && pItems->GetBoolean(XFA_ATTRIBUTE_Save)) {
1203         SetItemState(nIndex, false, true, bScriptModify, bSyncData);
1204         bSetValue = true;
1205       }
1206       int32_t i = 0;
1207       CXFA_Node* pNode = pItems->GetNodeItem(XFA_NODEITEM_FirstChild);
1208       while (pNode) {
1209         if (i == nIndex) {
1210           pItems->RemoveChild(pNode);
1211           break;
1212         }
1213         i++;
1214         pNode = pNode->GetNodeItem(XFA_NODEITEM_NextSibling);
1215       }
1216     }
1217   }
1218   if (bNotify)
1219     m_pNode->GetDocument()->GetNotify()->OnWidgetListItemRemoved(this, nIndex);
1220   return true;
1221 }
1222 
GetHorizontalScrollPolicy()1223 int32_t CXFA_WidgetData::GetHorizontalScrollPolicy() {
1224   CXFA_Node* pUIChild = GetUIChild();
1225   if (pUIChild)
1226     return pUIChild->GetEnum(XFA_ATTRIBUTE_HScrollPolicy);
1227   return XFA_ATTRIBUTEENUM_Auto;
1228 }
1229 
GetNumberOfCells()1230 int32_t CXFA_WidgetData::GetNumberOfCells() {
1231   CXFA_Node* pUIChild = GetUIChild();
1232   if (!pUIChild)
1233     return -1;
1234   if (CXFA_Node* pNode = pUIChild->GetChild(0, XFA_Element::Comb))
1235     return pNode->GetInteger(XFA_ATTRIBUTE_NumberOfCells);
1236   return -1;
1237 }
1238 
GetBarcodeType()1239 CFX_WideString CXFA_WidgetData::GetBarcodeType() {
1240   CXFA_Node* pUIChild = GetUIChild();
1241   return pUIChild ? CFX_WideString(pUIChild->GetCData(XFA_ATTRIBUTE_Type))
1242                   : CFX_WideString();
1243 }
1244 
GetBarcodeAttribute_CharEncoding(int32_t & val)1245 bool CXFA_WidgetData::GetBarcodeAttribute_CharEncoding(int32_t& val) {
1246   CXFA_Node* pUIChild = GetUIChild();
1247   CFX_WideString wsCharEncoding;
1248   if (pUIChild->TryCData(XFA_ATTRIBUTE_CharEncoding, wsCharEncoding)) {
1249     if (wsCharEncoding.CompareNoCase(L"UTF-16")) {
1250       val = CHAR_ENCODING_UNICODE;
1251       return true;
1252     }
1253     if (wsCharEncoding.CompareNoCase(L"UTF-8")) {
1254       val = CHAR_ENCODING_UTF8;
1255       return true;
1256     }
1257   }
1258   return false;
1259 }
1260 
GetBarcodeAttribute_Checksum(bool & val)1261 bool CXFA_WidgetData::GetBarcodeAttribute_Checksum(bool& val) {
1262   CXFA_Node* pUIChild = GetUIChild();
1263   XFA_ATTRIBUTEENUM eChecksum;
1264   if (pUIChild->TryEnum(XFA_ATTRIBUTE_Checksum, eChecksum)) {
1265     switch (eChecksum) {
1266       case XFA_ATTRIBUTEENUM_None:
1267         val = false;
1268         return true;
1269       case XFA_ATTRIBUTEENUM_Auto:
1270         val = true;
1271         return true;
1272       case XFA_ATTRIBUTEENUM_1mod10:
1273         break;
1274       case XFA_ATTRIBUTEENUM_1mod10_1mod11:
1275         break;
1276       case XFA_ATTRIBUTEENUM_2mod10:
1277         break;
1278       default:
1279         break;
1280     }
1281   }
1282   return false;
1283 }
1284 
GetBarcodeAttribute_DataLength(int32_t & val)1285 bool CXFA_WidgetData::GetBarcodeAttribute_DataLength(int32_t& val) {
1286   CXFA_Node* pUIChild = GetUIChild();
1287   CFX_WideString wsDataLength;
1288   if (pUIChild->TryCData(XFA_ATTRIBUTE_DataLength, wsDataLength)) {
1289     val = FXSYS_wtoi(wsDataLength.c_str());
1290     return true;
1291   }
1292   return false;
1293 }
1294 
GetBarcodeAttribute_StartChar(FX_CHAR & val)1295 bool CXFA_WidgetData::GetBarcodeAttribute_StartChar(FX_CHAR& val) {
1296   CXFA_Node* pUIChild = GetUIChild();
1297   CFX_WideStringC wsStartEndChar;
1298   if (pUIChild->TryCData(XFA_ATTRIBUTE_StartChar, wsStartEndChar)) {
1299     if (wsStartEndChar.GetLength()) {
1300       val = (FX_CHAR)wsStartEndChar.GetAt(0);
1301       return true;
1302     }
1303   }
1304   return false;
1305 }
1306 
GetBarcodeAttribute_EndChar(FX_CHAR & val)1307 bool CXFA_WidgetData::GetBarcodeAttribute_EndChar(FX_CHAR& val) {
1308   CXFA_Node* pUIChild = GetUIChild();
1309   CFX_WideStringC wsStartEndChar;
1310   if (pUIChild->TryCData(XFA_ATTRIBUTE_EndChar, wsStartEndChar)) {
1311     if (wsStartEndChar.GetLength()) {
1312       val = (FX_CHAR)wsStartEndChar.GetAt(0);
1313       return true;
1314     }
1315   }
1316   return false;
1317 }
1318 
GetBarcodeAttribute_ECLevel(int32_t & val)1319 bool CXFA_WidgetData::GetBarcodeAttribute_ECLevel(int32_t& val) {
1320   CXFA_Node* pUIChild = GetUIChild();
1321   CFX_WideString wsECLevel;
1322   if (pUIChild->TryCData(XFA_ATTRIBUTE_ErrorCorrectionLevel, wsECLevel)) {
1323     val = FXSYS_wtoi(wsECLevel.c_str());
1324     return true;
1325   }
1326   return false;
1327 }
1328 
GetBarcodeAttribute_ModuleWidth(int32_t & val)1329 bool CXFA_WidgetData::GetBarcodeAttribute_ModuleWidth(int32_t& val) {
1330   CXFA_Node* pUIChild = GetUIChild();
1331   CXFA_Measurement mModuleWidthHeight;
1332   if (pUIChild->TryMeasure(XFA_ATTRIBUTE_ModuleWidth, mModuleWidthHeight)) {
1333     val = (int32_t)mModuleWidthHeight.ToUnit(XFA_UNIT_Pt);
1334     return true;
1335   }
1336   return false;
1337 }
1338 
GetBarcodeAttribute_ModuleHeight(int32_t & val)1339 bool CXFA_WidgetData::GetBarcodeAttribute_ModuleHeight(int32_t& val) {
1340   CXFA_Node* pUIChild = GetUIChild();
1341   CXFA_Measurement mModuleWidthHeight;
1342   if (pUIChild->TryMeasure(XFA_ATTRIBUTE_ModuleHeight, mModuleWidthHeight)) {
1343     val = (int32_t)mModuleWidthHeight.ToUnit(XFA_UNIT_Pt);
1344     return true;
1345   }
1346   return false;
1347 }
1348 
GetBarcodeAttribute_PrintChecksum(bool & val)1349 bool CXFA_WidgetData::GetBarcodeAttribute_PrintChecksum(bool& val) {
1350   CXFA_Node* pUIChild = GetUIChild();
1351   bool bPrintCheckDigit;
1352   if (pUIChild->TryBoolean(XFA_ATTRIBUTE_PrintCheckDigit, bPrintCheckDigit)) {
1353     val = bPrintCheckDigit;
1354     return true;
1355   }
1356   return false;
1357 }
1358 
GetBarcodeAttribute_TextLocation(int32_t & val)1359 bool CXFA_WidgetData::GetBarcodeAttribute_TextLocation(int32_t& val) {
1360   CXFA_Node* pUIChild = GetUIChild();
1361   XFA_ATTRIBUTEENUM eTextLocation;
1362   if (pUIChild->TryEnum(XFA_ATTRIBUTE_TextLocation, eTextLocation)) {
1363     switch (eTextLocation) {
1364       case XFA_ATTRIBUTEENUM_None:
1365         val = BC_TEXT_LOC_NONE;
1366         return true;
1367       case XFA_ATTRIBUTEENUM_Above:
1368         val = BC_TEXT_LOC_ABOVE;
1369         return true;
1370       case XFA_ATTRIBUTEENUM_Below:
1371         val = BC_TEXT_LOC_BELOW;
1372         return true;
1373       case XFA_ATTRIBUTEENUM_AboveEmbedded:
1374         val = BC_TEXT_LOC_ABOVEEMBED;
1375         return true;
1376       case XFA_ATTRIBUTEENUM_BelowEmbedded:
1377         val = BC_TEXT_LOC_BELOWEMBED;
1378         return true;
1379       default:
1380         break;
1381     }
1382   }
1383   return false;
1384 }
1385 
GetBarcodeAttribute_Truncate(bool & val)1386 bool CXFA_WidgetData::GetBarcodeAttribute_Truncate(bool& val) {
1387   CXFA_Node* pUIChild = GetUIChild();
1388   bool bTruncate;
1389   if (pUIChild->TryBoolean(XFA_ATTRIBUTE_Truncate, bTruncate)) {
1390     val = bTruncate;
1391     return true;
1392   }
1393   return false;
1394 }
1395 
GetBarcodeAttribute_WideNarrowRatio(FX_FLOAT & val)1396 bool CXFA_WidgetData::GetBarcodeAttribute_WideNarrowRatio(FX_FLOAT& val) {
1397   CXFA_Node* pUIChild = GetUIChild();
1398   CFX_WideString wsWideNarrowRatio;
1399   if (pUIChild->TryCData(XFA_ATTRIBUTE_WideNarrowRatio, wsWideNarrowRatio)) {
1400     FX_STRSIZE ptPos = wsWideNarrowRatio.Find(':');
1401     FX_FLOAT fRatio = 0;
1402     if (ptPos >= 0) {
1403       fRatio = (FX_FLOAT)FXSYS_wtoi(wsWideNarrowRatio.c_str());
1404     } else {
1405       int32_t fA, fB;
1406       fA = FXSYS_wtoi(wsWideNarrowRatio.Left(ptPos).c_str());
1407       fB = FXSYS_wtoi(wsWideNarrowRatio.Mid(ptPos + 1).c_str());
1408       if (fB)
1409         fRatio = (FX_FLOAT)fA / fB;
1410     }
1411     val = fRatio;
1412     return true;
1413   }
1414   return false;
1415 }
1416 
GetPasswordChar(CFX_WideString & wsPassWord)1417 void CXFA_WidgetData::GetPasswordChar(CFX_WideString& wsPassWord) {
1418   CXFA_Node* pUIChild = GetUIChild();
1419   if (pUIChild) {
1420     pUIChild->TryCData(XFA_ATTRIBUTE_PasswordChar, wsPassWord);
1421   } else {
1422     wsPassWord = GetAttributeDefaultValue_Cdata(XFA_Element::PasswordEdit,
1423                                                 XFA_ATTRIBUTE_PasswordChar,
1424                                                 XFA_XDPPACKET_Form);
1425   }
1426 }
1427 
IsMultiLine()1428 bool CXFA_WidgetData::IsMultiLine() {
1429   CXFA_Node* pUIChild = GetUIChild();
1430   if (pUIChild)
1431     return pUIChild->GetBoolean(XFA_ATTRIBUTE_MultiLine);
1432   return GetAttributeDefaultValue_Boolean(
1433       XFA_Element::TextEdit, XFA_ATTRIBUTE_MultiLine, XFA_XDPPACKET_Form);
1434 }
1435 
GetVerticalScrollPolicy()1436 int32_t CXFA_WidgetData::GetVerticalScrollPolicy() {
1437   CXFA_Node* pUIChild = GetUIChild();
1438   if (pUIChild)
1439     return pUIChild->GetEnum(XFA_ATTRIBUTE_VScrollPolicy);
1440   return GetAttributeDefaultValue_Enum(
1441       XFA_Element::TextEdit, XFA_ATTRIBUTE_VScrollPolicy, XFA_XDPPACKET_Form);
1442 }
1443 
GetMaxChars(XFA_Element & eType)1444 int32_t CXFA_WidgetData::GetMaxChars(XFA_Element& eType) {
1445   if (CXFA_Node* pNode = m_pNode->GetChild(0, XFA_Element::Value)) {
1446     if (CXFA_Node* pChild = pNode->GetNodeItem(XFA_NODEITEM_FirstChild)) {
1447       switch (pChild->GetElementType()) {
1448         case XFA_Element::Text:
1449           eType = XFA_Element::Text;
1450           return pChild->GetInteger(XFA_ATTRIBUTE_MaxChars);
1451         case XFA_Element::ExData: {
1452           eType = XFA_Element::ExData;
1453           int32_t iMax = pChild->GetInteger(XFA_ATTRIBUTE_MaxLength);
1454           return iMax < 0 ? 0 : iMax;
1455         }
1456         default:
1457           break;
1458       }
1459     }
1460   }
1461   return 0;
1462 }
1463 
GetFracDigits(int32_t & iFracDigits)1464 bool CXFA_WidgetData::GetFracDigits(int32_t& iFracDigits) {
1465   if (CXFA_Node* pNode = m_pNode->GetChild(0, XFA_Element::Value)) {
1466     if (CXFA_Node* pChild = pNode->GetChild(0, XFA_Element::Decimal))
1467       return pChild->TryInteger(XFA_ATTRIBUTE_FracDigits, iFracDigits);
1468   }
1469   iFracDigits = -1;
1470   return false;
1471 }
1472 
GetLeadDigits(int32_t & iLeadDigits)1473 bool CXFA_WidgetData::GetLeadDigits(int32_t& iLeadDigits) {
1474   if (CXFA_Node* pNode = m_pNode->GetChild(0, XFA_Element::Value)) {
1475     if (CXFA_Node* pChild = pNode->GetChild(0, XFA_Element::Decimal))
1476       return pChild->TryInteger(XFA_ATTRIBUTE_LeadDigits, iLeadDigits);
1477   }
1478   iLeadDigits = -1;
1479   return false;
1480 }
1481 
SetValue(const CFX_WideString & wsValue,XFA_VALUEPICTURE eValueType)1482 bool CXFA_WidgetData::SetValue(const CFX_WideString& wsValue,
1483                                XFA_VALUEPICTURE eValueType) {
1484   if (wsValue.IsEmpty()) {
1485     SyncValue(wsValue, true);
1486     return true;
1487   }
1488   m_bPreNull = m_bIsNull;
1489   m_bIsNull = false;
1490   CFX_WideString wsNewText(wsValue);
1491   CFX_WideString wsPicture;
1492   GetPictureContent(wsPicture, eValueType);
1493   bool bValidate = true;
1494   bool bSyncData = false;
1495   CXFA_Node* pNode = GetUIChild();
1496   if (!pNode)
1497     return true;
1498 
1499   XFA_Element eType = pNode->GetElementType();
1500   if (!wsPicture.IsEmpty()) {
1501     CXFA_LocaleMgr* pLocalMgr = m_pNode->GetDocument()->GetLocalMgr();
1502     IFX_Locale* pLocale = GetLocal();
1503     CXFA_LocaleValue widgetValue = XFA_GetLocaleValue(this);
1504     bValidate =
1505         widgetValue.ValidateValue(wsValue, wsPicture, pLocale, &wsPicture);
1506     if (bValidate) {
1507       widgetValue = CXFA_LocaleValue(widgetValue.GetType(), wsNewText,
1508                                      wsPicture, pLocale, pLocalMgr);
1509       wsNewText = widgetValue.GetValue();
1510       if (eType == XFA_Element::NumericEdit) {
1511         int32_t iLeadDigits = 0;
1512         int32_t iFracDigits = 0;
1513         GetLeadDigits(iLeadDigits);
1514         GetFracDigits(iFracDigits);
1515         wsNewText = NumericLimit(wsNewText, iLeadDigits, iFracDigits);
1516       }
1517       bSyncData = true;
1518     }
1519   } else {
1520     if (eType == XFA_Element::NumericEdit) {
1521       if (wsNewText != L"0") {
1522         int32_t iLeadDigits = 0;
1523         int32_t iFracDigits = 0;
1524         GetLeadDigits(iLeadDigits);
1525         GetFracDigits(iFracDigits);
1526         wsNewText = NumericLimit(wsNewText, iLeadDigits, iFracDigits);
1527       }
1528       bSyncData = true;
1529     }
1530   }
1531   if (eType != XFA_Element::NumericEdit || bSyncData)
1532     SyncValue(wsNewText, true);
1533 
1534   return bValidate;
1535 }
1536 
GetPictureContent(CFX_WideString & wsPicture,XFA_VALUEPICTURE ePicture)1537 bool CXFA_WidgetData::GetPictureContent(CFX_WideString& wsPicture,
1538                                         XFA_VALUEPICTURE ePicture) {
1539   if (ePicture == XFA_VALUEPICTURE_Raw)
1540     return false;
1541 
1542   CXFA_LocaleValue widgetValue = XFA_GetLocaleValue(this);
1543   switch (ePicture) {
1544     case XFA_VALUEPICTURE_Display: {
1545       if (CXFA_Node* pFormat = m_pNode->GetChild(0, XFA_Element::Format)) {
1546         if (CXFA_Node* pPicture = pFormat->GetChild(0, XFA_Element::Picture)) {
1547           if (pPicture->TryContent(wsPicture))
1548             return true;
1549         }
1550       }
1551       CFX_WideString wsDataPicture, wsTimePicture;
1552       IFX_Locale* pLocale = GetLocal();
1553       if (!pLocale)
1554         return false;
1555 
1556       uint32_t dwType = widgetValue.GetType();
1557       switch (dwType) {
1558         case XFA_VT_DATE:
1559           pLocale->GetDatePattern(FX_LOCALEDATETIMESUBCATEGORY_Medium,
1560                                   wsPicture);
1561           break;
1562         case XFA_VT_TIME:
1563           pLocale->GetTimePattern(FX_LOCALEDATETIMESUBCATEGORY_Medium,
1564                                   wsPicture);
1565           break;
1566         case XFA_VT_DATETIME:
1567           pLocale->GetDatePattern(FX_LOCALEDATETIMESUBCATEGORY_Medium,
1568                                   wsDataPicture);
1569           pLocale->GetTimePattern(FX_LOCALEDATETIMESUBCATEGORY_Medium,
1570                                   wsTimePicture);
1571           wsPicture = wsDataPicture + L"T" + wsTimePicture;
1572           break;
1573         case XFA_VT_DECIMAL:
1574         case XFA_VT_FLOAT:
1575           break;
1576         default:
1577           break;
1578       }
1579       return true;
1580     }
1581 
1582     case XFA_VALUEPICTURE_Edit: {
1583       CXFA_Node* pUI = m_pNode->GetChild(0, XFA_Element::Ui);
1584       if (pUI) {
1585         if (CXFA_Node* pPicture = pUI->GetChild(0, XFA_Element::Picture)) {
1586           if (pPicture->TryContent(wsPicture))
1587             return true;
1588         }
1589       }
1590       {
1591         CFX_WideString wsDataPicture, wsTimePicture;
1592         IFX_Locale* pLocale = GetLocal();
1593         if (!pLocale) {
1594           return false;
1595         }
1596         uint32_t dwType = widgetValue.GetType();
1597         switch (dwType) {
1598           case XFA_VT_DATE:
1599             pLocale->GetDatePattern(FX_LOCALEDATETIMESUBCATEGORY_Short,
1600                                     wsPicture);
1601             break;
1602           case XFA_VT_TIME:
1603             pLocale->GetTimePattern(FX_LOCALEDATETIMESUBCATEGORY_Short,
1604                                     wsPicture);
1605             break;
1606           case XFA_VT_DATETIME:
1607             pLocale->GetDatePattern(FX_LOCALEDATETIMESUBCATEGORY_Short,
1608                                     wsDataPicture);
1609             pLocale->GetTimePattern(FX_LOCALEDATETIMESUBCATEGORY_Short,
1610                                     wsTimePicture);
1611             wsPicture = wsDataPicture + L"T" + wsTimePicture;
1612             break;
1613           default:
1614             break;
1615         }
1616       }
1617       return true;
1618     }
1619     case XFA_VALUEPICTURE_DataBind: {
1620       if (CXFA_Bind bind = GetBind()) {
1621         bind.GetPicture(wsPicture);
1622         return true;
1623       }
1624       break;
1625     }
1626     default:
1627       break;
1628   }
1629   return false;
1630 }
1631 
GetLocal()1632 IFX_Locale* CXFA_WidgetData::GetLocal() {
1633   if (!m_pNode)
1634     return nullptr;
1635 
1636   CFX_WideString wsLocaleName;
1637   if (!m_pNode->GetLocaleName(wsLocaleName))
1638     return nullptr;
1639   if (wsLocaleName == L"ambient")
1640     return m_pNode->GetDocument()->GetLocalMgr()->GetDefLocale();
1641   return m_pNode->GetDocument()->GetLocalMgr()->GetLocaleByName(wsLocaleName);
1642 }
1643 
GetValue(CFX_WideString & wsValue,XFA_VALUEPICTURE eValueType)1644 bool CXFA_WidgetData::GetValue(CFX_WideString& wsValue,
1645                                XFA_VALUEPICTURE eValueType) {
1646   wsValue = m_pNode->GetContent();
1647 
1648   if (eValueType == XFA_VALUEPICTURE_Display)
1649     GetItemLabel(wsValue.AsStringC(), wsValue);
1650 
1651   CFX_WideString wsPicture;
1652   GetPictureContent(wsPicture, eValueType);
1653   CXFA_Node* pNode = GetUIChild();
1654   if (!pNode)
1655     return true;
1656 
1657   switch (GetUIChild()->GetElementType()) {
1658     case XFA_Element::ChoiceList: {
1659       if (eValueType == XFA_VALUEPICTURE_Display) {
1660         int32_t iSelItemIndex = GetSelectedItem(0);
1661         if (iSelItemIndex >= 0) {
1662           GetChoiceListItem(wsValue, iSelItemIndex);
1663           wsPicture.clear();
1664         }
1665       }
1666     } break;
1667     case XFA_Element::NumericEdit:
1668       if (eValueType != XFA_VALUEPICTURE_Raw && wsPicture.IsEmpty()) {
1669         IFX_Locale* pLocale = GetLocal();
1670         if (eValueType == XFA_VALUEPICTURE_Display && pLocale) {
1671           CFX_WideString wsOutput;
1672           NormalizeNumStr(wsValue, wsOutput);
1673           FormatNumStr(wsOutput, pLocale, wsOutput);
1674           wsValue = wsOutput;
1675         }
1676       }
1677       break;
1678     default:
1679       break;
1680   }
1681   if (wsPicture.IsEmpty())
1682     return true;
1683 
1684   if (IFX_Locale* pLocale = GetLocal()) {
1685     CXFA_LocaleValue widgetValue = XFA_GetLocaleValue(this);
1686     CXFA_LocaleMgr* pLocalMgr = m_pNode->GetDocument()->GetLocalMgr();
1687     switch (widgetValue.GetType()) {
1688       case XFA_VT_DATE: {
1689         CFX_WideString wsDate, wsTime;
1690         if (SplitDateTime(wsValue, wsDate, wsTime)) {
1691           CXFA_LocaleValue date(XFA_VT_DATE, wsDate, pLocalMgr);
1692           if (date.FormatPatterns(wsValue, wsPicture, pLocale, eValueType))
1693             return true;
1694         }
1695         break;
1696       }
1697       case XFA_VT_TIME: {
1698         CFX_WideString wsDate, wsTime;
1699         if (SplitDateTime(wsValue, wsDate, wsTime)) {
1700           CXFA_LocaleValue time(XFA_VT_TIME, wsTime, pLocalMgr);
1701           if (time.FormatPatterns(wsValue, wsPicture, pLocale, eValueType))
1702             return true;
1703         }
1704         break;
1705       }
1706       default:
1707         break;
1708     }
1709     widgetValue.FormatPatterns(wsValue, wsPicture, pLocale, eValueType);
1710   }
1711   return true;
1712 }
1713 
GetNormalizeDataValue(const CFX_WideString & wsValue,CFX_WideString & wsNormalizeValue)1714 bool CXFA_WidgetData::GetNormalizeDataValue(const CFX_WideString& wsValue,
1715                                             CFX_WideString& wsNormalizeValue) {
1716   wsNormalizeValue = wsValue;
1717   if (wsValue.IsEmpty())
1718     return true;
1719 
1720   CFX_WideString wsPicture;
1721   GetPictureContent(wsPicture, XFA_VALUEPICTURE_DataBind);
1722   if (wsPicture.IsEmpty())
1723     return true;
1724 
1725   ASSERT(GetNode());
1726   CXFA_LocaleMgr* pLocalMgr = GetNode()->GetDocument()->GetLocalMgr();
1727   IFX_Locale* pLocale = GetLocal();
1728   CXFA_LocaleValue widgetValue = XFA_GetLocaleValue(this);
1729   if (widgetValue.ValidateValue(wsValue, wsPicture, pLocale, &wsPicture)) {
1730     widgetValue = CXFA_LocaleValue(widgetValue.GetType(), wsNormalizeValue,
1731                                    wsPicture, pLocale, pLocalMgr);
1732     wsNormalizeValue = widgetValue.GetValue();
1733     return true;
1734   }
1735   return false;
1736 }
1737 
GetFormatDataValue(const CFX_WideString & wsValue,CFX_WideString & wsFormattedValue)1738 bool CXFA_WidgetData::GetFormatDataValue(const CFX_WideString& wsValue,
1739                                          CFX_WideString& wsFormattedValue) {
1740   wsFormattedValue = wsValue;
1741   if (wsValue.IsEmpty())
1742     return true;
1743 
1744   CFX_WideString wsPicture;
1745   GetPictureContent(wsPicture, XFA_VALUEPICTURE_DataBind);
1746   if (wsPicture.IsEmpty())
1747     return true;
1748 
1749   if (IFX_Locale* pLocale = GetLocal()) {
1750     ASSERT(GetNode());
1751     CXFA_Node* pNodeValue = GetNode()->GetChild(0, XFA_Element::Value);
1752     if (!pNodeValue)
1753       return false;
1754 
1755     CXFA_Node* pValueChild = pNodeValue->GetNodeItem(XFA_NODEITEM_FirstChild);
1756     if (!pValueChild)
1757       return false;
1758 
1759     int32_t iVTType = XFA_VT_NULL;
1760     switch (pValueChild->GetElementType()) {
1761       case XFA_Element::Decimal:
1762         iVTType = XFA_VT_DECIMAL;
1763         break;
1764       case XFA_Element::Float:
1765         iVTType = XFA_VT_FLOAT;
1766         break;
1767       case XFA_Element::Date:
1768         iVTType = XFA_VT_DATE;
1769         break;
1770       case XFA_Element::Time:
1771         iVTType = XFA_VT_TIME;
1772         break;
1773       case XFA_Element::DateTime:
1774         iVTType = XFA_VT_DATETIME;
1775         break;
1776       case XFA_Element::Boolean:
1777         iVTType = XFA_VT_BOOLEAN;
1778         break;
1779       case XFA_Element::Integer:
1780         iVTType = XFA_VT_INTEGER;
1781         break;
1782       case XFA_Element::Text:
1783         iVTType = XFA_VT_TEXT;
1784         break;
1785       default:
1786         iVTType = XFA_VT_NULL;
1787         break;
1788     }
1789     CXFA_LocaleMgr* pLocalMgr = GetNode()->GetDocument()->GetLocalMgr();
1790     CXFA_LocaleValue widgetValue(iVTType, wsValue, pLocalMgr);
1791     switch (widgetValue.GetType()) {
1792       case XFA_VT_DATE: {
1793         CFX_WideString wsDate, wsTime;
1794         if (SplitDateTime(wsValue, wsDate, wsTime)) {
1795           CXFA_LocaleValue date(XFA_VT_DATE, wsDate, pLocalMgr);
1796           if (date.FormatPatterns(wsFormattedValue, wsPicture, pLocale,
1797                                   XFA_VALUEPICTURE_DataBind)) {
1798             return true;
1799           }
1800         }
1801         break;
1802       }
1803       case XFA_VT_TIME: {
1804         CFX_WideString wsDate, wsTime;
1805         if (SplitDateTime(wsValue, wsDate, wsTime)) {
1806           CXFA_LocaleValue time(XFA_VT_TIME, wsTime, pLocalMgr);
1807           if (time.FormatPatterns(wsFormattedValue, wsPicture, pLocale,
1808                                   XFA_VALUEPICTURE_DataBind)) {
1809             return true;
1810           }
1811         }
1812         break;
1813       }
1814       default:
1815         break;
1816     }
1817     widgetValue.FormatPatterns(wsFormattedValue, wsPicture, pLocale,
1818                                XFA_VALUEPICTURE_DataBind);
1819   }
1820   return false;
1821 }
1822 
NormalizeNumStr(const CFX_WideString & wsValue,CFX_WideString & wsOutput)1823 void CXFA_WidgetData::NormalizeNumStr(const CFX_WideString& wsValue,
1824                                       CFX_WideString& wsOutput) {
1825   if (wsValue.IsEmpty())
1826     return;
1827 
1828   wsOutput = wsValue;
1829   wsOutput.TrimLeft('0');
1830   int32_t dot_index = wsOutput.Find('.');
1831   int32_t iFracDigits = 0;
1832   if (!wsOutput.IsEmpty() && dot_index >= 0 &&
1833       (!GetFracDigits(iFracDigits) || iFracDigits != -1)) {
1834     wsOutput.TrimRight(L"0");
1835     wsOutput.TrimRight(L".");
1836   }
1837   if (wsOutput.IsEmpty() || wsOutput[0] == '.')
1838     wsOutput.Insert(0, '0');
1839 }
1840 
FormatNumStr(const CFX_WideString & wsValue,IFX_Locale * pLocale,CFX_WideString & wsOutput)1841 void CXFA_WidgetData::FormatNumStr(const CFX_WideString& wsValue,
1842                                    IFX_Locale* pLocale,
1843                                    CFX_WideString& wsOutput) {
1844   if (wsValue.IsEmpty())
1845     return;
1846 
1847   CFX_WideString wsSrcNum = wsValue;
1848   CFX_WideString wsGroupSymbol;
1849   pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Grouping, wsGroupSymbol);
1850   bool bNeg = false;
1851   if (wsSrcNum[0] == '-') {
1852     bNeg = true;
1853     wsSrcNum.Delete(0, 1);
1854   }
1855   int32_t len = wsSrcNum.GetLength();
1856   int32_t dot_index = wsSrcNum.Find('.');
1857   if (dot_index == -1)
1858     dot_index = len;
1859 
1860   int32_t cc = dot_index - 1;
1861   if (cc >= 0) {
1862     int nPos = dot_index % 3;
1863     wsOutput.clear();
1864     for (int32_t i = 0; i < dot_index; i++) {
1865       if (i % 3 == nPos && i != 0)
1866         wsOutput += wsGroupSymbol;
1867 
1868       wsOutput += wsSrcNum[i];
1869     }
1870     if (dot_index < len) {
1871       CFX_WideString wsSymbol;
1872       pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Decimal, wsSymbol);
1873       wsOutput += wsSymbol;
1874       wsOutput += wsSrcNum.Right(len - dot_index - 1);
1875     }
1876     if (bNeg) {
1877       CFX_WideString wsMinusymbol;
1878       pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Minus, wsMinusymbol);
1879       wsOutput = wsMinusymbol + wsOutput;
1880     }
1881   }
1882 }
1883 
SyncValue(const CFX_WideString & wsValue,bool bNotify)1884 void CXFA_WidgetData::SyncValue(const CFX_WideString& wsValue, bool bNotify) {
1885   if (!m_pNode)
1886     return;
1887 
1888   CFX_WideString wsFormatValue(wsValue);
1889   CXFA_WidgetData* pContainerWidgetData = m_pNode->GetContainerWidgetData();
1890   if (pContainerWidgetData)
1891     pContainerWidgetData->GetFormatDataValue(wsValue, wsFormatValue);
1892 
1893   m_pNode->SetContent(wsValue, wsFormatValue, bNotify);
1894 }
1895 
InsertListTextItem(CXFA_Node * pItems,const CFX_WideString & wsText,int32_t nIndex)1896 void CXFA_WidgetData::InsertListTextItem(CXFA_Node* pItems,
1897                                          const CFX_WideString& wsText,
1898                                          int32_t nIndex) {
1899   CXFA_Node* pText = pItems->CreateSamePacketNode(XFA_Element::Text);
1900   pItems->InsertChild(nIndex, pText);
1901   pText->SetContent(wsText, wsText, false, false, false);
1902 }
1903 
NumericLimit(const CFX_WideString & wsValue,int32_t iLead,int32_t iTread) const1904 CFX_WideString CXFA_WidgetData::NumericLimit(const CFX_WideString& wsValue,
1905                                              int32_t iLead,
1906                                              int32_t iTread) const {
1907   if ((iLead == -1) && (iTread == -1))
1908     return wsValue;
1909 
1910   CFX_WideString wsRet;
1911   int32_t iLead_ = 0, iTread_ = -1;
1912   int32_t iCount = wsValue.GetLength();
1913   if (iCount == 0)
1914     return wsValue;
1915 
1916   int32_t i = 0;
1917   if (wsValue[i] == L'-') {
1918     wsRet += L'-';
1919     i++;
1920   }
1921   for (; i < iCount; i++) {
1922     FX_WCHAR wc = wsValue[i];
1923     if (FXSYS_isDecimalDigit(wc)) {
1924       if (iLead >= 0) {
1925         iLead_++;
1926         if (iLead_ > iLead)
1927           return L"0";
1928       } else if (iTread_ >= 0) {
1929         iTread_++;
1930         if (iTread_ > iTread) {
1931           if (iTread != -1) {
1932             CFX_Decimal wsDeci = CFX_Decimal(wsValue.AsStringC());
1933             wsDeci.SetScale(iTread);
1934             wsRet = wsDeci;
1935           }
1936           return wsRet;
1937         }
1938       }
1939     } else if (wc == L'.') {
1940       iTread_ = 0;
1941       iLead = -1;
1942     }
1943     wsRet += wc;
1944   }
1945   return wsRet;
1946 }
1947