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