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 #include "xfa/fxfa/cxfa_textprovider.h"
8
9 #include <algorithm>
10 #include <memory>
11 #include <vector>
12
13 #include "core/fxcrt/xml/cfx_xmlelement.h"
14 #include "core/fxcrt/xml/cfx_xmlnode.h"
15 #include "fxjs/xfa/cfxjse_engine.h"
16 #include "fxjs/xfa/cfxjse_value.h"
17 #include "fxjs/xfa/cjx_object.h"
18 #include "xfa/fde/cfde_textout.h"
19 #include "xfa/fxfa/cxfa_eventparam.h"
20 #include "xfa/fxfa/cxfa_ffapp.h"
21 #include "xfa/fxfa/cxfa_ffcheckbutton.h"
22 #include "xfa/fxfa/cxfa_ffdoc.h"
23 #include "xfa/fxfa/cxfa_ffdocview.h"
24 #include "xfa/fxfa/cxfa_fffield.h"
25 #include "xfa/fxfa/cxfa_ffpageview.h"
26 #include "xfa/fxfa/cxfa_ffwidget.h"
27 #include "xfa/fxfa/cxfa_fontmgr.h"
28 #include "xfa/fxfa/cxfa_fwladapterwidgetmgr.h"
29 #include "xfa/fxfa/parser/cxfa_caption.h"
30 #include "xfa/fxfa/parser/cxfa_font.h"
31 #include "xfa/fxfa/parser/cxfa_items.h"
32 #include "xfa/fxfa/parser/cxfa_localevalue.h"
33 #include "xfa/fxfa/parser/cxfa_node.h"
34 #include "xfa/fxfa/parser/cxfa_para.h"
35 #include "xfa/fxfa/parser/cxfa_value.h"
36 #include "xfa/fxfa/parser/xfa_resolvenode_rs.h"
37 #include "xfa/fxfa/parser/xfa_utils.h"
38
GetTextNode(bool * bRichText)39 CXFA_Node* CXFA_TextProvider::GetTextNode(bool* bRichText) {
40 *bRichText = false;
41 if (m_eType == XFA_TEXTPROVIDERTYPE_Text) {
42 CXFA_Value* pValueNode =
43 m_pNode->GetChild<CXFA_Value>(0, XFA_Element::Value, false);
44 if (!pValueNode)
45 return nullptr;
46
47 CXFA_Node* pChildNode = pValueNode->GetFirstChild();
48 if (pChildNode && pChildNode->GetElementType() == XFA_Element::ExData) {
49 Optional<WideString> contentType = pChildNode->JSObject()->TryAttribute(
50 XFA_Attribute::ContentType, false);
51 if (contentType.has_value() &&
52 contentType.value().EqualsASCII("text/html")) {
53 *bRichText = true;
54 }
55 }
56 return pChildNode;
57 }
58
59 if (m_eType == XFA_TEXTPROVIDERTYPE_Datasets) {
60 CXFA_Node* pBind = m_pNode->GetBindData();
61 CFX_XMLNode* pXMLNode = pBind->GetXMLMappingNode();
62 for (CFX_XMLNode* pXMLChild = pXMLNode->GetFirstChild(); pXMLChild;
63 pXMLChild = pXMLChild->GetNextSibling()) {
64 CFX_XMLElement* pElement = ToXMLElement(pXMLChild);
65 if (pElement && XFA_RecognizeRichText(pElement)) {
66 *bRichText = true;
67 break;
68 }
69 }
70 return pBind;
71 }
72
73 if (m_eType == XFA_TEXTPROVIDERTYPE_Caption) {
74 CXFA_Caption* pCaptionNode =
75 m_pNode->GetChild<CXFA_Caption>(0, XFA_Element::Caption, false);
76 if (!pCaptionNode)
77 return nullptr;
78
79 CXFA_Value* pValueNode =
80 pCaptionNode->GetChild<CXFA_Value>(0, XFA_Element::Value, false);
81 if (!pValueNode)
82 return nullptr;
83
84 CXFA_Node* pChildNode = pValueNode->GetFirstChild();
85 if (pChildNode && pChildNode->GetElementType() == XFA_Element::ExData) {
86 Optional<WideString> contentType = pChildNode->JSObject()->TryAttribute(
87 XFA_Attribute::ContentType, false);
88 if (contentType.has_value() &&
89 contentType.value().EqualsASCII("text/html")) {
90 *bRichText = true;
91 }
92 }
93 return pChildNode;
94 }
95
96 CXFA_Items* pItemNode =
97 m_pNode->GetChild<CXFA_Items>(0, XFA_Element::Items, false);
98 if (!pItemNode)
99 return nullptr;
100
101 CXFA_Node* pNode = pItemNode->GetFirstChild();
102 while (pNode) {
103 WideString wsName = pNode->JSObject()->GetCData(XFA_Attribute::Name);
104 if (m_eType == XFA_TEXTPROVIDERTYPE_Rollover &&
105 wsName.EqualsASCII("rollover")) {
106 return pNode;
107 }
108 if (m_eType == XFA_TEXTPROVIDERTYPE_Down && wsName.EqualsASCII("down"))
109 return pNode;
110
111 pNode = pNode->GetNextSibling();
112 }
113 return nullptr;
114 }
115
GetParaIfExists()116 CXFA_Para* CXFA_TextProvider::GetParaIfExists() {
117 if (m_eType == XFA_TEXTPROVIDERTYPE_Text)
118 return m_pNode->GetParaIfExists();
119
120 CXFA_Caption* pNode =
121 m_pNode->GetChild<CXFA_Caption>(0, XFA_Element::Caption, false);
122 return pNode->GetChild<CXFA_Para>(0, XFA_Element::Para, false);
123 }
124
GetFontIfExists()125 CXFA_Font* CXFA_TextProvider::GetFontIfExists() {
126 if (m_eType == XFA_TEXTPROVIDERTYPE_Text)
127 return m_pNode->GetFontIfExists();
128
129 CXFA_Caption* pNode =
130 m_pNode->GetChild<CXFA_Caption>(0, XFA_Element::Caption, false);
131 CXFA_Font* font = pNode->GetChild<CXFA_Font>(0, XFA_Element::Font, false);
132 return font ? font : m_pNode->GetFontIfExists();
133 }
134
IsCheckButtonAndAutoWidth() const135 bool CXFA_TextProvider::IsCheckButtonAndAutoWidth() const {
136 if (m_pNode->GetFFWidgetType() != XFA_FFWidgetType::kCheckButton)
137 return false;
138 return !m_pNode->TryWidth();
139 }
140
GetEmbeddedObj(const WideString & wsAttr) const141 Optional<WideString> CXFA_TextProvider::GetEmbeddedObj(
142 const WideString& wsAttr) const {
143 if (m_eType != XFA_TEXTPROVIDERTYPE_Text)
144 return {};
145
146 CXFA_Node* pParent = m_pNode->GetParent();
147 CXFA_Document* pDocument = m_pNode->GetDocument();
148 CXFA_Node* pIDNode = nullptr;
149 if (pParent)
150 pIDNode = pDocument->GetNodeByID(pParent, wsAttr.AsStringView());
151
152 if (!pIDNode) {
153 pIDNode = pDocument->GetNodeByID(
154 ToNode(pDocument->GetXFAObject(XFA_HASHCODE_Form)),
155 wsAttr.AsStringView());
156 }
157 if (!pIDNode || !pIDNode->IsWidgetReady())
158 return {};
159
160 return pIDNode->GetValue(XFA_VALUEPICTURE_Display);
161 }
162