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, ¶m) !=
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, ¶m);
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, ¶m);
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