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