1// Copyright 2014 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#ifndef _XFA_UTILS_H_
8#define _XFA_UTILS_H_
9FX_BOOL XFA_FDEExtension_ResolveNamespaceQualifier(
10    IFDE_XMLElement* pNode,
11    const CFX_WideStringC& wsQualifier,
12    CFX_WideString& wsNamespaceURI);
13template <class NodeType, class TraverseStrategy>
14class CXFA_NodeIteratorTemplate {
15 public:
16  CXFA_NodeIteratorTemplate(NodeType* pRootNode = NULL) : m_pRoot(pRootNode) {
17    if (pRootNode) {
18      m_NodeStack.Push(pRootNode);
19    }
20  }
21  FX_BOOL Init(NodeType* pRootNode) {
22    if (!pRootNode) {
23      return FALSE;
24    }
25    m_pRoot = pRootNode;
26    m_NodeStack.RemoveAll();
27    m_NodeStack.Push(pRootNode);
28    return TRUE;
29  }
30  void Clear() { m_NodeStack.RemoveAll(); }
31  void Reset() {
32    Clear();
33    if (m_pRoot) {
34      m_NodeStack.Push(m_pRoot);
35    }
36  }
37  FX_BOOL SetCurrent(NodeType* pCurNode) {
38    m_NodeStack.RemoveAll();
39    if (pCurNode) {
40      CFX_StackTemplate<NodeType*> revStack;
41      NodeType* pNode;
42      for (pNode = pCurNode; pNode && pNode != m_pRoot;
43           pNode = TraverseStrategy::GetParent(pNode)) {
44        revStack.Push(pNode);
45      }
46      if (!pNode) {
47        return FALSE;
48      }
49      revStack.Push(m_pRoot);
50      while (revStack.GetSize()) {
51        m_NodeStack.Push(*revStack.GetTopElement());
52        revStack.Pop();
53      }
54    }
55    return TRUE;
56  }
57  NodeType* GetCurrent() const {
58    return m_NodeStack.GetSize() ? *m_NodeStack.GetTopElement() : NULL;
59  }
60  NodeType* GetRoot() const { return m_pRoot; }
61  NodeType* MoveToPrev() {
62    int32_t nStackLength = m_NodeStack.GetSize();
63    if (nStackLength == 1) {
64      return NULL;
65    } else if (nStackLength > 1) {
66      NodeType* pCurItem = *m_NodeStack.GetTopElement();
67      m_NodeStack.Pop();
68      NodeType* pParentItem = *m_NodeStack.GetTopElement();
69      NodeType* pParentFirstChildItem =
70          TraverseStrategy::GetFirstChild(pParentItem);
71      if (pCurItem == pParentFirstChildItem) {
72        return pParentItem;
73      }
74      NodeType *pPrevItem = pParentFirstChildItem, *pPrevItemNext = NULL;
75      for (; pPrevItem; pPrevItem = pPrevItemNext) {
76        pPrevItemNext = TraverseStrategy::GetNextSibling(pPrevItem);
77        if (!pPrevItemNext || pPrevItemNext == pCurItem) {
78          break;
79        }
80      }
81      m_NodeStack.Push(pPrevItem);
82    } else {
83      m_NodeStack.RemoveAll();
84      if (m_pRoot) {
85        m_NodeStack.Push(m_pRoot);
86      }
87    }
88    if (m_NodeStack.GetSize() > 0) {
89      NodeType* pChildItem = *m_NodeStack.GetTopElement();
90      while ((pChildItem = TraverseStrategy::GetFirstChild(pChildItem)) !=
91             NULL) {
92        while (NodeType* pNextItem =
93                   TraverseStrategy::GetNextSibling(pChildItem)) {
94          pChildItem = pNextItem;
95        }
96        m_NodeStack.Push(pChildItem);
97      }
98      return *m_NodeStack.GetTopElement();
99    }
100    return NULL;
101  }
102  NodeType* MoveToNext() {
103    NodeType** ppNode = NULL;
104    NodeType* pCurrent = GetCurrent();
105    while (m_NodeStack.GetSize() > 0) {
106      while ((ppNode = m_NodeStack.GetTopElement()) != NULL) {
107        if (pCurrent != *ppNode) {
108          return *ppNode;
109        }
110        NodeType* pChild = TraverseStrategy::GetFirstChild(*ppNode);
111        if (pChild == NULL) {
112          break;
113        }
114        m_NodeStack.Push(pChild);
115      }
116      while ((ppNode = m_NodeStack.GetTopElement()) != NULL) {
117        NodeType* pNext = TraverseStrategy::GetNextSibling(*ppNode);
118        m_NodeStack.Pop();
119        if (m_NodeStack.GetSize() == 0) {
120          break;
121        }
122        if (pNext) {
123          m_NodeStack.Push(pNext);
124          break;
125        }
126      }
127    }
128    return NULL;
129  }
130  NodeType* SkipChildrenAndMoveToNext() {
131    NodeType** ppNode = NULL;
132    while ((ppNode = m_NodeStack.GetTopElement()) != NULL) {
133      NodeType* pNext = TraverseStrategy::GetNextSibling(*ppNode);
134      m_NodeStack.Pop();
135      if (m_NodeStack.GetSize() == 0) {
136        break;
137      }
138      if (pNext) {
139        m_NodeStack.Push(pNext);
140        break;
141      }
142    }
143    return GetCurrent();
144  }
145
146 protected:
147  NodeType* m_pRoot;
148  CFX_StackTemplate<NodeType*> m_NodeStack;
149};
150template <class KeyType>
151class CXFA_PtrSetTemplate : private CFX_MapPtrToPtr {
152 public:
153  CXFA_PtrSetTemplate() : CFX_MapPtrToPtr(10) {}
154
155  int GetCount() const { return CFX_MapPtrToPtr::GetCount(); }
156
157  FX_BOOL IsEmpty() const { return CFX_MapPtrToPtr::IsEmpty(); }
158
159  FX_BOOL Lookup(KeyType key) const {
160    void* pValue = NULL;
161    return CFX_MapPtrToPtr::Lookup((void*)key, pValue);
162  }
163
164  FX_BOOL operator[](KeyType key) { return Lookup(key); }
165
166  void Add(KeyType key) { CFX_MapPtrToPtr::SetAt((void*)key, (void*)key); }
167
168  FX_BOOL RemoveKey(KeyType key) {
169    return CFX_MapPtrToPtr::RemoveKey((void*)key);
170  }
171
172  void RemoveAll() { CFX_MapPtrToPtr::RemoveAll(); }
173
174  FX_POSITION GetStartPosition() const {
175    return CFX_MapPtrToPtr::GetStartPosition();
176  }
177
178  void GetNextAssoc(FX_POSITION& rNextPosition, KeyType& rKey) const {
179    void* pKey = NULL;
180    void* pValue = NULL;
181    CFX_MapPtrToPtr::GetNextAssoc(rNextPosition, pKey, pValue);
182    rKey = (KeyType)(uintptr_t)pKey;
183  }
184};
185class CXFA_Node;
186class CXFA_WidgetData;
187#include "fxfa_localevalue.h"
188CXFA_Node* XFA_CreateUIChild(CXFA_Node* pNode, XFA_ELEMENT& eWidgetType);
189CXFA_LocaleValue XFA_GetLocaleValue(CXFA_WidgetData* pWidgetData);
190CFX_WideString XFA_NumericLimit(const CFX_WideString& wsValue,
191                                int32_t iLead,
192                                int32_t iTread);
193FX_DOUBLE XFA_WideStringToDouble(const CFX_WideString& wsStringVal);
194FX_DOUBLE XFA_ByteStringToDouble(const CFX_ByteStringC& szStringVal);
195int32_t XFA_MapRotation(int32_t nRotation);
196#ifndef XFA_PARSE_HAS_LINEIDENTIFIER
197#define XFA_PARSE_HAS_LINEIDENTIFIER
198#endif
199FX_BOOL XFA_RecognizeRichText(IFDE_XMLElement* pRichTextXMLNode);
200void XFA_GetPlainTextFromRichText(IFDE_XMLNode* pXMLNode,
201                                  CFX_WideString& wsPlainText);
202FX_BOOL XFA_FieldIsMultiListBox(CXFA_Node* pFieldNode);
203IFX_Stream* XFA_CreateWideTextRead(const CFX_WideString& wsBuffer);
204FX_BOOL XFA_IsLayoutElement(XFA_ELEMENT eElement,
205                            FX_BOOL bLayoutContainer = FALSE);
206FX_BOOL XFA_IsTakingupSpace(XFA_ATTRIBUTEENUM ePresence);
207FX_BOOL XFA_IsFlowingLayout(XFA_ATTRIBUTEENUM eLayout);
208FX_BOOL XFA_IsHorizontalFlow(XFA_ATTRIBUTEENUM eLayout);
209void XFA_DataExporter_DealWithDataGroupNode(CXFA_Node* pDataNode);
210void XFA_DataExporter_RegenerateFormFile(CXFA_Node* pNode,
211                                         IFX_Stream* pStream,
212                                         const FX_CHAR* pChecksum = NULL,
213                                         FX_BOOL bSaveXML = FALSE);
214#endif
215