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_ffwidgethandler.h"
8 
9 #include <vector>
10 
11 #include "fxjs/xfa/cjx_object.h"
12 #include "xfa/fxfa/cxfa_ffdoc.h"
13 #include "xfa/fxfa/cxfa_ffdocview.h"
14 #include "xfa/fxfa/cxfa_fffield.h"
15 #include "xfa/fxfa/cxfa_ffwidget.h"
16 #include "xfa/fxfa/cxfa_fwladapterwidgetmgr.h"
17 #include "xfa/fxfa/layout/cxfa_layoutprocessor.h"
18 #include "xfa/fxfa/parser/cxfa_calculate.h"
19 #include "xfa/fxfa/parser/cxfa_checkbutton.h"
20 #include "xfa/fxfa/parser/cxfa_measurement.h"
21 #include "xfa/fxfa/parser/cxfa_node.h"
22 #include "xfa/fxfa/parser/cxfa_ui.h"
23 #include "xfa/fxfa/parser/cxfa_validate.h"
24 
CXFA_FFWidgetHandler(CXFA_FFDocView * pDocView)25 CXFA_FFWidgetHandler::CXFA_FFWidgetHandler(CXFA_FFDocView* pDocView)
26     : m_pDocView(pDocView) {}
27 
~CXFA_FFWidgetHandler()28 CXFA_FFWidgetHandler::~CXFA_FFWidgetHandler() {}
29 
OnMouseEnter(CXFA_FFWidget * hWidget)30 bool CXFA_FFWidgetHandler::OnMouseEnter(CXFA_FFWidget* hWidget) {
31   m_pDocView->LockUpdate();
32   bool bRet = hWidget->OnMouseEnter();
33   m_pDocView->UnlockUpdate();
34   m_pDocView->UpdateDocView();
35   return bRet;
36 }
37 
OnMouseExit(CXFA_FFWidget * hWidget)38 bool CXFA_FFWidgetHandler::OnMouseExit(CXFA_FFWidget* hWidget) {
39   m_pDocView->LockUpdate();
40   bool bRet = hWidget->OnMouseExit();
41   m_pDocView->UnlockUpdate();
42   m_pDocView->UpdateDocView();
43   return bRet;
44 }
45 
OnLButtonDown(CXFA_FFWidget * hWidget,uint32_t dwFlags,const CFX_PointF & point)46 bool CXFA_FFWidgetHandler::OnLButtonDown(CXFA_FFWidget* hWidget,
47                                          uint32_t dwFlags,
48                                          const CFX_PointF& point) {
49   m_pDocView->LockUpdate();
50   bool bRet = hWidget->AcceptsFocusOnButtonDown(
51       dwFlags, hWidget->Rotate2Normal(point), FWL_MouseCommand::LeftButtonDown);
52   if (bRet) {
53     if (m_pDocView->SetFocus(hWidget)) {
54       m_pDocView->GetDoc()->GetDocEnvironment()->SetFocusWidget(
55           m_pDocView->GetDoc(), hWidget);
56     }
57     bRet = hWidget->OnLButtonDown(dwFlags, hWidget->Rotate2Normal(point));
58   }
59   m_pDocView->UnlockUpdate();
60   m_pDocView->UpdateDocView();
61   return bRet;
62 }
63 
OnLButtonUp(CXFA_FFWidget * hWidget,uint32_t dwFlags,const CFX_PointF & point)64 bool CXFA_FFWidgetHandler::OnLButtonUp(CXFA_FFWidget* hWidget,
65                                        uint32_t dwFlags,
66                                        const CFX_PointF& point) {
67   m_pDocView->LockUpdate();
68   m_pDocView->m_bLayoutEvent = true;
69   bool bRet = hWidget->OnLButtonUp(dwFlags, hWidget->Rotate2Normal(point));
70   m_pDocView->UnlockUpdate();
71   m_pDocView->UpdateDocView();
72   return bRet;
73 }
74 
OnLButtonDblClk(CXFA_FFWidget * hWidget,uint32_t dwFlags,const CFX_PointF & point)75 bool CXFA_FFWidgetHandler::OnLButtonDblClk(CXFA_FFWidget* hWidget,
76                                            uint32_t dwFlags,
77                                            const CFX_PointF& point) {
78   bool bRet = hWidget->OnLButtonDblClk(dwFlags, hWidget->Rotate2Normal(point));
79   return bRet;
80 }
81 
OnMouseMove(CXFA_FFWidget * hWidget,uint32_t dwFlags,const CFX_PointF & point)82 bool CXFA_FFWidgetHandler::OnMouseMove(CXFA_FFWidget* hWidget,
83                                        uint32_t dwFlags,
84                                        const CFX_PointF& point) {
85   bool bRet = hWidget->OnMouseMove(dwFlags, hWidget->Rotate2Normal(point));
86   return bRet;
87 }
88 
OnMouseWheel(CXFA_FFWidget * hWidget,uint32_t dwFlags,int16_t zDelta,const CFX_PointF & point)89 bool CXFA_FFWidgetHandler::OnMouseWheel(CXFA_FFWidget* hWidget,
90                                         uint32_t dwFlags,
91                                         int16_t zDelta,
92                                         const CFX_PointF& point) {
93   bool bRet =
94       hWidget->OnMouseWheel(dwFlags, zDelta, hWidget->Rotate2Normal(point));
95   return bRet;
96 }
97 
OnRButtonDown(CXFA_FFWidget * hWidget,uint32_t dwFlags,const CFX_PointF & point)98 bool CXFA_FFWidgetHandler::OnRButtonDown(CXFA_FFWidget* hWidget,
99                                          uint32_t dwFlags,
100                                          const CFX_PointF& point) {
101   bool bRet =
102       hWidget->AcceptsFocusOnButtonDown(dwFlags, hWidget->Rotate2Normal(point),
103                                         FWL_MouseCommand::RightButtonDown);
104   if (bRet) {
105     if (m_pDocView->SetFocus(hWidget)) {
106       m_pDocView->GetDoc()->GetDocEnvironment()->SetFocusWidget(
107           m_pDocView->GetDoc(), hWidget);
108     }
109     bRet = hWidget->OnRButtonDown(dwFlags, hWidget->Rotate2Normal(point));
110   }
111   return bRet;
112 }
113 
OnRButtonUp(CXFA_FFWidget * hWidget,uint32_t dwFlags,const CFX_PointF & point)114 bool CXFA_FFWidgetHandler::OnRButtonUp(CXFA_FFWidget* hWidget,
115                                        uint32_t dwFlags,
116                                        const CFX_PointF& point) {
117   bool bRet = hWidget->OnRButtonUp(dwFlags, hWidget->Rotate2Normal(point));
118   return bRet;
119 }
120 
OnRButtonDblClk(CXFA_FFWidget * hWidget,uint32_t dwFlags,const CFX_PointF & point)121 bool CXFA_FFWidgetHandler::OnRButtonDblClk(CXFA_FFWidget* hWidget,
122                                            uint32_t dwFlags,
123                                            const CFX_PointF& point) {
124   bool bRet = hWidget->OnRButtonDblClk(dwFlags, hWidget->Rotate2Normal(point));
125   return bRet;
126 }
127 
OnKeyDown(CXFA_FFWidget * hWidget,uint32_t dwKeyCode,uint32_t dwFlags)128 bool CXFA_FFWidgetHandler::OnKeyDown(CXFA_FFWidget* hWidget,
129                                      uint32_t dwKeyCode,
130                                      uint32_t dwFlags) {
131   bool bRet = hWidget->OnKeyDown(dwKeyCode, dwFlags);
132   m_pDocView->UpdateDocView();
133   return bRet;
134 }
135 
OnKeyUp(CXFA_FFWidget * hWidget,uint32_t dwKeyCode,uint32_t dwFlags)136 bool CXFA_FFWidgetHandler::OnKeyUp(CXFA_FFWidget* hWidget,
137                                    uint32_t dwKeyCode,
138                                    uint32_t dwFlags) {
139   bool bRet = hWidget->OnKeyUp(dwKeyCode, dwFlags);
140   return bRet;
141 }
142 
OnChar(CXFA_FFWidget * hWidget,uint32_t dwChar,uint32_t dwFlags)143 bool CXFA_FFWidgetHandler::OnChar(CXFA_FFWidget* hWidget,
144                                   uint32_t dwChar,
145                                   uint32_t dwFlags) {
146   bool bRet = hWidget->OnChar(dwChar, dwFlags);
147   return bRet;
148 }
149 
GetText(CXFA_FFWidget * widget)150 WideString CXFA_FFWidgetHandler::GetText(CXFA_FFWidget* widget) {
151   return widget->GetText();
152 }
153 
GetSelectedText(CXFA_FFWidget * widget)154 WideString CXFA_FFWidgetHandler::GetSelectedText(CXFA_FFWidget* widget) {
155   if (!widget->CanCopy())
156     return WideString();
157 
158   return widget->Copy().value_or(WideString());
159 }
160 
PasteText(CXFA_FFWidget * widget,const WideString & text)161 void CXFA_FFWidgetHandler::PasteText(CXFA_FFWidget* widget,
162                                      const WideString& text) {
163   if (!widget->CanPaste())
164     return;
165 
166   widget->Paste(text);
167 }
168 
CanUndo(CXFA_FFWidget * widget)169 bool CXFA_FFWidgetHandler::CanUndo(CXFA_FFWidget* widget) {
170   return widget->CanUndo();
171 }
172 
CanRedo(CXFA_FFWidget * widget)173 bool CXFA_FFWidgetHandler::CanRedo(CXFA_FFWidget* widget) {
174   return widget->CanRedo();
175 }
176 
Undo(CXFA_FFWidget * widget)177 bool CXFA_FFWidgetHandler::Undo(CXFA_FFWidget* widget) {
178   return widget->Undo();
179 }
180 
Redo(CXFA_FFWidget * widget)181 bool CXFA_FFWidgetHandler::Redo(CXFA_FFWidget* widget) {
182   return widget->Redo();
183 }
184 
HitTest(CXFA_FFWidget * pWidget,const CFX_PointF & point)185 FWL_WidgetHit CXFA_FFWidgetHandler::HitTest(CXFA_FFWidget* pWidget,
186                                             const CFX_PointF& point) {
187   if (!pWidget->GetLayoutItem()->TestStatusBits(XFA_WidgetStatus_Visible))
188     return FWL_WidgetHit::Unknown;
189   return pWidget->HitTest(pWidget->Rotate2Normal(point));
190 }
191 
OnSetCursor(CXFA_FFWidget * hWidget,const CFX_PointF & point)192 bool CXFA_FFWidgetHandler::OnSetCursor(CXFA_FFWidget* hWidget,
193                                        const CFX_PointF& point) {
194   return hWidget->OnSetCursor(hWidget->Rotate2Normal(point));
195 }
196 
RenderWidget(CXFA_FFWidget * hWidget,CXFA_Graphics * pGS,const CFX_Matrix & matrix,bool bHighlight)197 void CXFA_FFWidgetHandler::RenderWidget(CXFA_FFWidget* hWidget,
198                                         CXFA_Graphics* pGS,
199                                         const CFX_Matrix& matrix,
200                                         bool bHighlight) {
201   hWidget->RenderWidget(
202       pGS, matrix,
203       bHighlight ? CXFA_FFWidget::kHighlight : CXFA_FFWidget::kNoHighlight);
204 }
205 
HasEvent(CXFA_Node * pNode,XFA_EVENTTYPE eEventType)206 bool CXFA_FFWidgetHandler::HasEvent(CXFA_Node* pNode,
207                                     XFA_EVENTTYPE eEventType) {
208   if (eEventType == XFA_EVENT_Unknown)
209     return false;
210   if (!pNode || pNode->GetElementType() == XFA_Element::Draw)
211     return false;
212 
213   switch (eEventType) {
214     case XFA_EVENT_Calculate: {
215       CXFA_Calculate* calc = pNode->GetCalculateIfExists();
216       return calc && calc->GetScriptIfExists();
217     }
218     case XFA_EVENT_Validate: {
219       CXFA_Validate* validate = pNode->GetValidateIfExists();
220       return validate && validate->GetScriptIfExists();
221     }
222     default:
223       break;
224   }
225   return !pNode->GetEventByActivity(gs_EventActivity[eEventType], false)
226               .empty();
227 }
228 
ProcessEvent(CXFA_Node * pNode,CXFA_EventParam * pParam)229 XFA_EventError CXFA_FFWidgetHandler::ProcessEvent(CXFA_Node* pNode,
230                                                   CXFA_EventParam* pParam) {
231   if (!pParam || pParam->m_eType == XFA_EVENT_Unknown)
232     return XFA_EventError::kNotExist;
233   if (!pNode || pNode->GetElementType() == XFA_Element::Draw)
234     return XFA_EventError::kNotExist;
235 
236   switch (pParam->m_eType) {
237     case XFA_EVENT_Calculate:
238       return pNode->ProcessCalculate(m_pDocView.Get());
239     case XFA_EVENT_Validate:
240       if (m_pDocView->GetDoc()->GetDocEnvironment()->IsValidationsEnabled(
241               m_pDocView->GetDoc())) {
242         return pNode->ProcessValidate(m_pDocView.Get(), 0);
243       }
244       return XFA_EventError::kDisabled;
245     case XFA_EVENT_InitCalculate: {
246       CXFA_Calculate* calc = pNode->GetCalculateIfExists();
247       if (!calc)
248         return XFA_EventError::kNotExist;
249       if (pNode->IsUserInteractive())
250         return XFA_EventError::kDisabled;
251       return pNode->ExecuteScript(m_pDocView.Get(), calc->GetScriptIfExists(),
252                                   pParam);
253     }
254     default:
255       break;
256   }
257   return pNode->ProcessEvent(m_pDocView.Get(),
258                              gs_EventActivity[pParam->m_eType], pParam);
259 }
260