Changes to master to more closely match XFA.
[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 = m_pPageView->GetPDFDocument();
1422   ASSERT(pDoc != NULL);
1423
1424   CPDF_Dictionary* pAPDict = m_pAnnot->GetAnnotDict()->GetDict("AP");
1425   ASSERT(pAPDict != NULL);
1426
1427   CPDF_Stream* pStream = pAPDict->GetStream(sAPType);
1428   ASSERT(pStream != NULL);
1429
1430   CPDF_Dictionary* pStreamDict = pStream->GetDict();
1431   ASSERT(pStreamDict != NULL);
1432
1433   CFX_ByteString sImageAlias = "IMG";
1434
1435   if (CPDF_Dictionary* pImageDict = pImage->GetDict()) {
1436     sImageAlias = pImageDict->GetString("Name");
1437     if (sImageAlias.IsEmpty())
1438       sImageAlias = "IMG";
1439   }
1440
1441   CPDF_Dictionary* pStreamResList = pStreamDict->GetDict("Resources");
1442   if (!pStreamResList) {
1443     pStreamResList = new CPDF_Dictionary();
1444     pStreamDict->SetAt("Resources", pStreamResList);
1445   }
1446
1447   if (pStreamResList) {
1448     CPDF_Dictionary* pXObject = new CPDF_Dictionary;
1449     pXObject->SetAtReference(sImageAlias, pDoc, pImage);
1450     pStreamResList->SetAt("XObject", pXObject);
1451   }
1452 }
1453
1454 void CPDFSDK_Widget::RemoveAppearance(const CFX_ByteString& sAPType) {
1455   if (CPDF_Dictionary* pAPDict = m_pAnnot->GetAnnotDict()->GetDict("AP")) {
1456     pAPDict->RemoveAt(sAPType);
1457   }
1458 }
1459
1460 FX_BOOL CPDFSDK_Widget::OnAAction(CPDF_AAction::AActionType type,
1461                                   PDFSDK_FieldAction& data,
1462                                   CPDFSDK_PageView* pPageView) {
1463   CPDF_Action action = GetAAction(type);
1464
1465   if (action && action.GetType() != CPDF_Action::Unknown) {
1466     CPDFSDK_Document* pDocument = pPageView->GetSDKDocument();
1467     ASSERT(pDocument != NULL);
1468
1469     CPDFDoc_Environment* pEnv = pDocument->GetEnv();
1470     ASSERT(pEnv != NULL);
1471
1472     CPDFSDK_ActionHandler* pActionHandler =
1473         pEnv->GetActionHander(); /*(CPDFSDK_ActionHandler*)pApp->GetActionHandler();*/
1474     ASSERT(pActionHandler != NULL);
1475
1476     return pActionHandler->DoAction_Field(action, type, pDocument,
1477                                           GetFormField(), data);
1478   }
1479
1480   return FALSE;
1481 }
1482
1483 CPDF_Action CPDFSDK_Widget::GetAAction(CPDF_AAction::AActionType eAAT) {
1484   switch (eAAT) {
1485     case CPDF_AAction::CursorEnter:
1486     case CPDF_AAction::CursorExit:
1487     case CPDF_AAction::ButtonDown:
1488     case CPDF_AAction::ButtonUp:
1489     case CPDF_AAction::GetFocus:
1490     case CPDF_AAction::LoseFocus:
1491     case CPDF_AAction::PageOpen:
1492     case CPDF_AAction::PageClose:
1493     case CPDF_AAction::PageVisible:
1494     case CPDF_AAction::PageInvisible:
1495       return CPDFSDK_Annot::GetAAction(eAAT);
1496
1497     case CPDF_AAction::KeyStroke:
1498     case CPDF_AAction::Format:
1499     case CPDF_AAction::Validate:
1500     case CPDF_AAction::Calculate: {
1501       CPDF_FormField* pField = GetFormField();
1502       if (CPDF_AAction aa = pField->GetAdditionalAction())
1503         return aa.GetAction(eAAT);
1504
1505       return CPDFSDK_Annot::GetAAction(eAAT);
1506     }
1507     default:
1508       break;
1509   }
1510
1511   return CPDF_Action();
1512 }
1513
1514 CFX_WideString CPDFSDK_Widget::GetAlternateName() const {
1515   CPDF_FormField* pFormField = GetFormField();
1516   ASSERT(pFormField != NULL);
1517
1518   return pFormField->GetAlternateName();
1519 }
1520
1521 int32_t CPDFSDK_Widget::GetAppearanceAge() const {
1522   return m_nAppAge;
1523 }
1524
1525 int32_t CPDFSDK_Widget::GetValueAge() const {
1526   return m_nValueAge;
1527 }
1528
1529 FX_BOOL CPDFSDK_Widget::HitTest(FX_FLOAT pageX, FX_FLOAT pageY) {
1530   CPDF_Annot* pAnnot = GetPDFAnnot();
1531   CFX_FloatRect annotRect;
1532   pAnnot->GetRect(annotRect);
1533   if (annotRect.Contains(pageX, pageY)) {
1534     if (!IsVisible())
1535       return FALSE;
1536
1537     int nFieldFlags = GetFieldFlags();
1538     if ((nFieldFlags & FIELDFLAG_READONLY) == FIELDFLAG_READONLY)
1539       return FALSE;
1540
1541     return TRUE;
1542   }
1543   return FALSE;
1544 }
1545
1546 CPDFSDK_InterForm::CPDFSDK_InterForm(CPDFSDK_Document* pDocument)
1547     : m_pDocument(pDocument),
1548       m_pInterForm(NULL),
1549       m_bCalculate(TRUE),
1550       m_bBusy(FALSE) {
1551   ASSERT(m_pDocument != NULL);
1552   m_pInterForm = new CPDF_InterForm(m_pDocument->GetDocument(), FALSE);
1553   ASSERT(m_pInterForm != NULL);
1554   m_pInterForm->SetFormNotify(this);
1555
1556   for (int i = 0; i < 6; i++)
1557     m_bNeedHightlight[i] = FALSE;
1558   m_iHighlightAlpha = 0;
1559 }
1560
1561 CPDFSDK_InterForm::~CPDFSDK_InterForm() {
1562   delete m_pInterForm;
1563   m_pInterForm = nullptr;
1564   m_Map.clear();
1565 }
1566
1567 FX_BOOL CPDFSDK_InterForm::HighlightWidgets() {
1568   return FALSE;
1569 }
1570
1571 CPDFSDK_Widget* CPDFSDK_InterForm::GetSibling(CPDFSDK_Widget* pWidget,
1572                                               FX_BOOL bNext) const {
1573   nonstd::unique_ptr<CBA_AnnotIterator> pIterator(
1574       new CBA_AnnotIterator(pWidget->GetPageView(), "Widget", ""));
1575
1576   if (bNext) {
1577     return (CPDFSDK_Widget*)pIterator->GetNextAnnot(pWidget);
1578   }
1579   return (CPDFSDK_Widget*)pIterator->GetPrevAnnot(pWidget);
1580 }
1581
1582 CPDFSDK_Widget* CPDFSDK_InterForm::GetWidget(CPDF_FormControl* pControl) const {
1583   if (!pControl || !m_pInterForm)
1584     return nullptr;
1585
1586   CPDFSDK_Widget* pWidget = nullptr;
1587   const auto it = m_Map.find(pControl);
1588   if (it != m_Map.end())
1589     pWidget = it->second;
1590
1591   if (pWidget)
1592     return pWidget;
1593
1594   CPDF_Dictionary* pControlDict = pControl->GetWidget();
1595   CPDF_Document* pDocument = m_pDocument->GetDocument();
1596   CPDFSDK_PageView* pPage = nullptr;
1597
1598   if (CPDF_Dictionary* pPageDict = pControlDict->GetDict("P")) {
1599     int nPageIndex = pDocument->GetPageIndex(pPageDict->GetObjNum());
1600     if (nPageIndex >= 0) {
1601       pPage = m_pDocument->GetPageView(nPageIndex);
1602     }
1603   }
1604
1605   if (!pPage) {
1606     int nPageIndex = GetPageIndexByAnnotDict(pDocument, pControlDict);
1607     if (nPageIndex >= 0) {
1608       pPage = m_pDocument->GetPageView(nPageIndex);
1609     }
1610   }
1611
1612   if (!pPage)
1613     return nullptr;
1614   return (CPDFSDK_Widget*)pPage->GetAnnotByDict(pControlDict);
1615 }
1616
1617 void CPDFSDK_InterForm::GetWidgets(const CFX_WideString& sFieldName,
1618                                    CFX_PtrArray& widgets) {
1619   ASSERT(m_pInterForm != NULL);
1620
1621   for (int i = 0, sz = m_pInterForm->CountFields(sFieldName); i < sz; i++) {
1622     CPDF_FormField* pFormField = m_pInterForm->GetField(i, sFieldName);
1623     ASSERT(pFormField != NULL);
1624
1625     GetWidgets(pFormField, widgets);
1626   }
1627 }
1628
1629 void CPDFSDK_InterForm::GetWidgets(CPDF_FormField* pField,
1630                                    CFX_PtrArray& widgets) {
1631   ASSERT(pField != NULL);
1632
1633   for (int i = 0, isz = pField->CountControls(); i < isz; i++) {
1634     CPDF_FormControl* pFormCtrl = pField->GetControl(i);
1635     ASSERT(pFormCtrl != NULL);
1636
1637     CPDFSDK_Widget* pWidget = GetWidget(pFormCtrl);
1638
1639     if (pWidget)
1640       widgets.Add(pWidget);
1641   }
1642 }
1643
1644 int CPDFSDK_InterForm::GetPageIndexByAnnotDict(
1645     CPDF_Document* pDocument,
1646     CPDF_Dictionary* pAnnotDict) const {
1647   ASSERT(pDocument != NULL);
1648   ASSERT(pAnnotDict != NULL);
1649
1650   for (int i = 0, sz = pDocument->GetPageCount(); i < sz; i++) {
1651     if (CPDF_Dictionary* pPageDict = pDocument->GetPage(i)) {
1652       if (CPDF_Array* pAnnots = pPageDict->GetArray("Annots")) {
1653         for (int j = 0, jsz = pAnnots->GetCount(); j < jsz; j++) {
1654           CPDF_Object* pDict = pAnnots->GetElementValue(j);
1655           if (pAnnotDict == pDict) {
1656             return i;
1657           }
1658         }
1659       }
1660     }
1661   }
1662
1663   return -1;
1664 }
1665
1666 void CPDFSDK_InterForm::AddMap(CPDF_FormControl* pControl,
1667                                CPDFSDK_Widget* pWidget) {
1668   m_Map[pControl] = pWidget;
1669 }
1670
1671 void CPDFSDK_InterForm::RemoveMap(CPDF_FormControl* pControl) {
1672   m_Map.erase(pControl);
1673 }
1674
1675 void CPDFSDK_InterForm::EnableCalculate(FX_BOOL bEnabled) {
1676   m_bCalculate = bEnabled;
1677 }
1678
1679 FX_BOOL CPDFSDK_InterForm::IsCalculateEnabled() const {
1680   return m_bCalculate;
1681 }
1682
1683 #ifdef _WIN32
1684 CPDF_Stream* CPDFSDK_InterForm::LoadImageFromFile(const CFX_WideString& sFile) {
1685   ASSERT(m_pDocument != NULL);
1686   CPDF_Document* pDocument = m_pDocument->GetDocument();
1687   ASSERT(pDocument != NULL);
1688
1689   CPDF_Stream* pRetStream = NULL;
1690
1691   if (CFX_DIBitmap* pBmp = CFX_WindowsDIB::LoadFromFile(sFile.c_str())) {
1692     int nWidth = pBmp->GetWidth();
1693     int nHeight = pBmp->GetHeight();
1694
1695     CPDF_Image Image(pDocument);
1696     Image.SetImage(pBmp, FALSE);
1697     CPDF_Stream* pImageStream = Image.GetStream();
1698     if (pImageStream) {
1699       if (pImageStream->GetObjNum() == 0)
1700         pDocument->AddIndirectObject(pImageStream);
1701
1702       CPDF_Dictionary* pStreamDict = new CPDF_Dictionary();
1703       pStreamDict->SetAtName("Subtype", "Form");
1704       pStreamDict->SetAtName("Name", "IMG");
1705       CPDF_Array* pMatrix = new CPDF_Array();
1706       pStreamDict->SetAt("Matrix", pMatrix);
1707       pMatrix->AddInteger(1);
1708       pMatrix->AddInteger(0);
1709       pMatrix->AddInteger(0);
1710       pMatrix->AddInteger(1);
1711       pMatrix->AddInteger(-nWidth / 2);
1712       pMatrix->AddInteger(-nHeight / 2);
1713       CPDF_Dictionary* pResource = new CPDF_Dictionary();
1714       pStreamDict->SetAt("Resources", pResource);
1715       CPDF_Dictionary* pXObject = new CPDF_Dictionary();
1716       pResource->SetAt("XObject", pXObject);
1717       pXObject->SetAtReference("Img", pDocument, pImageStream);
1718       CPDF_Array* pProcSet = new CPDF_Array();
1719       pResource->SetAt("ProcSet", pProcSet);
1720       pProcSet->AddName("PDF");
1721       pProcSet->AddName("ImageC");
1722       pStreamDict->SetAtName("Type", "XObject");
1723       CPDF_Array* pBBox = new CPDF_Array();
1724       pStreamDict->SetAt("BBox", pBBox);
1725       pBBox->AddInteger(0);
1726       pBBox->AddInteger(0);
1727       pBBox->AddInteger(nWidth);
1728       pBBox->AddInteger(nHeight);
1729       pStreamDict->SetAtInteger("FormType", 1);
1730
1731       pRetStream = new CPDF_Stream(NULL, 0, NULL);
1732       CFX_ByteString csStream;
1733       csStream.Format("q\n%d 0 0 %d 0 0 cm\n/Img Do\nQ", nWidth, nHeight);
1734       pRetStream->InitStream((uint8_t*)csStream.c_str(), csStream.GetLength(),
1735                              pStreamDict);
1736       pDocument->AddIndirectObject(pRetStream);
1737     }
1738
1739     delete pBmp;
1740   }
1741
1742   return pRetStream;
1743 }
1744 #endif
1745
1746 void CPDFSDK_InterForm::OnCalculate(CPDF_FormField* pFormField) {
1747   ASSERT(m_pDocument != NULL);
1748   CPDFDoc_Environment* pEnv = m_pDocument->GetEnv();
1749   ASSERT(pEnv);
1750   if (!pEnv->IsJSInitiated())
1751     return;
1752
1753   if (m_bBusy)
1754     return;
1755
1756   m_bBusy = TRUE;
1757
1758   if (IsCalculateEnabled()) {
1759     IJS_Runtime* pRuntime = m_pDocument->GetJsRuntime();
1760     ASSERT(pRuntime != NULL);
1761
1762     pRuntime->SetReaderDocument(m_pDocument);
1763
1764     int nSize = m_pInterForm->CountFieldsInCalculationOrder();
1765     for (int i = 0; i < nSize; i++) {
1766       if (CPDF_FormField* pField =
1767               m_pInterForm->GetFieldInCalculationOrder(i)) {
1768         int nType = pField->GetFieldType();
1769         if (nType == FIELDTYPE_COMBOBOX || nType == FIELDTYPE_TEXTFIELD) {
1770           CPDF_AAction aAction = pField->GetAdditionalAction();
1771           if (aAction && aAction.ActionExist(CPDF_AAction::Calculate)) {
1772             CPDF_Action action = aAction.GetAction(CPDF_AAction::Calculate);
1773             if (action) {
1774               CFX_WideString csJS = action.GetJavaScript();
1775               if (!csJS.IsEmpty()) {
1776                 IJS_Context* pContext = pRuntime->NewContext();
1777                 ASSERT(pContext != NULL);
1778
1779                 CFX_WideString sOldValue = pField->GetValue();
1780                 CFX_WideString sValue = sOldValue;
1781                 FX_BOOL bRC = TRUE;
1782                 pContext->OnField_Calculate(pFormField, pField, sValue, bRC);
1783
1784                 CFX_WideString sInfo;
1785                 FX_BOOL bRet = pContext->RunScript(csJS, &sInfo);
1786                 pRuntime->ReleaseContext(pContext);
1787
1788                 if (bRet) {
1789                   if (bRC) {
1790                     if (sValue.Compare(sOldValue) != 0)
1791                       pField->SetValue(sValue, TRUE);
1792                   }
1793                 }
1794               }
1795             }
1796           }
1797         }
1798       }
1799     }
1800   }
1801
1802   m_bBusy = FALSE;
1803 }
1804
1805 CFX_WideString CPDFSDK_InterForm::OnFormat(CPDF_FormField* pFormField,
1806                                            FX_BOOL& bFormated) {
1807   ASSERT(m_pDocument != NULL);
1808   ASSERT(pFormField != NULL);
1809
1810   CFX_WideString sValue = pFormField->GetValue();
1811   CPDFDoc_Environment* pEnv = m_pDocument->GetEnv();
1812   ASSERT(pEnv);
1813   if (!pEnv->IsJSInitiated()) {
1814     bFormated = FALSE;
1815     return sValue;
1816   }
1817
1818   IJS_Runtime* pRuntime = m_pDocument->GetJsRuntime();
1819   ASSERT(pRuntime != NULL);
1820
1821   pRuntime->SetReaderDocument(m_pDocument);
1822
1823   if (pFormField->GetFieldType() == FIELDTYPE_COMBOBOX) {
1824     if (pFormField->CountSelectedItems() > 0) {
1825       int index = pFormField->GetSelectedIndex(0);
1826       if (index >= 0)
1827         sValue = pFormField->GetOptionLabel(index);
1828     }
1829   }
1830
1831   bFormated = FALSE;
1832
1833   CPDF_AAction aAction = pFormField->GetAdditionalAction();
1834   if (aAction != NULL && aAction.ActionExist(CPDF_AAction::Format)) {
1835     CPDF_Action action = aAction.GetAction(CPDF_AAction::Format);
1836     if (action) {
1837       CFX_WideString script = action.GetJavaScript();
1838       if (!script.IsEmpty()) {
1839         CFX_WideString Value = sValue;
1840
1841         IJS_Context* pContext = pRuntime->NewContext();
1842         ASSERT(pContext != NULL);
1843
1844         pContext->OnField_Format(pFormField, Value, TRUE);
1845
1846         CFX_WideString sInfo;
1847         FX_BOOL bRet = pContext->RunScript(script, &sInfo);
1848         pRuntime->ReleaseContext(pContext);
1849
1850         if (bRet) {
1851           sValue = Value;
1852           bFormated = TRUE;
1853         }
1854       }
1855     }
1856   }
1857
1858   return sValue;
1859 }
1860
1861 void CPDFSDK_InterForm::ResetFieldAppearance(CPDF_FormField* pFormField,
1862                                              const FX_WCHAR* sValue,
1863                                              FX_BOOL bValueChanged) {
1864   ASSERT(pFormField != NULL);
1865
1866   for (int i = 0, sz = pFormField->CountControls(); i < sz; i++) {
1867     CPDF_FormControl* pFormCtrl = pFormField->GetControl(i);
1868     ASSERT(pFormCtrl != NULL);
1869
1870     ASSERT(m_pInterForm != NULL);
1871     if (CPDFSDK_Widget* pWidget = GetWidget(pFormCtrl))
1872       pWidget->ResetAppearance(sValue, bValueChanged);
1873   }
1874 }
1875
1876 void CPDFSDK_InterForm::UpdateField(CPDF_FormField* pFormField) {
1877   ASSERT(pFormField != NULL);
1878
1879   for (int i = 0, sz = pFormField->CountControls(); i < sz; i++) {
1880     CPDF_FormControl* pFormCtrl = pFormField->GetControl(i);
1881     ASSERT(pFormCtrl != NULL);
1882
1883     if (CPDFSDK_Widget* pWidget = GetWidget(pFormCtrl)) {
1884       CPDFDoc_Environment* pEnv = m_pDocument->GetEnv();
1885       CFFL_IFormFiller* pIFormFiller = pEnv->GetIFormFiller();
1886
1887       CPDF_Page* pPage = pWidget->GetPDFPage();
1888       CPDFSDK_PageView* pPageView = m_pDocument->GetPageView(pPage, FALSE);
1889
1890       FX_RECT rcBBox = pIFormFiller->GetViewBBox(pPageView, pWidget);
1891
1892       pEnv->FFI_Invalidate(pPage, rcBBox.left, rcBBox.top, rcBBox.right,
1893                            rcBBox.bottom);
1894     }
1895   }
1896 }
1897
1898 void CPDFSDK_InterForm::OnKeyStrokeCommit(CPDF_FormField* pFormField,
1899                                           CFX_WideString& csValue,
1900                                           FX_BOOL& bRC) {
1901   ASSERT(pFormField != NULL);
1902
1903   CPDF_AAction aAction = pFormField->GetAdditionalAction();
1904   if (aAction != NULL && aAction.ActionExist(CPDF_AAction::KeyStroke)) {
1905     CPDF_Action action = aAction.GetAction(CPDF_AAction::KeyStroke);
1906     if (action) {
1907       ASSERT(m_pDocument != NULL);
1908       CPDFDoc_Environment* pEnv = m_pDocument->GetEnv();
1909       ASSERT(pEnv != NULL);
1910
1911       CPDFSDK_ActionHandler* pActionHandler = pEnv->GetActionHander();
1912       ASSERT(pActionHandler != NULL);
1913
1914       PDFSDK_FieldAction fa;
1915       fa.bModifier = pEnv->FFI_IsCTRLKeyDown(0);
1916       fa.bShift = pEnv->FFI_IsSHIFTKeyDown(0);
1917       fa.sValue = csValue;
1918
1919       pActionHandler->DoAction_FieldJavaScript(action, CPDF_AAction::KeyStroke,
1920                                                m_pDocument, pFormField, fa);
1921       bRC = fa.bRC;
1922     }
1923   }
1924 }
1925
1926 void CPDFSDK_InterForm::OnValidate(CPDF_FormField* pFormField,
1927                                    CFX_WideString& csValue,
1928                                    FX_BOOL& bRC) {
1929   ASSERT(pFormField != NULL);
1930
1931   CPDF_AAction aAction = pFormField->GetAdditionalAction();
1932   if (aAction != NULL && aAction.ActionExist(CPDF_AAction::Validate)) {
1933     CPDF_Action action = aAction.GetAction(CPDF_AAction::Validate);
1934     if (action) {
1935       ASSERT(m_pDocument != NULL);
1936       CPDFDoc_Environment* pEnv = m_pDocument->GetEnv();
1937       ASSERT(pEnv != NULL);
1938
1939       CPDFSDK_ActionHandler* pActionHandler = pEnv->GetActionHander();
1940       ASSERT(pActionHandler != NULL);
1941
1942       PDFSDK_FieldAction fa;
1943       fa.bModifier = pEnv->FFI_IsCTRLKeyDown(0);
1944       fa.bShift = pEnv->FFI_IsSHIFTKeyDown(0);
1945       fa.sValue = csValue;
1946
1947       pActionHandler->DoAction_FieldJavaScript(action, CPDF_AAction::Validate,
1948                                                m_pDocument, pFormField, fa);
1949       bRC = fa.bRC;
1950     }
1951   }
1952 }
1953
1954 /* ----------------------------- action ----------------------------- */
1955
1956 FX_BOOL CPDFSDK_InterForm::DoAction_Hide(const CPDF_Action& action) {
1957   ASSERT(action);
1958
1959   CPDF_ActionFields af = action.GetWidgets();
1960   CFX_PtrArray fieldObjects;
1961   af.GetAllFields(fieldObjects);
1962   CFX_PtrArray widgetArray;
1963   CFX_PtrArray fields;
1964   GetFieldFromObjects(fieldObjects, fields);
1965
1966   FX_BOOL bHide = action.GetHideStatus();
1967
1968   FX_BOOL bChanged = FALSE;
1969
1970   for (int i = 0, sz = fields.GetSize(); i < sz; i++) {
1971     CPDF_FormField* pField = (CPDF_FormField*)fields[i];
1972     ASSERT(pField != NULL);
1973
1974     for (int j = 0, jsz = pField->CountControls(); j < jsz; j++) {
1975       CPDF_FormControl* pControl = pField->GetControl(j);
1976       ASSERT(pControl != NULL);
1977
1978       if (CPDFSDK_Widget* pWidget = GetWidget(pControl)) {
1979         int nFlags = pWidget->GetFlags();
1980         if (bHide) {
1981           nFlags &= (~ANNOTFLAG_INVISIBLE);
1982           nFlags &= (~ANNOTFLAG_NOVIEW);
1983           nFlags |= (ANNOTFLAG_HIDDEN);
1984         } else {
1985           nFlags &= (~ANNOTFLAG_INVISIBLE);
1986           nFlags &= (~ANNOTFLAG_HIDDEN);
1987           nFlags &= (~ANNOTFLAG_NOVIEW);
1988         }
1989         pWidget->SetFlags(nFlags);
1990
1991         CPDFSDK_PageView* pPageView = pWidget->GetPageView();
1992         ASSERT(pPageView != NULL);
1993
1994         pPageView->UpdateView(pWidget);
1995
1996         bChanged = TRUE;
1997       }
1998     }
1999   }
2000
2001   return bChanged;
2002 }
2003
2004 FX_BOOL CPDFSDK_InterForm::DoAction_SubmitForm(const CPDF_Action& action) {
2005   ASSERT(m_pInterForm != NULL);
2006   CFX_WideString sDestination = action.GetFilePath();
2007   if (sDestination.IsEmpty())
2008     return FALSE;
2009
2010   CPDF_Dictionary* pActionDict = action.GetDict();
2011   if (pActionDict->KeyExist("Fields")) {
2012     CPDF_ActionFields af = action.GetWidgets();
2013     FX_DWORD dwFlags = action.GetFlags();
2014     CFX_PtrArray fieldObjects;
2015     af.GetAllFields(fieldObjects);
2016
2017     CFX_PtrArray fields;
2018     GetFieldFromObjects(fieldObjects, fields);
2019     if (fields.GetSize() != 0) {
2020       FX_BOOL bIncludeOrExclude = !(dwFlags & 0x01);
2021       if (m_pInterForm->CheckRequiredFields(&fields, bIncludeOrExclude))
2022         return FALSE;
2023
2024       return SubmitFields(sDestination, fields, bIncludeOrExclude, FALSE);
2025     }
2026   }
2027   if (m_pInterForm->CheckRequiredFields())
2028     return FALSE;
2029
2030   return SubmitForm(sDestination, FALSE);
2031 }
2032
2033 FX_BOOL CPDFSDK_InterForm::SubmitFields(const CFX_WideString& csDestination,
2034                                         const CFX_PtrArray& fields,
2035                                         FX_BOOL bIncludeOrExclude,
2036                                         FX_BOOL bUrlEncoded) {
2037   CPDFDoc_Environment* pEnv = m_pDocument->GetEnv();
2038   ASSERT(pEnv != NULL);
2039
2040   CFX_ByteTextBuf textBuf;
2041   ExportFieldsToFDFTextBuf(fields, bIncludeOrExclude, textBuf);
2042
2043   uint8_t* pBuffer = textBuf.GetBuffer();
2044   FX_STRSIZE nBufSize = textBuf.GetLength();
2045
2046   if (bUrlEncoded) {
2047     if (!FDFToURLEncodedData(pBuffer, nBufSize))
2048       return FALSE;
2049   }
2050
2051   pEnv->JS_docSubmitForm(pBuffer, nBufSize, csDestination.c_str());
2052
2053   return TRUE;
2054 }
2055
2056 void CPDFSDK_InterForm::DoFDFBuffer(CFX_ByteString sBuffer) {
2057   ASSERT(m_pDocument != NULL);
2058
2059   if (CFDF_Document* pFDFDocument = CFDF_Document::ParseMemory(
2060           (const unsigned char*)sBuffer.GetBuffer(sBuffer.GetLength()),
2061           sBuffer.GetLength())) {
2062     CPDF_Dictionary* pRootDic = pFDFDocument->GetRoot();
2063     if (pRootDic) {
2064       CPDF_Dictionary* pFDFDict = pRootDic->GetDict("FDF");
2065       if (pFDFDict) {
2066         CPDF_Dictionary* pJSDict = pFDFDict->GetDict("JavaScript");
2067         if (pJSDict) {
2068           CFX_WideString csJS;
2069
2070           CPDF_Object* pJS = pJSDict->GetElementValue("Before");
2071           if (pJS != NULL) {
2072             int iType = pJS->GetType();
2073             if (iType == PDFOBJ_STRING)
2074               csJS = pJSDict->GetUnicodeText("Before");
2075             else if (iType == PDFOBJ_STREAM)
2076               csJS = pJS->GetUnicodeText();
2077           }
2078         }
2079       }
2080     }
2081     delete pFDFDocument;
2082   }
2083
2084   sBuffer.ReleaseBuffer();
2085 }
2086
2087 FX_BOOL CPDFSDK_InterForm::FDFToURLEncodedData(CFX_WideString csFDFFile,
2088                                                CFX_WideString csTxtFile) {
2089   return TRUE;
2090 }
2091
2092 FX_BOOL CPDFSDK_InterForm::FDFToURLEncodedData(uint8_t*& pBuf,
2093                                                FX_STRSIZE& nBufSize) {
2094   CFDF_Document* pFDF = CFDF_Document::ParseMemory(pBuf, nBufSize);
2095   if (pFDF) {
2096     CPDF_Dictionary* pMainDict = pFDF->GetRoot()->GetDict("FDF");
2097     if (pMainDict == NULL)
2098       return FALSE;
2099
2100     // Get fields
2101     CPDF_Array* pFields = pMainDict->GetArray("Fields");
2102     if (pFields == NULL)
2103       return FALSE;
2104
2105     CFX_ByteTextBuf fdfEncodedData;
2106
2107     for (FX_DWORD i = 0; i < pFields->GetCount(); i++) {
2108       CPDF_Dictionary* pField = pFields->GetDict(i);
2109       if (pField == NULL)
2110         continue;
2111       CFX_WideString name;
2112       name = pField->GetUnicodeText("T");
2113       CFX_ByteString name_b = CFX_ByteString::FromUnicode(name);
2114       CFX_ByteString csBValue = pField->GetString("V");
2115       CFX_WideString csWValue = PDF_DecodeText(csBValue);
2116       CFX_ByteString csValue_b = CFX_ByteString::FromUnicode(csWValue);
2117
2118       fdfEncodedData = fdfEncodedData << name_b.GetBuffer(name_b.GetLength());
2119       name_b.ReleaseBuffer();
2120       fdfEncodedData = fdfEncodedData << "=";
2121       fdfEncodedData = fdfEncodedData
2122                        << csValue_b.GetBuffer(csValue_b.GetLength());
2123       csValue_b.ReleaseBuffer();
2124       if (i != pFields->GetCount() - 1)
2125         fdfEncodedData = fdfEncodedData << "&";
2126     }
2127
2128     nBufSize = fdfEncodedData.GetLength();
2129     pBuf = FX_Alloc(uint8_t, nBufSize);
2130     FXSYS_memcpy(pBuf, fdfEncodedData.GetBuffer(), nBufSize);
2131   }
2132   return TRUE;
2133 }
2134
2135 FX_BOOL CPDFSDK_InterForm::ExportFieldsToFDFTextBuf(const CFX_PtrArray& fields,
2136                                                     FX_BOOL bIncludeOrExclude,
2137                                                     CFX_ByteTextBuf& textBuf) {
2138   ASSERT(m_pDocument != NULL);
2139   ASSERT(m_pInterForm != NULL);
2140
2141   CFDF_Document* pFDF = m_pInterForm->ExportToFDF(
2142       m_pDocument->GetPath(), (CFX_PtrArray&)fields, bIncludeOrExclude);
2143   if (!pFDF)
2144     return FALSE;
2145   FX_BOOL bRet = pFDF->WriteBuf(textBuf);
2146   delete pFDF;
2147
2148   return bRet;
2149 }
2150
2151 CFX_WideString CPDFSDK_InterForm::GetTemporaryFileName(
2152     const CFX_WideString& sFileExt) {
2153   CFX_WideString sFileName;
2154   return L"";
2155 }
2156
2157 FX_BOOL CPDFSDK_InterForm::SubmitForm(const CFX_WideString& sDestination,
2158                                       FX_BOOL bUrlEncoded) {
2159   if (sDestination.IsEmpty())
2160     return FALSE;
2161
2162   CPDFDoc_Environment* pEnv = m_pDocument->GetEnv();
2163   ASSERT(pEnv != NULL);
2164
2165   if (NULL == m_pDocument)
2166     return FALSE;
2167   CFX_WideString wsPDFFilePath = m_pDocument->GetPath();
2168
2169   if (NULL == m_pInterForm)
2170     return FALSE;
2171   CFDF_Document* pFDFDoc = m_pInterForm->ExportToFDF(wsPDFFilePath);
2172   if (NULL == pFDFDoc)
2173     return FALSE;
2174
2175   CFX_ByteTextBuf FdfBuffer;
2176   FX_BOOL bRet = pFDFDoc->WriteBuf(FdfBuffer);
2177   delete pFDFDoc;
2178   if (!bRet)
2179     return FALSE;
2180
2181   uint8_t* pBuffer = FdfBuffer.GetBuffer();
2182   FX_STRSIZE nBufSize = FdfBuffer.GetLength();
2183
2184   if (bUrlEncoded) {
2185     if (!FDFToURLEncodedData(pBuffer, nBufSize))
2186       return FALSE;
2187   }
2188
2189   pEnv->JS_docSubmitForm(pBuffer, nBufSize, sDestination.c_str());
2190
2191   if (bUrlEncoded) {
2192     FX_Free(pBuffer);
2193     pBuffer = NULL;
2194   }
2195
2196   return TRUE;
2197 }
2198
2199 FX_BOOL CPDFSDK_InterForm::ExportFormToFDFTextBuf(CFX_ByteTextBuf& textBuf) {
2200   ASSERT(m_pInterForm != NULL);
2201   ASSERT(m_pDocument != NULL);
2202
2203   CFDF_Document* pFDF = m_pInterForm->ExportToFDF(m_pDocument->GetPath());
2204   if (!pFDF)
2205     return FALSE;
2206
2207   FX_BOOL bRet = pFDF->WriteBuf(textBuf);
2208   delete pFDF;
2209
2210   return bRet;
2211 }
2212
2213 FX_BOOL CPDFSDK_InterForm::DoAction_ResetForm(const CPDF_Action& action) {
2214   ASSERT(action);
2215
2216   CPDF_Dictionary* pActionDict = action.GetDict();
2217   if (pActionDict->KeyExist("Fields")) {
2218     CPDF_ActionFields af = action.GetWidgets();
2219     FX_DWORD dwFlags = action.GetFlags();
2220
2221     CFX_PtrArray fieldObjects;
2222     af.GetAllFields(fieldObjects);
2223     CFX_PtrArray fields;
2224     GetFieldFromObjects(fieldObjects, fields);
2225     return m_pInterForm->ResetForm(fields, !(dwFlags & 0x01), TRUE);
2226   }
2227
2228   return m_pInterForm->ResetForm(TRUE);
2229 }
2230
2231 FX_BOOL CPDFSDK_InterForm::DoAction_ImportData(const CPDF_Action& action) {
2232   return FALSE;
2233 }
2234
2235 void CPDFSDK_InterForm::GetFieldFromObjects(const CFX_PtrArray& objects,
2236                                             CFX_PtrArray& fields) {
2237   ASSERT(m_pInterForm != NULL);
2238
2239   int iCount = objects.GetSize();
2240   for (int i = 0; i < iCount; i++) {
2241     CPDF_Object* pObject = (CPDF_Object*)objects[i];
2242     if (pObject == NULL)
2243       continue;
2244
2245     int iType = pObject->GetType();
2246     if (iType == PDFOBJ_STRING) {
2247       CFX_WideString csName = pObject->GetUnicodeText();
2248       CPDF_FormField* pField = m_pInterForm->GetField(0, csName);
2249       if (pField != NULL)
2250         fields.Add(pField);
2251     } else if (iType == PDFOBJ_DICTIONARY) {
2252       if (m_pInterForm->IsValidFormField(pObject))
2253         fields.Add(pObject);
2254     }
2255   }
2256 }
2257
2258 /* ----------------------------- CPDF_FormNotify -----------------------------
2259  */
2260
2261 int CPDFSDK_InterForm::BeforeValueChange(const CPDF_FormField* pField,
2262                                          CFX_WideString& csValue) {
2263   CPDF_FormField* pFormField = (CPDF_FormField*)pField;
2264   int nType = pFormField->GetFieldType();
2265   if (nType == FIELDTYPE_COMBOBOX || nType == FIELDTYPE_TEXTFIELD) {
2266     FX_BOOL bRC = TRUE;
2267     OnKeyStrokeCommit(pFormField, csValue, bRC);
2268     if (bRC) {
2269       OnValidate(pFormField, csValue, bRC);
2270       return bRC ? 1 : -1;
2271     }
2272     return -1;
2273   }
2274   return 0;
2275 }
2276
2277 int CPDFSDK_InterForm::AfterValueChange(const CPDF_FormField* pField) {
2278   CPDF_FormField* pFormField = (CPDF_FormField*)pField;
2279   int nType = pFormField->GetFieldType();
2280   if (nType == FIELDTYPE_COMBOBOX || nType == FIELDTYPE_TEXTFIELD) {
2281     OnCalculate(pFormField);
2282     FX_BOOL bFormated = FALSE;
2283     CFX_WideString sValue = OnFormat(pFormField, bFormated);
2284     if (bFormated)
2285       ResetFieldAppearance(pFormField, sValue.c_str(), TRUE);
2286     else
2287       ResetFieldAppearance(pFormField, NULL, TRUE);
2288     UpdateField(pFormField);
2289   }
2290   return 0;
2291 }
2292
2293 int CPDFSDK_InterForm::BeforeSelectionChange(const CPDF_FormField* pField,
2294                                              CFX_WideString& csValue) {
2295   CPDF_FormField* pFormField = (CPDF_FormField*)pField;
2296   if (pFormField->GetFieldType() != FIELDTYPE_LISTBOX)
2297     return 0;
2298
2299   FX_BOOL bRC = TRUE;
2300   OnKeyStrokeCommit(pFormField, csValue, bRC);
2301   if (!bRC)
2302     return -1;
2303
2304   OnValidate(pFormField, csValue, bRC);
2305   if (!bRC)
2306     return -1;
2307
2308   return 1;
2309 }
2310
2311 int CPDFSDK_InterForm::AfterSelectionChange(const CPDF_FormField* pField) {
2312   CPDF_FormField* pFormField = (CPDF_FormField*)pField;
2313   if (pFormField->GetFieldType() == FIELDTYPE_LISTBOX) {
2314     OnCalculate(pFormField);
2315     ResetFieldAppearance(pFormField, NULL, TRUE);
2316     UpdateField(pFormField);
2317   }
2318   return 0;
2319 }
2320
2321 int CPDFSDK_InterForm::AfterCheckedStatusChange(
2322     const CPDF_FormField* pField,
2323     const CFX_ByteArray& statusArray) {
2324   CPDF_FormField* pFormField = (CPDF_FormField*)pField;
2325   int nType = pFormField->GetFieldType();
2326   if (nType == FIELDTYPE_CHECKBOX || nType == FIELDTYPE_RADIOBUTTON) {
2327     OnCalculate(pFormField);
2328     UpdateField(pFormField);
2329   }
2330   return 0;
2331 }
2332
2333 int CPDFSDK_InterForm::BeforeFormReset(const CPDF_InterForm* pForm) {
2334   return 0;
2335 }
2336
2337 int CPDFSDK_InterForm::AfterFormReset(const CPDF_InterForm* pForm) {
2338   OnCalculate(nullptr);
2339   return 0;
2340 }
2341
2342 int CPDFSDK_InterForm::BeforeFormImportData(const CPDF_InterForm* pForm) {
2343   return 0;
2344 }
2345
2346 int CPDFSDK_InterForm::AfterFormImportData(const CPDF_InterForm* pForm) {
2347   OnCalculate(nullptr);
2348   return 0;
2349 }
2350
2351 FX_BOOL CPDFSDK_InterForm::IsNeedHighLight(int nFieldType) {
2352   if (nFieldType < 1 || nFieldType > 6)
2353     return FALSE;
2354   return m_bNeedHightlight[nFieldType - 1];
2355 }
2356
2357 void CPDFSDK_InterForm::RemoveAllHighLight() {
2358   memset((void*)m_bNeedHightlight, 0, 6 * sizeof(FX_BOOL));
2359 }
2360 void CPDFSDK_InterForm::SetHighlightColor(FX_COLORREF clr, int nFieldType) {
2361   if (nFieldType < 0 || nFieldType > 6)
2362     return;
2363   switch (nFieldType) {
2364     case 0: {
2365       for (int i = 0; i < 6; i++) {
2366         m_aHighlightColor[i] = clr;
2367         m_bNeedHightlight[i] = TRUE;
2368       }
2369       break;
2370     }
2371     default: {
2372       m_aHighlightColor[nFieldType - 1] = clr;
2373       m_bNeedHightlight[nFieldType - 1] = TRUE;
2374       break;
2375     }
2376   }
2377 }
2378
2379 FX_COLORREF CPDFSDK_InterForm::GetHighlightColor(int nFieldType) {
2380   if (nFieldType < 0 || nFieldType > 6)
2381     return FXSYS_RGB(255, 255, 255);
2382   if (nFieldType == 0)
2383     return m_aHighlightColor[0];
2384   return m_aHighlightColor[nFieldType - 1];
2385 }
2386
2387 /* ------------------------- CBA_AnnotIterator ------------------------- */
2388
2389 CBA_AnnotIterator::CBA_AnnotIterator(CPDFSDK_PageView* pPageView,
2390                                      const CFX_ByteString& sType,
2391                                      const CFX_ByteString& sSubType)
2392     : m_pPageView(pPageView),
2393       m_sType(sType),
2394       m_sSubType(sSubType),
2395       m_nTabs(BAI_STRUCTURE) {
2396   ASSERT(m_pPageView != NULL);
2397
2398   CPDF_Page* pPDFPage = m_pPageView->GetPDFPage();
2399   ASSERT(pPDFPage != NULL);
2400   ASSERT(pPDFPage->m_pFormDict != NULL);
2401
2402   CFX_ByteString sTabs = pPDFPage->m_pFormDict->GetString("Tabs");
2403
2404   if (sTabs == "R") {
2405     m_nTabs = BAI_ROW;
2406   } else if (sTabs == "C") {
2407     m_nTabs = BAI_COLUMN;
2408   } else {
2409     m_nTabs = BAI_STRUCTURE;
2410   }
2411
2412   GenerateResults();
2413 }
2414
2415 CBA_AnnotIterator::~CBA_AnnotIterator() {
2416   m_Annots.RemoveAll();
2417 }
2418
2419 CPDFSDK_Annot* CBA_AnnotIterator::GetFirstAnnot() {
2420   if (m_Annots.GetSize() > 0)
2421     return m_Annots[0];
2422
2423   return NULL;
2424 }
2425
2426 CPDFSDK_Annot* CBA_AnnotIterator::GetLastAnnot() {
2427   if (m_Annots.GetSize() > 0)
2428     return m_Annots[m_Annots.GetSize() - 1];
2429
2430   return NULL;
2431 }
2432
2433 CPDFSDK_Annot* CBA_AnnotIterator::GetNextAnnot(CPDFSDK_Annot* pAnnot) {
2434   for (int i = 0, sz = m_Annots.GetSize(); i < sz; ++i) {
2435     if (m_Annots[i] == pAnnot)
2436       return (i + 1 < sz) ? m_Annots[i + 1] : m_Annots[0];
2437   }
2438   return NULL;
2439 }
2440
2441 CPDFSDK_Annot* CBA_AnnotIterator::GetPrevAnnot(CPDFSDK_Annot* pAnnot) {
2442   for (int i = 0, sz = m_Annots.GetSize(); i < sz; ++i) {
2443     if (m_Annots[i] == pAnnot)
2444       return (i - 1 >= 0) ? m_Annots[i - 1] : m_Annots[sz - 1];
2445   }
2446   return NULL;
2447 }
2448
2449 int CBA_AnnotIterator::CompareByLeft(CPDFSDK_Annot* p1, CPDFSDK_Annot* p2) {
2450   ASSERT(p1);
2451   ASSERT(p2);
2452
2453   CPDF_Rect rcAnnot1 = GetAnnotRect(p1);
2454   CPDF_Rect rcAnnot2 = GetAnnotRect(p2);
2455
2456   if (rcAnnot1.left < rcAnnot2.left)
2457     return -1;
2458   if (rcAnnot1.left > rcAnnot2.left)
2459     return 1;
2460   return 0;
2461 }
2462
2463 int CBA_AnnotIterator::CompareByTop(CPDFSDK_Annot* p1, CPDFSDK_Annot* p2) {
2464   ASSERT(p1 != NULL);
2465   ASSERT(p2 != NULL);
2466
2467   CPDF_Rect rcAnnot1 = GetAnnotRect(p1);
2468   CPDF_Rect rcAnnot2 = GetAnnotRect(p2);
2469
2470   if (rcAnnot1.top < rcAnnot2.top)
2471     return -1;
2472   if (rcAnnot1.top > rcAnnot2.top)
2473     return 1;
2474   return 0;
2475 }
2476
2477 void CBA_AnnotIterator::GenerateResults() {
2478   ASSERT(m_pPageView != NULL);
2479
2480   switch (m_nTabs) {
2481     case BAI_STRUCTURE: {
2482       for (int i = 0, sz = m_pPageView->CountAnnots(); i < sz; i++) {
2483         CPDFSDK_Annot* pAnnot = m_pPageView->GetAnnot(i);
2484         ASSERT(pAnnot != NULL);
2485
2486         if (pAnnot->GetType() == m_sType && pAnnot->GetSubType() == m_sSubType)
2487           m_Annots.Add(pAnnot);
2488       }
2489     } break;
2490     case BAI_ROW: {
2491       CPDFSDK_SortAnnots sa;
2492
2493       {
2494         for (int i = 0, sz = m_pPageView->CountAnnots(); i < sz; i++) {
2495           CPDFSDK_Annot* pAnnot = m_pPageView->GetAnnot(i);
2496           ASSERT(pAnnot != NULL);
2497
2498           if (pAnnot->GetType() == m_sType &&
2499               pAnnot->GetSubType() == m_sSubType)
2500             sa.Add(pAnnot);
2501         }
2502       }
2503
2504       if (sa.GetSize() > 0) {
2505         sa.Sort(CBA_AnnotIterator::CompareByLeft);
2506       }
2507
2508       while (sa.GetSize() > 0) {
2509         int nLeftTopIndex = -1;
2510
2511         {
2512           FX_FLOAT fTop = 0.0f;
2513
2514           for (int i = sa.GetSize() - 1; i >= 0; i--) {
2515             CPDFSDK_Annot* pAnnot = sa.GetAt(i);
2516             ASSERT(pAnnot != NULL);
2517
2518             CPDF_Rect rcAnnot = GetAnnotRect(pAnnot);
2519
2520             if (rcAnnot.top > fTop) {
2521               nLeftTopIndex = i;
2522               fTop = rcAnnot.top;
2523             }
2524           }
2525         }
2526
2527         if (nLeftTopIndex >= 0) {
2528           CPDFSDK_Annot* pLeftTopAnnot = sa.GetAt(nLeftTopIndex);
2529           ASSERT(pLeftTopAnnot != NULL);
2530
2531           CPDF_Rect rcLeftTop = GetAnnotRect(pLeftTopAnnot);
2532
2533           m_Annots.Add(pLeftTopAnnot);
2534           sa.RemoveAt(nLeftTopIndex);
2535
2536           CFX_ArrayTemplate<int> aSelect;
2537
2538           {
2539             for (int i = 0, sz = sa.GetSize(); i < sz; i++) {
2540               CPDFSDK_Annot* pAnnot = sa.GetAt(i);
2541               ASSERT(pAnnot != NULL);
2542
2543               CPDF_Rect rcAnnot = GetAnnotRect(pAnnot);
2544
2545               FX_FLOAT fCenterY = (rcAnnot.top + rcAnnot.bottom) / 2.0f;
2546
2547               if (fCenterY > rcLeftTop.bottom && fCenterY < rcLeftTop.top)
2548                 aSelect.Add(i);
2549             }
2550           }
2551
2552           {
2553             for (int i = 0, sz = aSelect.GetSize(); i < sz; i++) {
2554               m_Annots.Add(sa[aSelect[i]]);
2555             }
2556           }
2557
2558           {
2559             for (int i = aSelect.GetSize() - 1; i >= 0; i--) {
2560               sa.RemoveAt(aSelect[i]);
2561             }
2562           }
2563
2564           aSelect.RemoveAll();
2565         }
2566       }
2567       sa.RemoveAll();
2568     } break;
2569     case BAI_COLUMN: {
2570       CPDFSDK_SortAnnots sa;
2571
2572       {
2573         for (int i = 0, sz = m_pPageView->CountAnnots(); i < sz; i++) {
2574           CPDFSDK_Annot* pAnnot = m_pPageView->GetAnnot(i);
2575           ASSERT(pAnnot != NULL);
2576
2577           if (pAnnot->GetType() == m_sType &&
2578               pAnnot->GetSubType() == m_sSubType)
2579             sa.Add(pAnnot);
2580         }
2581       }
2582
2583       if (sa.GetSize() > 0) {
2584         sa.Sort(CBA_AnnotIterator::CompareByTop, FALSE);
2585       }
2586
2587       while (sa.GetSize() > 0) {
2588         int nLeftTopIndex = -1;
2589
2590         {
2591           FX_FLOAT fLeft = -1.0f;
2592
2593           for (int i = sa.GetSize() - 1; i >= 0; i--) {
2594             CPDFSDK_Annot* pAnnot = sa.GetAt(i);
2595             ASSERT(pAnnot != NULL);
2596
2597             CPDF_Rect rcAnnot = GetAnnotRect(pAnnot);
2598
2599             if (fLeft < 0) {
2600               nLeftTopIndex = 0;
2601               fLeft = rcAnnot.left;
2602             } else if (rcAnnot.left < fLeft) {
2603               nLeftTopIndex = i;
2604               fLeft = rcAnnot.left;
2605             }
2606           }
2607         }
2608
2609         if (nLeftTopIndex >= 0) {
2610           CPDFSDK_Annot* pLeftTopAnnot = sa.GetAt(nLeftTopIndex);
2611           ASSERT(pLeftTopAnnot != NULL);
2612
2613           CPDF_Rect rcLeftTop = GetAnnotRect(pLeftTopAnnot);
2614
2615           m_Annots.Add(pLeftTopAnnot);
2616           sa.RemoveAt(nLeftTopIndex);
2617
2618           CFX_ArrayTemplate<int> aSelect;
2619
2620           {
2621             for (int i = 0, sz = sa.GetSize(); i < sz; i++) {
2622               CPDFSDK_Annot* pAnnot = sa.GetAt(i);
2623               ASSERT(pAnnot != NULL);
2624
2625               CPDF_Rect rcAnnot = GetAnnotRect(pAnnot);
2626
2627               FX_FLOAT fCenterX = (rcAnnot.left + rcAnnot.right) / 2.0f;
2628
2629               if (fCenterX > rcLeftTop.left && fCenterX < rcLeftTop.right)
2630                 aSelect.Add(i);
2631             }
2632           }
2633
2634           {
2635             for (int i = 0, sz = aSelect.GetSize(); i < sz; i++) {
2636               m_Annots.Add(sa[aSelect[i]]);
2637             }
2638           }
2639
2640           {
2641             for (int i = aSelect.GetSize() - 1; i >= 0; i--) {
2642               sa.RemoveAt(aSelect[i]);
2643             }
2644           }
2645
2646           aSelect.RemoveAll();
2647         }
2648       }
2649       sa.RemoveAll();
2650     } break;
2651   }
2652 }
2653
2654 CPDF_Rect CBA_AnnotIterator::GetAnnotRect(CPDFSDK_Annot* pAnnot) {
2655   ASSERT(pAnnot != NULL);
2656
2657   CPDF_Annot* pPDFAnnot = pAnnot->GetPDFAnnot();
2658   ASSERT(pPDFAnnot != NULL);
2659
2660   CPDF_Rect rcAnnot;
2661   pPDFAnnot->GetRect(rcAnnot);
2662
2663   return rcAnnot;
2664 }