• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "fpdfsdk/cpdfsdk_widget.h"
8 
9 #include <memory>
10 #include <sstream>
11 
12 #include "core/fpdfapi/parser/cpdf_array.h"
13 #include "core/fpdfapi/parser/cpdf_dictionary.h"
14 #include "core/fpdfapi/parser/cpdf_document.h"
15 #include "core/fpdfapi/parser/cpdf_reference.h"
16 #include "core/fpdfapi/parser/cpdf_stream.h"
17 #include "core/fpdfapi/parser/cpdf_string.h"
18 #include "core/fpdfdoc/cpdf_defaultappearance.h"
19 #include "core/fpdfdoc/cpdf_formcontrol.h"
20 #include "core/fpdfdoc/cpdf_formfield.h"
21 #include "core/fpdfdoc/cpdf_iconfit.h"
22 #include "core/fpdfdoc/cpdf_interform.h"
23 #include "core/fxge/cfx_graphstatedata.h"
24 #include "core/fxge/cfx_pathdata.h"
25 #include "core/fxge/cfx_renderdevice.h"
26 #include "fpdfsdk/cpdfsdk_formfillenvironment.h"
27 #include "fpdfsdk/cpdfsdk_interform.h"
28 #include "fpdfsdk/cpdfsdk_pageview.h"
29 #include "fpdfsdk/formfiller/cba_fontmap.h"
30 #include "fpdfsdk/fsdk_actionhandler.h"
31 #include "fpdfsdk/fsdk_define.h"
32 #include "fpdfsdk/pwl/cpwl_appstream.h"
33 #include "fpdfsdk/pwl/cpwl_edit.h"
34 
35 #ifdef PDF_ENABLE_XFA
36 #include "fpdfsdk/fpdfxfa/cpdfxfa_context.h"
37 #include "xfa/fxfa/cxfa_eventparam.h"
38 #include "xfa/fxfa/cxfa_ffdocview.h"
39 #include "xfa/fxfa/cxfa_ffwidget.h"
40 #include "xfa/fxfa/cxfa_ffwidgethandler.h"
41 #include "xfa/fxfa/cxfa_widgetacc.h"
42 #include "xfa/fxfa/parser/cxfa_node.h"
43 #endif  // PDF_ENABLE_XFA
44 
45 namespace {
46 
47 // Convert a FX_ARGB to a FX_COLORREF.
ARGBToColorRef(FX_ARGB argb)48 FX_COLORREF ARGBToColorRef(FX_ARGB argb) {
49   return (((static_cast<uint32_t>(argb) & 0x00FF0000) >> 16) |
50           (static_cast<uint32_t>(argb) & 0x0000FF00) |
51           ((static_cast<uint32_t>(argb) & 0x000000FF) << 16));
52 }
53 
54 }  // namespace
55 
CPDFSDK_Widget(CPDF_Annot * pAnnot,CPDFSDK_PageView * pPageView,CPDFSDK_InterForm * pInterForm)56 CPDFSDK_Widget::CPDFSDK_Widget(CPDF_Annot* pAnnot,
57                                CPDFSDK_PageView* pPageView,
58                                CPDFSDK_InterForm* pInterForm)
59     : CPDFSDK_BAAnnot(pAnnot, pPageView),
60       m_pInterForm(pInterForm),
61       m_nAppearanceAge(0),
62       m_nValueAge(0)
63 #ifdef PDF_ENABLE_XFA
64       ,
65       m_hMixXFAWidget(nullptr),
66       m_pWidgetHandler(nullptr)
67 #endif  // PDF_ENABLE_XFA
68 {
69 }
70 
~CPDFSDK_Widget()71 CPDFSDK_Widget::~CPDFSDK_Widget() {}
72 
73 #ifdef PDF_ENABLE_XFA
GetMixXFAWidget() const74 CXFA_FFWidget* CPDFSDK_Widget::GetMixXFAWidget() const {
75   CPDFXFA_Context* pContext = m_pPageView->GetFormFillEnv()->GetXFAContext();
76   if (pContext->GetFormType() == FormType::kXFAForeground) {
77     if (!m_hMixXFAWidget) {
78       if (CXFA_FFDocView* pDocView = pContext->GetXFADocView()) {
79         WideString sName;
80         if (GetFieldType() == FormFieldType::kRadioButton) {
81           sName = GetAnnotName();
82           if (sName.IsEmpty())
83             sName = GetName();
84         } else {
85           sName = GetName();
86         }
87 
88         if (!sName.IsEmpty())
89           m_hMixXFAWidget = pDocView->GetWidgetByName(sName, nullptr);
90       }
91     }
92     return m_hMixXFAWidget.Get();
93   }
94   return nullptr;
95 }
96 
GetGroupMixXFAWidget()97 CXFA_FFWidget* CPDFSDK_Widget::GetGroupMixXFAWidget() {
98   CPDFXFA_Context* pContext = m_pPageView->GetFormFillEnv()->GetXFAContext();
99   if (pContext->GetFormType() != FormType::kXFAForeground)
100     return nullptr;
101 
102   CXFA_FFDocView* pDocView = pContext->GetXFADocView();
103   if (!pDocView)
104     return nullptr;
105 
106   WideString sName = GetName();
107   return !sName.IsEmpty() ? pDocView->GetWidgetByName(sName, nullptr) : nullptr;
108 }
109 
GetXFAWidgetHandler() const110 CXFA_FFWidgetHandler* CPDFSDK_Widget::GetXFAWidgetHandler() const {
111   CPDFXFA_Context* pContext = m_pPageView->GetFormFillEnv()->GetXFAContext();
112   if (pContext->GetFormType() != FormType::kXFAForeground)
113     return nullptr;
114 
115   if (!m_pWidgetHandler) {
116     CXFA_FFDocView* pDocView = pContext->GetXFADocView();
117     if (pDocView)
118       m_pWidgetHandler = pDocView->GetWidgetHandler();
119   }
120   return m_pWidgetHandler.Get();
121 }
122 
GetXFAEventType(PDFSDK_XFAAActionType eXFAAAT)123 static XFA_EVENTTYPE GetXFAEventType(PDFSDK_XFAAActionType eXFAAAT) {
124   XFA_EVENTTYPE eEventType = XFA_EVENT_Unknown;
125 
126   switch (eXFAAAT) {
127     case PDFSDK_XFA_Click:
128       eEventType = XFA_EVENT_Click;
129       break;
130     case PDFSDK_XFA_Full:
131       eEventType = XFA_EVENT_Full;
132       break;
133     case PDFSDK_XFA_PreOpen:
134       eEventType = XFA_EVENT_PreOpen;
135       break;
136     case PDFSDK_XFA_PostOpen:
137       eEventType = XFA_EVENT_PostOpen;
138       break;
139   }
140 
141   return eEventType;
142 }
143 
GetXFAEventType(CPDF_AAction::AActionType eAAT,bool bWillCommit)144 static XFA_EVENTTYPE GetXFAEventType(CPDF_AAction::AActionType eAAT,
145                                      bool bWillCommit) {
146   XFA_EVENTTYPE eEventType = XFA_EVENT_Unknown;
147 
148   switch (eAAT) {
149     case CPDF_AAction::CursorEnter:
150       eEventType = XFA_EVENT_MouseEnter;
151       break;
152     case CPDF_AAction::CursorExit:
153       eEventType = XFA_EVENT_MouseExit;
154       break;
155     case CPDF_AAction::ButtonDown:
156       eEventType = XFA_EVENT_MouseDown;
157       break;
158     case CPDF_AAction::ButtonUp:
159       eEventType = XFA_EVENT_MouseUp;
160       break;
161     case CPDF_AAction::GetFocus:
162       eEventType = XFA_EVENT_Enter;
163       break;
164     case CPDF_AAction::LoseFocus:
165       eEventType = XFA_EVENT_Exit;
166       break;
167     case CPDF_AAction::PageOpen:
168     case CPDF_AAction::PageClose:
169     case CPDF_AAction::PageVisible:
170     case CPDF_AAction::PageInvisible:
171       break;
172     case CPDF_AAction::KeyStroke:
173       if (!bWillCommit)
174         eEventType = XFA_EVENT_Change;
175       break;
176     case CPDF_AAction::Validate:
177       eEventType = XFA_EVENT_Validate;
178       break;
179     case CPDF_AAction::OpenPage:
180     case CPDF_AAction::ClosePage:
181     case CPDF_AAction::Format:
182     case CPDF_AAction::Calculate:
183     case CPDF_AAction::CloseDocument:
184     case CPDF_AAction::SaveDocument:
185     case CPDF_AAction::DocumentSaved:
186     case CPDF_AAction::PrintDocument:
187     case CPDF_AAction::DocumentPrinted:
188       break;
189     case CPDF_AAction::NumberOfActions:
190       NOTREACHED();
191       break;
192   }
193 
194   return eEventType;
195 }
196 
HasXFAAAction(PDFSDK_XFAAActionType eXFAAAT)197 bool CPDFSDK_Widget::HasXFAAAction(PDFSDK_XFAAActionType eXFAAAT) {
198   CXFA_FFWidget* hWidget = GetMixXFAWidget();
199   if (!hWidget)
200     return false;
201 
202   CXFA_FFWidgetHandler* pXFAWidgetHandler = GetXFAWidgetHandler();
203   if (!pXFAWidgetHandler)
204     return false;
205 
206   XFA_EVENTTYPE eEventType = GetXFAEventType(eXFAAAT);
207 
208   if ((eEventType == XFA_EVENT_Click || eEventType == XFA_EVENT_Change) &&
209       GetFieldType() == FormFieldType::kRadioButton) {
210     if (CXFA_FFWidget* hGroupWidget = GetGroupMixXFAWidget()) {
211       if (pXFAWidgetHandler->HasEvent(hGroupWidget->GetNode()->GetWidgetAcc(),
212                                       eEventType)) {
213         return true;
214       }
215     }
216   }
217 
218   return pXFAWidgetHandler->HasEvent(hWidget->GetNode()->GetWidgetAcc(),
219                                      eEventType);
220 }
221 
OnXFAAAction(PDFSDK_XFAAActionType eXFAAAT,PDFSDK_FieldAction & data,CPDFSDK_PageView * pPageView)222 bool CPDFSDK_Widget::OnXFAAAction(PDFSDK_XFAAActionType eXFAAAT,
223                                   PDFSDK_FieldAction& data,
224                                   CPDFSDK_PageView* pPageView) {
225   CPDFXFA_Context* pContext = m_pPageView->GetFormFillEnv()->GetXFAContext();
226 
227   CXFA_FFWidget* hWidget = GetMixXFAWidget();
228   if (!hWidget)
229     return false;
230 
231   XFA_EVENTTYPE eEventType = GetXFAEventType(eXFAAAT);
232   if (eEventType == XFA_EVENT_Unknown)
233     return false;
234 
235   CXFA_FFWidgetHandler* pXFAWidgetHandler = GetXFAWidgetHandler();
236   if (!pXFAWidgetHandler)
237     return false;
238 
239   CXFA_EventParam param;
240   param.m_eType = eEventType;
241   param.m_wsChange = data.sChange;
242   param.m_iCommitKey = data.nCommitKey;
243   param.m_bShift = data.bShift;
244   param.m_iSelStart = data.nSelStart;
245   param.m_iSelEnd = data.nSelEnd;
246   param.m_wsFullText = data.sValue;
247   param.m_bKeyDown = data.bKeyDown;
248   param.m_bModifier = data.bModifier;
249   param.m_wsNewText = data.sValue;
250   if (data.nSelEnd > data.nSelStart)
251     param.m_wsNewText.Delete(data.nSelStart, data.nSelEnd - data.nSelStart);
252 
253   for (const auto& c : data.sChange)
254     param.m_wsNewText.Insert(data.nSelStart, c);
255 
256   param.m_wsPrevText = data.sValue;
257   if ((eEventType == XFA_EVENT_Click || eEventType == XFA_EVENT_Change) &&
258       GetFieldType() == FormFieldType::kRadioButton) {
259     if (CXFA_FFWidget* hGroupWidget = GetGroupMixXFAWidget()) {
260       CXFA_WidgetAcc* pAcc = hGroupWidget->GetNode()->GetWidgetAcc();
261       param.m_pTarget = pAcc;
262       if (pXFAWidgetHandler->ProcessEvent(pAcc, &param) !=
263           XFA_EVENTERROR_Success) {
264         return false;
265       }
266     }
267   }
268   CXFA_WidgetAcc* pAcc = hWidget->GetNode()->GetWidgetAcc();
269   param.m_pTarget = pAcc;
270   int32_t nRet = pXFAWidgetHandler->ProcessEvent(pAcc, &param);
271 
272   if (CXFA_FFDocView* pDocView = pContext->GetXFADocView())
273     pDocView->UpdateDocView();
274 
275   return nRet == XFA_EVENTERROR_Success;
276 }
277 
Synchronize(bool bSynchronizeElse)278 void CPDFSDK_Widget::Synchronize(bool bSynchronizeElse) {
279   CXFA_FFWidget* hWidget = GetMixXFAWidget();
280   if (!hWidget)
281     return;
282 
283   CXFA_WidgetAcc* pWidgetAcc = hWidget->GetNode()->GetWidgetAcc();
284   if (!pWidgetAcc)
285     return;
286 
287   CPDF_FormField* pFormField = GetFormField();
288   switch (GetFieldType()) {
289     case FormFieldType::kCheckBox:
290     case FormFieldType::kRadioButton: {
291       CPDF_FormControl* pFormCtrl = GetFormControl();
292       XFA_CHECKSTATE eCheckState =
293           pFormCtrl->IsChecked() ? XFA_CHECKSTATE_On : XFA_CHECKSTATE_Off;
294       pWidgetAcc->SetCheckState(eCheckState, true);
295       break;
296     }
297     case FormFieldType::kTextField:
298       pWidgetAcc->SetValue(XFA_VALUEPICTURE_Edit, pFormField->GetValue());
299       break;
300     case FormFieldType::kListBox: {
301       pWidgetAcc->ClearAllSelections();
302 
303       for (int i = 0, sz = pFormField->CountSelectedItems(); i < sz; i++) {
304         int nIndex = pFormField->GetSelectedIndex(i);
305         if (nIndex > -1 && nIndex < pWidgetAcc->CountChoiceListItems(false))
306           pWidgetAcc->SetItemState(nIndex, true, false, false, true);
307       }
308       break;
309     }
310     case FormFieldType::kComboBox: {
311       pWidgetAcc->ClearAllSelections();
312 
313       for (int i = 0, sz = pFormField->CountSelectedItems(); i < sz; i++) {
314         int nIndex = pFormField->GetSelectedIndex(i);
315         if (nIndex > -1 && nIndex < pWidgetAcc->CountChoiceListItems(false))
316           pWidgetAcc->SetItemState(nIndex, true, false, false, true);
317       }
318       pWidgetAcc->SetValue(XFA_VALUEPICTURE_Edit, pFormField->GetValue());
319       break;
320     }
321     default:
322       break;
323   }
324 
325   if (bSynchronizeElse) {
326     CPDFXFA_Context* context = m_pPageView->GetFormFillEnv()->GetXFAContext();
327     context->GetXFADocView()->ProcessValueChanged(pWidgetAcc);
328   }
329 }
330 
SynchronizeXFAValue()331 void CPDFSDK_Widget::SynchronizeXFAValue() {
332   CPDFXFA_Context* pContext = m_pPageView->GetFormFillEnv()->GetXFAContext();
333   CXFA_FFDocView* pXFADocView = pContext->GetXFADocView();
334   if (!pXFADocView)
335     return;
336 
337   if (CXFA_FFWidget* hWidget = GetMixXFAWidget()) {
338     if (GetXFAWidgetHandler()) {
339       CPDFSDK_Widget::SynchronizeXFAValue(pXFADocView, hWidget, GetFormField(),
340                                           GetFormControl());
341     }
342   }
343 }
344 
SynchronizeXFAItems()345 void CPDFSDK_Widget::SynchronizeXFAItems() {
346   CPDFXFA_Context* pContext = m_pPageView->GetFormFillEnv()->GetXFAContext();
347   CXFA_FFDocView* pXFADocView = pContext->GetXFADocView();
348   if (!pXFADocView)
349     return;
350 
351   if (CXFA_FFWidget* hWidget = GetMixXFAWidget()) {
352     if (GetXFAWidgetHandler())
353       SynchronizeXFAItems(pXFADocView, hWidget, GetFormField(), nullptr);
354   }
355 }
356 
SynchronizeXFAValue(CXFA_FFDocView * pXFADocView,CXFA_FFWidget * hWidget,CPDF_FormField * pFormField,CPDF_FormControl * pFormControl)357 void CPDFSDK_Widget::SynchronizeXFAValue(CXFA_FFDocView* pXFADocView,
358                                          CXFA_FFWidget* hWidget,
359                                          CPDF_FormField* pFormField,
360                                          CPDF_FormControl* pFormControl) {
361   ASSERT(hWidget);
362   ASSERT(pFormControl);
363 
364   switch (pFormField->GetFieldType()) {
365     case FormFieldType::kCheckBox: {
366       if (CXFA_WidgetAcc* pWidgetAcc = hWidget->GetNode()->GetWidgetAcc()) {
367         pFormField->CheckControl(
368             pFormField->GetControlIndex(pFormControl),
369             pWidgetAcc->GetCheckState() == XFA_CHECKSTATE_On, true);
370       }
371       break;
372     }
373     case FormFieldType::kRadioButton: {
374       // TODO(weili): Check whether we need to handle checkbox and radio
375       // button differently, otherwise, merge these two cases.
376       if (CXFA_WidgetAcc* pWidgetAcc = hWidget->GetNode()->GetWidgetAcc()) {
377         pFormField->CheckControl(
378             pFormField->GetControlIndex(pFormControl),
379             pWidgetAcc->GetCheckState() == XFA_CHECKSTATE_On, true);
380       }
381       break;
382     }
383     case FormFieldType::kTextField: {
384       if (CXFA_WidgetAcc* pWidgetAcc = hWidget->GetNode()->GetWidgetAcc()) {
385         pFormField->SetValue(pWidgetAcc->GetValue(XFA_VALUEPICTURE_Display),
386                              true);
387       }
388       break;
389     }
390     case FormFieldType::kListBox: {
391       pFormField->ClearSelection(false);
392 
393       if (CXFA_WidgetAcc* pWidgetAcc = hWidget->GetNode()->GetWidgetAcc()) {
394         for (int i = 0, sz = pWidgetAcc->CountSelectedItems(); i < sz; i++) {
395           int nIndex = pWidgetAcc->GetSelectedItem(i);
396 
397           if (nIndex > -1 && nIndex < pFormField->CountOptions()) {
398             pFormField->SetItemSelection(nIndex, true, true);
399           }
400         }
401       }
402       break;
403     }
404     case FormFieldType::kComboBox: {
405       pFormField->ClearSelection(false);
406 
407       if (CXFA_WidgetAcc* pWidgetAcc = hWidget->GetNode()->GetWidgetAcc()) {
408         for (int i = 0, sz = pWidgetAcc->CountSelectedItems(); i < sz; i++) {
409           int nIndex = pWidgetAcc->GetSelectedItem(i);
410 
411           if (nIndex > -1 && nIndex < pFormField->CountOptions()) {
412             pFormField->SetItemSelection(nIndex, true, true);
413           }
414         }
415         pFormField->SetValue(pWidgetAcc->GetValue(XFA_VALUEPICTURE_Display),
416                              true);
417       }
418       break;
419     }
420     default:
421       break;
422   }
423 }
424 
SynchronizeXFAItems(CXFA_FFDocView * pXFADocView,CXFA_FFWidget * hWidget,CPDF_FormField * pFormField,CPDF_FormControl * pFormControl)425 void CPDFSDK_Widget::SynchronizeXFAItems(CXFA_FFDocView* pXFADocView,
426                                          CXFA_FFWidget* hWidget,
427                                          CPDF_FormField* pFormField,
428                                          CPDF_FormControl* pFormControl) {
429   ASSERT(hWidget);
430 
431   switch (pFormField->GetFieldType()) {
432     case FormFieldType::kListBox: {
433       pFormField->ClearSelection(false);
434       pFormField->ClearOptions(true);
435 
436       if (CXFA_WidgetAcc* pWidgetAcc = hWidget->GetNode()->GetWidgetAcc()) {
437         for (int i = 0, sz = pWidgetAcc->CountChoiceListItems(false); i < sz;
438              i++) {
439           pFormField->InsertOption(
440               pWidgetAcc->GetChoiceListItem(i, false).value_or(L""), i, true);
441         }
442       }
443       break;
444     }
445     case FormFieldType::kComboBox: {
446       pFormField->ClearSelection(false);
447       pFormField->ClearOptions(false);
448 
449       if (CXFA_WidgetAcc* pWidgetAcc = hWidget->GetNode()->GetWidgetAcc()) {
450         for (int i = 0, sz = pWidgetAcc->CountChoiceListItems(false); i < sz;
451              i++) {
452           pFormField->InsertOption(
453               pWidgetAcc->GetChoiceListItem(i, false).value_or(L""), i, false);
454         }
455       }
456 
457       pFormField->SetValue(L"", true);
458       break;
459     }
460     default:
461       break;
462   }
463 }
464 #endif  // PDF_ENABLE_XFA
465 
IsWidgetAppearanceValid(CPDF_Annot::AppearanceMode mode)466 bool CPDFSDK_Widget::IsWidgetAppearanceValid(CPDF_Annot::AppearanceMode mode) {
467   CPDF_Dictionary* pAP = m_pAnnot->GetAnnotDict()->GetDictFor("AP");
468   if (!pAP)
469     return false;
470 
471   // Choose the right sub-ap
472   const char* ap_entry = "N";
473   if (mode == CPDF_Annot::Down)
474     ap_entry = "D";
475   else if (mode == CPDF_Annot::Rollover)
476     ap_entry = "R";
477   if (!pAP->KeyExist(ap_entry))
478     ap_entry = "N";
479 
480   // Get the AP stream or subdirectory
481   CPDF_Object* psub = pAP->GetDirectObjectFor(ap_entry);
482   if (!psub)
483     return false;
484 
485   FormFieldType fieldType = GetFieldType();
486   switch (fieldType) {
487     case FormFieldType::kPushButton:
488     case FormFieldType::kComboBox:
489     case FormFieldType::kListBox:
490     case FormFieldType::kTextField:
491     case FormFieldType::kSignature:
492       return psub->IsStream();
493     case FormFieldType::kCheckBox:
494     case FormFieldType::kRadioButton:
495       if (CPDF_Dictionary* pSubDict = psub->AsDictionary()) {
496         return !!pSubDict->GetStreamFor(GetAppState());
497       }
498       return false;
499     default:
500       return true;
501   }
502 }
503 
GetFieldType() const504 FormFieldType CPDFSDK_Widget::GetFieldType() const {
505   CPDF_FormField* pField = GetFormField();
506   return pField ? pField->GetFieldType() : FormFieldType::kUnknown;
507 }
508 
IsAppearanceValid()509 bool CPDFSDK_Widget::IsAppearanceValid() {
510 #ifdef PDF_ENABLE_XFA
511   CPDFXFA_Context* pContext = m_pPageView->GetFormFillEnv()->GetXFAContext();
512   FormType formType = pContext->GetFormType();
513   if (formType == FormType::kXFAFull)
514     return true;
515 #endif  // PDF_ENABLE_XFA
516   return CPDFSDK_BAAnnot::IsAppearanceValid();
517 }
518 
GetLayoutOrder() const519 int CPDFSDK_Widget::GetLayoutOrder() const {
520   return 2;
521 }
522 
GetFieldFlags() const523 int CPDFSDK_Widget::GetFieldFlags() const {
524   CPDF_InterForm* pPDFInterForm = m_pInterForm->GetInterForm();
525   CPDF_FormControl* pFormControl =
526       pPDFInterForm->GetControlByDict(m_pAnnot->GetAnnotDict());
527   CPDF_FormField* pFormField = pFormControl->GetField();
528   return pFormField->GetFieldFlags();
529 }
530 
IsSignatureWidget() const531 bool CPDFSDK_Widget::IsSignatureWidget() const {
532   return GetFieldType() == FormFieldType::kSignature;
533 }
534 
GetFormField() const535 CPDF_FormField* CPDFSDK_Widget::GetFormField() const {
536   CPDF_FormControl* pControl = GetFormControl();
537   return pControl ? pControl->GetField() : nullptr;
538 }
539 
GetFormControl() const540 CPDF_FormControl* CPDFSDK_Widget::GetFormControl() const {
541   CPDF_InterForm* pPDFInterForm = m_pInterForm->GetInterForm();
542   return pPDFInterForm->GetControlByDict(GetAnnotDict());
543 }
544 
GetFormControl(CPDF_InterForm * pInterForm,const CPDF_Dictionary * pAnnotDict)545 CPDF_FormControl* CPDFSDK_Widget::GetFormControl(
546     CPDF_InterForm* pInterForm,
547     const CPDF_Dictionary* pAnnotDict) {
548   ASSERT(pAnnotDict);
549   return pInterForm->GetControlByDict(pAnnotDict);
550 }
551 
GetRotate() const552 int CPDFSDK_Widget::GetRotate() const {
553   CPDF_FormControl* pCtrl = GetFormControl();
554   return pCtrl->GetRotation() % 360;
555 }
556 
557 #ifdef PDF_ENABLE_XFA
GetName() const558 WideString CPDFSDK_Widget::GetName() const {
559   CPDF_FormField* pFormField = GetFormField();
560   return pFormField->GetFullName();
561 }
562 #endif  // PDF_ENABLE_XFA
563 
GetFillColor(FX_COLORREF & color) const564 bool CPDFSDK_Widget::GetFillColor(FX_COLORREF& color) const {
565   CPDF_FormControl* pFormCtrl = GetFormControl();
566   int iColorType = 0;
567   color = ARGBToColorRef(pFormCtrl->GetBackgroundColor(iColorType));
568   return iColorType != CFX_Color::kTransparent;
569 }
570 
GetBorderColor(FX_COLORREF & color) const571 bool CPDFSDK_Widget::GetBorderColor(FX_COLORREF& color) const {
572   CPDF_FormControl* pFormCtrl = GetFormControl();
573   int iColorType = 0;
574   color = ARGBToColorRef(pFormCtrl->GetBorderColor(iColorType));
575   return iColorType != CFX_Color::kTransparent;
576 }
577 
GetTextColor(FX_COLORREF & color) const578 bool CPDFSDK_Widget::GetTextColor(FX_COLORREF& color) const {
579   CPDF_FormControl* pFormCtrl = GetFormControl();
580   CPDF_DefaultAppearance da = pFormCtrl->GetDefaultAppearance();
581   if (!da.HasColor())
582     return false;
583 
584   FX_ARGB argb;
585   int iColorType = CFX_Color::kTransparent;
586   da.GetColor(argb, iColorType);
587   color = ARGBToColorRef(argb);
588   return iColorType != CFX_Color::kTransparent;
589 }
590 
GetFontSize() const591 float CPDFSDK_Widget::GetFontSize() const {
592   CPDF_FormControl* pFormCtrl = GetFormControl();
593   CPDF_DefaultAppearance pDa = pFormCtrl->GetDefaultAppearance();
594   float fFontSize;
595   pDa.GetFont(&fFontSize);
596   return fFontSize;
597 }
598 
GetSelectedIndex(int nIndex) const599 int CPDFSDK_Widget::GetSelectedIndex(int nIndex) const {
600 #ifdef PDF_ENABLE_XFA
601   if (CXFA_FFWidget* hWidget = GetMixXFAWidget()) {
602     if (CXFA_WidgetAcc* pWidgetAcc = hWidget->GetNode()->GetWidgetAcc()) {
603       if (nIndex < pWidgetAcc->CountSelectedItems())
604         return pWidgetAcc->GetSelectedItem(nIndex);
605     }
606   }
607 #endif  // PDF_ENABLE_XFA
608   CPDF_FormField* pFormField = GetFormField();
609   return pFormField->GetSelectedIndex(nIndex);
610 }
611 
612 #ifdef PDF_ENABLE_XFA
GetValue(bool bDisplay) const613 WideString CPDFSDK_Widget::GetValue(bool bDisplay) const {
614   if (CXFA_FFWidget* hWidget = GetMixXFAWidget()) {
615     if (CXFA_WidgetAcc* pWidgetAcc = hWidget->GetNode()->GetWidgetAcc()) {
616       return pWidgetAcc->GetValue(bDisplay ? XFA_VALUEPICTURE_Display
617                                            : XFA_VALUEPICTURE_Edit);
618     }
619   }
620 #else
621 WideString CPDFSDK_Widget::GetValue() const {
622 #endif  // PDF_ENABLE_XFA
623   CPDF_FormField* pFormField = GetFormField();
624   return pFormField->GetValue();
625 }
626 
627 WideString CPDFSDK_Widget::GetDefaultValue() const {
628   CPDF_FormField* pFormField = GetFormField();
629   return pFormField->GetDefaultValue();
630 }
631 
632 WideString CPDFSDK_Widget::GetOptionLabel(int nIndex) const {
633   CPDF_FormField* pFormField = GetFormField();
634   return pFormField->GetOptionLabel(nIndex);
635 }
636 
637 int CPDFSDK_Widget::CountOptions() const {
638   CPDF_FormField* pFormField = GetFormField();
639   return pFormField->CountOptions();
640 }
641 
642 bool CPDFSDK_Widget::IsOptionSelected(int nIndex) const {
643 #ifdef PDF_ENABLE_XFA
644   if (CXFA_FFWidget* hWidget = GetMixXFAWidget()) {
645     if (CXFA_WidgetAcc* pWidgetAcc = hWidget->GetNode()->GetWidgetAcc()) {
646       if (nIndex > -1 && nIndex < pWidgetAcc->CountChoiceListItems(false))
647         return pWidgetAcc->GetItemState(nIndex);
648 
649       return false;
650     }
651   }
652 #endif  // PDF_ENABLE_XFA
653   CPDF_FormField* pFormField = GetFormField();
654   return pFormField->IsItemSelected(nIndex);
655 }
656 
657 int CPDFSDK_Widget::GetTopVisibleIndex() const {
658   CPDF_FormField* pFormField = GetFormField();
659   return pFormField->GetTopVisibleIndex();
660 }
661 
662 bool CPDFSDK_Widget::IsChecked() const {
663 #ifdef PDF_ENABLE_XFA
664   if (CXFA_FFWidget* hWidget = GetMixXFAWidget()) {
665     if (CXFA_WidgetAcc* pWidgetAcc = hWidget->GetNode()->GetWidgetAcc())
666       return pWidgetAcc->GetCheckState() == XFA_CHECKSTATE_On;
667   }
668 #endif  // PDF_ENABLE_XFA
669   CPDF_FormControl* pFormCtrl = GetFormControl();
670   return pFormCtrl->IsChecked();
671 }
672 
673 int CPDFSDK_Widget::GetAlignment() const {
674   CPDF_FormControl* pFormCtrl = GetFormControl();
675   return pFormCtrl->GetControlAlignment();
676 }
677 
678 int CPDFSDK_Widget::GetMaxLen() const {
679   CPDF_FormField* pFormField = GetFormField();
680   return pFormField->GetMaxLen();
681 }
682 
683 void CPDFSDK_Widget::SetCheck(bool bChecked, bool bNotify) {
684   CPDF_FormControl* pFormCtrl = GetFormControl();
685   CPDF_FormField* pFormField = pFormCtrl->GetField();
686   pFormField->CheckControl(pFormField->GetControlIndex(pFormCtrl), bChecked,
687                            bNotify);
688 #ifdef PDF_ENABLE_XFA
689   if (!IsWidgetAppearanceValid(CPDF_Annot::Normal))
690     ResetAppearance(true);
691   if (!bNotify)
692     Synchronize(true);
693 #endif  // PDF_ENABLE_XFA
694 }
695 
696 void CPDFSDK_Widget::SetValue(const WideString& sValue, bool bNotify) {
697   CPDF_FormField* pFormField = GetFormField();
698   pFormField->SetValue(sValue, bNotify);
699 #ifdef PDF_ENABLE_XFA
700   if (!bNotify)
701     Synchronize(true);
702 #endif  // PDF_ENABLE_XFA
703 }
704 
705 void CPDFSDK_Widget::SetDefaultValue(const WideString& sValue) {}
706 void CPDFSDK_Widget::SetOptionSelection(int index,
707                                         bool bSelected,
708                                         bool bNotify) {
709   CPDF_FormField* pFormField = GetFormField();
710   pFormField->SetItemSelection(index, bSelected, bNotify);
711 #ifdef PDF_ENABLE_XFA
712   if (!bNotify)
713     Synchronize(true);
714 #endif  // PDF_ENABLE_XFA
715 }
716 
717 void CPDFSDK_Widget::ClearSelection(bool bNotify) {
718   CPDF_FormField* pFormField = GetFormField();
719   pFormField->ClearSelection(bNotify);
720 #ifdef PDF_ENABLE_XFA
721   if (!bNotify)
722     Synchronize(true);
723 #endif  // PDF_ENABLE_XFA
724 }
725 
726 void CPDFSDK_Widget::SetTopVisibleIndex(int index) {}
727 
728 void CPDFSDK_Widget::SetAppModified() {
729   m_bAppModified = true;
730 }
731 
732 void CPDFSDK_Widget::ClearAppModified() {
733   m_bAppModified = false;
734 }
735 
736 bool CPDFSDK_Widget::IsAppModified() const {
737   return m_bAppModified;
738 }
739 
740 #ifdef PDF_ENABLE_XFA
741 void CPDFSDK_Widget::ResetAppearance(bool bValueChanged) {
742   switch (GetFieldType()) {
743     case FormFieldType::kTextField:
744     case FormFieldType::kComboBox: {
745       bool bFormatted = false;
746       WideString sValue = OnFormat(bFormatted);
747       ResetAppearance(bFormatted ? &sValue : nullptr, true);
748       break;
749     }
750     default:
751       ResetAppearance(nullptr, false);
752       break;
753   }
754 }
755 #endif  // PDF_ENABLE_XFA
756 
757 void CPDFSDK_Widget::ResetAppearance(const WideString* sValue,
758                                      bool bValueChanged) {
759   SetAppModified();
760 
761   m_nAppearanceAge++;
762   if (bValueChanged)
763     m_nValueAge++;
764 
765   CPWL_AppStream appStream(this, GetAPDict());
766   switch (GetFieldType()) {
767     case FormFieldType::kPushButton:
768       appStream.SetAsPushButton();
769       break;
770     case FormFieldType::kCheckBox:
771       appStream.SetAsCheckBox();
772       break;
773     case FormFieldType::kRadioButton:
774       appStream.SetAsRadioButton();
775       break;
776     case FormFieldType::kComboBox:
777       appStream.SetAsComboBox(sValue);
778       break;
779     case FormFieldType::kListBox:
780       appStream.SetAsListBox();
781       break;
782     case FormFieldType::kTextField:
783       appStream.SetAsTextField(sValue);
784       break;
785     default:
786       break;
787   }
788 
789   m_pAnnot->ClearCachedAP();
790 }
791 
792 WideString CPDFSDK_Widget::OnFormat(bool& bFormatted) {
793   CPDF_FormField* pFormField = GetFormField();
794   ASSERT(pFormField);
795   return m_pInterForm->OnFormat(pFormField, bFormatted);
796 }
797 
798 void CPDFSDK_Widget::ResetFieldAppearance(bool bValueChanged) {
799   CPDF_FormField* pFormField = GetFormField();
800   ASSERT(pFormField);
801   m_pInterForm->ResetFieldAppearance(pFormField, nullptr, bValueChanged);
802 }
803 
804 void CPDFSDK_Widget::DrawAppearance(CFX_RenderDevice* pDevice,
805                                     const CFX_Matrix& mtUser2Device,
806                                     CPDF_Annot::AppearanceMode mode,
807                                     const CPDF_RenderOptions* pOptions) {
808   FormFieldType fieldType = GetFieldType();
809 
810   if ((fieldType == FormFieldType::kCheckBox ||
811        fieldType == FormFieldType::kRadioButton) &&
812       mode == CPDF_Annot::Normal &&
813       !IsWidgetAppearanceValid(CPDF_Annot::Normal)) {
814     CFX_PathData pathData;
815 
816     CFX_FloatRect rcAnnot = GetRect();
817 
818     pathData.AppendRect(rcAnnot.left, rcAnnot.bottom, rcAnnot.right,
819                         rcAnnot.top);
820 
821     CFX_GraphStateData gsd;
822     gsd.m_LineWidth = 0.0f;
823 
824     pDevice->DrawPath(&pathData, &mtUser2Device, &gsd, 0, 0xFFAAAAAA,
825                       FXFILL_ALTERNATE);
826   } else {
827     CPDFSDK_BAAnnot::DrawAppearance(pDevice, mtUser2Device, mode, pOptions);
828   }
829 }
830 
831 void CPDFSDK_Widget::UpdateField() {
832   CPDF_FormField* pFormField = GetFormField();
833   ASSERT(pFormField);
834   m_pInterForm->UpdateField(pFormField);
835 }
836 
837 void CPDFSDK_Widget::DrawShadow(CFX_RenderDevice* pDevice,
838                                 CPDFSDK_PageView* pPageView) {
839   FormFieldType fieldType = GetFieldType();
840   if (!m_pInterForm->IsNeedHighLight(fieldType))
841     return;
842 
843   CFX_Matrix page2device;
844   pPageView->GetCurrentMatrix(page2device);
845 
846   CFX_FloatRect rcDevice = GetRect();
847   CFX_PointF tmp =
848       page2device.Transform(CFX_PointF(rcDevice.left, rcDevice.bottom));
849   rcDevice.left = tmp.x;
850   rcDevice.bottom = tmp.y;
851 
852   tmp = page2device.Transform(CFX_PointF(rcDevice.right, rcDevice.top));
853   rcDevice.right = tmp.x;
854   rcDevice.top = tmp.y;
855   rcDevice.Normalize();
856 
857   FX_RECT rcDev = rcDevice.ToFxRect();
858   pDevice->FillRect(
859       &rcDev, ArgbEncode(static_cast<int>(m_pInterForm->GetHighlightAlpha()),
860                          m_pInterForm->GetHighlightColor(fieldType)));
861 }
862 
863 CFX_FloatRect CPDFSDK_Widget::GetClientRect() const {
864   CFX_FloatRect rcWindow = GetRotatedRect();
865   float fBorderWidth = (float)GetBorderWidth();
866   switch (GetBorderStyle()) {
867     case BorderStyle::BEVELED:
868     case BorderStyle::INSET:
869       fBorderWidth *= 2.0f;
870       break;
871     default:
872       break;
873   }
874   return rcWindow.GetDeflated(fBorderWidth, fBorderWidth);
875 }
876 
877 CFX_FloatRect CPDFSDK_Widget::GetRotatedRect() const {
878   CFX_FloatRect rectAnnot = GetRect();
879   float fWidth = rectAnnot.right - rectAnnot.left;
880   float fHeight = rectAnnot.top - rectAnnot.bottom;
881 
882   CPDF_FormControl* pControl = GetFormControl();
883   CFX_FloatRect rcPDFWindow;
884   switch (abs(pControl->GetRotation() % 360)) {
885     case 0:
886     case 180:
887     default:
888       rcPDFWindow = CFX_FloatRect(0, 0, fWidth, fHeight);
889       break;
890     case 90:
891     case 270:
892       rcPDFWindow = CFX_FloatRect(0, 0, fHeight, fWidth);
893       break;
894   }
895 
896   return rcPDFWindow;
897 }
898 
899 CFX_Matrix CPDFSDK_Widget::GetMatrix() const {
900   CFX_Matrix mt;
901   CPDF_FormControl* pControl = GetFormControl();
902   CFX_FloatRect rcAnnot = GetRect();
903   float fWidth = rcAnnot.right - rcAnnot.left;
904   float fHeight = rcAnnot.top - rcAnnot.bottom;
905 
906   switch (abs(pControl->GetRotation() % 360)) {
907     default:
908     case 0:
909       break;
910     case 90:
911       mt = CFX_Matrix(0, 1, -1, 0, fWidth, 0);
912       break;
913     case 180:
914       mt = CFX_Matrix(-1, 0, 0, -1, fWidth, fHeight);
915       break;
916     case 270:
917       mt = CFX_Matrix(0, -1, 1, 0, 0, fHeight);
918       break;
919   }
920 
921   return mt;
922 }
923 
924 CFX_Color CPDFSDK_Widget::GetTextPWLColor() const {
925   CFX_Color crText = CFX_Color(CFX_Color::kGray, 0);
926 
927   CPDF_FormControl* pFormCtrl = GetFormControl();
928   CPDF_DefaultAppearance da = pFormCtrl->GetDefaultAppearance();
929   if (da.HasColor()) {
930     int32_t iColorType;
931     float fc[4];
932     da.GetColor(iColorType, fc);
933     crText = CFX_Color(iColorType, fc[0], fc[1], fc[2], fc[3]);
934   }
935 
936   return crText;
937 }
938 
939 CFX_Color CPDFSDK_Widget::GetBorderPWLColor() const {
940   CFX_Color crBorder;
941 
942   CPDF_FormControl* pFormCtrl = GetFormControl();
943   int32_t iColorType;
944   float fc[4];
945   pFormCtrl->GetOriginalBorderColor(iColorType, fc);
946   if (iColorType > 0)
947     crBorder = CFX_Color(iColorType, fc[0], fc[1], fc[2], fc[3]);
948 
949   return crBorder;
950 }
951 
952 CFX_Color CPDFSDK_Widget::GetFillPWLColor() const {
953   CFX_Color crFill;
954 
955   CPDF_FormControl* pFormCtrl = GetFormControl();
956   int32_t iColorType;
957   float fc[4];
958   pFormCtrl->GetOriginalBackgroundColor(iColorType, fc);
959   if (iColorType > 0)
960     crFill = CFX_Color(iColorType, fc[0], fc[1], fc[2], fc[3]);
961 
962   return crFill;
963 }
964 
965 bool CPDFSDK_Widget::OnAAction(CPDF_AAction::AActionType type,
966                                PDFSDK_FieldAction& data,
967                                CPDFSDK_PageView* pPageView) {
968   CPDFSDK_FormFillEnvironment* pFormFillEnv = pPageView->GetFormFillEnv();
969 
970 #ifdef PDF_ENABLE_XFA
971   CPDFXFA_Context* pContext = pFormFillEnv->GetXFAContext();
972   if (CXFA_FFWidget* hWidget = GetMixXFAWidget()) {
973     XFA_EVENTTYPE eEventType = GetXFAEventType(type, data.bWillCommit);
974 
975     if (eEventType != XFA_EVENT_Unknown) {
976       if (CXFA_FFWidgetHandler* pXFAWidgetHandler = GetXFAWidgetHandler()) {
977         CXFA_EventParam param;
978         param.m_eType = eEventType;
979         param.m_wsChange = data.sChange;
980         param.m_iCommitKey = data.nCommitKey;
981         param.m_bShift = data.bShift;
982         param.m_iSelStart = data.nSelStart;
983         param.m_iSelEnd = data.nSelEnd;
984         param.m_wsFullText = data.sValue;
985         param.m_bKeyDown = data.bKeyDown;
986         param.m_bModifier = data.bModifier;
987         param.m_wsNewText = data.sValue;
988         if (data.nSelEnd > data.nSelStart)
989           param.m_wsNewText.Delete(data.nSelStart,
990                                    data.nSelEnd - data.nSelStart);
991         for (int i = data.sChange.GetLength() - 1; i >= 0; i--)
992           param.m_wsNewText.Insert(data.nSelStart, data.sChange[i]);
993         param.m_wsPrevText = data.sValue;
994 
995         CXFA_WidgetAcc* pAcc = hWidget->GetNode()->GetWidgetAcc();
996         param.m_pTarget = pAcc;
997         int32_t nRet = pXFAWidgetHandler->ProcessEvent(pAcc, &param);
998 
999         if (CXFA_FFDocView* pDocView = pContext->GetXFADocView())
1000           pDocView->UpdateDocView();
1001 
1002         if (nRet == XFA_EVENTERROR_Success)
1003           return true;
1004       }
1005     }
1006   }
1007 #endif  // PDF_ENABLE_XFA
1008 
1009   CPDF_Action action = GetAAction(type);
1010   if (action.GetDict() && action.GetType() != CPDF_Action::Unknown) {
1011     CPDFSDK_ActionHandler* pActionHandler = pFormFillEnv->GetActionHandler();
1012     return pActionHandler->DoAction_Field(action, type, pFormFillEnv,
1013                                           GetFormField(), data);
1014   }
1015   return false;
1016 }
1017 
1018 CPDF_Action CPDFSDK_Widget::GetAAction(CPDF_AAction::AActionType eAAT) {
1019   switch (eAAT) {
1020     case CPDF_AAction::CursorEnter:
1021     case CPDF_AAction::CursorExit:
1022     case CPDF_AAction::ButtonDown:
1023     case CPDF_AAction::ButtonUp:
1024     case CPDF_AAction::GetFocus:
1025     case CPDF_AAction::LoseFocus:
1026     case CPDF_AAction::PageOpen:
1027     case CPDF_AAction::PageClose:
1028     case CPDF_AAction::PageVisible:
1029     case CPDF_AAction::PageInvisible:
1030       return CPDFSDK_BAAnnot::GetAAction(eAAT);
1031 
1032     case CPDF_AAction::KeyStroke:
1033     case CPDF_AAction::Format:
1034     case CPDF_AAction::Validate:
1035     case CPDF_AAction::Calculate: {
1036       CPDF_FormField* pField = GetFormField();
1037       if (pField->GetAdditionalAction().GetDict())
1038         return pField->GetAdditionalAction().GetAction(eAAT);
1039       return CPDFSDK_BAAnnot::GetAAction(eAAT);
1040     }
1041     default:
1042       break;
1043   }
1044 
1045   return CPDF_Action(nullptr);
1046 }
1047 
1048 WideString CPDFSDK_Widget::GetAlternateName() const {
1049   CPDF_FormField* pFormField = GetFormField();
1050   return pFormField->GetAlternateName();
1051 }
1052