Home | History | Annotate | Download | only in parser
      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 
     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 
     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 
     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 
    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 
    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 
    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 
    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 
    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 
    260 XFA_Element CXFA_WidgetData::GetUIType() {
    261   GetUIChild();
    262   return m_eUIType;
    263 }
    264 
    265 CFX_WideString CXFA_WidgetData::GetRawValue() {
    266   return m_pNode->GetContent();
    267 }
    268 
    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 
    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 
    298 CXFA_Border CXFA_WidgetData::GetBorder(bool bModified) {
    299   return CXFA_Border(m_pNode->GetProperty(0, XFA_Element::Border, bModified));
    300 }
    301 
    302 CXFA_Caption CXFA_WidgetData::GetCaption(bool bModified) {
    303   return CXFA_Caption(m_pNode->GetProperty(0, XFA_Element::Caption, bModified));
    304 }
    305 
    306 CXFA_Font CXFA_WidgetData::GetFont(bool bModified) {
    307   return CXFA_Font(m_pNode->GetProperty(0, XFA_Element::Font, bModified));
    308 }
    309 
    310 CXFA_Margin CXFA_WidgetData::GetMargin(bool bModified) {
    311   return CXFA_Margin(m_pNode->GetProperty(0, XFA_Element::Margin, bModified));
    312 }
    313 
    314 CXFA_Para CXFA_WidgetData::GetPara(bool bModified) {
    315   return CXFA_Para(m_pNode->GetProperty(0, XFA_Element::Para, bModified));
    316 }
    317 
    318 void CXFA_WidgetData::GetEventList(CXFA_NodeArray& events) {
    319   m_pNode->GetNodeList(events, 0, XFA_Element::Event);
    320 }
    321 
    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 
    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 
    356 CXFA_Value CXFA_WidgetData::GetFormValue(bool bModified) {
    357   return CXFA_Value(m_pNode->GetProperty(0, XFA_Element::Value, bModified));
    358 }
    359 
    360 CXFA_Calculate CXFA_WidgetData::GetCalculate(bool bModified) {
    361   return CXFA_Calculate(
    362       m_pNode->GetProperty(0, XFA_Element::Calculate, bModified));
    363 }
    364 
    365 CXFA_Validate CXFA_WidgetData::GetValidate(bool bModified) {
    366   return CXFA_Validate(
    367       m_pNode->GetProperty(0, XFA_Element::Validate, bModified));
    368 }
    369 
    370 CXFA_Bind CXFA_WidgetData::GetBind(bool bModified) {
    371   return CXFA_Bind(m_pNode->GetProperty(0, XFA_Element::Bind, bModified));
    372 }
    373 
    374 CXFA_Assist CXFA_WidgetData::GetAssist(bool bModified) {
    375   return CXFA_Assist(m_pNode->GetProperty(0, XFA_Element::Assist, bModified));
    376 }
    377 
    378 bool CXFA_WidgetData::GetWidth(FX_FLOAT& fWidth) {
    379   return TryMeasure(XFA_ATTRIBUTE_W, fWidth);
    380 }
    381 
    382 bool CXFA_WidgetData::GetHeight(FX_FLOAT& fHeight) {
    383   return TryMeasure(XFA_ATTRIBUTE_H, fHeight);
    384 }
    385 
    386 bool CXFA_WidgetData::GetMinWidth(FX_FLOAT& fMinWidth) {
    387   return TryMeasure(XFA_ATTRIBUTE_MinW, fMinWidth);
    388 }
    389 
    390 bool CXFA_WidgetData::GetMinHeight(FX_FLOAT& fMinHeight) {
    391   return TryMeasure(XFA_ATTRIBUTE_MinH, fMinHeight);
    392 }
    393 
    394 bool CXFA_WidgetData::GetMaxWidth(FX_FLOAT& fMaxWidth) {
    395   return TryMeasure(XFA_ATTRIBUTE_MaxW, fMaxWidth);
    396 }
    397 
    398 bool CXFA_WidgetData::GetMaxHeight(FX_FLOAT& fMaxHeight) {
    399   return TryMeasure(XFA_ATTRIBUTE_MaxH, fMaxHeight);
    400 }
    401 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 }
    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 
    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 
    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 
    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 
    734 bool CXFA_WidgetData::IsListBox() {
    735   int32_t iOpenMode = GetChoiceListOpen();
    736   return (iOpenMode == XFA_ATTRIBUTEENUM_Always ||
    737           iOpenMode == XFA_ATTRIBUTEENUM_MultiSelect);
    738 }
    739 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   1904 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