• 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 "constants/annotation_common.h"
13 #include "core/fpdfapi/parser/cpdf_array.h"
14 #include "core/fpdfapi/parser/cpdf_dictionary.h"
15 #include "core/fpdfapi/parser/cpdf_document.h"
16 #include "core/fpdfapi/parser/cpdf_reference.h"
17 #include "core/fpdfapi/parser/cpdf_stream.h"
18 #include "core/fpdfapi/parser/cpdf_string.h"
19 #include "core/fpdfdoc/cba_fontmap.h"
20 #include "core/fpdfdoc/cpdf_defaultappearance.h"
21 #include "core/fpdfdoc/cpdf_formcontrol.h"
22 #include "core/fpdfdoc/cpdf_formfield.h"
23 #include "core/fpdfdoc/cpdf_iconfit.h"
24 #include "core/fpdfdoc/cpdf_interactiveform.h"
25 #include "core/fxge/cfx_graphstatedata.h"
26 #include "core/fxge/cfx_pathdata.h"
27 #include "core/fxge/cfx_renderdevice.h"
28 #include "fpdfsdk/cpdfsdk_actionhandler.h"
29 #include "fpdfsdk/cpdfsdk_appstream.h"
30 #include "fpdfsdk/cpdfsdk_fieldaction.h"
31 #include "fpdfsdk/cpdfsdk_formfillenvironment.h"
32 #include "fpdfsdk/cpdfsdk_interactiveform.h"
33 #include "fpdfsdk/cpdfsdk_pageview.h"
34 #include "fpdfsdk/pwl/cpwl_edit.h"
35 
36 #ifdef PDF_ENABLE_XFA
37 #include "fpdfsdk/fpdfxfa/cpdfxfa_context.h"
38 #include "xfa/fxfa/cxfa_eventparam.h"
39 #include "xfa/fxfa/cxfa_ffdocview.h"
40 #include "xfa/fxfa/cxfa_ffwidget.h"
41 #include "xfa/fxfa/cxfa_ffwidgethandler.h"
42 #include "xfa/fxfa/parser/cxfa_node.h"
43 #endif  // PDF_ENABLE_XFA
44 
CPDFSDK_Widget(CPDF_Annot * pAnnot,CPDFSDK_PageView * pPageView,CPDFSDK_InteractiveForm * pInteractiveForm)45 CPDFSDK_Widget::CPDFSDK_Widget(CPDF_Annot* pAnnot,
46                                CPDFSDK_PageView* pPageView,
47                                CPDFSDK_InteractiveForm* pInteractiveForm)
48     : CPDFSDK_BAAnnot(pAnnot, pPageView),
49       m_pInteractiveForm(pInteractiveForm) {}
50 
51 CPDFSDK_Widget::~CPDFSDK_Widget() = default;
52 
53 #ifdef PDF_ENABLE_XFA
GetMixXFAWidget() const54 CXFA_FFWidget* CPDFSDK_Widget::GetMixXFAWidget() const {
55   CPDF_Document::Extension* pContext =
56       m_pPageView->GetFormFillEnv()->GetDocExtension();
57   if (!pContext || !pContext->ContainsExtensionForegroundForm())
58     return nullptr;
59 
60   CXFA_FFDocView* pDocView =
61       static_cast<CPDFXFA_Context*>(pContext)->GetXFADocView();
62   if (!pDocView)
63     return nullptr;
64 
65   WideString sName;
66   if (GetFieldType() == FormFieldType::kRadioButton) {
67     sName = GetAnnotName();
68     if (sName.IsEmpty())
69       sName = GetName();
70   } else {
71     sName = GetName();
72   }
73 
74   if (sName.IsEmpty())
75     return nullptr;
76 
77   return pDocView->GetWidgetByName(sName, nullptr);
78 }
79 
GetGroupMixXFAWidget() const80 CXFA_FFWidget* CPDFSDK_Widget::GetGroupMixXFAWidget() const {
81   CPDF_Document::Extension* pContext =
82       m_pPageView->GetFormFillEnv()->GetDocExtension();
83   if (!pContext || !pContext->ContainsExtensionForegroundForm())
84     return nullptr;
85 
86   CXFA_FFDocView* pDocView =
87       static_cast<CPDFXFA_Context*>(pContext)->GetXFADocView();
88   if (!pDocView)
89     return nullptr;
90 
91   WideString sName = GetName();
92   return !sName.IsEmpty() ? pDocView->GetWidgetByName(sName, nullptr) : nullptr;
93 }
94 
GetXFAWidgetHandler() const95 CXFA_FFWidgetHandler* CPDFSDK_Widget::GetXFAWidgetHandler() const {
96   CPDF_Document::Extension* pContext =
97       m_pPageView->GetFormFillEnv()->GetDocExtension();
98   if (!pContext || !pContext->ContainsExtensionForegroundForm())
99     return nullptr;
100 
101   if (!m_pWidgetHandler) {
102     CXFA_FFDocView* pDocView =
103         static_cast<CPDFXFA_Context*>(pContext)->GetXFADocView();
104     if (pDocView)
105       m_pWidgetHandler = pDocView->GetWidgetHandler();
106   }
107   return m_pWidgetHandler.Get();
108 }
109 
GetXFAEventType(PDFSDK_XFAAActionType eXFAAAT)110 static XFA_EVENTTYPE GetXFAEventType(PDFSDK_XFAAActionType eXFAAAT) {
111   XFA_EVENTTYPE eEventType = XFA_EVENT_Unknown;
112 
113   switch (eXFAAAT) {
114     case PDFSDK_XFA_Click:
115       eEventType = XFA_EVENT_Click;
116       break;
117     case PDFSDK_XFA_Full:
118       eEventType = XFA_EVENT_Full;
119       break;
120     case PDFSDK_XFA_PreOpen:
121       eEventType = XFA_EVENT_PreOpen;
122       break;
123     case PDFSDK_XFA_PostOpen:
124       eEventType = XFA_EVENT_PostOpen;
125       break;
126   }
127 
128   return eEventType;
129 }
130 
GetXFAEventType(CPDF_AAction::AActionType eAAT,bool bWillCommit)131 static XFA_EVENTTYPE GetXFAEventType(CPDF_AAction::AActionType eAAT,
132                                      bool bWillCommit) {
133   XFA_EVENTTYPE eEventType = XFA_EVENT_Unknown;
134 
135   switch (eAAT) {
136     case CPDF_AAction::kCursorEnter:
137       eEventType = XFA_EVENT_MouseEnter;
138       break;
139     case CPDF_AAction::kCursorExit:
140       eEventType = XFA_EVENT_MouseExit;
141       break;
142     case CPDF_AAction::kButtonDown:
143       eEventType = XFA_EVENT_MouseDown;
144       break;
145     case CPDF_AAction::kButtonUp:
146       eEventType = XFA_EVENT_MouseUp;
147       break;
148     case CPDF_AAction::kGetFocus:
149       eEventType = XFA_EVENT_Enter;
150       break;
151     case CPDF_AAction::kLoseFocus:
152       eEventType = XFA_EVENT_Exit;
153       break;
154     case CPDF_AAction::kPageOpen:
155     case CPDF_AAction::kPageClose:
156     case CPDF_AAction::kPageVisible:
157     case CPDF_AAction::kPageInvisible:
158       break;
159     case CPDF_AAction::kKeyStroke:
160       if (!bWillCommit)
161         eEventType = XFA_EVENT_Change;
162       break;
163     case CPDF_AAction::kValidate:
164       eEventType = XFA_EVENT_Validate;
165       break;
166     case CPDF_AAction::kOpenPage:
167     case CPDF_AAction::kClosePage:
168     case CPDF_AAction::kFormat:
169     case CPDF_AAction::kCalculate:
170     case CPDF_AAction::kCloseDocument:
171     case CPDF_AAction::kSaveDocument:
172     case CPDF_AAction::kDocumentSaved:
173     case CPDF_AAction::kPrintDocument:
174     case CPDF_AAction::kDocumentPrinted:
175       break;
176     case CPDF_AAction::kDocumentOpen:
177     case CPDF_AAction::kNumberOfActions:
178       NOTREACHED();
179       break;
180   }
181 
182   return eEventType;
183 }
184 
HasXFAAAction(PDFSDK_XFAAActionType eXFAAAT) const185 bool CPDFSDK_Widget::HasXFAAAction(PDFSDK_XFAAActionType eXFAAAT) const {
186   ObservedPtr<CXFA_FFWidget> pWidget(GetMixXFAWidget());
187   if (!pWidget)
188     return false;
189 
190   CXFA_FFWidgetHandler* pXFAWidgetHandler = GetXFAWidgetHandler();
191   if (!pXFAWidgetHandler)
192     return false;
193 
194   XFA_EVENTTYPE eEventType = GetXFAEventType(eXFAAAT);
195   if ((eEventType == XFA_EVENT_Click || eEventType == XFA_EVENT_Change) &&
196       GetFieldType() == FormFieldType::kRadioButton) {
197     CXFA_FFWidget* hGroupWidget = GetGroupMixXFAWidget();
198     if (hGroupWidget &&
199         hGroupWidget->HasEventUnderHandler(eEventType, pXFAWidgetHandler)) {
200       return true;
201     }
202   }
203 
204   // Check |pWidget| again because JS may have destroyed it in the block above.
205   return pWidget &&
206          pWidget->HasEventUnderHandler(eEventType, pXFAWidgetHandler);
207 }
208 
OnXFAAAction(PDFSDK_XFAAActionType eXFAAAT,CPDFSDK_FieldAction * data,CPDFSDK_PageView * pPageView)209 bool CPDFSDK_Widget::OnXFAAAction(PDFSDK_XFAAActionType eXFAAAT,
210                                   CPDFSDK_FieldAction* data,
211                                   CPDFSDK_PageView* pPageView) {
212   auto* pContext = static_cast<CPDFXFA_Context*>(
213       m_pPageView->GetFormFillEnv()->GetDocExtension());
214   if (!pContext)
215     return false;
216 
217   ObservedPtr<CXFA_FFWidget> pWidget(GetMixXFAWidget());
218   if (!pWidget)
219     return false;
220 
221   XFA_EVENTTYPE eEventType = GetXFAEventType(eXFAAAT);
222   if (eEventType == XFA_EVENT_Unknown)
223     return false;
224 
225   CXFA_FFWidgetHandler* pXFAWidgetHandler = GetXFAWidgetHandler();
226   if (!pXFAWidgetHandler)
227     return false;
228 
229   CXFA_EventParam param;
230   param.m_eType = eEventType;
231   param.m_wsChange = data->sChange;
232   param.m_iCommitKey = 0;
233   param.m_bShift = data->bShift;
234   param.m_iSelStart = data->nSelStart;
235   param.m_iSelEnd = data->nSelEnd;
236   param.m_wsFullText = data->sValue;
237   param.m_bKeyDown = data->bKeyDown;
238   param.m_bModifier = data->bModifier;
239   param.m_wsPrevText = data->sValue;
240   if ((eEventType == XFA_EVENT_Click || eEventType == XFA_EVENT_Change) &&
241       GetFieldType() == FormFieldType::kRadioButton) {
242     CXFA_FFWidget* hGroupWidget = GetGroupMixXFAWidget();
243     if (hGroupWidget &&
244         !hGroupWidget->ProcessEventUnderHandler(&param, pXFAWidgetHandler)) {
245       return false;
246     }
247   }
248 
249   // Check |pWidget| again because JS may have destroyed it in the block above.
250   if (!pWidget)
251     return false;
252 
253   bool ret = pWidget->ProcessEventUnderHandler(&param, pXFAWidgetHandler);
254   if (CXFA_FFDocView* pDocView = pContext->GetXFADocView())
255     pDocView->UpdateDocView();
256 
257   return ret;
258 }
259 
Synchronize(bool bSynchronizeElse)260 void CPDFSDK_Widget::Synchronize(bool bSynchronizeElse) {
261   CXFA_FFWidget* hWidget = GetMixXFAWidget();
262   if (!hWidget)
263     return;
264 
265   CXFA_Node* node = hWidget->GetNode();
266   if (!node->IsWidgetReady())
267     return;
268 
269   CPDF_FormField* pFormField = GetFormField();
270   switch (GetFieldType()) {
271     case FormFieldType::kCheckBox:
272     case FormFieldType::kRadioButton: {
273       CPDF_FormControl* pFormCtrl = GetFormControl();
274       XFA_CHECKSTATE eCheckState =
275           pFormCtrl->IsChecked() ? XFA_CHECKSTATE_On : XFA_CHECKSTATE_Off;
276       node->SetCheckState(eCheckState, true);
277       break;
278     }
279     case FormFieldType::kTextField:
280       node->SetValue(XFA_VALUEPICTURE_Edit, pFormField->GetValue());
281       break;
282     case FormFieldType::kComboBox:
283     case FormFieldType::kListBox: {
284       node->ClearAllSelections();
285 
286       for (int i = 0; i < pFormField->CountSelectedItems(); ++i) {
287         int nIndex = pFormField->GetSelectedIndex(i);
288         if (nIndex > -1 && nIndex < node->CountChoiceListItems(false))
289           node->SetItemState(nIndex, true, false, false, true);
290       }
291       if (GetFieldType() == FormFieldType::kComboBox)
292         node->SetValue(XFA_VALUEPICTURE_Edit, pFormField->GetValue());
293       break;
294     }
295     default:
296       break;
297   }
298 
299   if (bSynchronizeElse) {
300     auto* context = static_cast<CPDFXFA_Context*>(
301         m_pPageView->GetFormFillEnv()->GetDocExtension());
302     context->GetXFADocView()->ProcessValueChanged(node);
303   }
304 }
305 #endif  // PDF_ENABLE_XFA
306 
IsWidgetAppearanceValid(CPDF_Annot::AppearanceMode mode)307 bool CPDFSDK_Widget::IsWidgetAppearanceValid(CPDF_Annot::AppearanceMode mode) {
308   const CPDF_Dictionary* pAP =
309       GetAnnotDict()->GetDictFor(pdfium::annotation::kAP);
310   if (!pAP)
311     return false;
312 
313   // Choose the right sub-ap
314   const char* ap_entry = "N";
315   if (mode == CPDF_Annot::Down)
316     ap_entry = "D";
317   else if (mode == CPDF_Annot::Rollover)
318     ap_entry = "R";
319   if (!pAP->KeyExist(ap_entry))
320     ap_entry = "N";
321 
322   // Get the AP stream or subdirectory
323   const CPDF_Object* pSub = pAP->GetDirectObjectFor(ap_entry);
324   if (!pSub)
325     return false;
326 
327   FormFieldType fieldType = GetFieldType();
328   switch (fieldType) {
329     case FormFieldType::kPushButton:
330     case FormFieldType::kComboBox:
331     case FormFieldType::kListBox:
332     case FormFieldType::kTextField:
333     case FormFieldType::kSignature:
334       return pSub->IsStream();
335     case FormFieldType::kCheckBox:
336     case FormFieldType::kRadioButton:
337       if (const CPDF_Dictionary* pSubDict = pSub->AsDictionary()) {
338         return !!pSubDict->GetStreamFor(GetAppState());
339       }
340       return false;
341     default:
342       return true;
343   }
344 }
345 
GetFieldType() const346 FormFieldType CPDFSDK_Widget::GetFieldType() const {
347   CPDF_FormField* pField = GetFormField();
348   return pField ? pField->GetFieldType() : FormFieldType::kUnknown;
349 }
350 
IsAppearanceValid()351 bool CPDFSDK_Widget::IsAppearanceValid() {
352 #ifdef PDF_ENABLE_XFA
353   CPDF_Document::Extension* pContext =
354       m_pPageView->GetFormFillEnv()->GetDocExtension();
355   if (pContext && pContext->ContainsExtensionFullForm())
356     return true;
357 #endif  // PDF_ENABLE_XFA
358   return CPDFSDK_BAAnnot::IsAppearanceValid();
359 }
360 
GetLayoutOrder() const361 int CPDFSDK_Widget::GetLayoutOrder() const {
362   return 2;
363 }
364 
GetFieldFlags() const365 int CPDFSDK_Widget::GetFieldFlags() const {
366   return GetFormField()->GetFieldFlags();
367 }
368 
IsSignatureWidget() const369 bool CPDFSDK_Widget::IsSignatureWidget() const {
370   return GetFieldType() == FormFieldType::kSignature;
371 }
372 
GetFormField() const373 CPDF_FormField* CPDFSDK_Widget::GetFormField() const {
374   CPDF_FormControl* pControl = GetFormControl();
375   return pControl ? pControl->GetField() : nullptr;
376 }
377 
GetFormControl() const378 CPDF_FormControl* CPDFSDK_Widget::GetFormControl() const {
379   CPDF_InteractiveForm* pPDFInteractiveForm =
380       m_pInteractiveForm->GetInteractiveForm();
381   return pPDFInteractiveForm->GetControlByDict(GetAnnotDict());
382 }
383 
GetRotate() const384 int CPDFSDK_Widget::GetRotate() const {
385   CPDF_FormControl* pCtrl = GetFormControl();
386   return pCtrl->GetRotation() % 360;
387 }
388 
389 #ifdef PDF_ENABLE_XFA
GetName() const390 WideString CPDFSDK_Widget::GetName() const {
391   return GetFormField()->GetFullName();
392 }
393 #endif  // PDF_ENABLE_XFA
394 
GetFillColor() const395 Optional<FX_COLORREF> CPDFSDK_Widget::GetFillColor() const {
396   CPDF_FormControl* pFormCtrl = GetFormControl();
397   int iColorType = 0;
398   FX_COLORREF color = ArgbToColorRef(pFormCtrl->GetBackgroundColor(iColorType));
399   if (iColorType == CFX_Color::kTransparent)
400     return {};
401   return color;
402 }
403 
GetBorderColor() const404 Optional<FX_COLORREF> CPDFSDK_Widget::GetBorderColor() const {
405   CPDF_FormControl* pFormCtrl = GetFormControl();
406   int iColorType = 0;
407   FX_COLORREF color = ArgbToColorRef(pFormCtrl->GetBorderColor(iColorType));
408   if (iColorType == CFX_Color::kTransparent)
409     return {};
410   return color;
411 }
412 
GetTextColor() const413 Optional<FX_COLORREF> CPDFSDK_Widget::GetTextColor() const {
414   CPDF_FormControl* pFormCtrl = GetFormControl();
415   CPDF_DefaultAppearance da = pFormCtrl->GetDefaultAppearance();
416   FX_ARGB argb;
417   Optional<CFX_Color::Type> iColorType;
418   std::tie(iColorType, argb) = da.GetColor();
419   if (!iColorType.has_value())
420     return {};
421 
422   FX_COLORREF color = ArgbToColorRef(argb);
423   if (iColorType.value() == CFX_Color::kTransparent)
424     return {};
425   return color;
426 }
427 
GetFontSize() const428 float CPDFSDK_Widget::GetFontSize() const {
429   CPDF_FormControl* pFormCtrl = GetFormControl();
430   CPDF_DefaultAppearance pDa = pFormCtrl->GetDefaultAppearance();
431   float fFontSize;
432   pDa.GetFont(&fFontSize);
433   return fFontSize;
434 }
435 
GetSelectedIndex(int nIndex) const436 int CPDFSDK_Widget::GetSelectedIndex(int nIndex) const {
437 #ifdef PDF_ENABLE_XFA
438   if (CXFA_FFWidget* hWidget = GetMixXFAWidget()) {
439     CXFA_Node* node = hWidget->GetNode();
440     if (node->IsWidgetReady()) {
441       if (nIndex < node->CountSelectedItems())
442         return node->GetSelectedItem(nIndex);
443     }
444   }
445 #endif  // PDF_ENABLE_XFA
446   CPDF_FormField* pFormField = GetFormField();
447   return pFormField->GetSelectedIndex(nIndex);
448 }
449 
GetValue() const450 WideString CPDFSDK_Widget::GetValue() const {
451 #ifdef PDF_ENABLE_XFA
452   if (CXFA_FFWidget* hWidget = GetMixXFAWidget()) {
453     CXFA_Node* node = hWidget->GetNode();
454     if (node->IsWidgetReady())
455       return node->GetValue(XFA_VALUEPICTURE_Display);
456   }
457 #endif  // PDF_ENABLE_XFA
458   CPDF_FormField* pFormField = GetFormField();
459   return pFormField->GetValue();
460 }
461 
GetDefaultValue() const462 WideString CPDFSDK_Widget::GetDefaultValue() const {
463   CPDF_FormField* pFormField = GetFormField();
464   return pFormField->GetDefaultValue();
465 }
466 
GetOptionLabel(int nIndex) const467 WideString CPDFSDK_Widget::GetOptionLabel(int nIndex) const {
468   CPDF_FormField* pFormField = GetFormField();
469   return pFormField->GetOptionLabel(nIndex);
470 }
471 
CountOptions() const472 int CPDFSDK_Widget::CountOptions() const {
473   CPDF_FormField* pFormField = GetFormField();
474   return pFormField->CountOptions();
475 }
476 
IsOptionSelected(int nIndex) const477 bool CPDFSDK_Widget::IsOptionSelected(int nIndex) const {
478 #ifdef PDF_ENABLE_XFA
479   if (CXFA_FFWidget* hWidget = GetMixXFAWidget()) {
480     CXFA_Node* node = hWidget->GetNode();
481     if (node->IsWidgetReady()) {
482       if (nIndex > -1 && nIndex < node->CountChoiceListItems(false))
483         return node->GetItemState(nIndex);
484 
485       return false;
486     }
487   }
488 #endif  // PDF_ENABLE_XFA
489   CPDF_FormField* pFormField = GetFormField();
490   return pFormField->IsItemSelected(nIndex);
491 }
492 
GetTopVisibleIndex() const493 int CPDFSDK_Widget::GetTopVisibleIndex() const {
494   CPDF_FormField* pFormField = GetFormField();
495   return pFormField->GetTopVisibleIndex();
496 }
497 
IsChecked() const498 bool CPDFSDK_Widget::IsChecked() const {
499 #ifdef PDF_ENABLE_XFA
500   if (CXFA_FFWidget* hWidget = GetMixXFAWidget()) {
501     CXFA_Node* node = hWidget->GetNode();
502     if (node->IsWidgetReady())
503       return node->GetCheckState() == XFA_CHECKSTATE_On;
504   }
505 #endif  // PDF_ENABLE_XFA
506   CPDF_FormControl* pFormCtrl = GetFormControl();
507   return pFormCtrl->IsChecked();
508 }
509 
GetAlignment() const510 int CPDFSDK_Widget::GetAlignment() const {
511   CPDF_FormControl* pFormCtrl = GetFormControl();
512   return pFormCtrl->GetControlAlignment();
513 }
514 
GetMaxLen() const515 int CPDFSDK_Widget::GetMaxLen() const {
516   CPDF_FormField* pFormField = GetFormField();
517   return pFormField->GetMaxLen();
518 }
519 
SetCheck(bool bChecked,NotificationOption notify)520 void CPDFSDK_Widget::SetCheck(bool bChecked, NotificationOption notify) {
521   CPDF_FormControl* pFormCtrl = GetFormControl();
522   CPDF_FormField* pFormField = pFormCtrl->GetField();
523   pFormField->CheckControl(pFormField->GetControlIndex(pFormCtrl), bChecked,
524                            notify);
525 #ifdef PDF_ENABLE_XFA
526   if (!IsWidgetAppearanceValid(CPDF_Annot::Normal))
527     ResetXFAAppearance(true);
528   if (notify == NotificationOption::kDoNotNotify)
529     Synchronize(true);
530 #endif  // PDF_ENABLE_XFA
531 }
532 
SetValue(const WideString & sValue,NotificationOption notify)533 void CPDFSDK_Widget::SetValue(const WideString& sValue,
534                               NotificationOption notify) {
535   CPDF_FormField* pFormField = GetFormField();
536   pFormField->SetValue(sValue, notify);
537 #ifdef PDF_ENABLE_XFA
538   if (notify == NotificationOption::kDoNotNotify)
539     Synchronize(true);
540 #endif  // PDF_ENABLE_XFA
541 }
542 
SetOptionSelection(int index,bool bSelected,NotificationOption notify)543 void CPDFSDK_Widget::SetOptionSelection(int index,
544                                         bool bSelected,
545                                         NotificationOption notify) {
546   CPDF_FormField* pFormField = GetFormField();
547   pFormField->SetItemSelection(index, bSelected, notify);
548 #ifdef PDF_ENABLE_XFA
549   if (notify == NotificationOption::kDoNotNotify)
550     Synchronize(true);
551 #endif  // PDF_ENABLE_XFA
552 }
553 
ClearSelection(NotificationOption notify)554 void CPDFSDK_Widget::ClearSelection(NotificationOption notify) {
555   CPDF_FormField* pFormField = GetFormField();
556   pFormField->ClearSelection(notify);
557 #ifdef PDF_ENABLE_XFA
558   if (notify == NotificationOption::kDoNotNotify)
559     Synchronize(true);
560 #endif  // PDF_ENABLE_XFA
561 }
562 
SetTopVisibleIndex(int index)563 void CPDFSDK_Widget::SetTopVisibleIndex(int index) {}
564 
SetAppModified()565 void CPDFSDK_Widget::SetAppModified() {
566   m_bAppModified = true;
567 }
568 
ClearAppModified()569 void CPDFSDK_Widget::ClearAppModified() {
570   m_bAppModified = false;
571 }
572 
IsAppModified() const573 bool CPDFSDK_Widget::IsAppModified() const {
574   return m_bAppModified;
575 }
576 
577 #ifdef PDF_ENABLE_XFA
ResetXFAAppearance(bool bValueChanged)578 void CPDFSDK_Widget::ResetXFAAppearance(bool bValueChanged) {
579   switch (GetFieldType()) {
580     case FormFieldType::kTextField:
581     case FormFieldType::kComboBox: {
582       ResetAppearance(OnFormat(), true);
583       break;
584     }
585     default:
586       ResetAppearance(pdfium::nullopt, false);
587       break;
588   }
589 }
590 #endif  // PDF_ENABLE_XFA
591 
ResetAppearance(Optional<WideString> sValue,bool bValueChanged)592 void CPDFSDK_Widget::ResetAppearance(Optional<WideString> sValue,
593                                      bool bValueChanged) {
594   SetAppModified();
595 
596   m_nAppearanceAge++;
597   if (bValueChanged)
598     m_nValueAge++;
599 
600   CPDFSDK_AppStream appStream(this, GetAPDict());
601   switch (GetFieldType()) {
602     case FormFieldType::kPushButton:
603       appStream.SetAsPushButton();
604       break;
605     case FormFieldType::kCheckBox:
606       appStream.SetAsCheckBox();
607       break;
608     case FormFieldType::kRadioButton:
609       appStream.SetAsRadioButton();
610       break;
611     case FormFieldType::kComboBox:
612       appStream.SetAsComboBox(sValue);
613       break;
614     case FormFieldType::kListBox:
615       appStream.SetAsListBox();
616       break;
617     case FormFieldType::kTextField:
618       appStream.SetAsTextField(sValue);
619       break;
620     default:
621       break;
622   }
623 
624   m_pAnnot->ClearCachedAP();
625 }
626 
OnFormat()627 Optional<WideString> CPDFSDK_Widget::OnFormat() {
628   CPDF_FormField* pFormField = GetFormField();
629   ASSERT(pFormField);
630   return m_pInteractiveForm->OnFormat(pFormField);
631 }
632 
ResetFieldAppearance()633 void CPDFSDK_Widget::ResetFieldAppearance() {
634   CPDF_FormField* pFormField = GetFormField();
635   ASSERT(pFormField);
636   m_pInteractiveForm->ResetFieldAppearance(pFormField, pdfium::nullopt);
637 }
638 
DrawAppearance(CFX_RenderDevice * pDevice,const CFX_Matrix & mtUser2Device,CPDF_Annot::AppearanceMode mode,const CPDF_RenderOptions * pOptions)639 void CPDFSDK_Widget::DrawAppearance(CFX_RenderDevice* pDevice,
640                                     const CFX_Matrix& mtUser2Device,
641                                     CPDF_Annot::AppearanceMode mode,
642                                     const CPDF_RenderOptions* pOptions) {
643   FormFieldType fieldType = GetFieldType();
644 
645   if ((fieldType == FormFieldType::kCheckBox ||
646        fieldType == FormFieldType::kRadioButton) &&
647       mode == CPDF_Annot::Normal &&
648       !IsWidgetAppearanceValid(CPDF_Annot::Normal)) {
649     CFX_GraphStateData gsd;
650     gsd.m_LineWidth = 0.0f;
651 
652     CFX_PathData pathData;
653     pathData.AppendFloatRect(GetRect());
654     pDevice->DrawPath(&pathData, &mtUser2Device, &gsd, 0, 0xFFAAAAAA,
655                       FXFILL_ALTERNATE);
656   } else {
657     CPDFSDK_BAAnnot::DrawAppearance(pDevice, mtUser2Device, mode, pOptions);
658   }
659 }
660 
UpdateField()661 void CPDFSDK_Widget::UpdateField() {
662   CPDF_FormField* pFormField = GetFormField();
663   ASSERT(pFormField);
664   m_pInteractiveForm->UpdateField(pFormField);
665 }
666 
DrawShadow(CFX_RenderDevice * pDevice,CPDFSDK_PageView * pPageView)667 void CPDFSDK_Widget::DrawShadow(CFX_RenderDevice* pDevice,
668                                 CPDFSDK_PageView* pPageView) {
669   FormFieldType fieldType = GetFieldType();
670   if (!m_pInteractiveForm->IsNeedHighLight(fieldType))
671     return;
672 
673   CFX_Matrix page2device = pPageView->GetCurrentMatrix();
674   CFX_FloatRect rcDevice = GetRect();
675   CFX_PointF tmp =
676       page2device.Transform(CFX_PointF(rcDevice.left, rcDevice.bottom));
677   rcDevice.left = tmp.x;
678   rcDevice.bottom = tmp.y;
679 
680   tmp = page2device.Transform(CFX_PointF(rcDevice.right, rcDevice.top));
681   rcDevice.right = tmp.x;
682   rcDevice.top = tmp.y;
683   rcDevice.Normalize();
684 
685   pDevice->FillRect(
686       rcDevice.ToFxRect(),
687       AlphaAndColorRefToArgb(
688           static_cast<int>(m_pInteractiveForm->GetHighlightAlpha()),
689           m_pInteractiveForm->GetHighlightColor(fieldType)));
690 }
691 
GetClientRect() const692 CFX_FloatRect CPDFSDK_Widget::GetClientRect() const {
693   CFX_FloatRect rcWindow = GetRotatedRect();
694   float fBorderWidth = GetBorderWidth();
695   switch (GetBorderStyle()) {
696     case BorderStyle::BEVELED:
697     case BorderStyle::INSET:
698       fBorderWidth *= 2.0f;
699       break;
700     default:
701       break;
702   }
703   return rcWindow.GetDeflated(fBorderWidth, fBorderWidth);
704 }
705 
GetRotatedRect() const706 CFX_FloatRect CPDFSDK_Widget::GetRotatedRect() const {
707   CFX_FloatRect rectAnnot = GetRect();
708   float fWidth = rectAnnot.Width();
709   float fHeight = rectAnnot.Height();
710 
711   CPDF_FormControl* pControl = GetFormControl();
712   CFX_FloatRect rcPWLWindow;
713   switch (abs(pControl->GetRotation() % 360)) {
714     case 0:
715     case 180:
716     default:
717       rcPWLWindow = CFX_FloatRect(0, 0, fWidth, fHeight);
718       break;
719     case 90:
720     case 270:
721       rcPWLWindow = CFX_FloatRect(0, 0, fHeight, fWidth);
722       break;
723   }
724 
725   return rcPWLWindow;
726 }
727 
GetMatrix() const728 CFX_Matrix CPDFSDK_Widget::GetMatrix() const {
729   CFX_Matrix mt;
730   CPDF_FormControl* pControl = GetFormControl();
731   CFX_FloatRect rcAnnot = GetRect();
732   float fWidth = rcAnnot.Width();
733   float fHeight = rcAnnot.Height();
734 
735   switch (abs(pControl->GetRotation() % 360)) {
736     default:
737     case 0:
738       break;
739     case 90:
740       mt = CFX_Matrix(0, 1, -1, 0, fWidth, 0);
741       break;
742     case 180:
743       mt = CFX_Matrix(-1, 0, 0, -1, fWidth, fHeight);
744       break;
745     case 270:
746       mt = CFX_Matrix(0, -1, 1, 0, 0, fHeight);
747       break;
748   }
749 
750   return mt;
751 }
752 
GetTextPWLColor() const753 CFX_Color CPDFSDK_Widget::GetTextPWLColor() const {
754   CFX_Color crText = CFX_Color(CFX_Color::kGray, 0);
755 
756   CPDF_FormControl* pFormCtrl = GetFormControl();
757   CPDF_DefaultAppearance da = pFormCtrl->GetDefaultAppearance();
758 
759   float fc[4];
760   Optional<CFX_Color::Type> iColorType = da.GetColor(fc);
761   if (iColorType)
762     crText = CFX_Color(*iColorType, fc[0], fc[1], fc[2], fc[3]);
763 
764   return crText;
765 }
766 
GetBorderPWLColor() const767 CFX_Color CPDFSDK_Widget::GetBorderPWLColor() const {
768   CFX_Color crBorder;
769 
770   CPDF_FormControl* pFormCtrl = GetFormControl();
771   int32_t iColorType;
772   float fc[4];
773   pFormCtrl->GetOriginalBorderColor(iColorType, fc);
774   if (iColorType > 0)
775     crBorder = CFX_Color(iColorType, fc[0], fc[1], fc[2], fc[3]);
776 
777   return crBorder;
778 }
779 
GetFillPWLColor() const780 CFX_Color CPDFSDK_Widget::GetFillPWLColor() const {
781   CFX_Color crFill;
782 
783   CPDF_FormControl* pFormCtrl = GetFormControl();
784   int32_t iColorType;
785   float fc[4];
786   pFormCtrl->GetOriginalBackgroundColor(iColorType, fc);
787   if (iColorType > 0)
788     crFill = CFX_Color(iColorType, fc[0], fc[1], fc[2], fc[3]);
789 
790   return crFill;
791 }
792 
OnAAction(CPDF_AAction::AActionType type,CPDFSDK_FieldAction * data,CPDFSDK_PageView * pPageView)793 bool CPDFSDK_Widget::OnAAction(CPDF_AAction::AActionType type,
794                                CPDFSDK_FieldAction* data,
795                                CPDFSDK_PageView* pPageView) {
796   CPDFSDK_FormFillEnvironment* pFormFillEnv = pPageView->GetFormFillEnv();
797 
798 #ifdef PDF_ENABLE_XFA
799   auto* pContext =
800       static_cast<CPDFXFA_Context*>(pFormFillEnv->GetDocExtension());
801   if (pContext) {
802     CXFA_FFWidget* hWidget = GetMixXFAWidget();
803     if (hWidget) {
804       XFA_EVENTTYPE eEventType = GetXFAEventType(type, data->bWillCommit);
805       if (eEventType != XFA_EVENT_Unknown) {
806         if (CXFA_FFWidgetHandler* pXFAWidgetHandler = GetXFAWidgetHandler()) {
807           CXFA_EventParam param;
808           param.m_eType = eEventType;
809           param.m_wsChange = data->sChange;
810           param.m_iCommitKey = 0;
811           param.m_bShift = data->bShift;
812           param.m_iSelStart = data->nSelStart;
813           param.m_iSelEnd = data->nSelEnd;
814           param.m_wsFullText = data->sValue;
815           param.m_bKeyDown = data->bKeyDown;
816           param.m_bModifier = data->bModifier;
817           param.m_wsPrevText = data->sValue;
818           bool ret =
819               hWidget->ProcessEventUnderHandler(&param, pXFAWidgetHandler);
820           if (CXFA_FFDocView* pDocView = pContext->GetXFADocView())
821             pDocView->UpdateDocView();
822           if (ret)
823             return true;
824         }
825       }
826     }
827   }
828 #endif  // PDF_ENABLE_XFA
829 
830   CPDF_Action action = GetAAction(type);
831   if (action.GetType() != CPDF_Action::Unknown) {
832     pFormFillEnv->GetActionHandler()->DoAction_Field(action, type, pFormFillEnv,
833                                                      GetFormField(), data);
834   }
835   return false;
836 }
837 
GetAAction(CPDF_AAction::AActionType eAAT)838 CPDF_Action CPDFSDK_Widget::GetAAction(CPDF_AAction::AActionType eAAT) {
839   switch (eAAT) {
840     case CPDF_AAction::kCursorEnter:
841     case CPDF_AAction::kCursorExit:
842     case CPDF_AAction::kButtonDown:
843     case CPDF_AAction::kButtonUp:
844     case CPDF_AAction::kGetFocus:
845     case CPDF_AAction::kLoseFocus:
846     case CPDF_AAction::kPageOpen:
847     case CPDF_AAction::kPageClose:
848     case CPDF_AAction::kPageVisible:
849     case CPDF_AAction::kPageInvisible:
850       return CPDFSDK_BAAnnot::GetAAction(eAAT);
851 
852     case CPDF_AAction::kKeyStroke:
853     case CPDF_AAction::kFormat:
854     case CPDF_AAction::kValidate:
855     case CPDF_AAction::kCalculate: {
856       CPDF_FormField* pField = GetFormField();
857       if (pField->GetAdditionalAction().GetDict())
858         return pField->GetAdditionalAction().GetAction(eAAT);
859       return CPDFSDK_BAAnnot::GetAAction(eAAT);
860     }
861     default:
862       break;
863   }
864 
865   return CPDF_Action(nullptr);
866 }
867 
GetAlternateName() const868 WideString CPDFSDK_Widget::GetAlternateName() const {
869   CPDF_FormField* pFormField = GetFormField();
870   return pFormField->GetAlternateName();
871 }
872