1 // Copyright 2014 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6 
7 #include "fpdfsdk/include/fsdk_baseform.h"
8 
9 #include <memory>
10 
11 #include "fpdfsdk/include/formfiller/FFL_FormFiller.h"
12 #include "fpdfsdk/include/fsdk_actionhandler.h"
13 #include "fpdfsdk/include/fsdk_baseannot.h"
14 #include "fpdfsdk/include/fsdk_define.h"
15 #include "fpdfsdk/include/fsdk_mgr.h"
16 #include "fpdfsdk/include/javascript/IJavaScript.h"
17 #include "fpdfsdk/include/pdfwindow/PWL_Utils.h"
18 
19 #ifdef PDF_ENABLE_XFA
20 #include "fpdfsdk/include/fpdfxfa/fpdfxfa_doc.h"
21 #include "fpdfsdk/include/fpdfxfa/fpdfxfa_util.h"
22 #endif  // PDF_ENABLE_XFA
23 
24 #define IsFloatZero(f) ((f) < 0.01 && (f) > -0.01)
25 #define IsFloatBigger(fa, fb) ((fa) > (fb) && !IsFloatZero((fa) - (fb)))
26 #define IsFloatSmaller(fa, fb) ((fa) < (fb) && !IsFloatZero((fa) - (fb)))
27 #define IsFloatEqual(fa, fb) IsFloatZero((fa) - (fb))
28 
CPDFSDK_Widget(CPDF_Annot * pAnnot,CPDFSDK_PageView * pPageView,CPDFSDK_InterForm * pInterForm)29 CPDFSDK_Widget::CPDFSDK_Widget(CPDF_Annot* pAnnot,
30                                CPDFSDK_PageView* pPageView,
31                                CPDFSDK_InterForm* pInterForm)
32     : CPDFSDK_BAAnnot(pAnnot, pPageView),
33       m_pInterForm(pInterForm),
34       m_nAppAge(0),
35       m_nValueAge(0)
36 #ifdef PDF_ENABLE_XFA
37       ,
38       m_hMixXFAWidget(NULL),
39       m_pWidgetHandler(NULL)
40 #endif  // PDF_ENABLE_XFA
41 {
42 }
43 
~CPDFSDK_Widget()44 CPDFSDK_Widget::~CPDFSDK_Widget() {}
45 
46 #ifdef PDF_ENABLE_XFA
GetMixXFAWidget() const47 IXFA_Widget* CPDFSDK_Widget::GetMixXFAWidget() const {
48   CPDFSDK_Document* pSDKDoc = m_pPageView->GetSDKDocument();
49   CPDFXFA_Document* pDoc = pSDKDoc->GetXFADocument();
50   if (pDoc->GetDocType() == DOCTYPE_STATIC_XFA) {
51     if (!m_hMixXFAWidget) {
52       if (IXFA_DocView* pDocView = pDoc->GetXFADocView()) {
53         CFX_WideString sName;
54         if (this->GetFieldType() == FIELDTYPE_RADIOBUTTON) {
55           sName = this->GetAnnotName();
56           if (sName.IsEmpty())
57             sName = GetName();
58         } else
59           sName = GetName();
60 
61         if (!sName.IsEmpty())
62           m_hMixXFAWidget = pDocView->GetWidgetByName(sName);
63       }
64     }
65     return m_hMixXFAWidget;
66   }
67 
68   return NULL;
69 }
70 
GetGroupMixXFAWidget()71 IXFA_Widget* CPDFSDK_Widget::GetGroupMixXFAWidget() {
72   CPDFSDK_Document* pSDKDoc = m_pPageView->GetSDKDocument();
73   CPDFXFA_Document* pDoc = pSDKDoc->GetXFADocument();
74   if (pDoc->GetDocType() == DOCTYPE_STATIC_XFA) {
75     if (IXFA_DocView* pDocView = pDoc->GetXFADocView()) {
76       CFX_WideString sName = GetName();
77       if (!sName.IsEmpty())
78         return pDocView->GetWidgetByName(sName);
79     }
80   }
81 
82   return nullptr;
83 }
84 
GetXFAWidgetHandler() const85 IXFA_WidgetHandler* CPDFSDK_Widget::GetXFAWidgetHandler() const {
86   CPDFSDK_Document* pSDKDoc = m_pPageView->GetSDKDocument();
87   CPDFXFA_Document* pDoc = pSDKDoc->GetXFADocument();
88   if (pDoc->GetDocType() == DOCTYPE_STATIC_XFA) {
89     if (!m_pWidgetHandler) {
90       if (IXFA_DocView* pDocView = pDoc->GetXFADocView()) {
91         m_pWidgetHandler = pDocView->GetWidgetHandler();
92       }
93     }
94     return m_pWidgetHandler;
95   }
96 
97   return NULL;
98 }
99 
GetXFAEventType(PDFSDK_XFAAActionType eXFAAAT)100 static XFA_EVENTTYPE GetXFAEventType(PDFSDK_XFAAActionType eXFAAAT) {
101   XFA_EVENTTYPE eEventType = XFA_EVENT_Unknown;
102 
103   switch (eXFAAAT) {
104     case PDFSDK_XFA_Click:
105       eEventType = XFA_EVENT_Click;
106       break;
107     case PDFSDK_XFA_Full:
108       eEventType = XFA_EVENT_Full;
109       break;
110     case PDFSDK_XFA_PreOpen:
111       eEventType = XFA_EVENT_PreOpen;
112       break;
113     case PDFSDK_XFA_PostOpen:
114       eEventType = XFA_EVENT_PostOpen;
115       break;
116   }
117 
118   return eEventType;
119 }
120 
GetXFAEventType(CPDF_AAction::AActionType eAAT,FX_BOOL bWillCommit)121 static XFA_EVENTTYPE GetXFAEventType(CPDF_AAction::AActionType eAAT,
122                                      FX_BOOL bWillCommit) {
123   XFA_EVENTTYPE eEventType = XFA_EVENT_Unknown;
124 
125   switch (eAAT) {
126     case CPDF_AAction::CursorEnter:
127       eEventType = XFA_EVENT_MouseEnter;
128       break;
129     case CPDF_AAction::CursorExit:
130       eEventType = XFA_EVENT_MouseExit;
131       break;
132     case CPDF_AAction::ButtonDown:
133       eEventType = XFA_EVENT_MouseDown;
134       break;
135     case CPDF_AAction::ButtonUp:
136       eEventType = XFA_EVENT_MouseUp;
137       break;
138     case CPDF_AAction::GetFocus:
139       eEventType = XFA_EVENT_Enter;
140       break;
141     case CPDF_AAction::LoseFocus:
142       eEventType = XFA_EVENT_Exit;
143       break;
144     case CPDF_AAction::PageOpen:
145       break;
146     case CPDF_AAction::PageClose:
147       break;
148     case CPDF_AAction::PageVisible:
149       break;
150     case CPDF_AAction::PageInvisible:
151       break;
152     case CPDF_AAction::KeyStroke:
153       if (!bWillCommit) {
154         eEventType = XFA_EVENT_Change;
155       }
156       break;
157     case CPDF_AAction::Validate:
158       eEventType = XFA_EVENT_Validate;
159       break;
160     case CPDF_AAction::OpenPage:
161     case CPDF_AAction::ClosePage:
162     case CPDF_AAction::Format:
163     case CPDF_AAction::Calculate:
164     case CPDF_AAction::CloseDocument:
165     case CPDF_AAction::SaveDocument:
166     case CPDF_AAction::DocumentSaved:
167     case CPDF_AAction::PrintDocument:
168     case CPDF_AAction::DocumentPrinted:
169       break;
170   }
171 
172   return eEventType;
173 }
174 
HasXFAAAction(PDFSDK_XFAAActionType eXFAAAT)175 FX_BOOL CPDFSDK_Widget::HasXFAAAction(PDFSDK_XFAAActionType eXFAAAT) {
176   if (IXFA_Widget* hWidget = this->GetMixXFAWidget()) {
177     if (IXFA_WidgetHandler* pXFAWidgetHandler = this->GetXFAWidgetHandler()) {
178       XFA_EVENTTYPE eEventType = GetXFAEventType(eXFAAAT);
179 
180       if ((eEventType == XFA_EVENT_Click || eEventType == XFA_EVENT_Change) &&
181           GetFieldType() == FIELDTYPE_RADIOBUTTON) {
182         if (IXFA_Widget* hGroupWidget = GetGroupMixXFAWidget()) {
183           CXFA_WidgetAcc* pAcc = pXFAWidgetHandler->GetDataAcc(hGroupWidget);
184           if (pXFAWidgetHandler->HasEvent(pAcc, eEventType))
185             return TRUE;
186         }
187       }
188 
189       {
190         CXFA_WidgetAcc* pAcc = pXFAWidgetHandler->GetDataAcc(hWidget);
191         return pXFAWidgetHandler->HasEvent(pAcc, eEventType);
192       }
193     }
194   }
195 
196   return FALSE;
197 }
198 
OnXFAAAction(PDFSDK_XFAAActionType eXFAAAT,PDFSDK_FieldAction & data,CPDFSDK_PageView * pPageView)199 FX_BOOL CPDFSDK_Widget::OnXFAAAction(PDFSDK_XFAAActionType eXFAAAT,
200                                      PDFSDK_FieldAction& data,
201                                      CPDFSDK_PageView* pPageView) {
202   CPDFSDK_Document* pSDKDoc = m_pPageView->GetSDKDocument();
203   CPDFXFA_Document* pDoc = pSDKDoc->GetXFADocument();
204   if (IXFA_Widget* hWidget = GetMixXFAWidget()) {
205     XFA_EVENTTYPE eEventType = GetXFAEventType(eXFAAAT);
206 
207     if (eEventType != XFA_EVENT_Unknown) {
208       if (IXFA_WidgetHandler* pXFAWidgetHandler = this->GetXFAWidgetHandler()) {
209         CXFA_EventParam param;
210         param.m_eType = eEventType;
211         param.m_wsChange = data.sChange;
212         param.m_iCommitKey = data.nCommitKey;
213         param.m_bShift = data.bShift;
214         param.m_iSelStart = data.nSelStart;
215         param.m_iSelEnd = data.nSelEnd;
216         param.m_wsFullText = data.sValue;
217         param.m_bKeyDown = data.bKeyDown;
218         param.m_bModifier = data.bModifier;
219         param.m_wsNewText = data.sValue;
220         if (data.nSelEnd > data.nSelStart)
221           param.m_wsNewText.Delete(data.nSelStart,
222                                    data.nSelEnd - data.nSelStart);
223         for (int i = 0; i < data.sChange.GetLength(); i++)
224           param.m_wsNewText.Insert(data.nSelStart, data.sChange[i]);
225         param.m_wsPrevText = data.sValue;
226 
227         if ((eEventType == XFA_EVENT_Click || eEventType == XFA_EVENT_Change) &&
228             GetFieldType() == FIELDTYPE_RADIOBUTTON) {
229           if (IXFA_Widget* hGroupWidget = GetGroupMixXFAWidget()) {
230             CXFA_WidgetAcc* pAcc = pXFAWidgetHandler->GetDataAcc(hGroupWidget);
231             param.m_pTarget = pAcc;
232             pXFAWidgetHandler->ProcessEvent(pAcc, &param);
233           }
234 
235           {
236             CXFA_WidgetAcc* pAcc = pXFAWidgetHandler->GetDataAcc(hWidget);
237             param.m_pTarget = pAcc;
238             int32_t nRet = pXFAWidgetHandler->ProcessEvent(pAcc, &param);
239             return nRet == XFA_EVENTERROR_Sucess;
240           }
241         } else {
242           CXFA_WidgetAcc* pAcc = pXFAWidgetHandler->GetDataAcc(hWidget);
243           param.m_pTarget = pAcc;
244           int32_t nRet = pXFAWidgetHandler->ProcessEvent(pAcc, &param);
245           return nRet == XFA_EVENTERROR_Sucess;
246         }
247 
248         if (IXFA_DocView* pDocView = pDoc->GetXFADocView()) {
249           pDocView->UpdateDocView();
250         }
251       }
252     }
253   }
254 
255   return FALSE;
256 }
257 
Synchronize(FX_BOOL bSynchronizeElse)258 void CPDFSDK_Widget::Synchronize(FX_BOOL bSynchronizeElse) {
259   if (IXFA_Widget* hWidget = this->GetMixXFAWidget()) {
260     if (IXFA_WidgetHandler* pXFAWidgetHandler = this->GetXFAWidgetHandler()) {
261       CPDF_FormField* pFormField = GetFormField();
262       ASSERT(pFormField != NULL);
263 
264       if (CXFA_WidgetAcc* pWidgetAcc = pXFAWidgetHandler->GetDataAcc(hWidget)) {
265         switch (GetFieldType()) {
266           case FIELDTYPE_CHECKBOX:
267           case FIELDTYPE_RADIOBUTTON: {
268             CPDF_FormControl* pFormCtrl = GetFormControl();
269             ASSERT(pFormCtrl != NULL);
270 
271             XFA_CHECKSTATE eCheckState =
272                 pFormCtrl->IsChecked() ? XFA_CHECKSTATE_On : XFA_CHECKSTATE_Off;
273             pWidgetAcc->SetCheckState(eCheckState);
274           } break;
275           case FIELDTYPE_TEXTFIELD:
276             pWidgetAcc->SetValue(pFormField->GetValue(), XFA_VALUEPICTURE_Edit);
277             break;
278           case FIELDTYPE_LISTBOX: {
279             pWidgetAcc->ClearAllSelections();
280 
281             for (int i = 0, sz = pFormField->CountSelectedItems(); i < sz;
282                  i++) {
283               int nIndex = pFormField->GetSelectedIndex(i);
284               if (nIndex > -1 && nIndex < pWidgetAcc->CountChoiceListItems())
285                 pWidgetAcc->SetItemState(nIndex, TRUE, FALSE);
286             }
287           } break;
288           case FIELDTYPE_COMBOBOX: {
289             pWidgetAcc->ClearAllSelections();
290 
291             for (int i = 0, sz = pFormField->CountSelectedItems(); i < sz;
292                  i++) {
293               int nIndex = pFormField->GetSelectedIndex(i);
294               if (nIndex > -1 && nIndex < pWidgetAcc->CountChoiceListItems())
295                 pWidgetAcc->SetItemState(nIndex, TRUE, FALSE);
296             }
297           }
298 
299             pWidgetAcc->SetValue(pFormField->GetValue(), XFA_VALUEPICTURE_Edit);
300             break;
301         }
302 
303         if (bSynchronizeElse)
304           pWidgetAcc->ProcessValueChanged();
305       }
306     }
307   }
308 }
309 
SynchronizeXFAValue()310 void CPDFSDK_Widget::SynchronizeXFAValue() {
311   CPDFSDK_Document* pSDKDoc = m_pPageView->GetSDKDocument();
312   CPDFXFA_Document* pDoc = pSDKDoc->GetXFADocument();
313   IXFA_DocView* pXFADocView = pDoc->GetXFADocView();
314   if (!pXFADocView)
315     return;
316 
317   if (IXFA_Widget* hWidget = GetMixXFAWidget()) {
318     if (GetXFAWidgetHandler()) {
319       CPDFSDK_Widget::SynchronizeXFAValue(pXFADocView, hWidget, GetFormField(),
320                                           GetFormControl());
321     }
322   }
323 }
324 
SynchronizeXFAItems()325 void CPDFSDK_Widget::SynchronizeXFAItems() {
326   CPDFSDK_Document* pSDKDoc = m_pPageView->GetSDKDocument();
327   CPDFXFA_Document* pDoc = pSDKDoc->GetXFADocument();
328   IXFA_DocView* pXFADocView = pDoc->GetXFADocView();
329   if (!pXFADocView)
330     return;
331 
332   if (IXFA_Widget* hWidget = GetMixXFAWidget()) {
333     if (GetXFAWidgetHandler())
334       SynchronizeXFAItems(pXFADocView, hWidget, GetFormField(), nullptr);
335   }
336 }
337 
SynchronizeXFAValue(IXFA_DocView * pXFADocView,IXFA_Widget * hWidget,CPDF_FormField * pFormField,CPDF_FormControl * pFormControl)338 void CPDFSDK_Widget::SynchronizeXFAValue(IXFA_DocView* pXFADocView,
339                                          IXFA_Widget* hWidget,
340                                          CPDF_FormField* pFormField,
341                                          CPDF_FormControl* pFormControl) {
342   ASSERT(pXFADocView != NULL);
343   ASSERT(hWidget != NULL);
344 
345   if (IXFA_WidgetHandler* pXFAWidgetHandler = pXFADocView->GetWidgetHandler()) {
346     ASSERT(pFormField != NULL);
347     ASSERT(pFormControl != NULL);
348 
349     switch (pFormField->GetFieldType()) {
350       case FIELDTYPE_CHECKBOX: {
351         if (CXFA_WidgetAcc* pWidgetAcc =
352                 pXFAWidgetHandler->GetDataAcc(hWidget)) {
353           FX_BOOL bChecked = pWidgetAcc->GetCheckState() == XFA_CHECKSTATE_On;
354 
355           pFormField->CheckControl(pFormField->GetControlIndex(pFormControl),
356                                    bChecked, TRUE);
357         }
358       } break;
359       case FIELDTYPE_RADIOBUTTON: {
360         if (CXFA_WidgetAcc* pWidgetAcc =
361                 pXFAWidgetHandler->GetDataAcc(hWidget)) {
362           FX_BOOL bChecked = pWidgetAcc->GetCheckState() == XFA_CHECKSTATE_On;
363 
364           pFormField->CheckControl(pFormField->GetControlIndex(pFormControl),
365                                    bChecked, TRUE);
366         }
367       } break;
368       case FIELDTYPE_TEXTFIELD: {
369         if (CXFA_WidgetAcc* pWidgetAcc =
370                 pXFAWidgetHandler->GetDataAcc(hWidget)) {
371           CFX_WideString sValue;
372           pWidgetAcc->GetValue(sValue, XFA_VALUEPICTURE_Display);
373           pFormField->SetValue(sValue, TRUE);
374         }
375       } break;
376       case FIELDTYPE_LISTBOX: {
377         pFormField->ClearSelection(FALSE);
378 
379         if (CXFA_WidgetAcc* pWidgetAcc =
380                 pXFAWidgetHandler->GetDataAcc(hWidget)) {
381           for (int i = 0, sz = pWidgetAcc->CountSelectedItems(); i < sz; i++) {
382             int nIndex = pWidgetAcc->GetSelectedItem(i);
383 
384             if (nIndex > -1 && nIndex < pFormField->CountOptions()) {
385               pFormField->SetItemSelection(nIndex, TRUE, TRUE);
386             }
387           }
388         }
389       } break;
390       case FIELDTYPE_COMBOBOX: {
391         pFormField->ClearSelection(FALSE);
392 
393         if (CXFA_WidgetAcc* pWidgetAcc =
394                 pXFAWidgetHandler->GetDataAcc(hWidget)) {
395           for (int i = 0, sz = pWidgetAcc->CountSelectedItems(); i < sz; i++) {
396             int nIndex = pWidgetAcc->GetSelectedItem(i);
397 
398             if (nIndex > -1 && nIndex < pFormField->CountOptions()) {
399               pFormField->SetItemSelection(nIndex, TRUE, TRUE);
400             }
401           }
402 
403           CFX_WideString sValue;
404           pWidgetAcc->GetValue(sValue, XFA_VALUEPICTURE_Display);
405           pFormField->SetValue(sValue, TRUE);
406         }
407       } break;
408     }
409   }
410 }
411 
SynchronizeXFAItems(IXFA_DocView * pXFADocView,IXFA_Widget * hWidget,CPDF_FormField * pFormField,CPDF_FormControl * pFormControl)412 void CPDFSDK_Widget::SynchronizeXFAItems(IXFA_DocView* pXFADocView,
413                                          IXFA_Widget* hWidget,
414                                          CPDF_FormField* pFormField,
415                                          CPDF_FormControl* pFormControl) {
416   ASSERT(pXFADocView != NULL);
417   ASSERT(hWidget != NULL);
418 
419   if (IXFA_WidgetHandler* pXFAWidgetHandler = pXFADocView->GetWidgetHandler()) {
420     ASSERT(pFormField != NULL);
421 
422     switch (pFormField->GetFieldType()) {
423       case FIELDTYPE_LISTBOX: {
424         pFormField->ClearSelection(FALSE);
425         pFormField->ClearOptions(TRUE);
426 
427         if (CXFA_WidgetAcc* pWidgetAcc =
428                 pXFAWidgetHandler->GetDataAcc(hWidget)) {
429           for (int i = 0, sz = pWidgetAcc->CountChoiceListItems(); i < sz;
430                i++) {
431             CFX_WideString swText;
432             pWidgetAcc->GetChoiceListItem(swText, i);
433 
434             pFormField->InsertOption(swText, i, TRUE);
435           }
436         }
437       } break;
438       case FIELDTYPE_COMBOBOX: {
439         pFormField->ClearSelection(FALSE);
440         pFormField->ClearOptions(FALSE);
441 
442         if (CXFA_WidgetAcc* pWidgetAcc =
443                 pXFAWidgetHandler->GetDataAcc(hWidget)) {
444           for (int i = 0, sz = pWidgetAcc->CountChoiceListItems(); i < sz;
445                i++) {
446             CFX_WideString swText;
447             pWidgetAcc->GetChoiceListItem(swText, i);
448 
449             pFormField->InsertOption(swText, i, FALSE);
450           }
451         }
452 
453         pFormField->SetValue(L"", TRUE);
454       } break;
455     }
456   }
457 }
458 #endif  // PDF_ENABLE_XFA
459 
IsWidgetAppearanceValid(CPDF_Annot::AppearanceMode mode)460 FX_BOOL CPDFSDK_Widget::IsWidgetAppearanceValid(
461     CPDF_Annot::AppearanceMode mode) {
462   CPDF_Dictionary* pAP = m_pAnnot->GetAnnotDict()->GetDict("AP");
463   if (!pAP)
464     return FALSE;
465 
466   // Choose the right sub-ap
467   const FX_CHAR* ap_entry = "N";
468   if (mode == CPDF_Annot::Down)
469     ap_entry = "D";
470   else if (mode == CPDF_Annot::Rollover)
471     ap_entry = "R";
472   if (!pAP->KeyExist(ap_entry))
473     ap_entry = "N";
474 
475   // Get the AP stream or subdirectory
476   CPDF_Object* psub = pAP->GetElementValue(ap_entry);
477   if (!psub)
478     return FALSE;
479 
480   int nFieldType = GetFieldType();
481   switch (nFieldType) {
482     case FIELDTYPE_PUSHBUTTON:
483     case FIELDTYPE_COMBOBOX:
484     case FIELDTYPE_LISTBOX:
485     case FIELDTYPE_TEXTFIELD:
486     case FIELDTYPE_SIGNATURE:
487       return psub->IsStream();
488     case FIELDTYPE_CHECKBOX:
489     case FIELDTYPE_RADIOBUTTON:
490       if (CPDF_Dictionary* pSubDict = psub->AsDictionary()) {
491         return pSubDict->GetStream(GetAppState()) != NULL;
492       }
493       return FALSE;
494   }
495   return TRUE;
496 }
497 
GetFieldType() const498 int CPDFSDK_Widget::GetFieldType() const {
499   return GetFormField()->GetFieldType();
500 }
501 
IsAppearanceValid()502 FX_BOOL CPDFSDK_Widget::IsAppearanceValid() {
503 #ifdef PDF_ENABLE_XFA
504   CPDFSDK_Document* pSDKDoc = m_pPageView->GetSDKDocument();
505   CPDFXFA_Document* pDoc = pSDKDoc->GetXFADocument();
506   int nDocType = pDoc->GetDocType();
507   if (nDocType != DOCTYPE_PDF && nDocType != DOCTYPE_STATIC_XFA)
508     return TRUE;
509 #endif  // PDF_ENABLE_XFA
510   return CPDFSDK_BAAnnot::IsAppearanceValid();
511 }
512 
GetFieldFlags() const513 int CPDFSDK_Widget::GetFieldFlags() const {
514   CPDF_InterForm* pPDFInterForm = m_pInterForm->GetInterForm();
515   CPDF_FormControl* pFormControl =
516       pPDFInterForm->GetControlByDict(m_pAnnot->GetAnnotDict());
517   CPDF_FormField* pFormField = pFormControl->GetField();
518   return pFormField->GetFieldFlags();
519 }
520 
GetSubType() const521 CFX_ByteString CPDFSDK_Widget::GetSubType() const {
522   int nType = GetFieldType();
523 
524   if (nType == FIELDTYPE_SIGNATURE)
525     return BFFT_SIGNATURE;
526   return CPDFSDK_Annot::GetSubType();
527 }
528 
GetFormField() const529 CPDF_FormField* CPDFSDK_Widget::GetFormField() const {
530   return GetFormControl()->GetField();
531 }
532 
GetFormControl() const533 CPDF_FormControl* CPDFSDK_Widget::GetFormControl() const {
534   CPDF_InterForm* pPDFInterForm = m_pInterForm->GetInterForm();
535   return pPDFInterForm->GetControlByDict(GetAnnotDict());
536 }
537 
GetFormControl(CPDF_InterForm * pInterForm,const CPDF_Dictionary * pAnnotDict)538 CPDF_FormControl* CPDFSDK_Widget::GetFormControl(
539     CPDF_InterForm* pInterForm,
540     const CPDF_Dictionary* pAnnotDict) {
541   ASSERT(pAnnotDict);
542   return pInterForm->GetControlByDict(pAnnotDict);
543 }
544 
GetRotate() const545 int CPDFSDK_Widget::GetRotate() const {
546   CPDF_FormControl* pCtrl = GetFormControl();
547   return pCtrl->GetRotation() % 360;
548 }
549 
550 #ifdef PDF_ENABLE_XFA
GetName() const551 CFX_WideString CPDFSDK_Widget::GetName() const {
552   CPDF_FormField* pFormField = GetFormField();
553   return pFormField->GetFullName();
554 }
555 #endif  // PDF_ENABLE_XFA
556 
GetFillColor(FX_COLORREF & color) const557 FX_BOOL CPDFSDK_Widget::GetFillColor(FX_COLORREF& color) const {
558   CPDF_FormControl* pFormCtrl = GetFormControl();
559   int iColorType = 0;
560   color = FX_ARGBTOCOLORREF(pFormCtrl->GetBackgroundColor(iColorType));
561 
562   return iColorType != COLORTYPE_TRANSPARENT;
563 }
564 
GetBorderColor(FX_COLORREF & color) const565 FX_BOOL CPDFSDK_Widget::GetBorderColor(FX_COLORREF& color) const {
566   CPDF_FormControl* pFormCtrl = GetFormControl();
567   int iColorType = 0;
568   color = FX_ARGBTOCOLORREF(pFormCtrl->GetBorderColor(iColorType));
569 
570   return iColorType != COLORTYPE_TRANSPARENT;
571 }
572 
GetTextColor(FX_COLORREF & color) const573 FX_BOOL CPDFSDK_Widget::GetTextColor(FX_COLORREF& color) const {
574   CPDF_FormControl* pFormCtrl = GetFormControl();
575   CPDF_DefaultAppearance da = pFormCtrl->GetDefaultAppearance();
576   if (da.HasColor()) {
577     FX_ARGB argb;
578     int iColorType = COLORTYPE_TRANSPARENT;
579     da.GetColor(argb, iColorType);
580     color = FX_ARGBTOCOLORREF(argb);
581 
582     return iColorType != COLORTYPE_TRANSPARENT;
583   }
584 
585   return FALSE;
586 }
587 
GetFontSize() const588 FX_FLOAT CPDFSDK_Widget::GetFontSize() const {
589   CPDF_FormControl* pFormCtrl = GetFormControl();
590   CPDF_DefaultAppearance pDa = pFormCtrl->GetDefaultAppearance();
591   CFX_ByteString csFont = "";
592   FX_FLOAT fFontSize = 0.0f;
593   pDa.GetFont(csFont, fFontSize);
594 
595   return fFontSize;
596 }
597 
GetSelectedIndex(int nIndex) const598 int CPDFSDK_Widget::GetSelectedIndex(int nIndex) const {
599 #ifdef PDF_ENABLE_XFA
600   if (IXFA_Widget* hWidget = this->GetMixXFAWidget()) {
601     if (IXFA_WidgetHandler* pXFAWidgetHandler = this->GetXFAWidgetHandler()) {
602       if (CXFA_WidgetAcc* pWidgetAcc = pXFAWidgetHandler->GetDataAcc(hWidget)) {
603         if (nIndex < pWidgetAcc->CountSelectedItems())
604           return pWidgetAcc->GetSelectedItem(nIndex);
605       }
606     }
607   }
608 #endif  // PDF_ENABLE_XFA
609   CPDF_FormField* pFormField = GetFormField();
610   return pFormField->GetSelectedIndex(nIndex);
611 }
612 
613 #ifdef PDF_ENABLE_XFA
GetValue(FX_BOOL bDisplay) const614 CFX_WideString CPDFSDK_Widget::GetValue(FX_BOOL bDisplay) const {
615   if (IXFA_Widget* hWidget = this->GetMixXFAWidget()) {
616     if (IXFA_WidgetHandler* pXFAWidgetHandler = this->GetXFAWidgetHandler()) {
617       if (CXFA_WidgetAcc* pWidgetAcc = pXFAWidgetHandler->GetDataAcc(hWidget)) {
618         CFX_WideString sValue;
619         pWidgetAcc->GetValue(sValue, bDisplay ? XFA_VALUEPICTURE_Display
620                                               : XFA_VALUEPICTURE_Edit);
621         return sValue;
622       }
623     }
624   }
625 #else
626 CFX_WideString CPDFSDK_Widget::GetValue() const {
627 #endif  // PDF_ENABLE_XFA
628   CPDF_FormField* pFormField = GetFormField();
629   return pFormField->GetValue();
630 }
631 
632 CFX_WideString CPDFSDK_Widget::GetDefaultValue() const {
633   CPDF_FormField* pFormField = GetFormField();
634   return pFormField->GetDefaultValue();
635 }
636 
637 CFX_WideString CPDFSDK_Widget::GetOptionLabel(int nIndex) const {
638   CPDF_FormField* pFormField = GetFormField();
639   return pFormField->GetOptionLabel(nIndex);
640 }
641 
642 int CPDFSDK_Widget::CountOptions() const {
643   CPDF_FormField* pFormField = GetFormField();
644   return pFormField->CountOptions();
645 }
646 
647 FX_BOOL CPDFSDK_Widget::IsOptionSelected(int nIndex) const {
648 #ifdef PDF_ENABLE_XFA
649   if (IXFA_Widget* hWidget = this->GetMixXFAWidget()) {
650     if (IXFA_WidgetHandler* pXFAWidgetHandler = this->GetXFAWidgetHandler()) {
651       if (CXFA_WidgetAcc* pWidgetAcc = pXFAWidgetHandler->GetDataAcc(hWidget)) {
652         if (nIndex > -1 && nIndex < pWidgetAcc->CountChoiceListItems())
653           return pWidgetAcc->GetItemState(nIndex);
654 
655         return FALSE;
656       }
657     }
658   }
659 #endif  // PDF_ENABLE_XFA
660   CPDF_FormField* pFormField = GetFormField();
661   return pFormField->IsItemSelected(nIndex);
662 }
663 
664 int CPDFSDK_Widget::GetTopVisibleIndex() const {
665   CPDF_FormField* pFormField = GetFormField();
666   return pFormField->GetTopVisibleIndex();
667 }
668 
669 FX_BOOL CPDFSDK_Widget::IsChecked() const {
670 #ifdef PDF_ENABLE_XFA
671   if (IXFA_WidgetHandler* pXFAWidgetHandler = this->GetXFAWidgetHandler()) {
672     if (IXFA_Widget* hWidget = this->GetMixXFAWidget()) {
673       if (CXFA_WidgetAcc* pWidgetAcc = pXFAWidgetHandler->GetDataAcc(hWidget)) {
674         FX_BOOL bChecked = pWidgetAcc->GetCheckState() == XFA_CHECKSTATE_On;
675         return bChecked;
676       }
677     }
678   }
679 #endif  // PDF_ENABLE_XFA
680   CPDF_FormControl* pFormCtrl = GetFormControl();
681   return pFormCtrl->IsChecked();
682 }
683 
684 int CPDFSDK_Widget::GetAlignment() const {
685   CPDF_FormControl* pFormCtrl = GetFormControl();
686   return pFormCtrl->GetControlAlignment();
687 }
688 
689 int CPDFSDK_Widget::GetMaxLen() const {
690   CPDF_FormField* pFormField = GetFormField();
691   return pFormField->GetMaxLen();
692 }
693 
694 void CPDFSDK_Widget::SetCheck(FX_BOOL bChecked, FX_BOOL bNotify) {
695   CPDF_FormControl* pFormCtrl = GetFormControl();
696   CPDF_FormField* pFormField = pFormCtrl->GetField();
697   pFormField->CheckControl(pFormField->GetControlIndex(pFormCtrl), bChecked,
698                            bNotify);
699 #ifdef PDF_ENABLE_XFA
700   if (!IsWidgetAppearanceValid(CPDF_Annot::Normal))
701     ResetAppearance(TRUE);
702   if (!bNotify)
703     Synchronize(TRUE);
704 #endif  // PDF_ENABLE_XFA
705 }
706 
707 void CPDFSDK_Widget::SetValue(const CFX_WideString& sValue, FX_BOOL bNotify) {
708   CPDF_FormField* pFormField = GetFormField();
709   pFormField->SetValue(sValue, bNotify);
710 #ifdef PDF_ENABLE_XFA
711   if (!bNotify)
712     Synchronize(TRUE);
713 #endif  // PDF_ENABLE_XFA
714 }
715 
716 void CPDFSDK_Widget::SetDefaultValue(const CFX_WideString& sValue) {}
717 void CPDFSDK_Widget::SetOptionSelection(int index,
718                                         FX_BOOL bSelected,
719                                         FX_BOOL bNotify) {
720   CPDF_FormField* pFormField = GetFormField();
721   pFormField->SetItemSelection(index, bSelected, bNotify);
722 #ifdef PDF_ENABLE_XFA
723   if (!bNotify)
724     Synchronize(TRUE);
725 #endif  // PDF_ENABLE_XFA
726 }
727 
728 void CPDFSDK_Widget::ClearSelection(FX_BOOL bNotify) {
729   CPDF_FormField* pFormField = GetFormField();
730   pFormField->ClearSelection(bNotify);
731 #ifdef PDF_ENABLE_XFA
732   if (!bNotify)
733     Synchronize(TRUE);
734 #endif  // PDF_ENABLE_XFA
735 }
736 
737 void CPDFSDK_Widget::SetTopVisibleIndex(int index) {}
738 
739 void CPDFSDK_Widget::SetAppModified() {
740   m_bAppModified = TRUE;
741 }
742 
743 void CPDFSDK_Widget::ClearAppModified() {
744   m_bAppModified = FALSE;
745 }
746 
747 FX_BOOL CPDFSDK_Widget::IsAppModified() const {
748   return m_bAppModified;
749 }
750 
751 #ifdef PDF_ENABLE_XFA
752 void CPDFSDK_Widget::ResetAppearance(FX_BOOL bValueChanged) {
753   switch (GetFieldType()) {
754     case FIELDTYPE_TEXTFIELD:
755     case FIELDTYPE_COMBOBOX: {
756       FX_BOOL bFormated = FALSE;
757       CFX_WideString sValue = this->OnFormat(bFormated);
758       if (bFormated)
759         this->ResetAppearance(sValue, TRUE);
760       else
761         this->ResetAppearance(NULL, TRUE);
762     } break;
763     default:
764       this->ResetAppearance(NULL, FALSE);
765       break;
766   }
767 }
768 #endif  // PDF_ENABLE_XFA
769 
770 void CPDFSDK_Widget::ResetAppearance(const FX_WCHAR* sValue,
771                                      FX_BOOL bValueChanged) {
772   SetAppModified();
773 
774   m_nAppAge++;
775   if (m_nAppAge > 999999)
776     m_nAppAge = 0;
777   if (bValueChanged)
778     m_nValueAge++;
779 
780   int nFieldType = GetFieldType();
781 
782   switch (nFieldType) {
783     case FIELDTYPE_PUSHBUTTON:
784       ResetAppearance_PushButton();
785       break;
786     case FIELDTYPE_CHECKBOX:
787       ResetAppearance_CheckBox();
788       break;
789     case FIELDTYPE_RADIOBUTTON:
790       ResetAppearance_RadioButton();
791       break;
792     case FIELDTYPE_COMBOBOX:
793       ResetAppearance_ComboBox(sValue);
794       break;
795     case FIELDTYPE_LISTBOX:
796       ResetAppearance_ListBox();
797       break;
798     case FIELDTYPE_TEXTFIELD:
799       ResetAppearance_TextField(sValue);
800       break;
801   }
802 
803   m_pAnnot->ClearCachedAP();
804 }
805 
806 CFX_WideString CPDFSDK_Widget::OnFormat(FX_BOOL& bFormated) {
807   CPDF_FormField* pFormField = GetFormField();
808   ASSERT(pFormField);
809   return m_pInterForm->OnFormat(pFormField, bFormated);
810 }
811 
812 void CPDFSDK_Widget::ResetFieldAppearance(FX_BOOL bValueChanged) {
813   CPDF_FormField* pFormField = GetFormField();
814   ASSERT(pFormField);
815   m_pInterForm->ResetFieldAppearance(pFormField, NULL, bValueChanged);
816 }
817 
818 void CPDFSDK_Widget::DrawAppearance(CFX_RenderDevice* pDevice,
819                                     const CFX_Matrix* pUser2Device,
820                                     CPDF_Annot::AppearanceMode mode,
821                                     const CPDF_RenderOptions* pOptions) {
822   int nFieldType = GetFieldType();
823 
824   if ((nFieldType == FIELDTYPE_CHECKBOX ||
825        nFieldType == FIELDTYPE_RADIOBUTTON) &&
826       mode == CPDF_Annot::Normal &&
827       !IsWidgetAppearanceValid(CPDF_Annot::Normal)) {
828     CFX_PathData pathData;
829 
830     CPDF_Rect rcAnnot = GetRect();
831 
832     pathData.AppendRect(rcAnnot.left, rcAnnot.bottom, rcAnnot.right,
833                         rcAnnot.top);
834 
835     CFX_GraphStateData gsd;
836     gsd.m_LineWidth = 0.0f;
837 
838     pDevice->DrawPath(&pathData, pUser2Device, &gsd, 0, 0xFFAAAAAA,
839                       FXFILL_ALTERNATE);
840   } else {
841     CPDFSDK_BAAnnot::DrawAppearance(pDevice, pUser2Device, mode, pOptions);
842   }
843 }
844 
845 void CPDFSDK_Widget::UpdateField() {
846   CPDF_FormField* pFormField = GetFormField();
847   ASSERT(pFormField);
848   m_pInterForm->UpdateField(pFormField);
849 }
850 
851 void CPDFSDK_Widget::DrawShadow(CFX_RenderDevice* pDevice,
852                                 CPDFSDK_PageView* pPageView) {
853   int nFieldType = GetFieldType();
854   if (m_pInterForm->IsNeedHighLight(nFieldType)) {
855     CPDF_Rect rc = GetRect();
856     FX_COLORREF color = m_pInterForm->GetHighlightColor(nFieldType);
857     uint8_t alpha = m_pInterForm->GetHighlightAlpha();
858 
859     CFX_FloatRect rcDevice;
860     ASSERT(m_pInterForm->GetDocument());
861     CPDFDoc_Environment* pEnv = m_pInterForm->GetDocument()->GetEnv();
862     if (!pEnv)
863       return;
864     CFX_Matrix page2device;
865     pPageView->GetCurrentMatrix(page2device);
866     page2device.Transform(((FX_FLOAT)rc.left), ((FX_FLOAT)rc.bottom),
867                           rcDevice.left, rcDevice.bottom);
868     page2device.Transform(((FX_FLOAT)rc.right), ((FX_FLOAT)rc.top),
869                           rcDevice.right, rcDevice.top);
870 
871     rcDevice.Normalize();
872 
873     FX_ARGB argb = ArgbEncode((int)alpha, color);
874     FX_RECT rcDev((int)rcDevice.left, (int)rcDevice.top, (int)rcDevice.right,
875                   (int)rcDevice.bottom);
876     pDevice->FillRect(&rcDev, argb);
877   }
878 }
879 
880 void CPDFSDK_Widget::ResetAppearance_PushButton() {
881   CPDF_FormControl* pControl = GetFormControl();
882   CPDF_Rect rcWindow = GetRotatedRect();
883   int32_t nLayout = 0;
884   switch (pControl->GetTextPosition()) {
885     case TEXTPOS_ICON:
886       nLayout = PPBL_ICON;
887       break;
888     case TEXTPOS_BELOW:
889       nLayout = PPBL_ICONTOPLABELBOTTOM;
890       break;
891     case TEXTPOS_ABOVE:
892       nLayout = PPBL_LABELTOPICONBOTTOM;
893       break;
894     case TEXTPOS_RIGHT:
895       nLayout = PPBL_ICONLEFTLABELRIGHT;
896       break;
897     case TEXTPOS_LEFT:
898       nLayout = PPBL_LABELLEFTICONRIGHT;
899       break;
900     case TEXTPOS_OVERLAID:
901       nLayout = PPBL_LABELOVERICON;
902       break;
903     default:
904       nLayout = PPBL_LABEL;
905       break;
906   }
907 
908   CPWL_Color crBackground, crBorder;
909 
910   int iColorType;
911   FX_FLOAT fc[4];
912 
913   pControl->GetOriginalBackgroundColor(iColorType, fc);
914   if (iColorType > 0)
915     crBackground = CPWL_Color(iColorType, fc[0], fc[1], fc[2], fc[3]);
916 
917   pControl->GetOriginalBorderColor(iColorType, fc);
918   if (iColorType > 0)
919     crBorder = CPWL_Color(iColorType, fc[0], fc[1], fc[2], fc[3]);
920 
921   FX_FLOAT fBorderWidth = (FX_FLOAT)GetBorderWidth();
922   int32_t nBorderStyle = 0;
923   CPWL_Dash dsBorder(3, 0, 0);
924   CPWL_Color crLeftTop, crRightBottom;
925 
926   switch (GetBorderStyle()) {
927     case BBS_DASH:
928       nBorderStyle = PBS_DASH;
929       dsBorder = CPWL_Dash(3, 3, 0);
930       break;
931     case BBS_BEVELED:
932       nBorderStyle = PBS_BEVELED;
933       fBorderWidth *= 2;
934       crLeftTop = CPWL_Color(COLORTYPE_GRAY, 1);
935       crRightBottom = CPWL_Utils::DevideColor(crBackground, 2);
936       break;
937     case BBS_INSET:
938       nBorderStyle = PBS_INSET;
939       fBorderWidth *= 2;
940       crLeftTop = CPWL_Color(COLORTYPE_GRAY, 0.5);
941       crRightBottom = CPWL_Color(COLORTYPE_GRAY, 0.75);
942       break;
943     case BBS_UNDERLINE:
944       nBorderStyle = PBS_UNDERLINED;
945       break;
946     default:
947       nBorderStyle = PBS_SOLID;
948       break;
949   }
950 
951   CPDF_Rect rcClient = CPWL_Utils::DeflateRect(rcWindow, fBorderWidth);
952 
953   CPWL_Color crText(COLORTYPE_GRAY, 0);
954 
955   FX_FLOAT fFontSize = 12.0f;
956   CFX_ByteString csNameTag;
957 
958   CPDF_DefaultAppearance da = pControl->GetDefaultAppearance();
959   if (da.HasColor()) {
960     da.GetColor(iColorType, fc);
961     crText = CPWL_Color(iColorType, fc[0], fc[1], fc[2], fc[3]);
962   }
963 
964   if (da.HasFont())
965     da.GetFont(csNameTag, fFontSize);
966 
967   CFX_WideString csWCaption;
968   CFX_WideString csNormalCaption, csRolloverCaption, csDownCaption;
969 
970   if (pControl->HasMKEntry("CA")) {
971     csNormalCaption = pControl->GetNormalCaption();
972   }
973   if (pControl->HasMKEntry("RC")) {
974     csRolloverCaption = pControl->GetRolloverCaption();
975   }
976   if (pControl->HasMKEntry("AC")) {
977     csDownCaption = pControl->GetDownCaption();
978   }
979 
980   CPDF_Stream* pNormalIcon = NULL;
981   CPDF_Stream* pRolloverIcon = NULL;
982   CPDF_Stream* pDownIcon = NULL;
983 
984   if (pControl->HasMKEntry("I")) {
985     pNormalIcon = pControl->GetNormalIcon();
986   }
987   if (pControl->HasMKEntry("RI")) {
988     pRolloverIcon = pControl->GetRolloverIcon();
989   }
990   if (pControl->HasMKEntry("IX")) {
991     pDownIcon = pControl->GetDownIcon();
992   }
993 
994   if (pNormalIcon) {
995     if (CPDF_Dictionary* pImageDict = pNormalIcon->GetDict()) {
996       if (pImageDict->GetString("Name").IsEmpty())
997         pImageDict->SetAtString("Name", "ImgA");
998     }
999   }
1000 
1001   if (pRolloverIcon) {
1002     if (CPDF_Dictionary* pImageDict = pRolloverIcon->GetDict()) {
1003       if (pImageDict->GetString("Name").IsEmpty())
1004         pImageDict->SetAtString("Name", "ImgB");
1005     }
1006   }
1007 
1008   if (pDownIcon) {
1009     if (CPDF_Dictionary* pImageDict = pDownIcon->GetDict()) {
1010       if (pImageDict->GetString("Name").IsEmpty())
1011         pImageDict->SetAtString("Name", "ImgC");
1012     }
1013   }
1014 
1015   CPDF_IconFit iconFit = pControl->GetIconFit();
1016 
1017   CPDFSDK_Document* pDoc = m_pInterForm->GetDocument();
1018   CPDFDoc_Environment* pEnv = pDoc->GetEnv();
1019 
1020   CBA_FontMap font_map(this, pEnv->GetSysHandler());
1021   font_map.SetAPType("N");
1022 
1023   CFX_ByteString csAP =
1024       CPWL_Utils::GetRectFillAppStream(rcWindow, crBackground) +
1025       CPWL_Utils::GetBorderAppStream(rcWindow, fBorderWidth, crBorder,
1026                                      crLeftTop, crRightBottom, nBorderStyle,
1027                                      dsBorder) +
1028       CPWL_Utils::GetPushButtonAppStream(
1029           iconFit.GetFittingBounds() ? rcWindow : rcClient, &font_map,
1030           pNormalIcon, iconFit, csNormalCaption, crText, fFontSize, nLayout);
1031 
1032   WriteAppearance("N", GetRotatedRect(), GetMatrix(), csAP);
1033   if (pNormalIcon)
1034     AddImageToAppearance("N", pNormalIcon);
1035 
1036   CPDF_FormControl::HighlightingMode eHLM = pControl->GetHighlightingMode();
1037   if (eHLM == CPDF_FormControl::Push || eHLM == CPDF_FormControl::Toggle) {
1038     if (csRolloverCaption.IsEmpty() && !pRolloverIcon) {
1039       csRolloverCaption = csNormalCaption;
1040       pRolloverIcon = pNormalIcon;
1041     }
1042 
1043     font_map.SetAPType("R");
1044 
1045     csAP = CPWL_Utils::GetRectFillAppStream(rcWindow, crBackground) +
1046            CPWL_Utils::GetBorderAppStream(rcWindow, fBorderWidth, crBorder,
1047                                           crLeftTop, crRightBottom,
1048                                           nBorderStyle, dsBorder) +
1049            CPWL_Utils::GetPushButtonAppStream(
1050                iconFit.GetFittingBounds() ? rcWindow : rcClient, &font_map,
1051                pRolloverIcon, iconFit, csRolloverCaption, crText, fFontSize,
1052                nLayout);
1053 
1054     WriteAppearance("R", GetRotatedRect(), GetMatrix(), csAP);
1055     if (pRolloverIcon)
1056       AddImageToAppearance("R", pRolloverIcon);
1057 
1058     if (csDownCaption.IsEmpty() && !pDownIcon) {
1059       csDownCaption = csNormalCaption;
1060       pDownIcon = pNormalIcon;
1061     }
1062 
1063     switch (nBorderStyle) {
1064       case PBS_BEVELED: {
1065         CPWL_Color crTemp = crLeftTop;
1066         crLeftTop = crRightBottom;
1067         crRightBottom = crTemp;
1068       } break;
1069       case PBS_INSET:
1070         crLeftTop = CPWL_Color(COLORTYPE_GRAY, 0);
1071         crRightBottom = CPWL_Color(COLORTYPE_GRAY, 1);
1072         break;
1073     }
1074 
1075     font_map.SetAPType("D");
1076 
1077     csAP = CPWL_Utils::GetRectFillAppStream(
1078                rcWindow, CPWL_Utils::SubstractColor(crBackground, 0.25f)) +
1079            CPWL_Utils::GetBorderAppStream(rcWindow, fBorderWidth, crBorder,
1080                                           crLeftTop, crRightBottom,
1081                                           nBorderStyle, dsBorder) +
1082            CPWL_Utils::GetPushButtonAppStream(
1083                iconFit.GetFittingBounds() ? rcWindow : rcClient, &font_map,
1084                pDownIcon, iconFit, csDownCaption, crText, fFontSize, nLayout);
1085 
1086     WriteAppearance("D", GetRotatedRect(), GetMatrix(), csAP);
1087     if (pDownIcon)
1088       AddImageToAppearance("D", pDownIcon);
1089   } else {
1090     RemoveAppearance("D");
1091     RemoveAppearance("R");
1092   }
1093 }
1094 
1095 void CPDFSDK_Widget::ResetAppearance_CheckBox() {
1096   CPDF_FormControl* pControl = GetFormControl();
1097   CPWL_Color crBackground, crBorder, crText;
1098   int iColorType;
1099   FX_FLOAT fc[4];
1100 
1101   pControl->GetOriginalBackgroundColor(iColorType, fc);
1102   if (iColorType > 0)
1103     crBackground = CPWL_Color(iColorType, fc[0], fc[1], fc[2], fc[3]);
1104 
1105   pControl->GetOriginalBorderColor(iColorType, fc);
1106   if (iColorType > 0)
1107     crBorder = CPWL_Color(iColorType, fc[0], fc[1], fc[2], fc[3]);
1108 
1109   FX_FLOAT fBorderWidth = (FX_FLOAT)GetBorderWidth();
1110   int32_t nBorderStyle = 0;
1111   CPWL_Dash dsBorder(3, 0, 0);
1112   CPWL_Color crLeftTop, crRightBottom;
1113 
1114   switch (GetBorderStyle()) {
1115     case BBS_DASH:
1116       nBorderStyle = PBS_DASH;
1117       dsBorder = CPWL_Dash(3, 3, 0);
1118       break;
1119     case BBS_BEVELED:
1120       nBorderStyle = PBS_BEVELED;
1121       fBorderWidth *= 2;
1122       crLeftTop = CPWL_Color(COLORTYPE_GRAY, 1);
1123       crRightBottom = CPWL_Utils::DevideColor(crBackground, 2);
1124       break;
1125     case BBS_INSET:
1126       nBorderStyle = PBS_INSET;
1127       fBorderWidth *= 2;
1128       crLeftTop = CPWL_Color(COLORTYPE_GRAY, 0.5);
1129       crRightBottom = CPWL_Color(COLORTYPE_GRAY, 0.75);
1130       break;
1131     case BBS_UNDERLINE:
1132       nBorderStyle = PBS_UNDERLINED;
1133       break;
1134     default:
1135       nBorderStyle = PBS_SOLID;
1136       break;
1137   }
1138 
1139   CPDF_Rect rcWindow = GetRotatedRect();
1140   CPDF_Rect rcClient = CPWL_Utils::DeflateRect(rcWindow, fBorderWidth);
1141 
1142   CPDF_DefaultAppearance da = pControl->GetDefaultAppearance();
1143   if (da.HasColor()) {
1144     da.GetColor(iColorType, fc);
1145     crText = CPWL_Color(iColorType, fc[0], fc[1], fc[2], fc[3]);
1146   }
1147 
1148   int32_t nStyle = 0;
1149 
1150   CFX_WideString csWCaption = pControl->GetNormalCaption();
1151   if (csWCaption.GetLength() > 0) {
1152     switch (csWCaption[0]) {
1153       case L'l':
1154         nStyle = PCS_CIRCLE;
1155         break;
1156       case L'8':
1157         nStyle = PCS_CROSS;
1158         break;
1159       case L'u':
1160         nStyle = PCS_DIAMOND;
1161         break;
1162       case L'n':
1163         nStyle = PCS_SQUARE;
1164         break;
1165       case L'H':
1166         nStyle = PCS_STAR;
1167         break;
1168       default:  // L'4'
1169         nStyle = PCS_CHECK;
1170         break;
1171     }
1172   } else {
1173     nStyle = PCS_CHECK;
1174   }
1175 
1176   CFX_ByteString csAP_N_ON =
1177       CPWL_Utils::GetRectFillAppStream(rcWindow, crBackground) +
1178       CPWL_Utils::GetBorderAppStream(rcWindow, fBorderWidth, crBorder,
1179                                      crLeftTop, crRightBottom, nBorderStyle,
1180                                      dsBorder);
1181 
1182   CFX_ByteString csAP_N_OFF = csAP_N_ON;
1183 
1184   switch (nBorderStyle) {
1185     case PBS_BEVELED: {
1186       CPWL_Color crTemp = crLeftTop;
1187       crLeftTop = crRightBottom;
1188       crRightBottom = crTemp;
1189     } break;
1190     case PBS_INSET:
1191       crLeftTop = CPWL_Color(COLORTYPE_GRAY, 0);
1192       crRightBottom = CPWL_Color(COLORTYPE_GRAY, 1);
1193       break;
1194   }
1195 
1196   CFX_ByteString csAP_D_ON =
1197       CPWL_Utils::GetRectFillAppStream(
1198           rcWindow, CPWL_Utils::SubstractColor(crBackground, 0.25f)) +
1199       CPWL_Utils::GetBorderAppStream(rcWindow, fBorderWidth, crBorder,
1200                                      crLeftTop, crRightBottom, nBorderStyle,
1201                                      dsBorder);
1202 
1203   CFX_ByteString csAP_D_OFF = csAP_D_ON;
1204 
1205   csAP_N_ON += CPWL_Utils::GetCheckBoxAppStream(rcClient, nStyle, crText);
1206   csAP_D_ON += CPWL_Utils::GetCheckBoxAppStream(rcClient, nStyle, crText);
1207 
1208   WriteAppearance("N", GetRotatedRect(), GetMatrix(), csAP_N_ON,
1209                   pControl->GetCheckedAPState());
1210   WriteAppearance("N", GetRotatedRect(), GetMatrix(), csAP_N_OFF, "Off");
1211 
1212   WriteAppearance("D", GetRotatedRect(), GetMatrix(), csAP_D_ON,
1213                   pControl->GetCheckedAPState());
1214   WriteAppearance("D", GetRotatedRect(), GetMatrix(), csAP_D_OFF, "Off");
1215 
1216   CFX_ByteString csAS = GetAppState();
1217   if (csAS.IsEmpty())
1218     SetAppState("Off");
1219 }
1220 
1221 void CPDFSDK_Widget::ResetAppearance_RadioButton() {
1222   CPDF_FormControl* pControl = GetFormControl();
1223   CPWL_Color crBackground, crBorder, crText;
1224   int iColorType;
1225   FX_FLOAT fc[4];
1226 
1227   pControl->GetOriginalBackgroundColor(iColorType, fc);
1228   if (iColorType > 0)
1229     crBackground = CPWL_Color(iColorType, fc[0], fc[1], fc[2], fc[3]);
1230 
1231   pControl->GetOriginalBorderColor(iColorType, fc);
1232   if (iColorType > 0)
1233     crBorder = CPWL_Color(iColorType, fc[0], fc[1], fc[2], fc[3]);
1234 
1235   FX_FLOAT fBorderWidth = (FX_FLOAT)GetBorderWidth();
1236   int32_t nBorderStyle = 0;
1237   CPWL_Dash dsBorder(3, 0, 0);
1238   CPWL_Color crLeftTop, crRightBottom;
1239 
1240   switch (GetBorderStyle()) {
1241     case BBS_DASH:
1242       nBorderStyle = PBS_DASH;
1243       dsBorder = CPWL_Dash(3, 3, 0);
1244       break;
1245     case BBS_BEVELED:
1246       nBorderStyle = PBS_BEVELED;
1247       fBorderWidth *= 2;
1248       crLeftTop = CPWL_Color(COLORTYPE_GRAY, 1);
1249       crRightBottom = CPWL_Utils::DevideColor(crBackground, 2);
1250       break;
1251     case BBS_INSET:
1252       nBorderStyle = PBS_INSET;
1253       fBorderWidth *= 2;
1254       crLeftTop = CPWL_Color(COLORTYPE_GRAY, 0.5);
1255       crRightBottom = CPWL_Color(COLORTYPE_GRAY, 0.75);
1256       break;
1257     case BBS_UNDERLINE:
1258       nBorderStyle = PBS_UNDERLINED;
1259       break;
1260     default:
1261       nBorderStyle = PBS_SOLID;
1262       break;
1263   }
1264 
1265   CPDF_Rect rcWindow = GetRotatedRect();
1266   CPDF_Rect rcClient = CPWL_Utils::DeflateRect(rcWindow, fBorderWidth);
1267 
1268   CPDF_DefaultAppearance da = pControl->GetDefaultAppearance();
1269   if (da.HasColor()) {
1270     da.GetColor(iColorType, fc);
1271     crText = CPWL_Color(iColorType, fc[0], fc[1], fc[2], fc[3]);
1272   }
1273 
1274   int32_t nStyle = 0;
1275 
1276   CFX_WideString csWCaption = pControl->GetNormalCaption();
1277   if (csWCaption.GetLength() > 0) {
1278     switch (csWCaption[0]) {
1279       default:  // L'l':
1280         nStyle = PCS_CIRCLE;
1281         break;
1282       case L'8':
1283         nStyle = PCS_CROSS;
1284         break;
1285       case L'u':
1286         nStyle = PCS_DIAMOND;
1287         break;
1288       case L'n':
1289         nStyle = PCS_SQUARE;
1290         break;
1291       case L'H':
1292         nStyle = PCS_STAR;
1293         break;
1294       case L'4':
1295         nStyle = PCS_CHECK;
1296         break;
1297     }
1298   } else {
1299     nStyle = PCS_CIRCLE;
1300   }
1301 
1302   CFX_ByteString csAP_N_ON;
1303 
1304   CPDF_Rect rcCenter =
1305       CPWL_Utils::DeflateRect(CPWL_Utils::GetCenterSquare(rcWindow), 1.0f);
1306 
1307   if (nStyle == PCS_CIRCLE) {
1308     if (nBorderStyle == PBS_BEVELED) {
1309       crLeftTop = CPWL_Color(COLORTYPE_GRAY, 1);
1310       crRightBottom = CPWL_Utils::SubstractColor(crBackground, 0.25f);
1311     } else if (nBorderStyle == PBS_INSET) {
1312       crLeftTop = CPWL_Color(COLORTYPE_GRAY, 0.5f);
1313       crRightBottom = CPWL_Color(COLORTYPE_GRAY, 0.75f);
1314     }
1315 
1316     csAP_N_ON = CPWL_Utils::GetCircleFillAppStream(rcCenter, crBackground) +
1317                 CPWL_Utils::GetCircleBorderAppStream(
1318                     rcCenter, fBorderWidth, crBorder, crLeftTop, crRightBottom,
1319                     nBorderStyle, dsBorder);
1320   } else {
1321     csAP_N_ON = CPWL_Utils::GetRectFillAppStream(rcWindow, crBackground) +
1322                 CPWL_Utils::GetBorderAppStream(rcWindow, fBorderWidth, crBorder,
1323                                                crLeftTop, crRightBottom,
1324                                                nBorderStyle, dsBorder);
1325   }
1326 
1327   CFX_ByteString csAP_N_OFF = csAP_N_ON;
1328 
1329   switch (nBorderStyle) {
1330     case PBS_BEVELED: {
1331       CPWL_Color crTemp = crLeftTop;
1332       crLeftTop = crRightBottom;
1333       crRightBottom = crTemp;
1334     } break;
1335     case PBS_INSET:
1336       crLeftTop = CPWL_Color(COLORTYPE_GRAY, 0);
1337       crRightBottom = CPWL_Color(COLORTYPE_GRAY, 1);
1338       break;
1339   }
1340 
1341   CFX_ByteString csAP_D_ON;
1342 
1343   if (nStyle == PCS_CIRCLE) {
1344     CPWL_Color crBK = CPWL_Utils::SubstractColor(crBackground, 0.25f);
1345     if (nBorderStyle == PBS_BEVELED) {
1346       crLeftTop = CPWL_Utils::SubstractColor(crBackground, 0.25f);
1347       crRightBottom = CPWL_Color(COLORTYPE_GRAY, 1);
1348       crBK = crBackground;
1349     } else if (nBorderStyle == PBS_INSET) {
1350       crLeftTop = CPWL_Color(COLORTYPE_GRAY, 0);
1351       crRightBottom = CPWL_Color(COLORTYPE_GRAY, 1);
1352     }
1353 
1354     csAP_D_ON = CPWL_Utils::GetCircleFillAppStream(rcCenter, crBK) +
1355                 CPWL_Utils::GetCircleBorderAppStream(
1356                     rcCenter, fBorderWidth, crBorder, crLeftTop, crRightBottom,
1357                     nBorderStyle, dsBorder);
1358   } else {
1359     csAP_D_ON = CPWL_Utils::GetRectFillAppStream(
1360                     rcWindow, CPWL_Utils::SubstractColor(crBackground, 0.25f)) +
1361                 CPWL_Utils::GetBorderAppStream(rcWindow, fBorderWidth, crBorder,
1362                                                crLeftTop, crRightBottom,
1363                                                nBorderStyle, dsBorder);
1364   }
1365 
1366   CFX_ByteString csAP_D_OFF = csAP_D_ON;
1367 
1368   csAP_N_ON += CPWL_Utils::GetRadioButtonAppStream(rcClient, nStyle, crText);
1369   csAP_D_ON += CPWL_Utils::GetRadioButtonAppStream(rcClient, nStyle, crText);
1370 
1371   WriteAppearance("N", GetRotatedRect(), GetMatrix(), csAP_N_ON,
1372                   pControl->GetCheckedAPState());
1373   WriteAppearance("N", GetRotatedRect(), GetMatrix(), csAP_N_OFF, "Off");
1374 
1375   WriteAppearance("D", GetRotatedRect(), GetMatrix(), csAP_D_ON,
1376                   pControl->GetCheckedAPState());
1377   WriteAppearance("D", GetRotatedRect(), GetMatrix(), csAP_D_OFF, "Off");
1378 
1379   CFX_ByteString csAS = GetAppState();
1380   if (csAS.IsEmpty())
1381     SetAppState("Off");
1382 }
1383 
1384 void CPDFSDK_Widget::ResetAppearance_ComboBox(const FX_WCHAR* sValue) {
1385   CPDF_FormControl* pControl = GetFormControl();
1386   CPDF_FormField* pField = pControl->GetField();
1387   CFX_ByteTextBuf sBody, sLines;
1388 
1389   CPDF_Rect rcClient = GetClientRect();
1390   CPDF_Rect rcButton = rcClient;
1391   rcButton.left = rcButton.right - 13;
1392   rcButton.Normalize();
1393 
1394   if (IFX_Edit* pEdit = IFX_Edit::NewEdit()) {
1395     pEdit->EnableRefresh(FALSE);
1396 
1397     CPDFSDK_Document* pDoc = m_pInterForm->GetDocument();
1398     CPDFDoc_Environment* pEnv = pDoc->GetEnv();
1399     CBA_FontMap font_map(this, pEnv->GetSysHandler());
1400     pEdit->SetFontMap(&font_map);
1401 
1402     CPDF_Rect rcEdit = rcClient;
1403     rcEdit.right = rcButton.left;
1404     rcEdit.Normalize();
1405 
1406     pEdit->SetPlateRect(rcEdit);
1407     pEdit->SetAlignmentV(1);
1408 
1409     FX_FLOAT fFontSize = GetFontSize();
1410     if (IsFloatZero(fFontSize))
1411       pEdit->SetAutoFontSize(TRUE);
1412     else
1413       pEdit->SetFontSize(fFontSize);
1414 
1415     pEdit->Initialize();
1416 
1417     if (sValue) {
1418       pEdit->SetText(sValue);
1419     } else {
1420       int32_t nCurSel = pField->GetSelectedIndex(0);
1421 
1422       if (nCurSel < 0)
1423         pEdit->SetText(pField->GetValue().c_str());
1424       else
1425         pEdit->SetText(pField->GetOptionLabel(nCurSel).c_str());
1426     }
1427 
1428     CPDF_Rect rcContent = pEdit->GetContentRect();
1429 
1430     CFX_ByteString sEdit =
1431         CPWL_Utils::GetEditAppStream(pEdit, CPDF_Point(0.0f, 0.0f));
1432     if (sEdit.GetLength() > 0) {
1433       sBody << "/Tx BMC\n"
1434             << "q\n";
1435       if (rcContent.Width() > rcEdit.Width() ||
1436           rcContent.Height() > rcEdit.Height()) {
1437         sBody << rcEdit.left << " " << rcEdit.bottom << " " << rcEdit.Width()
1438               << " " << rcEdit.Height() << " re\nW\nn\n";
1439       }
1440 
1441       CPWL_Color crText = GetTextPWLColor();
1442       sBody << "BT\n" << CPWL_Utils::GetColorAppStream(crText) << sEdit
1443             << "ET\n"
1444             << "Q\nEMC\n";
1445     }
1446 
1447     IFX_Edit::DelEdit(pEdit);
1448   }
1449 
1450   sBody << CPWL_Utils::GetDropButtonAppStream(rcButton);
1451 
1452   CFX_ByteString sAP = GetBackgroundAppStream() + GetBorderAppStream() +
1453                        sLines.GetByteString() + sBody.GetByteString();
1454 
1455   WriteAppearance("N", GetRotatedRect(), GetMatrix(), sAP);
1456 }
1457 
1458 void CPDFSDK_Widget::ResetAppearance_ListBox() {
1459   CPDF_FormControl* pControl = GetFormControl();
1460   CPDF_FormField* pField = pControl->GetField();
1461   CPDF_Rect rcClient = GetClientRect();
1462   CFX_ByteTextBuf sBody, sLines;
1463 
1464   if (IFX_Edit* pEdit = IFX_Edit::NewEdit()) {
1465     pEdit->EnableRefresh(FALSE);
1466 
1467     CPDFSDK_Document* pDoc = m_pInterForm->GetDocument();
1468     CPDFDoc_Environment* pEnv = pDoc->GetEnv();
1469 
1470     CBA_FontMap font_map(this, pEnv->GetSysHandler());
1471     pEdit->SetFontMap(&font_map);
1472 
1473     pEdit->SetPlateRect(CPDF_Rect(rcClient.left, 0.0f, rcClient.right, 0.0f));
1474 
1475     FX_FLOAT fFontSize = GetFontSize();
1476 
1477     if (IsFloatZero(fFontSize))
1478       pEdit->SetFontSize(12.0f);
1479     else
1480       pEdit->SetFontSize(fFontSize);
1481 
1482     pEdit->Initialize();
1483 
1484     CFX_ByteTextBuf sList;
1485     FX_FLOAT fy = rcClient.top;
1486 
1487     int32_t nTop = pField->GetTopVisibleIndex();
1488     int32_t nCount = pField->CountOptions();
1489     int32_t nSelCount = pField->CountSelectedItems();
1490 
1491     for (int32_t i = nTop; i < nCount; i++) {
1492       FX_BOOL bSelected = FALSE;
1493       for (int32_t j = 0; j < nSelCount; j++) {
1494         if (pField->GetSelectedIndex(j) == i) {
1495           bSelected = TRUE;
1496           break;
1497         }
1498       }
1499 
1500       pEdit->SetText(pField->GetOptionLabel(i).c_str());
1501 
1502       CPDF_Rect rcContent = pEdit->GetContentRect();
1503       FX_FLOAT fItemHeight = rcContent.Height();
1504 
1505       if (bSelected) {
1506         CPDF_Rect rcItem =
1507             CPDF_Rect(rcClient.left, fy - fItemHeight, rcClient.right, fy);
1508         sList << "q\n" << CPWL_Utils::GetColorAppStream(
1509                               CPWL_Color(COLORTYPE_RGB, 0, 51.0f / 255.0f,
1510                                          113.0f / 255.0f),
1511                               TRUE)
1512               << rcItem.left << " " << rcItem.bottom << " " << rcItem.Width()
1513               << " " << rcItem.Height() << " re f\n"
1514               << "Q\n";
1515 
1516         sList << "BT\n" << CPWL_Utils::GetColorAppStream(
1517                                CPWL_Color(COLORTYPE_GRAY, 1), TRUE)
1518               << CPWL_Utils::GetEditAppStream(pEdit, CPDF_Point(0.0f, fy))
1519               << "ET\n";
1520       } else {
1521         CPWL_Color crText = GetTextPWLColor();
1522         sList << "BT\n" << CPWL_Utils::GetColorAppStream(crText, TRUE)
1523               << CPWL_Utils::GetEditAppStream(pEdit, CPDF_Point(0.0f, fy))
1524               << "ET\n";
1525       }
1526 
1527       fy -= fItemHeight;
1528     }
1529 
1530     if (sList.GetSize() > 0) {
1531       sBody << "/Tx BMC\n"
1532             << "q\n" << rcClient.left << " " << rcClient.bottom << " "
1533             << rcClient.Width() << " " << rcClient.Height() << " re\nW\nn\n";
1534       sBody << sList << "Q\nEMC\n";
1535     }
1536 
1537     IFX_Edit::DelEdit(pEdit);
1538   }
1539 
1540   CFX_ByteString sAP = GetBackgroundAppStream() + GetBorderAppStream() +
1541                        sLines.GetByteString() + sBody.GetByteString();
1542 
1543   WriteAppearance("N", GetRotatedRect(), GetMatrix(), sAP);
1544 }
1545 
1546 void CPDFSDK_Widget::ResetAppearance_TextField(const FX_WCHAR* sValue) {
1547   CPDF_FormControl* pControl = GetFormControl();
1548   CPDF_FormField* pField = pControl->GetField();
1549   CFX_ByteTextBuf sBody, sLines;
1550 
1551   if (IFX_Edit* pEdit = IFX_Edit::NewEdit()) {
1552     pEdit->EnableRefresh(FALSE);
1553 
1554     CPDFSDK_Document* pDoc = m_pInterForm->GetDocument();
1555     CPDFDoc_Environment* pEnv = pDoc->GetEnv();
1556 
1557     CBA_FontMap font_map(this, pEnv->GetSysHandler());
1558     pEdit->SetFontMap(&font_map);
1559 
1560     CPDF_Rect rcClient = GetClientRect();
1561     pEdit->SetPlateRect(rcClient);
1562     pEdit->SetAlignmentH(pControl->GetControlAlignment());
1563 
1564     FX_DWORD dwFieldFlags = pField->GetFieldFlags();
1565     FX_BOOL bMultiLine = (dwFieldFlags >> 12) & 1;
1566 
1567     if (bMultiLine) {
1568       pEdit->SetMultiLine(TRUE);
1569       pEdit->SetAutoReturn(TRUE);
1570     } else {
1571       pEdit->SetAlignmentV(1);
1572     }
1573 
1574     FX_WORD subWord = 0;
1575     if ((dwFieldFlags >> 13) & 1) {
1576       subWord = '*';
1577       pEdit->SetPasswordChar(subWord);
1578     }
1579 
1580     int nMaxLen = pField->GetMaxLen();
1581     FX_BOOL bCharArray = (dwFieldFlags >> 24) & 1;
1582     FX_FLOAT fFontSize = GetFontSize();
1583 
1584 #ifdef PDF_ENABLE_XFA
1585     CFX_WideString sValueTmp;
1586     if (!sValue && (NULL != this->GetMixXFAWidget())) {
1587       sValueTmp = GetValue(TRUE);
1588       sValue = sValueTmp;
1589     }
1590 #endif  // PDF_ENABLE_XFA
1591 
1592     if (nMaxLen > 0) {
1593       if (bCharArray) {
1594         pEdit->SetCharArray(nMaxLen);
1595 
1596         if (IsFloatZero(fFontSize)) {
1597           fFontSize = CPWL_Edit::GetCharArrayAutoFontSize(
1598               font_map.GetPDFFont(0), rcClient, nMaxLen);
1599         }
1600       } else {
1601         if (sValue)
1602           nMaxLen = wcslen((const wchar_t*)sValue);
1603         pEdit->SetLimitChar(nMaxLen);
1604       }
1605     }
1606 
1607     if (IsFloatZero(fFontSize))
1608       pEdit->SetAutoFontSize(TRUE);
1609     else
1610       pEdit->SetFontSize(fFontSize);
1611 
1612     pEdit->Initialize();
1613 
1614     if (sValue)
1615       pEdit->SetText(sValue);
1616     else
1617       pEdit->SetText(pField->GetValue().c_str());
1618 
1619     CPDF_Rect rcContent = pEdit->GetContentRect();
1620 
1621     CFX_ByteString sEdit = CPWL_Utils::GetEditAppStream(
1622         pEdit, CPDF_Point(0.0f, 0.0f), NULL, !bCharArray, subWord);
1623 
1624     if (sEdit.GetLength() > 0) {
1625       sBody << "/Tx BMC\n"
1626             << "q\n";
1627       if (rcContent.Width() > rcClient.Width() ||
1628           rcContent.Height() > rcClient.Height()) {
1629         sBody << rcClient.left << " " << rcClient.bottom << " "
1630               << rcClient.Width() << " " << rcClient.Height() << " re\nW\nn\n";
1631       }
1632       CPWL_Color crText = GetTextPWLColor();
1633       sBody << "BT\n" << CPWL_Utils::GetColorAppStream(crText) << sEdit
1634             << "ET\n"
1635             << "Q\nEMC\n";
1636     }
1637 
1638     if (bCharArray) {
1639       switch (GetBorderStyle()) {
1640         case BBS_SOLID: {
1641           CFX_ByteString sColor =
1642               CPWL_Utils::GetColorAppStream(GetBorderPWLColor(), FALSE);
1643           if (sColor.GetLength() > 0) {
1644             sLines << "q\n" << GetBorderWidth() << " w\n"
1645                    << CPWL_Utils::GetColorAppStream(GetBorderPWLColor(), FALSE)
1646                    << " 2 J 0 j\n";
1647 
1648             for (int32_t i = 1; i < nMaxLen; i++) {
1649               sLines << rcClient.left +
1650                             ((rcClient.right - rcClient.left) / nMaxLen) * i
1651                      << " " << rcClient.bottom << " m\n"
1652                      << rcClient.left +
1653                             ((rcClient.right - rcClient.left) / nMaxLen) * i
1654                      << " " << rcClient.top << " l S\n";
1655             }
1656 
1657             sLines << "Q\n";
1658           }
1659         } break;
1660         case BBS_DASH: {
1661           CFX_ByteString sColor =
1662               CPWL_Utils::GetColorAppStream(GetBorderPWLColor(), FALSE);
1663           if (sColor.GetLength() > 0) {
1664             CPWL_Dash dsBorder = CPWL_Dash(3, 3, 0);
1665 
1666             sLines << "q\n" << GetBorderWidth() << " w\n"
1667                    << CPWL_Utils::GetColorAppStream(GetBorderPWLColor(), FALSE)
1668                    << "[" << dsBorder.nDash << " " << dsBorder.nGap << "] "
1669                    << dsBorder.nPhase << " d\n";
1670 
1671             for (int32_t i = 1; i < nMaxLen; i++) {
1672               sLines << rcClient.left +
1673                             ((rcClient.right - rcClient.left) / nMaxLen) * i
1674                      << " " << rcClient.bottom << " m\n"
1675                      << rcClient.left +
1676                             ((rcClient.right - rcClient.left) / nMaxLen) * i
1677                      << " " << rcClient.top << " l S\n";
1678             }
1679 
1680             sLines << "Q\n";
1681           }
1682         } break;
1683       }
1684     }
1685 
1686     IFX_Edit::DelEdit(pEdit);
1687   }
1688 
1689   CFX_ByteString sAP = GetBackgroundAppStream() + GetBorderAppStream() +
1690                        sLines.GetByteString() + sBody.GetByteString();
1691   WriteAppearance("N", GetRotatedRect(), GetMatrix(), sAP);
1692 }
1693 
1694 CPDF_Rect CPDFSDK_Widget::GetClientRect() const {
1695   CPDF_Rect rcWindow = GetRotatedRect();
1696   FX_FLOAT fBorderWidth = (FX_FLOAT)GetBorderWidth();
1697   switch (GetBorderStyle()) {
1698     case BBS_BEVELED:
1699     case BBS_INSET:
1700       fBorderWidth *= 2.0f;
1701       break;
1702   }
1703 
1704   return CPWL_Utils::DeflateRect(rcWindow, fBorderWidth);
1705 }
1706 
1707 CPDF_Rect CPDFSDK_Widget::GetRotatedRect() const {
1708   CPDF_Rect rectAnnot = GetRect();
1709   FX_FLOAT fWidth = rectAnnot.right - rectAnnot.left;
1710   FX_FLOAT fHeight = rectAnnot.top - rectAnnot.bottom;
1711 
1712   CPDF_FormControl* pControl = GetFormControl();
1713   CPDF_Rect rcPDFWindow;
1714   switch (abs(pControl->GetRotation() % 360)) {
1715     case 0:
1716     case 180:
1717     default:
1718       rcPDFWindow = CPDF_Rect(0, 0, fWidth, fHeight);
1719       break;
1720     case 90:
1721     case 270:
1722       rcPDFWindow = CPDF_Rect(0, 0, fHeight, fWidth);
1723       break;
1724   }
1725 
1726   return rcPDFWindow;
1727 }
1728 
1729 CFX_ByteString CPDFSDK_Widget::GetBackgroundAppStream() const {
1730   CPWL_Color crBackground = GetFillPWLColor();
1731   if (crBackground.nColorType != COLORTYPE_TRANSPARENT) {
1732     return CPWL_Utils::GetRectFillAppStream(GetRotatedRect(), crBackground);
1733   }
1734   return "";
1735 }
1736 
1737 CFX_ByteString CPDFSDK_Widget::GetBorderAppStream() const {
1738   CPDF_Rect rcWindow = GetRotatedRect();
1739   CPWL_Color crBorder = GetBorderPWLColor();
1740   CPWL_Color crBackground = GetFillPWLColor();
1741   CPWL_Color crLeftTop, crRightBottom;
1742 
1743   FX_FLOAT fBorderWidth = (FX_FLOAT)GetBorderWidth();
1744   int32_t nBorderStyle = 0;
1745   CPWL_Dash dsBorder(3, 0, 0);
1746 
1747   switch (GetBorderStyle()) {
1748     case BBS_DASH:
1749       nBorderStyle = PBS_DASH;
1750       dsBorder = CPWL_Dash(3, 3, 0);
1751       break;
1752     case BBS_BEVELED:
1753       nBorderStyle = PBS_BEVELED;
1754       fBorderWidth *= 2;
1755       crLeftTop = CPWL_Color(COLORTYPE_GRAY, 1);
1756       crRightBottom = CPWL_Utils::DevideColor(crBackground, 2);
1757       break;
1758     case BBS_INSET:
1759       nBorderStyle = PBS_INSET;
1760       fBorderWidth *= 2;
1761       crLeftTop = CPWL_Color(COLORTYPE_GRAY, 0.5);
1762       crRightBottom = CPWL_Color(COLORTYPE_GRAY, 0.75);
1763       break;
1764     case BBS_UNDERLINE:
1765       nBorderStyle = PBS_UNDERLINED;
1766       break;
1767     default:
1768       nBorderStyle = PBS_SOLID;
1769       break;
1770   }
1771 
1772   return CPWL_Utils::GetBorderAppStream(rcWindow, fBorderWidth, crBorder,
1773                                         crLeftTop, crRightBottom, nBorderStyle,
1774                                         dsBorder);
1775 }
1776 
1777 CFX_Matrix CPDFSDK_Widget::GetMatrix() const {
1778   CFX_Matrix mt;
1779   CPDF_FormControl* pControl = GetFormControl();
1780   CPDF_Rect rcAnnot = GetRect();
1781   FX_FLOAT fWidth = rcAnnot.right - rcAnnot.left;
1782   FX_FLOAT fHeight = rcAnnot.top - rcAnnot.bottom;
1783 
1784   switch (abs(pControl->GetRotation() % 360)) {
1785     case 0:
1786     default:
1787       mt = CFX_Matrix(1, 0, 0, 1, 0, 0);
1788       break;
1789     case 90:
1790       mt = CFX_Matrix(0, 1, -1, 0, fWidth, 0);
1791       break;
1792     case 180:
1793       mt = CFX_Matrix(-1, 0, 0, -1, fWidth, fHeight);
1794       break;
1795     case 270:
1796       mt = CFX_Matrix(0, -1, 1, 0, 0, fHeight);
1797       break;
1798   }
1799 
1800   return mt;
1801 }
1802 
1803 CPWL_Color CPDFSDK_Widget::GetTextPWLColor() const {
1804   CPWL_Color crText = CPWL_Color(COLORTYPE_GRAY, 0);
1805 
1806   CPDF_FormControl* pFormCtrl = GetFormControl();
1807   CPDF_DefaultAppearance da = pFormCtrl->GetDefaultAppearance();
1808   if (da.HasColor()) {
1809     int32_t iColorType;
1810     FX_FLOAT fc[4];
1811     da.GetColor(iColorType, fc);
1812     crText = CPWL_Color(iColorType, fc[0], fc[1], fc[2], fc[3]);
1813   }
1814 
1815   return crText;
1816 }
1817 
1818 CPWL_Color CPDFSDK_Widget::GetBorderPWLColor() const {
1819   CPWL_Color crBorder;
1820 
1821   CPDF_FormControl* pFormCtrl = GetFormControl();
1822   int32_t iColorType;
1823   FX_FLOAT fc[4];
1824   pFormCtrl->GetOriginalBorderColor(iColorType, fc);
1825   if (iColorType > 0)
1826     crBorder = CPWL_Color(iColorType, fc[0], fc[1], fc[2], fc[3]);
1827 
1828   return crBorder;
1829 }
1830 
1831 CPWL_Color CPDFSDK_Widget::GetFillPWLColor() const {
1832   CPWL_Color crFill;
1833 
1834   CPDF_FormControl* pFormCtrl = GetFormControl();
1835   int32_t iColorType;
1836   FX_FLOAT fc[4];
1837   pFormCtrl->GetOriginalBackgroundColor(iColorType, fc);
1838   if (iColorType > 0)
1839     crFill = CPWL_Color(iColorType, fc[0], fc[1], fc[2], fc[3]);
1840 
1841   return crFill;
1842 }
1843 
1844 void CPDFSDK_Widget::AddImageToAppearance(const CFX_ByteString& sAPType,
1845                                           CPDF_Stream* pImage) {
1846   CPDF_Document* pDoc = m_pPageView->GetPDFDocument();
1847   ASSERT(pDoc);
1848 
1849   CPDF_Dictionary* pAPDict = m_pAnnot->GetAnnotDict()->GetDict("AP");
1850   CPDF_Stream* pStream = pAPDict->GetStream(sAPType);
1851   CPDF_Dictionary* pStreamDict = pStream->GetDict();
1852   CFX_ByteString sImageAlias = "IMG";
1853 
1854   if (CPDF_Dictionary* pImageDict = pImage->GetDict()) {
1855     sImageAlias = pImageDict->GetString("Name");
1856     if (sImageAlias.IsEmpty())
1857       sImageAlias = "IMG";
1858   }
1859 
1860   CPDF_Dictionary* pStreamResList = pStreamDict->GetDict("Resources");
1861   if (!pStreamResList) {
1862     pStreamResList = new CPDF_Dictionary();
1863     pStreamDict->SetAt("Resources", pStreamResList);
1864   }
1865 
1866   if (pStreamResList) {
1867     CPDF_Dictionary* pXObject = new CPDF_Dictionary;
1868     pXObject->SetAtReference(sImageAlias, pDoc, pImage);
1869     pStreamResList->SetAt("XObject", pXObject);
1870   }
1871 }
1872 
1873 void CPDFSDK_Widget::RemoveAppearance(const CFX_ByteString& sAPType) {
1874   if (CPDF_Dictionary* pAPDict = m_pAnnot->GetAnnotDict()->GetDict("AP")) {
1875     pAPDict->RemoveAt(sAPType);
1876   }
1877 }
1878 
1879 FX_BOOL CPDFSDK_Widget::OnAAction(CPDF_AAction::AActionType type,
1880                                   PDFSDK_FieldAction& data,
1881                                   CPDFSDK_PageView* pPageView) {
1882   CPDFSDK_Document* pDocument = pPageView->GetSDKDocument();
1883   CPDFDoc_Environment* pEnv = pDocument->GetEnv();
1884 
1885 #ifdef PDF_ENABLE_XFA
1886   CPDFXFA_Document* pDoc = pDocument->GetXFADocument();
1887   if (IXFA_Widget* hWidget = GetMixXFAWidget()) {
1888     XFA_EVENTTYPE eEventType = GetXFAEventType(type, data.bWillCommit);
1889 
1890     if (eEventType != XFA_EVENT_Unknown) {
1891       if (IXFA_WidgetHandler* pXFAWidgetHandler = GetXFAWidgetHandler()) {
1892         CXFA_EventParam param;
1893         param.m_eType = eEventType;
1894         param.m_wsChange = data.sChange;
1895         param.m_iCommitKey = data.nCommitKey;
1896         param.m_bShift = data.bShift;
1897         param.m_iSelStart = data.nSelStart;
1898         param.m_iSelEnd = data.nSelEnd;
1899         param.m_wsFullText = data.sValue;
1900         param.m_bKeyDown = data.bKeyDown;
1901         param.m_bModifier = data.bModifier;
1902         param.m_wsNewText = data.sValue;
1903         if (data.nSelEnd > data.nSelStart)
1904           param.m_wsNewText.Delete(data.nSelStart,
1905                                    data.nSelEnd - data.nSelStart);
1906         for (int i = data.sChange.GetLength() - 1; i >= 0; i--)
1907           param.m_wsNewText.Insert(data.nSelStart, data.sChange[i]);
1908         param.m_wsPrevText = data.sValue;
1909 
1910         CXFA_WidgetAcc* pAcc = pXFAWidgetHandler->GetDataAcc(hWidget);
1911         param.m_pTarget = pAcc;
1912         int32_t nRet = pXFAWidgetHandler->ProcessEvent(pAcc, &param);
1913 
1914         if (IXFA_DocView* pDocView = pDoc->GetXFADocView()) {
1915           pDocView->UpdateDocView();
1916         }
1917 
1918         if (nRet == XFA_EVENTERROR_Sucess)
1919           return TRUE;
1920       }
1921     }
1922   }
1923 #endif  // PDF_ENABLE_XFA
1924 
1925   CPDF_Action action = GetAAction(type);
1926   if (action && action.GetType() != CPDF_Action::Unknown) {
1927     CPDFSDK_ActionHandler* pActionHandler = pEnv->GetActionHander();
1928     return pActionHandler->DoAction_Field(action, type, pDocument,
1929                                           GetFormField(), data);
1930   }
1931   return FALSE;
1932 }
1933 
1934 CPDF_Action CPDFSDK_Widget::GetAAction(CPDF_AAction::AActionType eAAT) {
1935   switch (eAAT) {
1936     case CPDF_AAction::CursorEnter:
1937     case CPDF_AAction::CursorExit:
1938     case CPDF_AAction::ButtonDown:
1939     case CPDF_AAction::ButtonUp:
1940     case CPDF_AAction::GetFocus:
1941     case CPDF_AAction::LoseFocus:
1942     case CPDF_AAction::PageOpen:
1943     case CPDF_AAction::PageClose:
1944     case CPDF_AAction::PageVisible:
1945     case CPDF_AAction::PageInvisible:
1946       return CPDFSDK_BAAnnot::GetAAction(eAAT);
1947 
1948     case CPDF_AAction::KeyStroke:
1949     case CPDF_AAction::Format:
1950     case CPDF_AAction::Validate:
1951     case CPDF_AAction::Calculate: {
1952       CPDF_FormField* pField = GetFormField();
1953       if (CPDF_AAction aa = pField->GetAdditionalAction())
1954         return aa.GetAction(eAAT);
1955       return CPDFSDK_BAAnnot::GetAAction(eAAT);
1956     }
1957     default:
1958       break;
1959   }
1960 
1961   return CPDF_Action();
1962 }
1963 
1964 CFX_WideString CPDFSDK_Widget::GetAlternateName() const {
1965   CPDF_FormField* pFormField = GetFormField();
1966   return pFormField->GetAlternateName();
1967 }
1968 
1969 int32_t CPDFSDK_Widget::GetAppearanceAge() const {
1970   return m_nAppAge;
1971 }
1972 
1973 int32_t CPDFSDK_Widget::GetValueAge() const {
1974   return m_nValueAge;
1975 }
1976 
1977 FX_BOOL CPDFSDK_Widget::HitTest(FX_FLOAT pageX, FX_FLOAT pageY) {
1978   CPDF_Annot* pAnnot = GetPDFAnnot();
1979   CFX_FloatRect annotRect;
1980   pAnnot->GetRect(annotRect);
1981   if (annotRect.Contains(pageX, pageY)) {
1982     if (!IsVisible())
1983       return FALSE;
1984 
1985     int nFieldFlags = GetFieldFlags();
1986     if ((nFieldFlags & FIELDFLAG_READONLY) == FIELDFLAG_READONLY)
1987       return FALSE;
1988 
1989     return TRUE;
1990   }
1991   return FALSE;
1992 }
1993 
1994 #ifdef PDF_ENABLE_XFA
1995 CPDFSDK_XFAWidget::CPDFSDK_XFAWidget(IXFA_Widget* pAnnot,
1996                                      CPDFSDK_PageView* pPageView,
1997                                      CPDFSDK_InterForm* pInterForm)
1998     : CPDFSDK_Annot(pPageView), m_pInterForm(pInterForm), m_hXFAWidget(pAnnot) {
1999 }
2000 
2001 FX_BOOL CPDFSDK_XFAWidget::IsXFAField() {
2002   return TRUE;
2003 }
2004 
2005 CFX_ByteString CPDFSDK_XFAWidget::GetType() const {
2006   return FSDK_XFAWIDGET_TYPENAME;
2007 }
2008 
2009 CFX_FloatRect CPDFSDK_XFAWidget::GetRect() const {
2010   CPDFSDK_PageView* pPageView = GetPageView();
2011   CPDFSDK_Document* pDocument = pPageView->GetSDKDocument();
2012   CPDFXFA_Document* pDoc = pDocument->GetXFADocument();
2013   IXFA_DocView* pDocView = pDoc->GetXFADocView();
2014   IXFA_WidgetHandler* pWidgetHandler = pDocView->GetWidgetHandler();
2015 
2016   CFX_RectF rcBBox;
2017   pWidgetHandler->GetRect(GetXFAWidget(), rcBBox);
2018 
2019   return CFX_FloatRect(rcBBox.left, rcBBox.top, rcBBox.left + rcBBox.width,
2020                        rcBBox.top + rcBBox.height);
2021 }
2022 #endif  // PDF_ENABLE_XFA
2023 
2024 CPDFSDK_InterForm::CPDFSDK_InterForm(CPDFSDK_Document* pDocument)
2025     : m_pDocument(pDocument),
2026       m_pInterForm(NULL),
2027 #ifdef PDF_ENABLE_XFA
2028       m_bXfaCalculate(TRUE),
2029       m_bXfaValidationsEnabled(TRUE),
2030 #endif  // PDF_ENABLE_XFA
2031       m_bCalculate(TRUE),
2032       m_bBusy(FALSE) {
2033   m_pInterForm = new CPDF_InterForm(m_pDocument->GetPDFDocument(), FALSE);
2034   m_pInterForm->SetFormNotify(this);
2035 
2036   for (int i = 0; i < kNumFieldTypes; ++i)
2037     m_bNeedHightlight[i] = FALSE;
2038   m_iHighlightAlpha = 0;
2039 }
2040 
2041 CPDFSDK_InterForm::~CPDFSDK_InterForm() {
2042   delete m_pInterForm;
2043   m_pInterForm = nullptr;
2044   m_Map.clear();
2045 #ifdef PDF_ENABLE_XFA
2046   m_XFAMap.RemoveAll();
2047 #endif  // PDF_ENABLE_XFA
2048 }
2049 
2050 FX_BOOL CPDFSDK_InterForm::HighlightWidgets() {
2051   return FALSE;
2052 }
2053 
2054 CPDFSDK_Widget* CPDFSDK_InterForm::GetSibling(CPDFSDK_Widget* pWidget,
2055                                               FX_BOOL bNext) const {
2056   std::unique_ptr<CBA_AnnotIterator> pIterator(
2057       new CBA_AnnotIterator(pWidget->GetPageView(), "Widget", ""));
2058 
2059   if (bNext) {
2060     return (CPDFSDK_Widget*)pIterator->GetNextAnnot(pWidget);
2061   }
2062   return (CPDFSDK_Widget*)pIterator->GetPrevAnnot(pWidget);
2063 }
2064 
2065 CPDFSDK_Widget* CPDFSDK_InterForm::GetWidget(CPDF_FormControl* pControl) const {
2066   if (!pControl || !m_pInterForm)
2067     return nullptr;
2068 
2069   CPDFSDK_Widget* pWidget = nullptr;
2070   const auto it = m_Map.find(pControl);
2071   if (it != m_Map.end())
2072     pWidget = it->second;
2073 
2074   if (pWidget)
2075     return pWidget;
2076 
2077   CPDF_Dictionary* pControlDict = pControl->GetWidget();
2078   CPDF_Document* pDocument = m_pDocument->GetPDFDocument();
2079   CPDFSDK_PageView* pPage = nullptr;
2080 
2081   if (CPDF_Dictionary* pPageDict = pControlDict->GetDict("P")) {
2082     int nPageIndex = pDocument->GetPageIndex(pPageDict->GetObjNum());
2083     if (nPageIndex >= 0) {
2084       pPage = m_pDocument->GetPageView(nPageIndex);
2085     }
2086   }
2087 
2088   if (!pPage) {
2089     int nPageIndex = GetPageIndexByAnnotDict(pDocument, pControlDict);
2090     if (nPageIndex >= 0) {
2091       pPage = m_pDocument->GetPageView(nPageIndex);
2092     }
2093   }
2094 
2095   if (!pPage)
2096     return nullptr;
2097   return (CPDFSDK_Widget*)pPage->GetAnnotByDict(pControlDict);
2098 }
2099 
2100 void CPDFSDK_InterForm::GetWidgets(
2101     const CFX_WideString& sFieldName,
2102     std::vector<CPDFSDK_Widget*>* widgets) const {
2103   for (int i = 0, sz = m_pInterForm->CountFields(sFieldName); i < sz; ++i) {
2104     CPDF_FormField* pFormField = m_pInterForm->GetField(i, sFieldName);
2105     ASSERT(pFormField);
2106     GetWidgets(pFormField, widgets);
2107   }
2108 }
2109 
2110 void CPDFSDK_InterForm::GetWidgets(
2111     CPDF_FormField* pField,
2112     std::vector<CPDFSDK_Widget*>* widgets) const {
2113   for (int i = 0, sz = pField->CountControls(); i < sz; ++i) {
2114     CPDF_FormControl* pFormCtrl = pField->GetControl(i);
2115     ASSERT(pFormCtrl);
2116     CPDFSDK_Widget* pWidget = GetWidget(pFormCtrl);
2117     if (pWidget)
2118       widgets->push_back(pWidget);
2119   }
2120 }
2121 
2122 int CPDFSDK_InterForm::GetPageIndexByAnnotDict(
2123     CPDF_Document* pDocument,
2124     CPDF_Dictionary* pAnnotDict) const {
2125   ASSERT(pAnnotDict);
2126 
2127   for (int i = 0, sz = pDocument->GetPageCount(); i < sz; i++) {
2128     if (CPDF_Dictionary* pPageDict = pDocument->GetPage(i)) {
2129       if (CPDF_Array* pAnnots = pPageDict->GetArray("Annots")) {
2130         for (int j = 0, jsz = pAnnots->GetCount(); j < jsz; j++) {
2131           CPDF_Object* pDict = pAnnots->GetElementValue(j);
2132           if (pAnnotDict == pDict) {
2133             return i;
2134           }
2135         }
2136       }
2137     }
2138   }
2139 
2140   return -1;
2141 }
2142 
2143 void CPDFSDK_InterForm::AddMap(CPDF_FormControl* pControl,
2144                                CPDFSDK_Widget* pWidget) {
2145   m_Map[pControl] = pWidget;
2146 }
2147 
2148 void CPDFSDK_InterForm::RemoveMap(CPDF_FormControl* pControl) {
2149   m_Map.erase(pControl);
2150 }
2151 
2152 void CPDFSDK_InterForm::EnableCalculate(FX_BOOL bEnabled) {
2153   m_bCalculate = bEnabled;
2154 }
2155 
2156 FX_BOOL CPDFSDK_InterForm::IsCalculateEnabled() const {
2157   return m_bCalculate;
2158 }
2159 
2160 #ifdef PDF_ENABLE_XFA
2161 void CPDFSDK_InterForm::AddXFAMap(IXFA_Widget* hWidget,
2162                                   CPDFSDK_XFAWidget* pWidget) {
2163   m_XFAMap.SetAt(hWidget, pWidget);
2164 }
2165 
2166 void CPDFSDK_InterForm::RemoveXFAMap(IXFA_Widget* hWidget) {
2167   m_XFAMap.RemoveKey(hWidget);
2168 }
2169 
2170 CPDFSDK_XFAWidget* CPDFSDK_InterForm::GetXFAWidget(IXFA_Widget* hWidget) {
2171   CPDFSDK_XFAWidget* pWidget = NULL;
2172   m_XFAMap.Lookup(hWidget, pWidget);
2173 
2174   return pWidget;
2175 }
2176 
2177 void CPDFSDK_InterForm::XfaEnableCalculate(FX_BOOL bEnabled) {
2178   m_bXfaCalculate = bEnabled;
2179 }
2180 FX_BOOL CPDFSDK_InterForm::IsXfaCalculateEnabled() const {
2181   return m_bXfaCalculate;
2182 }
2183 
2184 FX_BOOL CPDFSDK_InterForm::IsXfaValidationsEnabled() {
2185   return m_bXfaValidationsEnabled;
2186 }
2187 void CPDFSDK_InterForm::XfaSetValidationsEnabled(FX_BOOL bEnabled) {
2188   m_bXfaValidationsEnabled = bEnabled;
2189 }
2190 #endif  // PDF_ENABLE_XFA
2191 
2192 void CPDFSDK_InterForm::OnCalculate(CPDF_FormField* pFormField) {
2193   CPDFDoc_Environment* pEnv = m_pDocument->GetEnv();
2194   ASSERT(pEnv);
2195   if (!pEnv->IsJSInitiated())
2196     return;
2197 
2198   if (m_bBusy)
2199     return;
2200 
2201   m_bBusy = TRUE;
2202 
2203   if (IsCalculateEnabled()) {
2204     IJS_Runtime* pRuntime = m_pDocument->GetJsRuntime();
2205     pRuntime->SetReaderDocument(m_pDocument);
2206 
2207     int nSize = m_pInterForm->CountFieldsInCalculationOrder();
2208     for (int i = 0; i < nSize; i++) {
2209       if (CPDF_FormField* pField =
2210               m_pInterForm->GetFieldInCalculationOrder(i)) {
2211         int nType = pField->GetFieldType();
2212         if (nType == FIELDTYPE_COMBOBOX || nType == FIELDTYPE_TEXTFIELD) {
2213           CPDF_AAction aAction = pField->GetAdditionalAction();
2214           if (aAction && aAction.ActionExist(CPDF_AAction::Calculate)) {
2215             CPDF_Action action = aAction.GetAction(CPDF_AAction::Calculate);
2216             if (action) {
2217               CFX_WideString csJS = action.GetJavaScript();
2218               if (!csJS.IsEmpty()) {
2219                 IJS_Context* pContext = pRuntime->NewContext();
2220                 CFX_WideString sOldValue = pField->GetValue();
2221                 CFX_WideString sValue = sOldValue;
2222                 FX_BOOL bRC = TRUE;
2223                 pContext->OnField_Calculate(pFormField, pField, sValue, bRC);
2224 
2225                 CFX_WideString sInfo;
2226                 FX_BOOL bRet = pContext->RunScript(csJS, &sInfo);
2227                 pRuntime->ReleaseContext(pContext);
2228 
2229                 if (bRet) {
2230                   if (bRC) {
2231                     if (sValue.Compare(sOldValue) != 0)
2232                       pField->SetValue(sValue, TRUE);
2233                   }
2234                 }
2235               }
2236             }
2237           }
2238         }
2239       }
2240     }
2241   }
2242 
2243   m_bBusy = FALSE;
2244 }
2245 
2246 CFX_WideString CPDFSDK_InterForm::OnFormat(CPDF_FormField* pFormField,
2247                                            FX_BOOL& bFormated) {
2248   CFX_WideString sValue = pFormField->GetValue();
2249   CPDFDoc_Environment* pEnv = m_pDocument->GetEnv();
2250   ASSERT(pEnv);
2251   if (!pEnv->IsJSInitiated()) {
2252     bFormated = FALSE;
2253     return sValue;
2254   }
2255 
2256   IJS_Runtime* pRuntime = m_pDocument->GetJsRuntime();
2257   pRuntime->SetReaderDocument(m_pDocument);
2258 
2259   if (pFormField->GetFieldType() == FIELDTYPE_COMBOBOX) {
2260     if (pFormField->CountSelectedItems() > 0) {
2261       int index = pFormField->GetSelectedIndex(0);
2262       if (index >= 0)
2263         sValue = pFormField->GetOptionLabel(index);
2264     }
2265   }
2266 
2267   bFormated = FALSE;
2268 
2269   CPDF_AAction aAction = pFormField->GetAdditionalAction();
2270   if (aAction && aAction.ActionExist(CPDF_AAction::Format)) {
2271     CPDF_Action action = aAction.GetAction(CPDF_AAction::Format);
2272     if (action) {
2273       CFX_WideString script = action.GetJavaScript();
2274       if (!script.IsEmpty()) {
2275         CFX_WideString Value = sValue;
2276 
2277         IJS_Context* pContext = pRuntime->NewContext();
2278         pContext->OnField_Format(pFormField, Value, TRUE);
2279 
2280         CFX_WideString sInfo;
2281         FX_BOOL bRet = pContext->RunScript(script, &sInfo);
2282         pRuntime->ReleaseContext(pContext);
2283 
2284         if (bRet) {
2285           sValue = Value;
2286           bFormated = TRUE;
2287         }
2288       }
2289     }
2290   }
2291 
2292   return sValue;
2293 }
2294 
2295 void CPDFSDK_InterForm::ResetFieldAppearance(CPDF_FormField* pFormField,
2296                                              const FX_WCHAR* sValue,
2297                                              FX_BOOL bValueChanged) {
2298   for (int i = 0, sz = pFormField->CountControls(); i < sz; i++) {
2299     CPDF_FormControl* pFormCtrl = pFormField->GetControl(i);
2300     ASSERT(pFormCtrl);
2301     if (CPDFSDK_Widget* pWidget = GetWidget(pFormCtrl))
2302       pWidget->ResetAppearance(sValue, bValueChanged);
2303   }
2304 }
2305 
2306 void CPDFSDK_InterForm::UpdateField(CPDF_FormField* pFormField) {
2307   for (int i = 0, sz = pFormField->CountControls(); i < sz; i++) {
2308     CPDF_FormControl* pFormCtrl = pFormField->GetControl(i);
2309     ASSERT(pFormCtrl);
2310 
2311     if (CPDFSDK_Widget* pWidget = GetWidget(pFormCtrl)) {
2312       CPDFDoc_Environment* pEnv = m_pDocument->GetEnv();
2313       CFFL_IFormFiller* pIFormFiller = pEnv->GetIFormFiller();
2314       UnderlyingPageType* pPage = pWidget->GetUnderlyingPage();
2315       CPDFSDK_PageView* pPageView = m_pDocument->GetPageView(pPage, FALSE);
2316       FX_RECT rcBBox = pIFormFiller->GetViewBBox(pPageView, pWidget);
2317 
2318       pEnv->FFI_Invalidate(pPage, rcBBox.left, rcBBox.top, rcBBox.right,
2319                            rcBBox.bottom);
2320     }
2321   }
2322 }
2323 
2324 void CPDFSDK_InterForm::OnKeyStrokeCommit(CPDF_FormField* pFormField,
2325                                           CFX_WideString& csValue,
2326                                           FX_BOOL& bRC) {
2327   CPDF_AAction aAction = pFormField->GetAdditionalAction();
2328   if (aAction && aAction.ActionExist(CPDF_AAction::KeyStroke)) {
2329     CPDF_Action action = aAction.GetAction(CPDF_AAction::KeyStroke);
2330     if (action) {
2331       CPDFDoc_Environment* pEnv = m_pDocument->GetEnv();
2332       CPDFSDK_ActionHandler* pActionHandler = pEnv->GetActionHander();
2333       PDFSDK_FieldAction fa;
2334       fa.bModifier = pEnv->FFI_IsCTRLKeyDown(0);
2335       fa.bShift = pEnv->FFI_IsSHIFTKeyDown(0);
2336       fa.sValue = csValue;
2337 
2338       pActionHandler->DoAction_FieldJavaScript(action, CPDF_AAction::KeyStroke,
2339                                                m_pDocument, pFormField, fa);
2340       bRC = fa.bRC;
2341     }
2342   }
2343 }
2344 
2345 void CPDFSDK_InterForm::OnValidate(CPDF_FormField* pFormField,
2346                                    CFX_WideString& csValue,
2347                                    FX_BOOL& bRC) {
2348   CPDF_AAction aAction = pFormField->GetAdditionalAction();
2349   if (aAction && aAction.ActionExist(CPDF_AAction::Validate)) {
2350     CPDF_Action action = aAction.GetAction(CPDF_AAction::Validate);
2351     if (action) {
2352       CPDFDoc_Environment* pEnv = m_pDocument->GetEnv();
2353       CPDFSDK_ActionHandler* pActionHandler = pEnv->GetActionHander();
2354       PDFSDK_FieldAction fa;
2355       fa.bModifier = pEnv->FFI_IsCTRLKeyDown(0);
2356       fa.bShift = pEnv->FFI_IsSHIFTKeyDown(0);
2357       fa.sValue = csValue;
2358 
2359       pActionHandler->DoAction_FieldJavaScript(action, CPDF_AAction::Validate,
2360                                                m_pDocument, pFormField, fa);
2361       bRC = fa.bRC;
2362     }
2363   }
2364 }
2365 
2366 FX_BOOL CPDFSDK_InterForm::DoAction_Hide(const CPDF_Action& action) {
2367   ASSERT(action);
2368 
2369   CPDF_ActionFields af = action.GetWidgets();
2370   std::vector<CPDF_Object*> fieldObjects = af.GetAllFields();
2371   std::vector<CPDF_FormField*> fields = GetFieldFromObjects(fieldObjects);
2372 
2373   FX_BOOL bHide = action.GetHideStatus();
2374   FX_BOOL bChanged = FALSE;
2375 
2376   for (CPDF_FormField* pField : fields) {
2377     for (int i = 0, sz = pField->CountControls(); i < sz; ++i) {
2378       CPDF_FormControl* pControl = pField->GetControl(i);
2379       ASSERT(pControl);
2380 
2381       if (CPDFSDK_Widget* pWidget = GetWidget(pControl)) {
2382         int nFlags = pWidget->GetFlags();
2383         nFlags &= ~ANNOTFLAG_INVISIBLE;
2384         nFlags &= ~ANNOTFLAG_NOVIEW;
2385         if (bHide)
2386           nFlags |= ANNOTFLAG_HIDDEN;
2387         else
2388           nFlags &= ~ANNOTFLAG_HIDDEN;
2389         pWidget->SetFlags(nFlags);
2390         pWidget->GetPageView()->UpdateView(pWidget);
2391         bChanged = TRUE;
2392       }
2393     }
2394   }
2395 
2396   return bChanged;
2397 }
2398 
2399 FX_BOOL CPDFSDK_InterForm::DoAction_SubmitForm(const CPDF_Action& action) {
2400   CFX_WideString sDestination = action.GetFilePath();
2401   if (sDestination.IsEmpty())
2402     return FALSE;
2403 
2404   CPDF_Dictionary* pActionDict = action.GetDict();
2405   if (pActionDict->KeyExist("Fields")) {
2406     CPDF_ActionFields af = action.GetWidgets();
2407     FX_DWORD dwFlags = action.GetFlags();
2408     std::vector<CPDF_Object*> fieldObjects = af.GetAllFields();
2409     std::vector<CPDF_FormField*> fields = GetFieldFromObjects(fieldObjects);
2410     if (!fields.empty()) {
2411       bool bIncludeOrExclude = !(dwFlags & 0x01);
2412       if (m_pInterForm->CheckRequiredFields(&fields, bIncludeOrExclude))
2413         return FALSE;
2414 
2415       return SubmitFields(sDestination, fields, bIncludeOrExclude, FALSE);
2416     }
2417   }
2418   if (m_pInterForm->CheckRequiredFields(nullptr, true))
2419     return FALSE;
2420 
2421   return SubmitForm(sDestination, FALSE);
2422 }
2423 
2424 FX_BOOL CPDFSDK_InterForm::SubmitFields(
2425     const CFX_WideString& csDestination,
2426     const std::vector<CPDF_FormField*>& fields,
2427     FX_BOOL bIncludeOrExclude,
2428     FX_BOOL bUrlEncoded) {
2429   CPDFDoc_Environment* pEnv = m_pDocument->GetEnv();
2430 
2431   CFX_ByteTextBuf textBuf;
2432   ExportFieldsToFDFTextBuf(fields, bIncludeOrExclude, textBuf);
2433 
2434   uint8_t* pBuffer = textBuf.GetBuffer();
2435   FX_STRSIZE nBufSize = textBuf.GetLength();
2436 
2437   if (bUrlEncoded && !FDFToURLEncodedData(pBuffer, nBufSize))
2438     return FALSE;
2439 
2440   pEnv->JS_docSubmitForm(pBuffer, nBufSize, csDestination.c_str());
2441   return TRUE;
2442 }
2443 
2444 FX_BOOL CPDFSDK_InterForm::FDFToURLEncodedData(CFX_WideString csFDFFile,
2445                                                CFX_WideString csTxtFile) {
2446   return TRUE;
2447 }
2448 
2449 FX_BOOL CPDFSDK_InterForm::FDFToURLEncodedData(uint8_t*& pBuf,
2450                                                FX_STRSIZE& nBufSize) {
2451   CFDF_Document* pFDF = CFDF_Document::ParseMemory(pBuf, nBufSize);
2452   if (pFDF) {
2453     CPDF_Dictionary* pMainDict = pFDF->GetRoot()->GetDict("FDF");
2454     if (!pMainDict)
2455       return FALSE;
2456 
2457     // Get fields
2458     CPDF_Array* pFields = pMainDict->GetArray("Fields");
2459     if (!pFields)
2460       return FALSE;
2461 
2462     CFX_ByteTextBuf fdfEncodedData;
2463 
2464     for (FX_DWORD i = 0; i < pFields->GetCount(); i++) {
2465       CPDF_Dictionary* pField = pFields->GetDict(i);
2466       if (!pField)
2467         continue;
2468       CFX_WideString name;
2469       name = pField->GetUnicodeText("T");
2470       CFX_ByteString name_b = CFX_ByteString::FromUnicode(name);
2471       CFX_ByteString csBValue = pField->GetString("V");
2472       CFX_WideString csWValue = PDF_DecodeText(csBValue);
2473       CFX_ByteString csValue_b = CFX_ByteString::FromUnicode(csWValue);
2474 
2475       fdfEncodedData = fdfEncodedData << name_b.GetBuffer(name_b.GetLength());
2476       name_b.ReleaseBuffer();
2477       fdfEncodedData = fdfEncodedData << "=";
2478       fdfEncodedData = fdfEncodedData
2479                        << csValue_b.GetBuffer(csValue_b.GetLength());
2480       csValue_b.ReleaseBuffer();
2481       if (i != pFields->GetCount() - 1)
2482         fdfEncodedData = fdfEncodedData << "&";
2483     }
2484 
2485     nBufSize = fdfEncodedData.GetLength();
2486     pBuf = FX_Alloc(uint8_t, nBufSize);
2487     FXSYS_memcpy(pBuf, fdfEncodedData.GetBuffer(), nBufSize);
2488   }
2489   return TRUE;
2490 }
2491 
2492 FX_BOOL CPDFSDK_InterForm::ExportFieldsToFDFTextBuf(
2493     const std::vector<CPDF_FormField*>& fields,
2494     FX_BOOL bIncludeOrExclude,
2495     CFX_ByteTextBuf& textBuf) {
2496   std::unique_ptr<CFDF_Document> pFDF(m_pInterForm->ExportToFDF(
2497       m_pDocument->GetPath(), fields, bIncludeOrExclude));
2498   return pFDF ? pFDF->WriteBuf(textBuf) : FALSE;
2499 }
2500 
2501 #ifdef PDF_ENABLE_XFA
2502 void CPDFSDK_InterForm::SynchronizeField(CPDF_FormField* pFormField,
2503                                          FX_BOOL bSynchronizeElse) {
2504   ASSERT(pFormField != NULL);
2505 
2506   int x = 0;
2507   if (m_FieldSynchronizeMap.Lookup(pFormField, x))
2508     return;
2509 
2510   for (int i = 0, sz = pFormField->CountControls(); i < sz; i++) {
2511     CPDF_FormControl* pFormCtrl = pFormField->GetControl(i);
2512     ASSERT(pFormCtrl != NULL);
2513 
2514     ASSERT(m_pInterForm != NULL);
2515     if (CPDFSDK_Widget* pWidget = GetWidget(pFormCtrl)) {
2516       pWidget->Synchronize(bSynchronizeElse);
2517     }
2518   }
2519 }
2520 #endif  // PDF_ENABLE_XFA
2521 
2522 CFX_WideString CPDFSDK_InterForm::GetTemporaryFileName(
2523     const CFX_WideString& sFileExt) {
2524   CFX_WideString sFileName;
2525   return L"";
2526 }
2527 
2528 FX_BOOL CPDFSDK_InterForm::SubmitForm(const CFX_WideString& sDestination,
2529                                       FX_BOOL bUrlEncoded) {
2530   if (sDestination.IsEmpty())
2531     return FALSE;
2532 
2533   if (!m_pDocument || !m_pInterForm)
2534     return FALSE;
2535 
2536   CPDFDoc_Environment* pEnv = m_pDocument->GetEnv();
2537   CFX_WideString wsPDFFilePath = m_pDocument->GetPath();
2538   CFDF_Document* pFDFDoc = m_pInterForm->ExportToFDF(wsPDFFilePath);
2539   if (!pFDFDoc)
2540     return FALSE;
2541 
2542   CFX_ByteTextBuf FdfBuffer;
2543   FX_BOOL bRet = pFDFDoc->WriteBuf(FdfBuffer);
2544   delete pFDFDoc;
2545   if (!bRet)
2546     return FALSE;
2547 
2548   uint8_t* pBuffer = FdfBuffer.GetBuffer();
2549   FX_STRSIZE nBufSize = FdfBuffer.GetLength();
2550 
2551   if (bUrlEncoded) {
2552     if (!FDFToURLEncodedData(pBuffer, nBufSize))
2553       return FALSE;
2554   }
2555 
2556   pEnv->JS_docSubmitForm(pBuffer, nBufSize, sDestination.c_str());
2557 
2558   if (bUrlEncoded) {
2559     FX_Free(pBuffer);
2560     pBuffer = NULL;
2561   }
2562 
2563   return TRUE;
2564 }
2565 
2566 FX_BOOL CPDFSDK_InterForm::ExportFormToFDFTextBuf(CFX_ByteTextBuf& textBuf) {
2567   CFDF_Document* pFDF = m_pInterForm->ExportToFDF(m_pDocument->GetPath());
2568   if (!pFDF)
2569     return FALSE;
2570 
2571   FX_BOOL bRet = pFDF->WriteBuf(textBuf);
2572   delete pFDF;
2573 
2574   return bRet;
2575 }
2576 
2577 FX_BOOL CPDFSDK_InterForm::DoAction_ResetForm(const CPDF_Action& action) {
2578   ASSERT(action);
2579 
2580   CPDF_Dictionary* pActionDict = action.GetDict();
2581   if (!pActionDict->KeyExist("Fields"))
2582     return m_pInterForm->ResetForm(true);
2583 
2584   CPDF_ActionFields af = action.GetWidgets();
2585   FX_DWORD dwFlags = action.GetFlags();
2586 
2587   std::vector<CPDF_Object*> fieldObjects = af.GetAllFields();
2588   std::vector<CPDF_FormField*> fields = GetFieldFromObjects(fieldObjects);
2589   return m_pInterForm->ResetForm(fields, !(dwFlags & 0x01), true);
2590 }
2591 
2592 FX_BOOL CPDFSDK_InterForm::DoAction_ImportData(const CPDF_Action& action) {
2593   return FALSE;
2594 }
2595 
2596 std::vector<CPDF_FormField*> CPDFSDK_InterForm::GetFieldFromObjects(
2597     const std::vector<CPDF_Object*>& objects) const {
2598   std::vector<CPDF_FormField*> fields;
2599   for (CPDF_Object* pObject : objects) {
2600     if (pObject && pObject->IsString()) {
2601       CFX_WideString csName = pObject->GetUnicodeText();
2602       CPDF_FormField* pField = m_pInterForm->GetField(0, csName);
2603       if (pField)
2604         fields.push_back(pField);
2605     }
2606   }
2607   return fields;
2608 }
2609 
2610 int CPDFSDK_InterForm::BeforeValueChange(const CPDF_FormField* pField,
2611                                          CFX_WideString& csValue) {
2612   CPDF_FormField* pFormField = (CPDF_FormField*)pField;
2613   int nType = pFormField->GetFieldType();
2614   if (nType == FIELDTYPE_COMBOBOX || nType == FIELDTYPE_TEXTFIELD) {
2615     FX_BOOL bRC = TRUE;
2616     OnKeyStrokeCommit(pFormField, csValue, bRC);
2617     if (bRC) {
2618       OnValidate(pFormField, csValue, bRC);
2619       return bRC ? 1 : -1;
2620     }
2621     return -1;
2622   }
2623   return 0;
2624 }
2625 
2626 int CPDFSDK_InterForm::AfterValueChange(const CPDF_FormField* pField) {
2627   CPDF_FormField* pFormField = (CPDF_FormField*)pField;
2628 #ifdef PDF_ENABLE_XFA
2629   SynchronizeField(pFormField, FALSE);
2630 #endif  // PDF_ENABLE_XFA
2631   int nType = pFormField->GetFieldType();
2632   if (nType == FIELDTYPE_COMBOBOX || nType == FIELDTYPE_TEXTFIELD) {
2633     OnCalculate(pFormField);
2634     FX_BOOL bFormated = FALSE;
2635     CFX_WideString sValue = OnFormat(pFormField, bFormated);
2636     if (bFormated)
2637       ResetFieldAppearance(pFormField, sValue.c_str(), TRUE);
2638     else
2639       ResetFieldAppearance(pFormField, NULL, TRUE);
2640     UpdateField(pFormField);
2641   }
2642   return 0;
2643 }
2644 
2645 int CPDFSDK_InterForm::BeforeSelectionChange(const CPDF_FormField* pField,
2646                                              CFX_WideString& csValue) {
2647   CPDF_FormField* pFormField = (CPDF_FormField*)pField;
2648   if (pFormField->GetFieldType() != FIELDTYPE_LISTBOX)
2649     return 0;
2650 
2651   FX_BOOL bRC = TRUE;
2652   OnKeyStrokeCommit(pFormField, csValue, bRC);
2653   if (!bRC)
2654     return -1;
2655 
2656   OnValidate(pFormField, csValue, bRC);
2657   if (!bRC)
2658     return -1;
2659 
2660   return 1;
2661 }
2662 
2663 int CPDFSDK_InterForm::AfterSelectionChange(const CPDF_FormField* pField) {
2664   CPDF_FormField* pFormField = (CPDF_FormField*)pField;
2665   if (pFormField->GetFieldType() == FIELDTYPE_LISTBOX) {
2666     OnCalculate(pFormField);
2667     ResetFieldAppearance(pFormField, NULL, TRUE);
2668     UpdateField(pFormField);
2669   }
2670   return 0;
2671 }
2672 
2673 int CPDFSDK_InterForm::AfterCheckedStatusChange(
2674     const CPDF_FormField* pField,
2675     const CFX_ByteArray& statusArray) {
2676   CPDF_FormField* pFormField = (CPDF_FormField*)pField;
2677   int nType = pFormField->GetFieldType();
2678   if (nType == FIELDTYPE_CHECKBOX || nType == FIELDTYPE_RADIOBUTTON) {
2679     OnCalculate(pFormField);
2680     UpdateField(pFormField);
2681   }
2682   return 0;
2683 }
2684 
2685 int CPDFSDK_InterForm::BeforeFormReset(const CPDF_InterForm* pForm) {
2686   return 0;
2687 }
2688 
2689 int CPDFSDK_InterForm::AfterFormReset(const CPDF_InterForm* pForm) {
2690   OnCalculate(nullptr);
2691   return 0;
2692 }
2693 
2694 int CPDFSDK_InterForm::BeforeFormImportData(const CPDF_InterForm* pForm) {
2695   return 0;
2696 }
2697 
2698 int CPDFSDK_InterForm::AfterFormImportData(const CPDF_InterForm* pForm) {
2699   OnCalculate(nullptr);
2700   return 0;
2701 }
2702 
2703 FX_BOOL CPDFSDK_InterForm::IsNeedHighLight(int nFieldType) {
2704   if (nFieldType < 1 || nFieldType > kNumFieldTypes)
2705     return FALSE;
2706   return m_bNeedHightlight[nFieldType - 1];
2707 }
2708 
2709 void CPDFSDK_InterForm::RemoveAllHighLight() {
2710   for (int i = 0; i < kNumFieldTypes; ++i)
2711     m_bNeedHightlight[i] = FALSE;
2712 }
2713 
2714 void CPDFSDK_InterForm::SetHighlightColor(FX_COLORREF clr, int nFieldType) {
2715   if (nFieldType < 0 || nFieldType > kNumFieldTypes)
2716     return;
2717   switch (nFieldType) {
2718     case 0: {
2719       for (int i = 0; i < kNumFieldTypes; ++i) {
2720         m_aHighlightColor[i] = clr;
2721         m_bNeedHightlight[i] = TRUE;
2722       }
2723       break;
2724     }
2725     default: {
2726       m_aHighlightColor[nFieldType - 1] = clr;
2727       m_bNeedHightlight[nFieldType - 1] = TRUE;
2728       break;
2729     }
2730   }
2731 }
2732 
2733 FX_COLORREF CPDFSDK_InterForm::GetHighlightColor(int nFieldType) {
2734   if (nFieldType < 0 || nFieldType > kNumFieldTypes)
2735     return FXSYS_RGB(255, 255, 255);
2736   if (nFieldType == 0)
2737     return m_aHighlightColor[0];
2738   return m_aHighlightColor[nFieldType - 1];
2739 }
2740 
2741 CBA_AnnotIterator::CBA_AnnotIterator(CPDFSDK_PageView* pPageView,
2742                                      const CFX_ByteString& sType,
2743                                      const CFX_ByteString& sSubType)
2744     : m_pPageView(pPageView),
2745       m_sType(sType),
2746       m_sSubType(sSubType),
2747       m_nTabs(BAI_STRUCTURE) {
2748   CPDF_Page* pPDFPage = m_pPageView->GetPDFPage();
2749   CFX_ByteString sTabs = pPDFPage->m_pFormDict->GetString("Tabs");
2750 
2751   if (sTabs == "R") {
2752     m_nTabs = BAI_ROW;
2753   } else if (sTabs == "C") {
2754     m_nTabs = BAI_COLUMN;
2755   } else {
2756     m_nTabs = BAI_STRUCTURE;
2757   }
2758 
2759   GenerateResults();
2760 }
2761 
2762 CBA_AnnotIterator::~CBA_AnnotIterator() {
2763   m_Annots.RemoveAll();
2764 }
2765 
2766 CPDFSDK_Annot* CBA_AnnotIterator::GetFirstAnnot() {
2767   if (m_Annots.GetSize() > 0)
2768     return m_Annots[0];
2769 
2770   return NULL;
2771 }
2772 
2773 CPDFSDK_Annot* CBA_AnnotIterator::GetLastAnnot() {
2774   if (m_Annots.GetSize() > 0)
2775     return m_Annots[m_Annots.GetSize() - 1];
2776 
2777   return NULL;
2778 }
2779 
2780 CPDFSDK_Annot* CBA_AnnotIterator::GetNextAnnot(CPDFSDK_Annot* pAnnot) {
2781   for (int i = 0, sz = m_Annots.GetSize(); i < sz; ++i) {
2782     if (m_Annots[i] == pAnnot)
2783       return (i + 1 < sz) ? m_Annots[i + 1] : m_Annots[0];
2784   }
2785   return NULL;
2786 }
2787 
2788 CPDFSDK_Annot* CBA_AnnotIterator::GetPrevAnnot(CPDFSDK_Annot* pAnnot) {
2789   for (int i = 0, sz = m_Annots.GetSize(); i < sz; ++i) {
2790     if (m_Annots[i] == pAnnot)
2791       return (i - 1 >= 0) ? m_Annots[i - 1] : m_Annots[sz - 1];
2792   }
2793   return NULL;
2794 }
2795 
2796 int CBA_AnnotIterator::CompareByLeft(CPDFSDK_Annot* p1, CPDFSDK_Annot* p2) {
2797   ASSERT(p1);
2798   ASSERT(p2);
2799 
2800   CPDF_Rect rcAnnot1 = GetAnnotRect(p1);
2801   CPDF_Rect rcAnnot2 = GetAnnotRect(p2);
2802 
2803   if (rcAnnot1.left < rcAnnot2.left)
2804     return -1;
2805   if (rcAnnot1.left > rcAnnot2.left)
2806     return 1;
2807   return 0;
2808 }
2809 
2810 int CBA_AnnotIterator::CompareByTop(CPDFSDK_Annot* p1, CPDFSDK_Annot* p2) {
2811   ASSERT(p1);
2812   ASSERT(p2);
2813 
2814   CPDF_Rect rcAnnot1 = GetAnnotRect(p1);
2815   CPDF_Rect rcAnnot2 = GetAnnotRect(p2);
2816 
2817   if (rcAnnot1.top < rcAnnot2.top)
2818     return -1;
2819   if (rcAnnot1.top > rcAnnot2.top)
2820     return 1;
2821   return 0;
2822 }
2823 
2824 void CBA_AnnotIterator::GenerateResults() {
2825   switch (m_nTabs) {
2826     case BAI_STRUCTURE: {
2827       for (size_t i = 0; i < m_pPageView->CountAnnots(); ++i) {
2828         CPDFSDK_Annot* pAnnot = m_pPageView->GetAnnot(i);
2829         if (pAnnot->GetType() == m_sType && pAnnot->GetSubType() == m_sSubType)
2830           m_Annots.Add(pAnnot);
2831       }
2832       break;
2833     }
2834     case BAI_ROW: {
2835       CPDFSDK_SortAnnots sa;
2836       for (size_t i = 0; i < m_pPageView->CountAnnots(); ++i) {
2837         CPDFSDK_Annot* pAnnot = m_pPageView->GetAnnot(i);
2838         if (pAnnot->GetType() == m_sType && pAnnot->GetSubType() == m_sSubType)
2839           sa.Add(pAnnot);
2840       }
2841 
2842       if (sa.GetSize() > 0)
2843         sa.Sort(CBA_AnnotIterator::CompareByLeft);
2844 
2845       while (sa.GetSize() > 0) {
2846         int nLeftTopIndex = -1;
2847         FX_FLOAT fTop = 0.0f;
2848 
2849         for (int i = sa.GetSize() - 1; i >= 0; i--) {
2850           CPDFSDK_Annot* pAnnot = sa.GetAt(i);
2851           ASSERT(pAnnot);
2852 
2853           CPDF_Rect rcAnnot = GetAnnotRect(pAnnot);
2854 
2855           if (rcAnnot.top > fTop) {
2856             nLeftTopIndex = i;
2857             fTop = rcAnnot.top;
2858           }
2859         }
2860 
2861         if (nLeftTopIndex >= 0) {
2862           CPDFSDK_Annot* pLeftTopAnnot = sa.GetAt(nLeftTopIndex);
2863           ASSERT(pLeftTopAnnot);
2864 
2865           CPDF_Rect rcLeftTop = GetAnnotRect(pLeftTopAnnot);
2866 
2867           m_Annots.Add(pLeftTopAnnot);
2868           sa.RemoveAt(nLeftTopIndex);
2869 
2870           CFX_ArrayTemplate<int> aSelect;
2871 
2872           for (int i = 0, sz = sa.GetSize(); i < sz; ++i) {
2873             CPDFSDK_Annot* pAnnot = sa.GetAt(i);
2874             ASSERT(pAnnot);
2875 
2876             CPDF_Rect rcAnnot = GetAnnotRect(pAnnot);
2877             FX_FLOAT fCenterY = (rcAnnot.top + rcAnnot.bottom) / 2.0f;
2878             if (fCenterY > rcLeftTop.bottom && fCenterY < rcLeftTop.top)
2879               aSelect.Add(i);
2880           }
2881 
2882           for (int i = 0, sz = aSelect.GetSize(); i < sz; ++i)
2883             m_Annots.Add(sa[aSelect[i]]);
2884 
2885           for (int i = aSelect.GetSize() - 1; i >= 0; --i)
2886               sa.RemoveAt(aSelect[i]);
2887 
2888           aSelect.RemoveAll();
2889         }
2890       }
2891       sa.RemoveAll();
2892       break;
2893     }
2894     case BAI_COLUMN: {
2895       CPDFSDK_SortAnnots sa;
2896       for (size_t i = 0; i < m_pPageView->CountAnnots(); ++i) {
2897         CPDFSDK_Annot* pAnnot = m_pPageView->GetAnnot(i);
2898         if (pAnnot->GetType() == m_sType && pAnnot->GetSubType() == m_sSubType)
2899           sa.Add(pAnnot);
2900       }
2901 
2902       if (sa.GetSize() > 0)
2903         sa.Sort(CBA_AnnotIterator::CompareByTop, FALSE);
2904 
2905       while (sa.GetSize() > 0) {
2906         int nLeftTopIndex = -1;
2907         FX_FLOAT fLeft = -1.0f;
2908 
2909         for (int i = sa.GetSize() - 1; i >= 0; --i) {
2910           CPDFSDK_Annot* pAnnot = sa.GetAt(i);
2911           ASSERT(pAnnot);
2912 
2913           CPDF_Rect rcAnnot = GetAnnotRect(pAnnot);
2914 
2915           if (fLeft < 0) {
2916             nLeftTopIndex = 0;
2917             fLeft = rcAnnot.left;
2918           } else if (rcAnnot.left < fLeft) {
2919             nLeftTopIndex = i;
2920             fLeft = rcAnnot.left;
2921           }
2922         }
2923 
2924         if (nLeftTopIndex >= 0) {
2925           CPDFSDK_Annot* pLeftTopAnnot = sa.GetAt(nLeftTopIndex);
2926           ASSERT(pLeftTopAnnot);
2927 
2928           CPDF_Rect rcLeftTop = GetAnnotRect(pLeftTopAnnot);
2929 
2930           m_Annots.Add(pLeftTopAnnot);
2931           sa.RemoveAt(nLeftTopIndex);
2932 
2933           CFX_ArrayTemplate<int> aSelect;
2934           for (int i = 0, sz = sa.GetSize(); i < sz; ++i) {
2935             CPDFSDK_Annot* pAnnot = sa.GetAt(i);
2936             ASSERT(pAnnot);
2937 
2938             CPDF_Rect rcAnnot = GetAnnotRect(pAnnot);
2939             FX_FLOAT fCenterX = (rcAnnot.left + rcAnnot.right) / 2.0f;
2940             if (fCenterX > rcLeftTop.left && fCenterX < rcLeftTop.right)
2941               aSelect.Add(i);
2942           }
2943 
2944           for (int i = 0, sz = aSelect.GetSize(); i < sz; ++i)
2945             m_Annots.Add(sa[aSelect[i]]);
2946 
2947           for (int i = aSelect.GetSize() - 1; i >= 0; --i)
2948             sa.RemoveAt(aSelect[i]);
2949 
2950           aSelect.RemoveAll();
2951         }
2952       }
2953       sa.RemoveAll();
2954       break;
2955     }
2956   }
2957 }
2958 
2959 CPDF_Rect CBA_AnnotIterator::GetAnnotRect(CPDFSDK_Annot* pAnnot) {
2960   CPDF_Rect rcAnnot;
2961   pAnnot->GetPDFAnnot()->GetRect(rcAnnot);
2962   return rcAnnot;
2963 }
2964