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