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