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