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
29CPDFSDK_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
44CPDFSDK_Widget::~CPDFSDK_Widget() {}
45
46#ifdef PDF_ENABLE_XFA
47IXFA_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
71IXFA_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
85IXFA_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
100static 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
121static 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
175FX_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
199FX_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
258void 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
310void 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
325void 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
338void 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
412void 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
460FX_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
498int CPDFSDK_Widget::GetFieldType() const {
499  return GetFormField()->GetFieldType();
500}
501
502FX_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
513int 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
521CFX_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
529CPDF_FormField* CPDFSDK_Widget::GetFormField() const {
530  return GetFormControl()->GetField();
531}
532
533CPDF_FormControl* CPDFSDK_Widget::GetFormControl() const {
534  CPDF_InterForm* pPDFInterForm = m_pInterForm->GetInterForm();
535  return pPDFInterForm->GetControlByDict(GetAnnotDict());
536}
537
538CPDF_FormControl* CPDFSDK_Widget::GetFormControl(
539    CPDF_InterForm* pInterForm,
540    const CPDF_Dictionary* pAnnotDict) {
541  ASSERT(pAnnotDict);
542  return pInterForm->GetControlByDict(pAnnotDict);
543}
544
545int CPDFSDK_Widget::GetRotate() const {
546  CPDF_FormControl* pCtrl = GetFormControl();
547  return pCtrl->GetRotation() % 360;
548}
549
550#ifdef PDF_ENABLE_XFA
551CFX_WideString CPDFSDK_Widget::GetName() const {
552  CPDF_FormField* pFormField = GetFormField();
553  return pFormField->GetFullName();
554}
555#endif  // PDF_ENABLE_XFA
556
557FX_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
565FX_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
573FX_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
588FX_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
598int 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
614CFX_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
626CFX_WideString CPDFSDK_Widget::GetValue() const {
627#endif  // PDF_ENABLE_XFA
628  CPDF_FormField* pFormField = GetFormField();
629  return pFormField->GetValue();
630}
631
632CFX_WideString CPDFSDK_Widget::GetDefaultValue() const {
633  CPDF_FormField* pFormField = GetFormField();
634  return pFormField->GetDefaultValue();
635}
636
637CFX_WideString CPDFSDK_Widget::GetOptionLabel(int nIndex) const {
638  CPDF_FormField* pFormField = GetFormField();
639  return pFormField->GetOptionLabel(nIndex);
640}
641
642int CPDFSDK_Widget::CountOptions() const {
643  CPDF_FormField* pFormField = GetFormField();
644  return pFormField->CountOptions();
645}
646
647FX_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
664int CPDFSDK_Widget::GetTopVisibleIndex() const {
665  CPDF_FormField* pFormField = GetFormField();
666  return pFormField->GetTopVisibleIndex();
667}
668
669FX_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
684int CPDFSDK_Widget::GetAlignment() const {
685  CPDF_FormControl* pFormCtrl = GetFormControl();
686  return pFormCtrl->GetControlAlignment();
687}
688
689int CPDFSDK_Widget::GetMaxLen() const {
690  CPDF_FormField* pFormField = GetFormField();
691  return pFormField->GetMaxLen();
692}
693
694void 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
707void 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
716void CPDFSDK_Widget::SetDefaultValue(const CFX_WideString& sValue) {}
717void 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
728void 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
737void CPDFSDK_Widget::SetTopVisibleIndex(int index) {}
738
739void CPDFSDK_Widget::SetAppModified() {
740  m_bAppModified = TRUE;
741}
742
743void CPDFSDK_Widget::ClearAppModified() {
744  m_bAppModified = FALSE;
745}
746
747FX_BOOL CPDFSDK_Widget::IsAppModified() const {
748  return m_bAppModified;
749}
750
751#ifdef PDF_ENABLE_XFA
752void 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
770void 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
806CFX_WideString CPDFSDK_Widget::OnFormat(FX_BOOL& bFormated) {
807  CPDF_FormField* pFormField = GetFormField();
808  ASSERT(pFormField);
809  return m_pInterForm->OnFormat(pFormField, bFormated);
810}
811
812void CPDFSDK_Widget::ResetFieldAppearance(FX_BOOL bValueChanged) {
813  CPDF_FormField* pFormField = GetFormField();
814  ASSERT(pFormField);
815  m_pInterForm->ResetFieldAppearance(pFormField, NULL, bValueChanged);
816}
817
818void 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
845void CPDFSDK_Widget::UpdateField() {
846  CPDF_FormField* pFormField = GetFormField();
847  ASSERT(pFormField);
848  m_pInterForm->UpdateField(pFormField);
849}
850
851void 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
880void 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
1095void 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
1221void 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
1384void 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
1458void 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
1546void 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
1694CPDF_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
1707CPDF_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
1729CFX_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
1737CFX_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
1777CFX_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
1803CPWL_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
1818CPWL_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
1831CPWL_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
1844void 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
1873void CPDFSDK_Widget::RemoveAppearance(const CFX_ByteString& sAPType) {
1874  if (CPDF_Dictionary* pAPDict = m_pAnnot->GetAnnotDict()->GetDict("AP")) {
1875    pAPDict->RemoveAt(sAPType);
1876  }
1877}
1878
1879FX_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
1934CPDF_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
1964CFX_WideString CPDFSDK_Widget::GetAlternateName() const {
1965  CPDF_FormField* pFormField = GetFormField();
1966  return pFormField->GetAlternateName();
1967}
1968
1969int32_t CPDFSDK_Widget::GetAppearanceAge() const {
1970  return m_nAppAge;
1971}
1972
1973int32_t CPDFSDK_Widget::GetValueAge() const {
1974  return m_nValueAge;
1975}
1976
1977FX_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
1995CPDFSDK_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
2001FX_BOOL CPDFSDK_XFAWidget::IsXFAField() {
2002  return TRUE;
2003}
2004
2005CFX_ByteString CPDFSDK_XFAWidget::GetType() const {
2006  return FSDK_XFAWIDGET_TYPENAME;
2007}
2008
2009CFX_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
2024CPDFSDK_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
2041CPDFSDK_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
2050FX_BOOL CPDFSDK_InterForm::HighlightWidgets() {
2051  return FALSE;
2052}
2053
2054CPDFSDK_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
2065CPDFSDK_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
2100void 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
2110void 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
2122int 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
2143void CPDFSDK_InterForm::AddMap(CPDF_FormControl* pControl,
2144                               CPDFSDK_Widget* pWidget) {
2145  m_Map[pControl] = pWidget;
2146}
2147
2148void CPDFSDK_InterForm::RemoveMap(CPDF_FormControl* pControl) {
2149  m_Map.erase(pControl);
2150}
2151
2152void CPDFSDK_InterForm::EnableCalculate(FX_BOOL bEnabled) {
2153  m_bCalculate = bEnabled;
2154}
2155
2156FX_BOOL CPDFSDK_InterForm::IsCalculateEnabled() const {
2157  return m_bCalculate;
2158}
2159
2160#ifdef PDF_ENABLE_XFA
2161void CPDFSDK_InterForm::AddXFAMap(IXFA_Widget* hWidget,
2162                                  CPDFSDK_XFAWidget* pWidget) {
2163  m_XFAMap.SetAt(hWidget, pWidget);
2164}
2165
2166void CPDFSDK_InterForm::RemoveXFAMap(IXFA_Widget* hWidget) {
2167  m_XFAMap.RemoveKey(hWidget);
2168}
2169
2170CPDFSDK_XFAWidget* CPDFSDK_InterForm::GetXFAWidget(IXFA_Widget* hWidget) {
2171  CPDFSDK_XFAWidget* pWidget = NULL;
2172  m_XFAMap.Lookup(hWidget, pWidget);
2173
2174  return pWidget;
2175}
2176
2177void CPDFSDK_InterForm::XfaEnableCalculate(FX_BOOL bEnabled) {
2178  m_bXfaCalculate = bEnabled;
2179}
2180FX_BOOL CPDFSDK_InterForm::IsXfaCalculateEnabled() const {
2181  return m_bXfaCalculate;
2182}
2183
2184FX_BOOL CPDFSDK_InterForm::IsXfaValidationsEnabled() {
2185  return m_bXfaValidationsEnabled;
2186}
2187void CPDFSDK_InterForm::XfaSetValidationsEnabled(FX_BOOL bEnabled) {
2188  m_bXfaValidationsEnabled = bEnabled;
2189}
2190#endif  // PDF_ENABLE_XFA
2191
2192void 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
2246CFX_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
2295void 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
2306void 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
2324void 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
2345void 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
2366FX_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
2399FX_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
2424FX_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
2444FX_BOOL CPDFSDK_InterForm::FDFToURLEncodedData(CFX_WideString csFDFFile,
2445                                               CFX_WideString csTxtFile) {
2446  return TRUE;
2447}
2448
2449FX_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
2492FX_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
2502void 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
2522CFX_WideString CPDFSDK_InterForm::GetTemporaryFileName(
2523    const CFX_WideString& sFileExt) {
2524  CFX_WideString sFileName;
2525  return L"";
2526}
2527
2528FX_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
2566FX_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
2577FX_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
2592FX_BOOL CPDFSDK_InterForm::DoAction_ImportData(const CPDF_Action& action) {
2593  return FALSE;
2594}
2595
2596std::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
2610int 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
2626int 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
2645int 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
2663int 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
2673int 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
2685int CPDFSDK_InterForm::BeforeFormReset(const CPDF_InterForm* pForm) {
2686  return 0;
2687}
2688
2689int CPDFSDK_InterForm::AfterFormReset(const CPDF_InterForm* pForm) {
2690  OnCalculate(nullptr);
2691  return 0;
2692}
2693
2694int CPDFSDK_InterForm::BeforeFormImportData(const CPDF_InterForm* pForm) {
2695  return 0;
2696}
2697
2698int CPDFSDK_InterForm::AfterFormImportData(const CPDF_InterForm* pForm) {
2699  OnCalculate(nullptr);
2700  return 0;
2701}
2702
2703FX_BOOL CPDFSDK_InterForm::IsNeedHighLight(int nFieldType) {
2704  if (nFieldType < 1 || nFieldType > kNumFieldTypes)
2705    return FALSE;
2706  return m_bNeedHightlight[nFieldType - 1];
2707}
2708
2709void CPDFSDK_InterForm::RemoveAllHighLight() {
2710  for (int i = 0; i < kNumFieldTypes; ++i)
2711    m_bNeedHightlight[i] = FALSE;
2712}
2713
2714void 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
2733FX_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
2741CBA_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
2762CBA_AnnotIterator::~CBA_AnnotIterator() {
2763  m_Annots.RemoveAll();
2764}
2765
2766CPDFSDK_Annot* CBA_AnnotIterator::GetFirstAnnot() {
2767  if (m_Annots.GetSize() > 0)
2768    return m_Annots[0];
2769
2770  return NULL;
2771}
2772
2773CPDFSDK_Annot* CBA_AnnotIterator::GetLastAnnot() {
2774  if (m_Annots.GetSize() > 0)
2775    return m_Annots[m_Annots.GetSize() - 1];
2776
2777  return NULL;
2778}
2779
2780CPDFSDK_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
2788CPDFSDK_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
2796int 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
2810int 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
2824void 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
2959CPDF_Rect CBA_AnnotIterator::GetAnnotRect(CPDFSDK_Annot* pAnnot) {
2960  CPDF_Rect rcAnnot;
2961  pAnnot->GetPDFAnnot()->GetRect(rcAnnot);
2962  return rcAnnot;
2963}
2964