• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "PublicMethods.h"
8 
9 #include <algorithm>
10 
11 #include "Field.h"
12 #include "JS_Context.h"
13 #include "JS_Define.h"
14 #include "JS_EventHandler.h"
15 #include "JS_Object.h"
16 #include "JS_Runtime.h"
17 #include "JS_Value.h"
18 #include "color.h"
19 #include "core/include/fxcrt/fx_ext.h"
20 #include "fpdfsdk/include/fsdk_mgr.h"  // For CPDFDoc_Environment.
21 #include "fpdfsdk/include/javascript/IJavaScript.h"
22 #include "resource.h"
23 #include "util.h"
24 
25 #define DOUBLE_CORRECT 0.000000000000001
26 
27 BEGIN_JS_STATIC_GLOBAL_FUN(CJS_PublicMethods)
28 JS_STATIC_GLOBAL_FUN_ENTRY(AFNumber_Format)
29 JS_STATIC_GLOBAL_FUN_ENTRY(AFNumber_Keystroke)
30 JS_STATIC_GLOBAL_FUN_ENTRY(AFPercent_Format)
31 JS_STATIC_GLOBAL_FUN_ENTRY(AFPercent_Keystroke)
32 JS_STATIC_GLOBAL_FUN_ENTRY(AFDate_FormatEx)
33 JS_STATIC_GLOBAL_FUN_ENTRY(AFDate_KeystrokeEx)
34 JS_STATIC_GLOBAL_FUN_ENTRY(AFDate_Format)
35 JS_STATIC_GLOBAL_FUN_ENTRY(AFDate_Keystroke)
36 JS_STATIC_GLOBAL_FUN_ENTRY(AFTime_FormatEx)
37 JS_STATIC_GLOBAL_FUN_ENTRY(AFTime_KeystrokeEx)
38 JS_STATIC_GLOBAL_FUN_ENTRY(AFTime_Format)
39 JS_STATIC_GLOBAL_FUN_ENTRY(AFTime_Keystroke)
40 JS_STATIC_GLOBAL_FUN_ENTRY(AFSpecial_Format)
41 JS_STATIC_GLOBAL_FUN_ENTRY(AFSpecial_Keystroke)
42 JS_STATIC_GLOBAL_FUN_ENTRY(AFSpecial_KeystrokeEx)
43 JS_STATIC_GLOBAL_FUN_ENTRY(AFSimple)
44 JS_STATIC_GLOBAL_FUN_ENTRY(AFMakeNumber)
45 JS_STATIC_GLOBAL_FUN_ENTRY(AFSimple_Calculate)
46 JS_STATIC_GLOBAL_FUN_ENTRY(AFRange_Validate)
47 JS_STATIC_GLOBAL_FUN_ENTRY(AFMergeChange)
48 JS_STATIC_GLOBAL_FUN_ENTRY(AFParseDateEx)
49 JS_STATIC_GLOBAL_FUN_ENTRY(AFExtractNums)
50 END_JS_STATIC_GLOBAL_FUN()
51 
52 IMPLEMENT_JS_STATIC_GLOBAL_FUN(CJS_PublicMethods)
53 
54 static const FX_WCHAR* const months[] = {L"Jan",
55                                          L"Feb",
56                                          L"Mar",
57                                          L"Apr",
58                                          L"May",
59                                          L"Jun",
60                                          L"Jul",
61                                          L"Aug",
62                                          L"Sep",
63                                          L"Oct",
64                                          L"Nov",
65                                          L"Dec"};
66 
67 static const FX_WCHAR* const fullmonths[] = {L"January",
68                                              L"February",
69                                              L"March",
70                                              L"April",
71                                              L"May",
72                                              L"June",
73                                              L"July",
74                                              L"August",
75                                              L"September",
76                                              L"October",
77                                              L"November",
78                                              L"December"};
79 
IsNumber(const FX_WCHAR * string)80 FX_BOOL CJS_PublicMethods::IsNumber(const FX_WCHAR* string) {
81   CFX_WideString sTrim = StrTrim(string);
82   const FX_WCHAR* pTrim = sTrim.c_str();
83   const FX_WCHAR* p = pTrim;
84 
85   FX_BOOL bDot = FALSE;
86   FX_BOOL bKXJS = FALSE;
87 
88   wchar_t c;
89   while ((c = *p)) {
90     if (c == '.' || c == ',') {
91       if (bDot)
92         return FALSE;
93       bDot = TRUE;
94     } else if (c == '-' || c == '+') {
95       if (p != pTrim)
96         return FALSE;
97     } else if (c == 'e' || c == 'E') {
98       if (bKXJS)
99         return FALSE;
100 
101       p++;
102       c = *p;
103       if (c == '+' || c == '-') {
104         bKXJS = TRUE;
105       } else {
106         return FALSE;
107       }
108     } else if (!FXSYS_iswdigit(c)) {
109       return FALSE;
110     }
111     p++;
112   }
113 
114   return TRUE;
115 }
116 
maskSatisfied(wchar_t c_Change,wchar_t c_Mask)117 FX_BOOL CJS_PublicMethods::maskSatisfied(wchar_t c_Change, wchar_t c_Mask) {
118   switch (c_Mask) {
119     case L'9':
120       return FXSYS_iswdigit(c_Change);
121     case L'A':
122       return FXSYS_iswalpha(c_Change);
123     case L'O':
124       return FXSYS_iswalnum(c_Change);
125     case L'X':
126       return TRUE;
127     default:
128       return (c_Change == c_Mask);
129   }
130 }
131 
isReservedMaskChar(wchar_t ch)132 FX_BOOL CJS_PublicMethods::isReservedMaskChar(wchar_t ch) {
133   return ch == L'9' || ch == L'A' || ch == L'O' || ch == L'X';
134 }
135 
AF_Simple(const FX_WCHAR * sFuction,double dValue1,double dValue2)136 double CJS_PublicMethods::AF_Simple(const FX_WCHAR* sFuction,
137                                     double dValue1,
138                                     double dValue2) {
139   if (FXSYS_wcsicmp(sFuction, L"AVG") == 0 ||
140       FXSYS_wcsicmp(sFuction, L"SUM") == 0) {
141     return dValue1 + dValue2;
142   }
143   if (FXSYS_wcsicmp(sFuction, L"PRD") == 0) {
144     return dValue1 * dValue2;
145   }
146   if (FXSYS_wcsicmp(sFuction, L"MIN") == 0) {
147     return std::min(dValue1, dValue2);
148   }
149   if (FXSYS_wcsicmp(sFuction, L"MAX") == 0) {
150     return std::max(dValue1, dValue2);
151   }
152   return dValue1;
153 }
154 
StrLTrim(const FX_WCHAR * pStr)155 CFX_WideString CJS_PublicMethods::StrLTrim(const FX_WCHAR* pStr) {
156   while (*pStr && *pStr == L' ')
157     pStr++;
158 
159   return pStr;
160 }
161 
StrRTrim(const FX_WCHAR * pStr)162 CFX_WideString CJS_PublicMethods::StrRTrim(const FX_WCHAR* pStr) {
163   const FX_WCHAR* p = pStr;
164   while (*p)
165     p++;
166   while (p > pStr && *(p - 1) == L' ')
167     p--;
168 
169   return CFX_WideString(pStr, p - pStr);
170 }
171 
StrTrim(const FX_WCHAR * pStr)172 CFX_WideString CJS_PublicMethods::StrTrim(const FX_WCHAR* pStr) {
173   return StrRTrim(StrLTrim(pStr).c_str());
174 }
175 
StrLTrim(const FX_CHAR * pStr)176 CFX_ByteString CJS_PublicMethods::StrLTrim(const FX_CHAR* pStr) {
177   while (*pStr && *pStr == ' ')
178     pStr++;
179 
180   return pStr;
181 }
182 
StrRTrim(const FX_CHAR * pStr)183 CFX_ByteString CJS_PublicMethods::StrRTrim(const FX_CHAR* pStr) {
184   const FX_CHAR* p = pStr;
185   while (*p)
186     p++;
187   while (p > pStr && *(p - 1) == L' ')
188     p--;
189 
190   return CFX_ByteString(pStr, p - pStr);
191 }
192 
StrTrim(const FX_CHAR * pStr)193 CFX_ByteString CJS_PublicMethods::StrTrim(const FX_CHAR* pStr) {
194   return StrRTrim(StrLTrim(pStr));
195 }
196 
ParseNumber(const FX_WCHAR * swSource,FX_BOOL & bAllDigits,FX_BOOL & bDot,FX_BOOL & bSign,FX_BOOL & bKXJS)197 double CJS_PublicMethods::ParseNumber(const FX_WCHAR* swSource,
198                                       FX_BOOL& bAllDigits,
199                                       FX_BOOL& bDot,
200                                       FX_BOOL& bSign,
201                                       FX_BOOL& bKXJS) {
202   bDot = FALSE;
203   bSign = FALSE;
204   bKXJS = FALSE;
205 
206   FX_BOOL bDigitExist = FALSE;
207 
208   const FX_WCHAR* p = swSource;
209   wchar_t c;
210 
211   const FX_WCHAR* pStart = NULL;
212   const FX_WCHAR* pEnd = NULL;
213 
214   while ((c = *p)) {
215     if (!pStart && c != L' ') {
216       pStart = p;
217     }
218 
219     pEnd = p;
220     p++;
221   }
222 
223   if (!pStart) {
224     bAllDigits = FALSE;
225     return 0;
226   }
227 
228   while (pEnd != pStart) {
229     if (*pEnd == L' ')
230       pEnd--;
231     else
232       break;
233   }
234 
235   double dRet = 0;
236   p = pStart;
237   bAllDigits = TRUE;
238   CFX_WideString swDigits;
239 
240   while (p <= pEnd) {
241     c = *p;
242 
243     if (FXSYS_iswdigit(c)) {
244       swDigits += c;
245       bDigitExist = TRUE;
246     } else {
247       switch (c) {
248         case L' ':
249           bAllDigits = FALSE;
250           break;
251         case L'.':
252         case L',':
253           if (!bDot) {
254             if (bDigitExist) {
255               swDigits += L'.';
256             } else {
257               swDigits += L'0';
258               swDigits += L'.';
259               bDigitExist = TRUE;
260             }
261 
262             bDot = TRUE;
263             break;
264           }
265         case 'e':
266         case 'E':
267           if (!bKXJS) {
268             p++;
269             c = *p;
270             if (c == '+' || c == '-') {
271               bKXJS = TRUE;
272               swDigits += 'e';
273               swDigits += c;
274             }
275             break;
276           }
277         case L'-':
278           if (!bDigitExist && !bSign) {
279             swDigits += c;
280             bSign = TRUE;
281             break;
282           }
283         default:
284           bAllDigits = FALSE;
285 
286           if (p != pStart && !bDot && bDigitExist) {
287             swDigits += L'.';
288             bDot = TRUE;
289           } else {
290             bDot = FALSE;
291             bDigitExist = FALSE;
292             swDigits = L"";
293           }
294           break;
295       }
296     }
297 
298     p++;
299   }
300 
301   if (swDigits.GetLength() > 0 && swDigits.GetLength() < 17) {
302     CFX_ByteString sDigits = swDigits.UTF8Encode();
303 
304     if (bKXJS) {
305       dRet = atof(sDigits);
306     } else {
307       if (bDot) {
308         char* pStopString;
309         dRet = ::strtod(sDigits, &pStopString);
310       } else {
311         dRet = atol(sDigits);
312       }
313     }
314   }
315 
316   return dRet;
317 }
318 
ParseStringToNumber(const FX_WCHAR * swSource)319 double CJS_PublicMethods::ParseStringToNumber(const FX_WCHAR* swSource) {
320   FX_BOOL bAllDigits = FALSE;
321   FX_BOOL bDot = FALSE;
322   FX_BOOL bSign = FALSE;
323   FX_BOOL bKXJS = FALSE;
324 
325   return ParseNumber(swSource, bAllDigits, bDot, bSign, bKXJS);
326 }
327 
ConvertStringToNumber(const FX_WCHAR * swSource,double & dRet,FX_BOOL & bDot)328 FX_BOOL CJS_PublicMethods::ConvertStringToNumber(const FX_WCHAR* swSource,
329                                                  double& dRet,
330                                                  FX_BOOL& bDot) {
331   FX_BOOL bAllDigits = FALSE;
332   FX_BOOL bSign = FALSE;
333   FX_BOOL bKXJS = FALSE;
334 
335   dRet = ParseNumber(swSource, bAllDigits, bDot, bSign, bKXJS);
336 
337   return bAllDigits;
338 }
339 
AF_MakeArrayFromList(CJS_Runtime * pRuntime,CJS_Value val)340 CJS_Array CJS_PublicMethods::AF_MakeArrayFromList(CJS_Runtime* pRuntime,
341                                                   CJS_Value val) {
342   CJS_Array StrArray(pRuntime);
343   if (val.IsArrayObject()) {
344     val.ConvertToArray(StrArray);
345     return StrArray;
346   }
347   CFX_WideString wsStr = val.ToCFXWideString();
348   CFX_ByteString t = CFX_ByteString::FromUnicode(wsStr);
349   const char* p = (const char*)t;
350 
351   int ch = ',';
352   int nIndex = 0;
353 
354   while (*p) {
355     const char* pTemp = strchr(p, ch);
356     if (!pTemp) {
357       StrArray.SetElement(nIndex, CJS_Value(pRuntime, StrTrim(p).c_str()));
358       break;
359     }
360 
361     char* pSub = new char[pTemp - p + 1];
362     strncpy(pSub, p, pTemp - p);
363     *(pSub + (pTemp - p)) = '\0';
364 
365     StrArray.SetElement(nIndex, CJS_Value(pRuntime, StrTrim(pSub).c_str()));
366     delete[] pSub;
367 
368     nIndex++;
369     p = ++pTemp;
370   }
371   return StrArray;
372 }
373 
ParseStringInteger(const CFX_WideString & string,int nStart,int & nSkip,int nMaxStep)374 int CJS_PublicMethods::ParseStringInteger(const CFX_WideString& string,
375                                           int nStart,
376                                           int& nSkip,
377                                           int nMaxStep) {
378   int nRet = 0;
379   nSkip = 0;
380   for (int i = nStart, sz = string.GetLength(); i < sz; i++) {
381     if (i - nStart > 10)
382       break;
383 
384     FX_WCHAR c = string.GetAt(i);
385     if (!FXSYS_iswdigit(c))
386       break;
387 
388     nRet = nRet * 10 + FXSYS_toDecimalDigitWide(c);
389     nSkip = i - nStart + 1;
390     if (nSkip >= nMaxStep)
391       break;
392   }
393 
394   return nRet;
395 }
396 
ParseStringString(const CFX_WideString & string,int nStart,int & nSkip)397 CFX_WideString CJS_PublicMethods::ParseStringString(
398     const CFX_WideString& string,
399     int nStart,
400     int& nSkip) {
401   CFX_WideString swRet;
402   nSkip = 0;
403   for (int i = nStart, sz = string.GetLength(); i < sz; i++) {
404     FX_WCHAR c = string.GetAt(i);
405     if (!FXSYS_iswdigit(c))
406       break;
407 
408     swRet += c;
409     nSkip = i - nStart + 1;
410   }
411 
412   return swRet;
413 }
414 
ParseNormalDate(const CFX_WideString & value,bool * bWrongFormat)415 double CJS_PublicMethods::ParseNormalDate(const CFX_WideString& value,
416                                           bool* bWrongFormat) {
417   double dt = JS_GetDateTime();
418 
419   int nYear = JS_GetYearFromTime(dt);
420   int nMonth = JS_GetMonthFromTime(dt) + 1;
421   int nDay = JS_GetDayFromTime(dt);
422   int nHour = JS_GetHourFromTime(dt);
423   int nMin = JS_GetMinFromTime(dt);
424   int nSec = JS_GetSecFromTime(dt);
425 
426   int number[3];
427 
428   int nSkip = 0;
429   int nLen = value.GetLength();
430   int nIndex = 0;
431   int i = 0;
432   while (i < nLen) {
433     if (nIndex > 2)
434       break;
435 
436     FX_WCHAR c = value.GetAt(i);
437     if (FXSYS_iswdigit(c)) {
438       number[nIndex++] = ParseStringInteger(value, i, nSkip, 4);
439       i += nSkip;
440     } else {
441       i++;
442     }
443   }
444 
445   if (nIndex == 2) {
446     // case2: month/day
447     // case3: day/month
448     if ((number[0] >= 1 && number[0] <= 12) &&
449         (number[1] >= 1 && number[1] <= 31)) {
450       nMonth = number[0];
451       nDay = number[1];
452     } else if ((number[0] >= 1 && number[0] <= 31) &&
453                (number[1] >= 1 && number[1] <= 12)) {
454       nDay = number[0];
455       nMonth = number[1];
456     }
457 
458     if (bWrongFormat)
459       *bWrongFormat = false;
460   } else if (nIndex == 3) {
461     // case1: year/month/day
462     // case2: month/day/year
463     // case3: day/month/year
464 
465     if (number[0] > 12 && (number[1] >= 1 && number[1] <= 12) &&
466         (number[2] >= 1 && number[2] <= 31)) {
467       nYear = number[0];
468       nMonth = number[1];
469       nDay = number[2];
470     } else if ((number[0] >= 1 && number[0] <= 12) &&
471                (number[1] >= 1 && number[1] <= 31) && number[2] > 31) {
472       nMonth = number[0];
473       nDay = number[1];
474       nYear = number[2];
475     } else if ((number[0] >= 1 && number[0] <= 31) &&
476                (number[1] >= 1 && number[1] <= 12) && number[2] > 31) {
477       nDay = number[0];
478       nMonth = number[1];
479       nYear = number[2];
480     }
481 
482     if (bWrongFormat)
483       *bWrongFormat = false;
484   } else {
485     if (bWrongFormat)
486       *bWrongFormat = true;
487     return dt;
488   }
489 
490   CFX_WideString swTemp;
491   swTemp.Format(L"%d/%d/%d %d:%d:%d", nMonth, nDay, nYear, nHour, nMin, nSec);
492   return JS_DateParse(swTemp.c_str());
493 }
494 
MakeRegularDate(const CFX_WideString & value,const CFX_WideString & format,bool * bWrongFormat)495 double CJS_PublicMethods::MakeRegularDate(const CFX_WideString& value,
496                                           const CFX_WideString& format,
497                                           bool* bWrongFormat) {
498   double dt = JS_GetDateTime();
499 
500   if (format.IsEmpty() || value.IsEmpty())
501     return dt;
502 
503   int nYear = JS_GetYearFromTime(dt);
504   int nMonth = JS_GetMonthFromTime(dt) + 1;
505   int nDay = JS_GetDayFromTime(dt);
506   int nHour = JS_GetHourFromTime(dt);
507   int nMin = JS_GetMinFromTime(dt);
508   int nSec = JS_GetSecFromTime(dt);
509 
510   int nYearSub = 99;  // nYear - 2000;
511 
512   FX_BOOL bPm = FALSE;
513   FX_BOOL bExit = FALSE;
514   bool bBadFormat = false;
515 
516   int i = 0;
517   int j = 0;
518 
519   while (i < format.GetLength()) {
520     if (bExit)
521       break;
522 
523     FX_WCHAR c = format.GetAt(i);
524     switch (c) {
525       case ':':
526       case '.':
527       case '-':
528       case '\\':
529       case '/':
530         i++;
531         j++;
532         break;
533 
534       case 'y':
535       case 'm':
536       case 'd':
537       case 'H':
538       case 'h':
539       case 'M':
540       case 's':
541       case 't': {
542         int oldj = j;
543         int nSkip = 0;
544         int remaining = format.GetLength() - i - 1;
545 
546         if (remaining == 0 || format.GetAt(i + 1) != c) {
547           switch (c) {
548             case 'y':
549               i++;
550               j++;
551               break;
552             case 'm':
553               nMonth = ParseStringInteger(value, j, nSkip, 2);
554               i++;
555               j += nSkip;
556               break;
557             case 'd':
558               nDay = ParseStringInteger(value, j, nSkip, 2);
559               i++;
560               j += nSkip;
561               break;
562             case 'H':
563               nHour = ParseStringInteger(value, j, nSkip, 2);
564               i++;
565               j += nSkip;
566               break;
567             case 'h':
568               nHour = ParseStringInteger(value, j, nSkip, 2);
569               i++;
570               j += nSkip;
571               break;
572             case 'M':
573               nMin = ParseStringInteger(value, j, nSkip, 2);
574               i++;
575               j += nSkip;
576               break;
577             case 's':
578               nSec = ParseStringInteger(value, j, nSkip, 2);
579               i++;
580               j += nSkip;
581               break;
582             case 't':
583               bPm = (j < value.GetLength() && value.GetAt(j) == 'p');
584               i++;
585               j++;
586               break;
587           }
588         } else if (remaining == 1 || format.GetAt(i + 2) != c) {
589           switch (c) {
590             case 'y':
591               nYear = ParseStringInteger(value, j, nSkip, 4);
592               i += 2;
593               j += nSkip;
594               break;
595             case 'm':
596               nMonth = ParseStringInteger(value, j, nSkip, 2);
597               i += 2;
598               j += nSkip;
599               break;
600             case 'd':
601               nDay = ParseStringInteger(value, j, nSkip, 2);
602               i += 2;
603               j += nSkip;
604               break;
605             case 'H':
606               nHour = ParseStringInteger(value, j, nSkip, 2);
607               i += 2;
608               j += nSkip;
609               break;
610             case 'h':
611               nHour = ParseStringInteger(value, j, nSkip, 2);
612               i += 2;
613               j += nSkip;
614               break;
615             case 'M':
616               nMin = ParseStringInteger(value, j, nSkip, 2);
617               i += 2;
618               j += nSkip;
619               break;
620             case 's':
621               nSec = ParseStringInteger(value, j, nSkip, 2);
622               i += 2;
623               j += nSkip;
624               break;
625             case 't':
626               bPm = (j + 1 < value.GetLength() && value.GetAt(j) == 'p' &&
627                      value.GetAt(j + 1) == 'm');
628               i += 2;
629               j += 2;
630               break;
631           }
632         } else if (remaining == 2 || format.GetAt(i + 3) != c) {
633           switch (c) {
634             case 'm': {
635               CFX_WideString sMonth = ParseStringString(value, j, nSkip);
636               FX_BOOL bFind = FALSE;
637               for (int m = 0; m < 12; m++) {
638                 if (sMonth.CompareNoCase(months[m]) == 0) {
639                   nMonth = m + 1;
640                   i += 3;
641                   j += nSkip;
642                   bFind = TRUE;
643                   break;
644                 }
645               }
646 
647               if (!bFind) {
648                 nMonth = ParseStringInteger(value, j, nSkip, 3);
649                 i += 3;
650                 j += nSkip;
651               }
652             } break;
653             case 'y':
654               break;
655             default:
656               i += 3;
657               j += 3;
658               break;
659           }
660         } else if (remaining == 3 || format.GetAt(i + 4) != c) {
661           switch (c) {
662             case 'y':
663               nYear = ParseStringInteger(value, j, nSkip, 4);
664               j += nSkip;
665               i += 4;
666               break;
667             case 'm': {
668               FX_BOOL bFind = FALSE;
669 
670               CFX_WideString sMonth = ParseStringString(value, j, nSkip);
671               sMonth.MakeLower();
672 
673               for (int m = 0; m < 12; m++) {
674                 CFX_WideString sFullMonths = fullmonths[m];
675                 sFullMonths.MakeLower();
676 
677                 if (sFullMonths.Find(sMonth.c_str(), 0) != -1) {
678                   nMonth = m + 1;
679                   i += 4;
680                   j += nSkip;
681                   bFind = TRUE;
682                   break;
683                 }
684               }
685 
686               if (!bFind) {
687                 nMonth = ParseStringInteger(value, j, nSkip, 4);
688                 i += 4;
689                 j += nSkip;
690               }
691             } break;
692             default:
693               i += 4;
694               j += 4;
695               break;
696           }
697         } else {
698           if (j >= value.GetLength() || format.GetAt(i) != value.GetAt(j)) {
699             bBadFormat = true;
700             bExit = TRUE;
701           }
702           i++;
703           j++;
704         }
705 
706         if (oldj == j) {
707           bBadFormat = true;
708           bExit = TRUE;
709         }
710       }
711 
712       break;
713       default:
714         if (value.GetLength() <= j) {
715           bExit = TRUE;
716         } else if (format.GetAt(i) != value.GetAt(j)) {
717           bBadFormat = true;
718           bExit = TRUE;
719         }
720 
721         i++;
722         j++;
723         break;
724     }
725   }
726 
727   if (bPm)
728     nHour += 12;
729 
730   if (nYear >= 0 && nYear <= nYearSub)
731     nYear += 2000;
732 
733   if (nMonth < 1 || nMonth > 12)
734     bBadFormat = true;
735 
736   if (nDay < 1 || nDay > 31)
737     bBadFormat = true;
738 
739   if (nHour < 0 || nHour > 24)
740     bBadFormat = true;
741 
742   if (nMin < 0 || nMin > 60)
743     bBadFormat = true;
744 
745   if (nSec < 0 || nSec > 60)
746     bBadFormat = true;
747 
748   double dRet = 0;
749 
750   if (bBadFormat) {
751     dRet = ParseNormalDate(value, &bBadFormat);
752   } else {
753     dRet = JS_MakeDate(JS_MakeDay(nYear, nMonth - 1, nDay),
754                        JS_MakeTime(nHour, nMin, nSec, 0));
755 
756     if (JS_PortIsNan(dRet)) {
757       dRet = JS_DateParse(value.c_str());
758     }
759   }
760 
761   if (JS_PortIsNan(dRet)) {
762     dRet = ParseNormalDate(value, &bBadFormat);
763   }
764 
765   if (bWrongFormat)
766     *bWrongFormat = bBadFormat;
767   return dRet;
768 }
769 
MakeFormatDate(double dDate,const CFX_WideString & format)770 CFX_WideString CJS_PublicMethods::MakeFormatDate(double dDate,
771                                                  const CFX_WideString& format) {
772   CFX_WideString sRet = L"", sPart = L"";
773 
774   int nYear = JS_GetYearFromTime(dDate);
775   int nMonth = JS_GetMonthFromTime(dDate) + 1;
776   int nDay = JS_GetDayFromTime(dDate);
777   int nHour = JS_GetHourFromTime(dDate);
778   int nMin = JS_GetMinFromTime(dDate);
779   int nSec = JS_GetSecFromTime(dDate);
780 
781   int i = 0;
782   while (i < format.GetLength()) {
783     FX_WCHAR c = format.GetAt(i);
784     int remaining = format.GetLength() - i - 1;
785     sPart = L"";
786     switch (c) {
787       case 'y':
788       case 'm':
789       case 'd':
790       case 'H':
791       case 'h':
792       case 'M':
793       case 's':
794       case 't':
795         if (remaining == 0 || format.GetAt(i + 1) != c) {
796           switch (c) {
797             case 'y':
798               sPart += c;
799               break;
800             case 'm':
801               sPart.Format(L"%d", nMonth);
802               break;
803             case 'd':
804               sPart.Format(L"%d", nDay);
805               break;
806             case 'H':
807               sPart.Format(L"%d", nHour);
808               break;
809             case 'h':
810               sPart.Format(L"%d", nHour > 12 ? nHour - 12 : nHour);
811               break;
812             case 'M':
813               sPart.Format(L"%d", nMin);
814               break;
815             case 's':
816               sPart.Format(L"%d", nSec);
817               break;
818             case 't':
819               sPart += nHour > 12 ? 'p' : 'a';
820               break;
821           }
822           i++;
823         } else if (remaining == 1 || format.GetAt(i + 2) != c) {
824           switch (c) {
825             case 'y':
826               sPart.Format(L"%02d", nYear - (nYear / 100) * 100);
827               break;
828             case 'm':
829               sPart.Format(L"%02d", nMonth);
830               break;
831             case 'd':
832               sPart.Format(L"%02d", nDay);
833               break;
834             case 'H':
835               sPart.Format(L"%02d", nHour);
836               break;
837             case 'h':
838               sPart.Format(L"%02d", nHour > 12 ? nHour - 12 : nHour);
839               break;
840             case 'M':
841               sPart.Format(L"%02d", nMin);
842               break;
843             case 's':
844               sPart.Format(L"%02d", nSec);
845               break;
846             case 't':
847               sPart = nHour > 12 ? L"pm" : L"am";
848               break;
849           }
850           i += 2;
851         } else if (remaining == 2 || format.GetAt(i + 3) != c) {
852           switch (c) {
853             case 'm':
854               i += 3;
855               if (nMonth > 0 && nMonth <= 12)
856                 sPart += months[nMonth - 1];
857               break;
858             default:
859               i += 3;
860               sPart += c;
861               sPart += c;
862               sPart += c;
863               break;
864           }
865         } else if (remaining == 3 || format.GetAt(i + 4) != c) {
866           switch (c) {
867             case 'y':
868               sPart.Format(L"%04d", nYear);
869               i += 4;
870               break;
871             case 'm':
872               i += 4;
873               if (nMonth > 0 && nMonth <= 12)
874                 sPart += fullmonths[nMonth - 1];
875               break;
876             default:
877               i += 4;
878               sPart += c;
879               sPart += c;
880               sPart += c;
881               sPart += c;
882               break;
883           }
884         } else {
885           i++;
886           sPart += c;
887         }
888         break;
889       default:
890         i++;
891         sPart += c;
892         break;
893     }
894 
895     sRet += sPart;
896   }
897 
898   return sRet;
899 }
900 
901 /* -------------------------------------------------------------------------- */
902 
903 // function AFNumber_Format(nDec, sepStyle, negStyle, currStyle, strCurrency,
904 // bCurrencyPrepend)
AFNumber_Format(IJS_Context * cc,const std::vector<CJS_Value> & params,CJS_Value & vRet,CFX_WideString & sError)905 FX_BOOL CJS_PublicMethods::AFNumber_Format(IJS_Context* cc,
906                                            const std::vector<CJS_Value>& params,
907                                            CJS_Value& vRet,
908                                            CFX_WideString& sError) {
909 #if _FX_OS_ != _FX_ANDROID_
910   CJS_Context* pContext = (CJS_Context*)cc;
911   if (params.size() != 6) {
912     sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
913     return FALSE;
914   }
915 
916   CJS_Runtime* pRuntime = CJS_Runtime::FromContext(cc);
917   CJS_EventHandler* pEvent = pContext->GetEventHandler();
918   if (!pEvent->m_pValue)
919     return FALSE;
920 
921   CFX_WideString& Value = pEvent->Value();
922   CFX_ByteString strValue = StrTrim(CFX_ByteString::FromUnicode(Value));
923   if (strValue.IsEmpty())
924     return TRUE;
925 
926   int iDec = params[0].ToInt();
927   int iSepStyle = params[1].ToInt();
928   int iNegStyle = params[2].ToInt();
929   // params[3] is iCurrStyle, it's not used.
930   std::wstring wstrCurrency(params[4].ToCFXWideString().c_str());
931   FX_BOOL bCurrencyPrepend = params[5].ToBool();
932 
933   if (iDec < 0)
934     iDec = -iDec;
935 
936   if (iSepStyle < 0 || iSepStyle > 3)
937     iSepStyle = 0;
938 
939   if (iNegStyle < 0 || iNegStyle > 3)
940     iNegStyle = 0;
941 
942   //////////////////////////////////////////////////////
943   // for processing decimal places
944   strValue.Replace(",", ".");
945   double dValue = atof(strValue);
946   if (iDec > 0)
947     dValue += DOUBLE_CORRECT;
948 
949   int iDec2;
950   int iNegative = 0;
951 
952   strValue = fcvt(dValue, iDec, &iDec2, &iNegative);
953   if (strValue.IsEmpty()) {
954     dValue = 0;
955     strValue = fcvt(dValue, iDec, &iDec2, &iNegative);
956     if (strValue.IsEmpty()) {
957       strValue = "0";
958       iDec2 = 1;
959     }
960   }
961 
962   if (iDec2 < 0) {
963     for (int iNum = 0; iNum < abs(iDec2); iNum++) {
964       strValue = "0" + strValue;
965     }
966     iDec2 = 0;
967   }
968   int iMax = strValue.GetLength();
969   if (iDec2 > iMax) {
970     for (int iNum = 0; iNum <= iDec2 - iMax; iNum++) {
971       strValue += "0";
972     }
973     iMax = iDec2 + 1;
974   }
975   ///////////////////////////////////////////////////////
976   // for processing seperator style
977   if (iDec2 < iMax) {
978     if (iSepStyle == 0 || iSepStyle == 1) {
979       strValue.Insert(iDec2, '.');
980       iMax++;
981     } else if (iSepStyle == 2 || iSepStyle == 3) {
982       strValue.Insert(iDec2, ',');
983       iMax++;
984     }
985 
986     if (iDec2 == 0)
987       strValue.Insert(iDec2, '0');
988   }
989   if (iSepStyle == 0 || iSepStyle == 2) {
990     char cSeperator;
991     if (iSepStyle == 0)
992       cSeperator = ',';
993     else
994       cSeperator = '.';
995 
996     for (int iDecPositive = iDec2 - 3; iDecPositive > 0; iDecPositive -= 3) {
997       strValue.Insert(iDecPositive, cSeperator);
998       iMax++;
999     }
1000   }
1001 
1002   //////////////////////////////////////////////////////////////////////
1003   // for processing currency string
1004 
1005   Value = CFX_WideString::FromLocal(strValue);
1006   std::wstring strValue2 = Value.c_str();
1007 
1008   if (bCurrencyPrepend)
1009     strValue2 = wstrCurrency + strValue2;
1010   else
1011     strValue2 = strValue2 + wstrCurrency;
1012 
1013   /////////////////////////////////////////////////////////////////////////
1014   // for processing negative style
1015   if (iNegative) {
1016     if (iNegStyle == 0) {
1017       strValue2.insert(0, L"-");
1018     }
1019     if (iNegStyle == 2 || iNegStyle == 3) {
1020       strValue2.insert(0, L"(");
1021       strValue2.insert(strValue2.length(), L")");
1022     }
1023     if (iNegStyle == 1 || iNegStyle == 3) {
1024       if (Field* fTarget = pEvent->Target_Field()) {
1025         CJS_Array arColor(pRuntime);
1026         CJS_Value vColElm(pRuntime);
1027         vColElm = L"RGB";
1028         arColor.SetElement(0, vColElm);
1029         vColElm = 1;
1030         arColor.SetElement(1, vColElm);
1031         vColElm = 0;
1032         arColor.SetElement(2, vColElm);
1033 
1034         arColor.SetElement(3, vColElm);
1035 
1036         CJS_PropValue vProp(pRuntime);
1037         vProp.StartGetting();
1038         vProp << arColor;
1039         vProp.StartSetting();
1040         fTarget->textColor(cc, vProp, sError);  // red
1041       }
1042     }
1043   } else {
1044     if (iNegStyle == 1 || iNegStyle == 3) {
1045       if (Field* fTarget = pEvent->Target_Field()) {
1046         CJS_Array arColor(pRuntime);
1047         CJS_Value vColElm(pRuntime);
1048         vColElm = L"RGB";
1049         arColor.SetElement(0, vColElm);
1050         vColElm = 0;
1051         arColor.SetElement(1, vColElm);
1052         arColor.SetElement(2, vColElm);
1053         arColor.SetElement(3, vColElm);
1054 
1055         CJS_PropValue vProp(pRuntime);
1056         vProp.StartGetting();
1057         fTarget->textColor(cc, vProp, sError);
1058 
1059         CJS_Array aProp(pRuntime);
1060         vProp.ConvertToArray(aProp);
1061 
1062         CPWL_Color crProp;
1063         CPWL_Color crColor;
1064         color::ConvertArrayToPWLColor(aProp, crProp);
1065         color::ConvertArrayToPWLColor(arColor, crColor);
1066 
1067         if (crColor != crProp) {
1068           CJS_PropValue vProp2(pRuntime);
1069           vProp2.StartGetting();
1070           vProp2 << arColor;
1071           vProp2.StartSetting();
1072           fTarget->textColor(cc, vProp2, sError);
1073         }
1074       }
1075     }
1076   }
1077   Value = strValue2.c_str();
1078 #endif
1079   return TRUE;
1080 }
1081 
1082 // function AFNumber_Keystroke(nDec, sepStyle, negStyle, currStyle, strCurrency,
1083 // bCurrencyPrepend)
AFNumber_Keystroke(IJS_Context * cc,const std::vector<CJS_Value> & params,CJS_Value & vRet,CFX_WideString & sError)1084 FX_BOOL CJS_PublicMethods::AFNumber_Keystroke(
1085     IJS_Context* cc,
1086     const std::vector<CJS_Value>& params,
1087     CJS_Value& vRet,
1088     CFX_WideString& sError) {
1089   CJS_Context* pContext = (CJS_Context*)cc;
1090   CJS_EventHandler* pEvent = pContext->GetEventHandler();
1091 
1092   if (params.size() < 2)
1093     return FALSE;
1094   int iSepStyle = params[1].ToInt();
1095 
1096   if (iSepStyle < 0 || iSepStyle > 3)
1097     iSepStyle = 0;
1098   if (!pEvent->m_pValue)
1099     return FALSE;
1100   CFX_WideString& val = pEvent->Value();
1101   CFX_WideString& w_strChange = pEvent->Change();
1102   CFX_WideString w_strValue = val;
1103 
1104   if (pEvent->WillCommit()) {
1105     CFX_WideString wstrChange = w_strChange;
1106     CFX_WideString wstrValue = StrLTrim(w_strValue.c_str());
1107     if (wstrValue.IsEmpty())
1108       return TRUE;
1109 
1110     CFX_WideString swTemp = wstrValue;
1111     swTemp.Replace(L",", L".");
1112     if (!IsNumber(swTemp.c_str())) {
1113       pEvent->Rc() = FALSE;
1114       sError = JSGetStringFromID(pContext, IDS_STRING_JSAFNUMBER_KEYSTROKE);
1115       Alert(pContext, sError.c_str());
1116       return TRUE;
1117     }
1118     return TRUE;  // it happens after the last keystroke and before validating,
1119   }
1120 
1121   std::wstring w_strValue2 = w_strValue.c_str();
1122   std::wstring w_strChange2 = w_strChange.c_str();
1123   std::wstring w_strSelected;
1124   if (-1 != pEvent->SelStart())
1125     w_strSelected = w_strValue2.substr(pEvent->SelStart(),
1126                                        (pEvent->SelEnd() - pEvent->SelStart()));
1127   bool bHasSign = (w_strValue2.find('-') != std::wstring::npos) &&
1128                   (w_strSelected.find('-') == std::wstring::npos);
1129   if (bHasSign) {
1130     // can't insert "change" in front to sign postion.
1131     if (pEvent->SelStart() == 0) {
1132       FX_BOOL& bRc = pEvent->Rc();
1133       bRc = FALSE;
1134       return TRUE;
1135     }
1136   }
1137 
1138   char cSep = L'.';
1139 
1140   switch (iSepStyle) {
1141     case 0:
1142     case 1:
1143       cSep = L'.';
1144       break;
1145     case 2:
1146     case 3:
1147       cSep = L',';
1148       break;
1149   }
1150 
1151   bool bHasSep = (w_strValue2.find(cSep) != std::wstring::npos);
1152   for (std::wstring::iterator it = w_strChange2.begin();
1153        it != w_strChange2.end(); it++) {
1154     if (*it == cSep) {
1155       if (bHasSep) {
1156         FX_BOOL& bRc = pEvent->Rc();
1157         bRc = FALSE;
1158         return TRUE;
1159       }
1160       bHasSep = TRUE;
1161       continue;
1162     }
1163     if (*it == L'-') {
1164       if (bHasSign) {
1165         FX_BOOL& bRc = pEvent->Rc();
1166         bRc = FALSE;
1167         return TRUE;
1168       }
1169       // sign's position is not correct
1170       if (it != w_strChange2.begin()) {
1171         FX_BOOL& bRc = pEvent->Rc();
1172         bRc = FALSE;
1173         return TRUE;
1174       }
1175       if (pEvent->SelStart() != 0) {
1176         FX_BOOL& bRc = pEvent->Rc();
1177         bRc = FALSE;
1178         return TRUE;
1179       }
1180       bHasSign = TRUE;
1181       continue;
1182     }
1183 
1184     if (!FXSYS_iswdigit(*it)) {
1185       FX_BOOL& bRc = pEvent->Rc();
1186       bRc = FALSE;
1187       return TRUE;
1188     }
1189   }
1190 
1191   std::wstring w_prefix = w_strValue2.substr(0, pEvent->SelStart());
1192   std::wstring w_postfix;
1193   if (pEvent->SelEnd() < (int)w_strValue2.length())
1194     w_postfix = w_strValue2.substr(pEvent->SelEnd());
1195   w_strValue2 = w_prefix + w_strChange2 + w_postfix;
1196   w_strValue = w_strValue2.c_str();
1197   val = w_strValue;
1198   return TRUE;
1199 }
1200 
1201 // function AFPercent_Format(nDec, sepStyle)
AFPercent_Format(IJS_Context * cc,const std::vector<CJS_Value> & params,CJS_Value & vRet,CFX_WideString & sError)1202 FX_BOOL CJS_PublicMethods::AFPercent_Format(
1203     IJS_Context* cc,
1204     const std::vector<CJS_Value>& params,
1205     CJS_Value& vRet,
1206     CFX_WideString& sError) {
1207 #if _FX_OS_ != _FX_ANDROID_
1208   CJS_Context* pContext = (CJS_Context*)cc;
1209   CJS_EventHandler* pEvent = pContext->GetEventHandler();
1210 
1211   if (params.size() != 2) {
1212     sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
1213     return FALSE;
1214   }
1215   if (!pEvent->m_pValue)
1216     return FALSE;
1217 
1218   CFX_WideString& Value = pEvent->Value();
1219   CFX_ByteString strValue = StrTrim(CFX_ByteString::FromUnicode(Value));
1220   if (strValue.IsEmpty())
1221     return TRUE;
1222 
1223   int iDec = params[0].ToInt();
1224   if (iDec < 0)
1225     iDec = -iDec;
1226 
1227   int iSepStyle = params[1].ToInt();
1228   if (iSepStyle < 0 || iSepStyle > 3)
1229     iSepStyle = 0;
1230 
1231   //////////////////////////////////////////////////////
1232   // for processing decimal places
1233   double dValue = atof(strValue);
1234   dValue *= 100;
1235   if (iDec > 0)
1236     dValue += DOUBLE_CORRECT;
1237 
1238   int iDec2;
1239   int iNegative = 0;
1240   strValue = fcvt(dValue, iDec, &iDec2, &iNegative);
1241   if (strValue.IsEmpty()) {
1242     dValue = 0;
1243     strValue = fcvt(dValue, iDec, &iDec2, &iNegative);
1244   }
1245 
1246   if (iDec2 < 0) {
1247     for (int iNum = 0; iNum < abs(iDec2); iNum++) {
1248       strValue = "0" + strValue;
1249     }
1250     iDec2 = 0;
1251   }
1252   int iMax = strValue.GetLength();
1253   if (iDec2 > iMax) {
1254     for (int iNum = 0; iNum <= iDec2 - iMax; iNum++) {
1255       strValue += "0";
1256     }
1257     iMax = iDec2 + 1;
1258   }
1259   ///////////////////////////////////////////////////////
1260   // for processing seperator style
1261   if (iDec2 < iMax) {
1262     if (iSepStyle == 0 || iSepStyle == 1) {
1263       strValue.Insert(iDec2, '.');
1264       iMax++;
1265     } else if (iSepStyle == 2 || iSepStyle == 3) {
1266       strValue.Insert(iDec2, ',');
1267       iMax++;
1268     }
1269 
1270     if (iDec2 == 0)
1271       strValue.Insert(iDec2, '0');
1272   }
1273   if (iSepStyle == 0 || iSepStyle == 2) {
1274     char cSeperator;
1275     if (iSepStyle == 0)
1276       cSeperator = ',';
1277     else
1278       cSeperator = '.';
1279 
1280     for (int iDecPositive = iDec2 - 3; iDecPositive > 0; iDecPositive -= 3) {
1281       strValue.Insert(iDecPositive, cSeperator);
1282       iMax++;
1283     }
1284   }
1285   ////////////////////////////////////////////////////////////////////
1286   // negative mark
1287   if (iNegative)
1288     strValue = "-" + strValue;
1289   strValue += "%";
1290   Value = CFX_WideString::FromLocal(strValue);
1291 #endif
1292   return TRUE;
1293 }
1294 // AFPercent_Keystroke(nDec, sepStyle)
AFPercent_Keystroke(IJS_Context * cc,const std::vector<CJS_Value> & params,CJS_Value & vRet,CFX_WideString & sError)1295 FX_BOOL CJS_PublicMethods::AFPercent_Keystroke(
1296     IJS_Context* cc,
1297     const std::vector<CJS_Value>& params,
1298     CJS_Value& vRet,
1299     CFX_WideString& sError) {
1300   return AFNumber_Keystroke(cc, params, vRet, sError);
1301 }
1302 
1303 // function AFDate_FormatEx(cFormat)
AFDate_FormatEx(IJS_Context * cc,const std::vector<CJS_Value> & params,CJS_Value & vRet,CFX_WideString & sError)1304 FX_BOOL CJS_PublicMethods::AFDate_FormatEx(IJS_Context* cc,
1305                                            const std::vector<CJS_Value>& params,
1306                                            CJS_Value& vRet,
1307                                            CFX_WideString& sError) {
1308   CJS_Context* pContext = (CJS_Context*)cc;
1309   CJS_EventHandler* pEvent = pContext->GetEventHandler();
1310 
1311   if (params.size() != 1) {
1312     sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
1313     return FALSE;
1314   }
1315   if (!pEvent->m_pValue)
1316     return FALSE;
1317 
1318   CFX_WideString& val = pEvent->Value();
1319   CFX_WideString strValue = val;
1320   if (strValue.IsEmpty())
1321     return TRUE;
1322 
1323   CFX_WideString sFormat = params[0].ToCFXWideString();
1324   double dDate = 0.0f;
1325 
1326   if (strValue.Find(L"GMT") != -1) {
1327     // for GMT format time
1328     // such as "Tue Aug 11 14:24:16 GMT+08002009"
1329     dDate = MakeInterDate(strValue);
1330   } else {
1331     dDate = MakeRegularDate(strValue, sFormat, nullptr);
1332   }
1333 
1334   if (JS_PortIsNan(dDate)) {
1335     CFX_WideString swMsg;
1336     swMsg.Format(JSGetStringFromID(pContext, IDS_STRING_JSPARSEDATE).c_str(),
1337                  sFormat.c_str());
1338     Alert(pContext, swMsg.c_str());
1339     return FALSE;
1340   }
1341 
1342   val = MakeFormatDate(dDate, sFormat);
1343   return TRUE;
1344 }
1345 
MakeInterDate(CFX_WideString strValue)1346 double CJS_PublicMethods::MakeInterDate(CFX_WideString strValue) {
1347   int nHour;
1348   int nMin;
1349   int nSec;
1350   int nYear;
1351   int nMonth;
1352   int nDay;
1353 
1354   CFX_WideStringArray wsArray;
1355   CFX_WideString sMonth = L"";
1356   CFX_WideString sTemp = L"";
1357   int nSize = strValue.GetLength();
1358 
1359   for (int i = 0; i < nSize; i++) {
1360     FX_WCHAR c = strValue.GetAt(i);
1361     if (c == L' ' || c == L':') {
1362       wsArray.Add(sTemp);
1363       sTemp = L"";
1364       continue;
1365     }
1366 
1367     sTemp += c;
1368   }
1369 
1370   wsArray.Add(sTemp);
1371   if (wsArray.GetSize() != 8)
1372     return 0;
1373 
1374   sTemp = wsArray[1];
1375   if (sTemp.Compare(L"Jan") == 0)
1376     nMonth = 1;
1377   if (sTemp.Compare(L"Feb") == 0)
1378     nMonth = 2;
1379   if (sTemp.Compare(L"Mar") == 0)
1380     nMonth = 3;
1381   if (sTemp.Compare(L"Apr") == 0)
1382     nMonth = 4;
1383   if (sTemp.Compare(L"May") == 0)
1384     nMonth = 5;
1385   if (sTemp.Compare(L"Jun") == 0)
1386     nMonth = 6;
1387   if (sTemp.Compare(L"Jul") == 0)
1388     nMonth = 7;
1389   if (sTemp.Compare(L"Aug") == 0)
1390     nMonth = 8;
1391   if (sTemp.Compare(L"Sep") == 0)
1392     nMonth = 9;
1393   if (sTemp.Compare(L"Oct") == 0)
1394     nMonth = 10;
1395   if (sTemp.Compare(L"Nov") == 0)
1396     nMonth = 11;
1397   if (sTemp.Compare(L"Dec") == 0)
1398     nMonth = 12;
1399 
1400   nDay = (int)ParseStringToNumber(wsArray[2].c_str());
1401   nHour = (int)ParseStringToNumber(wsArray[3].c_str());
1402   nMin = (int)ParseStringToNumber(wsArray[4].c_str());
1403   nSec = (int)ParseStringToNumber(wsArray[5].c_str());
1404   nYear = (int)ParseStringToNumber(wsArray[7].c_str());
1405 
1406   double dRet = JS_MakeDate(JS_MakeDay(nYear, nMonth - 1, nDay),
1407                             JS_MakeTime(nHour, nMin, nSec, 0));
1408 
1409   if (JS_PortIsNan(dRet)) {
1410     dRet = JS_DateParse(strValue.c_str());
1411   }
1412 
1413   return dRet;
1414 }
1415 
1416 // AFDate_KeystrokeEx(cFormat)
AFDate_KeystrokeEx(IJS_Context * cc,const std::vector<CJS_Value> & params,CJS_Value & vRet,CFX_WideString & sError)1417 FX_BOOL CJS_PublicMethods::AFDate_KeystrokeEx(
1418     IJS_Context* cc,
1419     const std::vector<CJS_Value>& params,
1420     CJS_Value& vRet,
1421     CFX_WideString& sError) {
1422   CJS_Context* pContext = (CJS_Context*)cc;
1423   CJS_EventHandler* pEvent = pContext->GetEventHandler();
1424 
1425   if (params.size() != 1) {
1426     sError = L"AFDate_KeystrokeEx's parameters' size r not correct";
1427     return FALSE;
1428   }
1429 
1430   if (pEvent->WillCommit()) {
1431     if (!pEvent->m_pValue)
1432       return FALSE;
1433     CFX_WideString strValue = pEvent->Value();
1434     if (strValue.IsEmpty())
1435       return TRUE;
1436 
1437     CFX_WideString sFormat = params[0].ToCFXWideString();
1438     bool bWrongFormat = FALSE;
1439     double dRet = MakeRegularDate(strValue, sFormat, &bWrongFormat);
1440     if (bWrongFormat || JS_PortIsNan(dRet)) {
1441       CFX_WideString swMsg;
1442       swMsg.Format(JSGetStringFromID(pContext, IDS_STRING_JSPARSEDATE).c_str(),
1443                    sFormat.c_str());
1444       Alert(pContext, swMsg.c_str());
1445       pEvent->Rc() = FALSE;
1446       return TRUE;
1447     }
1448   }
1449   return TRUE;
1450 }
1451 
AFDate_Format(IJS_Context * cc,const std::vector<CJS_Value> & params,CJS_Value & vRet,CFX_WideString & sError)1452 FX_BOOL CJS_PublicMethods::AFDate_Format(IJS_Context* cc,
1453                                          const std::vector<CJS_Value>& params,
1454                                          CJS_Value& vRet,
1455                                          CFX_WideString& sError) {
1456   CJS_Context* pContext = (CJS_Context*)cc;
1457   if (params.size() != 1) {
1458     sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
1459     return FALSE;
1460   }
1461 
1462   int iIndex = params[0].ToInt();
1463   const FX_WCHAR* cFormats[] = {L"m/d",
1464                                 L"m/d/yy",
1465                                 L"mm/dd/yy",
1466                                 L"mm/yy",
1467                                 L"d-mmm",
1468                                 L"d-mmm-yy",
1469                                 L"dd-mmm-yy",
1470                                 L"yy-mm-dd",
1471                                 L"mmm-yy",
1472                                 L"mmmm-yy",
1473                                 L"mmm d, yyyy",
1474                                 L"mmmm d, yyyy",
1475                                 L"m/d/yy h:MM tt",
1476                                 L"m/d/yy HH:MM"};
1477 
1478   if (iIndex < 0 || (static_cast<size_t>(iIndex) >= FX_ArraySize(cFormats)))
1479     iIndex = 0;
1480 
1481   std::vector<CJS_Value> newParams;
1482   newParams.push_back(
1483       CJS_Value(CJS_Runtime::FromContext(cc), cFormats[iIndex]));
1484   return AFDate_FormatEx(cc, newParams, vRet, sError);
1485 }
1486 
1487 // AFDate_KeystrokeEx(cFormat)
AFDate_Keystroke(IJS_Context * cc,const std::vector<CJS_Value> & params,CJS_Value & vRet,CFX_WideString & sError)1488 FX_BOOL CJS_PublicMethods::AFDate_Keystroke(
1489     IJS_Context* cc,
1490     const std::vector<CJS_Value>& params,
1491     CJS_Value& vRet,
1492     CFX_WideString& sError) {
1493   CJS_Context* pContext = (CJS_Context*)cc;
1494   if (params.size() != 1) {
1495     sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
1496     return FALSE;
1497   }
1498 
1499   int iIndex = params[0].ToInt();
1500   const FX_WCHAR* cFormats[] = {L"m/d",
1501                                 L"m/d/yy",
1502                                 L"mm/dd/yy",
1503                                 L"mm/yy",
1504                                 L"d-mmm",
1505                                 L"d-mmm-yy",
1506                                 L"dd-mmm-yy",
1507                                 L"yy-mm-dd",
1508                                 L"mmm-yy",
1509                                 L"mmmm-yy",
1510                                 L"mmm d, yyyy",
1511                                 L"mmmm d, yyyy",
1512                                 L"m/d/yy h:MM tt",
1513                                 L"m/d/yy HH:MM"};
1514 
1515   if (iIndex < 0 || (static_cast<size_t>(iIndex) >= FX_ArraySize(cFormats)))
1516     iIndex = 0;
1517 
1518   std::vector<CJS_Value> newParams;
1519   newParams.push_back(
1520       CJS_Value(CJS_Runtime::FromContext(cc), cFormats[iIndex]));
1521   return AFDate_KeystrokeEx(cc, newParams, vRet, sError);
1522 }
1523 
1524 // function AFTime_Format(ptf)
AFTime_Format(IJS_Context * cc,const std::vector<CJS_Value> & params,CJS_Value & vRet,CFX_WideString & sError)1525 FX_BOOL CJS_PublicMethods::AFTime_Format(IJS_Context* cc,
1526                                          const std::vector<CJS_Value>& params,
1527                                          CJS_Value& vRet,
1528                                          CFX_WideString& sError) {
1529   CJS_Context* pContext = (CJS_Context*)cc;
1530   if (params.size() != 1) {
1531     sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
1532     return FALSE;
1533   }
1534 
1535   int iIndex = params[0].ToInt();
1536   const FX_WCHAR* cFormats[] = {L"HH:MM", L"h:MM tt", L"HH:MM:ss",
1537                                 L"h:MM:ss tt"};
1538 
1539   if (iIndex < 0 || (static_cast<size_t>(iIndex) >= FX_ArraySize(cFormats)))
1540     iIndex = 0;
1541 
1542   std::vector<CJS_Value> newParams;
1543   newParams.push_back(
1544       CJS_Value(CJS_Runtime::FromContext(cc), cFormats[iIndex]));
1545   return AFDate_FormatEx(cc, newParams, vRet, sError);
1546 }
1547 
AFTime_Keystroke(IJS_Context * cc,const std::vector<CJS_Value> & params,CJS_Value & vRet,CFX_WideString & sError)1548 FX_BOOL CJS_PublicMethods::AFTime_Keystroke(
1549     IJS_Context* cc,
1550     const std::vector<CJS_Value>& params,
1551     CJS_Value& vRet,
1552     CFX_WideString& sError) {
1553   CJS_Context* pContext = (CJS_Context*)cc;
1554   if (params.size() != 1) {
1555     sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
1556     return FALSE;
1557   }
1558 
1559   int iIndex = params[0].ToInt();
1560   const FX_WCHAR* cFormats[] = {L"HH:MM", L"h:MM tt", L"HH:MM:ss",
1561                                 L"h:MM:ss tt"};
1562 
1563   if (iIndex < 0 || (static_cast<size_t>(iIndex) >= FX_ArraySize(cFormats)))
1564     iIndex = 0;
1565 
1566   std::vector<CJS_Value> newParams;
1567   newParams.push_back(
1568       CJS_Value(CJS_Runtime::FromContext(cc), cFormats[iIndex]));
1569   return AFDate_KeystrokeEx(cc, newParams, vRet, sError);
1570 }
1571 
AFTime_FormatEx(IJS_Context * cc,const std::vector<CJS_Value> & params,CJS_Value & vRet,CFX_WideString & sError)1572 FX_BOOL CJS_PublicMethods::AFTime_FormatEx(IJS_Context* cc,
1573                                            const std::vector<CJS_Value>& params,
1574                                            CJS_Value& vRet,
1575                                            CFX_WideString& sError) {
1576   return AFDate_FormatEx(cc, params, vRet, sError);
1577 }
1578 
AFTime_KeystrokeEx(IJS_Context * cc,const std::vector<CJS_Value> & params,CJS_Value & vRet,CFX_WideString & sError)1579 FX_BOOL CJS_PublicMethods::AFTime_KeystrokeEx(
1580     IJS_Context* cc,
1581     const std::vector<CJS_Value>& params,
1582     CJS_Value& vRet,
1583     CFX_WideString& sError) {
1584   return AFDate_KeystrokeEx(cc, params, vRet, sError);
1585 }
1586 
1587 // function AFSpecial_Format(psf)
AFSpecial_Format(IJS_Context * cc,const std::vector<CJS_Value> & params,CJS_Value & vRet,CFX_WideString & sError)1588 FX_BOOL CJS_PublicMethods::AFSpecial_Format(
1589     IJS_Context* cc,
1590     const std::vector<CJS_Value>& params,
1591     CJS_Value& vRet,
1592     CFX_WideString& sError) {
1593   CJS_Context* pContext = (CJS_Context*)cc;
1594 
1595   if (params.size() != 1) {
1596     sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
1597     return FALSE;
1598   }
1599 
1600   std::string cFormat;
1601   int iIndex = params[0].ToInt();
1602 
1603   CJS_EventHandler* pEvent = pContext->GetEventHandler();
1604   if (!pEvent->m_pValue)
1605     return FALSE;
1606   CFX_WideString& Value = pEvent->Value();
1607   std::string strSrc = CFX_ByteString::FromUnicode(Value).c_str();
1608 
1609   switch (iIndex) {
1610     case 0:
1611       cFormat = "99999";
1612       break;
1613     case 1:
1614       cFormat = "99999-9999";
1615       break;
1616     case 2: {
1617       std::string NumberStr;
1618       util::printx("9999999999", strSrc, NumberStr);
1619       if (NumberStr.length() >= 10)
1620         cFormat = "(999) 999-9999";
1621       else
1622         cFormat = "999-9999";
1623       break;
1624     }
1625     case 3:
1626       cFormat = "999-99-9999";
1627       break;
1628   }
1629 
1630   std::string strDes;
1631   util::printx(cFormat, strSrc, strDes);
1632   Value = CFX_WideString::FromLocal(strDes.c_str());
1633   return TRUE;
1634 }
1635 
1636 // function AFSpecial_KeystrokeEx(mask)
AFSpecial_KeystrokeEx(IJS_Context * cc,const std::vector<CJS_Value> & params,CJS_Value & vRet,CFX_WideString & sError)1637 FX_BOOL CJS_PublicMethods::AFSpecial_KeystrokeEx(
1638     IJS_Context* cc,
1639     const std::vector<CJS_Value>& params,
1640     CJS_Value& vRet,
1641     CFX_WideString& sError) {
1642   CJS_Context* pContext = (CJS_Context*)cc;
1643   CJS_EventHandler* pEvent = pContext->GetEventHandler();
1644 
1645   if (params.size() < 1) {
1646     sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
1647     return FALSE;
1648   }
1649 
1650   if (!pEvent->m_pValue)
1651     return FALSE;
1652   CFX_WideString& valEvent = pEvent->Value();
1653 
1654   CFX_WideString wstrMask = params[0].ToCFXWideString();
1655   if (wstrMask.IsEmpty())
1656     return TRUE;
1657 
1658   const size_t wstrMaskLen = wstrMask.GetLength();
1659   const std::wstring wstrValue = valEvent.c_str();
1660 
1661   if (pEvent->WillCommit()) {
1662     if (wstrValue.empty())
1663       return TRUE;
1664     size_t iIndexMask = 0;
1665     for (const auto& w_Value : wstrValue) {
1666       if (!maskSatisfied(w_Value, wstrMask[iIndexMask]))
1667         break;
1668       iIndexMask++;
1669     }
1670 
1671     if (iIndexMask != wstrMaskLen ||
1672         (iIndexMask != wstrValue.size() && wstrMaskLen != 0)) {
1673       Alert(
1674           pContext,
1675           JSGetStringFromID(pContext, IDS_STRING_JSAFNUMBER_KEYSTROKE).c_str());
1676       pEvent->Rc() = FALSE;
1677     }
1678     return TRUE;
1679   }
1680 
1681   CFX_WideString& wideChange = pEvent->Change();
1682   std::wstring wChange = wideChange.c_str();
1683   if (wChange.empty())
1684     return TRUE;
1685 
1686   int iIndexMask = pEvent->SelStart();
1687 
1688   size_t combined_len = wstrValue.length() + wChange.length() -
1689                         (pEvent->SelEnd() - pEvent->SelStart());
1690   if (combined_len > wstrMaskLen) {
1691     Alert(pContext,
1692           JSGetStringFromID(pContext, IDS_STRING_JSPARAM_TOOLONG).c_str());
1693     pEvent->Rc() = FALSE;
1694     return TRUE;
1695   }
1696 
1697   if (iIndexMask >= wstrMaskLen && (!wChange.empty())) {
1698     Alert(pContext,
1699           JSGetStringFromID(pContext, IDS_STRING_JSPARAM_TOOLONG).c_str());
1700     pEvent->Rc() = FALSE;
1701     return TRUE;
1702   }
1703 
1704   for (std::wstring::iterator it = wChange.begin(); it != wChange.end(); it++) {
1705     if (iIndexMask >= wstrMaskLen) {
1706       Alert(pContext,
1707             JSGetStringFromID(pContext, IDS_STRING_JSPARAM_TOOLONG).c_str());
1708       pEvent->Rc() = FALSE;
1709       return TRUE;
1710     }
1711     wchar_t w_Mask = wstrMask[iIndexMask];
1712     if (!isReservedMaskChar(w_Mask)) {
1713       *it = w_Mask;
1714     }
1715     wchar_t w_Change = *it;
1716     if (!maskSatisfied(w_Change, w_Mask)) {
1717       pEvent->Rc() = FALSE;
1718       return TRUE;
1719     }
1720     iIndexMask++;
1721   }
1722 
1723   wideChange = wChange.c_str();
1724   return TRUE;
1725 }
1726 
1727 // function AFSpecial_Keystroke(psf)
AFSpecial_Keystroke(IJS_Context * cc,const std::vector<CJS_Value> & params,CJS_Value & vRet,CFX_WideString & sError)1728 FX_BOOL CJS_PublicMethods::AFSpecial_Keystroke(
1729     IJS_Context* cc,
1730     const std::vector<CJS_Value>& params,
1731     CJS_Value& vRet,
1732     CFX_WideString& sError) {
1733   CJS_Context* pContext = (CJS_Context*)cc;
1734   if (params.size() != 1) {
1735     sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
1736     return FALSE;
1737   }
1738 
1739   CJS_EventHandler* pEvent = pContext->GetEventHandler();
1740   if (!pEvent->m_pValue)
1741     return FALSE;
1742 
1743   std::string cFormat;
1744   int iIndex = params[0].ToInt();
1745   CFX_WideString& val = pEvent->Value();
1746   std::string strSrc = CFX_ByteString::FromUnicode(val).c_str();
1747   std::wstring wstrChange = pEvent->Change().c_str();
1748 
1749   switch (iIndex) {
1750     case 0:
1751       cFormat = "99999";
1752       break;
1753     case 1:
1754       // cFormat = "99999-9999";
1755       cFormat = "999999999";
1756       break;
1757     case 2: {
1758       std::string NumberStr;
1759       util::printx("9999999999", strSrc, NumberStr);
1760       if (strSrc.length() + wstrChange.length() > 7)
1761         // cFormat = "(999) 999-9999";
1762         cFormat = "9999999999";
1763       else
1764         // cFormat = "999-9999";
1765         cFormat = "9999999";
1766       break;
1767     }
1768     case 3:
1769       // cFormat = "999-99-9999";
1770       cFormat = "999999999";
1771       break;
1772   }
1773 
1774   std::vector<CJS_Value> params2;
1775   params2.push_back(CJS_Value(CJS_Runtime::FromContext(cc), cFormat.c_str()));
1776   return AFSpecial_KeystrokeEx(cc, params2, vRet, sError);
1777 }
1778 
AFMergeChange(IJS_Context * cc,const std::vector<CJS_Value> & params,CJS_Value & vRet,CFX_WideString & sError)1779 FX_BOOL CJS_PublicMethods::AFMergeChange(IJS_Context* cc,
1780                                          const std::vector<CJS_Value>& params,
1781                                          CJS_Value& vRet,
1782                                          CFX_WideString& sError) {
1783   CJS_Context* pContext = (CJS_Context*)cc;
1784   CJS_EventHandler* pEventHandler = pContext->GetEventHandler();
1785 
1786   if (params.size() != 1) {
1787     sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
1788     return FALSE;
1789   }
1790 
1791   CFX_WideString swValue;
1792   if (pEventHandler->m_pValue)
1793     swValue = pEventHandler->Value();
1794 
1795   if (pEventHandler->WillCommit()) {
1796     vRet = swValue.c_str();
1797     return TRUE;
1798   }
1799 
1800   CFX_WideString prefix, postfix;
1801 
1802   if (pEventHandler->SelStart() >= 0)
1803     prefix = swValue.Mid(0, pEventHandler->SelStart());
1804   else
1805     prefix = L"";
1806 
1807   if (pEventHandler->SelEnd() >= 0 &&
1808       pEventHandler->SelEnd() <= swValue.GetLength())
1809     postfix = swValue.Mid(pEventHandler->SelEnd(),
1810                           swValue.GetLength() - pEventHandler->SelEnd());
1811   else
1812     postfix = L"";
1813 
1814   vRet = (prefix + pEventHandler->Change() + postfix).c_str();
1815 
1816   return TRUE;
1817 }
1818 
AFParseDateEx(IJS_Context * cc,const std::vector<CJS_Value> & params,CJS_Value & vRet,CFX_WideString & sError)1819 FX_BOOL CJS_PublicMethods::AFParseDateEx(IJS_Context* cc,
1820                                          const std::vector<CJS_Value>& params,
1821                                          CJS_Value& vRet,
1822                                          CFX_WideString& sError) {
1823   CJS_Context* pContext = (CJS_Context*)cc;
1824   ASSERT(pContext);
1825 
1826   if (params.size() != 2) {
1827     sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
1828     return FALSE;
1829   }
1830 
1831   CFX_WideString sValue = params[0].ToCFXWideString();
1832   CFX_WideString sFormat = params[1].ToCFXWideString();
1833 
1834   double dDate = MakeRegularDate(sValue, sFormat, nullptr);
1835 
1836   if (JS_PortIsNan(dDate)) {
1837     CFX_WideString swMsg;
1838     swMsg.Format(JSGetStringFromID(pContext, IDS_STRING_JSPARSEDATE).c_str(),
1839                  sFormat.c_str());
1840     Alert((CJS_Context*)cc, swMsg.c_str());
1841     return FALSE;
1842   }
1843 
1844   vRet = dDate;
1845   return TRUE;
1846 }
1847 
AFSimple(IJS_Context * cc,const std::vector<CJS_Value> & params,CJS_Value & vRet,CFX_WideString & sError)1848 FX_BOOL CJS_PublicMethods::AFSimple(IJS_Context* cc,
1849                                     const std::vector<CJS_Value>& params,
1850                                     CJS_Value& vRet,
1851                                     CFX_WideString& sError) {
1852   if (params.size() != 3) {
1853     CJS_Context* pContext = (CJS_Context*)cc;
1854     ASSERT(pContext);
1855 
1856     sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
1857     return FALSE;
1858   }
1859 
1860   vRet = (double)AF_Simple(params[0].ToCFXWideString().c_str(),
1861                            params[1].ToDouble(), params[2].ToDouble());
1862   return TRUE;
1863 }
1864 
AFMakeNumber(IJS_Context * cc,const std::vector<CJS_Value> & params,CJS_Value & vRet,CFX_WideString & sError)1865 FX_BOOL CJS_PublicMethods::AFMakeNumber(IJS_Context* cc,
1866                                         const std::vector<CJS_Value>& params,
1867                                         CJS_Value& vRet,
1868                                         CFX_WideString& sError) {
1869   if (params.size() != 1) {
1870     CJS_Context* pContext = (CJS_Context*)cc;
1871     ASSERT(pContext);
1872 
1873     sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
1874     return FALSE;
1875   }
1876   vRet = ParseStringToNumber(params[0].ToCFXWideString().c_str());
1877   return TRUE;
1878 }
1879 
AFSimple_Calculate(IJS_Context * cc,const std::vector<CJS_Value> & params,CJS_Value & vRet,CFX_WideString & sError)1880 FX_BOOL CJS_PublicMethods::AFSimple_Calculate(
1881     IJS_Context* cc,
1882     const std::vector<CJS_Value>& params,
1883     CJS_Value& vRet,
1884     CFX_WideString& sError) {
1885   CJS_Context* pContext = (CJS_Context*)cc;
1886   if (params.size() != 2) {
1887     sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
1888     return FALSE;
1889   }
1890 
1891   CJS_Value params1 = params[1];
1892   if (!params1.IsArrayObject() && params1.GetType() != CJS_Value::VT_string) {
1893     sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
1894     return FALSE;
1895   }
1896 
1897   CPDFSDK_Document* pReaderDoc = pContext->GetReaderDocument();
1898   CPDFSDK_InterForm* pReaderInterForm = pReaderDoc->GetInterForm();
1899   CPDF_InterForm* pInterForm = pReaderInterForm->GetInterForm();
1900 
1901   CFX_WideString sFunction = params[0].ToCFXWideString();
1902   double dValue = wcscmp(sFunction.c_str(), L"PRD") == 0 ? 1.0 : 0.0;
1903 
1904   CJS_Runtime* pRuntime = CJS_Runtime::FromContext(cc);
1905   CJS_Array FieldNameArray = AF_MakeArrayFromList(pRuntime, params1);
1906   int nFieldsCount = 0;
1907 
1908   for (int i = 0, isz = FieldNameArray.GetLength(); i < isz; i++) {
1909     CJS_Value jsValue(pRuntime);
1910     FieldNameArray.GetElement(i, jsValue);
1911     CFX_WideString wsFieldName = jsValue.ToCFXWideString();
1912 
1913     for (int j = 0, jsz = pInterForm->CountFields(wsFieldName); j < jsz; j++) {
1914       if (CPDF_FormField* pFormField = pInterForm->GetField(j, wsFieldName)) {
1915         double dTemp = 0.0;
1916 
1917         switch (pFormField->GetFieldType()) {
1918           case FIELDTYPE_TEXTFIELD:
1919           case FIELDTYPE_COMBOBOX: {
1920             dTemp = ParseStringToNumber(pFormField->GetValue().c_str());
1921             break;
1922           }
1923           case FIELDTYPE_PUSHBUTTON: {
1924             dTemp = 0.0;
1925             break;
1926           }
1927           case FIELDTYPE_CHECKBOX:
1928           case FIELDTYPE_RADIOBUTTON: {
1929             dTemp = 0.0;
1930             for (int c = 0, csz = pFormField->CountControls(); c < csz; c++) {
1931               if (CPDF_FormControl* pFormCtrl = pFormField->GetControl(c)) {
1932                 if (pFormCtrl->IsChecked()) {
1933                   dTemp +=
1934                       ParseStringToNumber(pFormCtrl->GetExportValue().c_str());
1935                   break;
1936                 }
1937               }
1938             }
1939             break;
1940           }
1941           case FIELDTYPE_LISTBOX: {
1942             if (pFormField->CountSelectedItems() > 1)
1943               break;
1944 
1945             dTemp = ParseStringToNumber(pFormField->GetValue().c_str());
1946             break;
1947           }
1948           default:
1949             break;
1950         }
1951 
1952         if (i == 0 && j == 0 && (wcscmp(sFunction.c_str(), L"MIN") == 0 ||
1953                                  wcscmp(sFunction.c_str(), L"MAX") == 0))
1954           dValue = dTemp;
1955 
1956         dValue = AF_Simple(sFunction.c_str(), dValue, dTemp);
1957 
1958         nFieldsCount++;
1959       }
1960     }
1961   }
1962 
1963   if (wcscmp(sFunction.c_str(), L"AVG") == 0 && nFieldsCount > 0)
1964     dValue /= nFieldsCount;
1965 
1966   dValue = (double)floor(dValue * FXSYS_pow((double)10, (double)6) + 0.49) /
1967            FXSYS_pow((double)10, (double)6);
1968   CJS_Value jsValue(pRuntime, dValue);
1969   if (pContext->GetEventHandler()->m_pValue)
1970     pContext->GetEventHandler()->Value() = jsValue.ToCFXWideString();
1971 
1972   return TRUE;
1973 }
1974 
1975 /* This function validates the current event to ensure that its value is
1976 ** within the specified range. */
1977 
AFRange_Validate(IJS_Context * cc,const std::vector<CJS_Value> & params,CJS_Value & vRet,CFX_WideString & sError)1978 FX_BOOL CJS_PublicMethods::AFRange_Validate(
1979     IJS_Context* cc,
1980     const std::vector<CJS_Value>& params,
1981     CJS_Value& vRet,
1982     CFX_WideString& sError) {
1983   CJS_Context* pContext = (CJS_Context*)cc;
1984   CJS_EventHandler* pEvent = pContext->GetEventHandler();
1985 
1986   if (params.size() != 4) {
1987     sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
1988     return FALSE;
1989   }
1990 
1991   if (!pEvent->m_pValue)
1992     return FALSE;
1993   if (pEvent->Value().IsEmpty())
1994     return TRUE;
1995   double dEentValue = atof(CFX_ByteString::FromUnicode(pEvent->Value()));
1996   FX_BOOL bGreaterThan = params[0].ToBool();
1997   double dGreaterThan = params[1].ToDouble();
1998   FX_BOOL bLessThan = params[2].ToBool();
1999   double dLessThan = params[3].ToDouble();
2000   CFX_WideString swMsg;
2001 
2002   if (bGreaterThan && bLessThan) {
2003     if (dEentValue < dGreaterThan || dEentValue > dLessThan)
2004       swMsg.Format(JSGetStringFromID(pContext, IDS_STRING_JSRANGE1).c_str(),
2005                    params[1].ToCFXWideString().c_str(),
2006                    params[3].ToCFXWideString().c_str());
2007   } else if (bGreaterThan) {
2008     if (dEentValue < dGreaterThan)
2009       swMsg.Format(JSGetStringFromID(pContext, IDS_STRING_JSRANGE2).c_str(),
2010                    params[1].ToCFXWideString().c_str());
2011   } else if (bLessThan) {
2012     if (dEentValue > dLessThan)
2013       swMsg.Format(JSGetStringFromID(pContext, IDS_STRING_JSRANGE3).c_str(),
2014                    params[3].ToCFXWideString().c_str());
2015   }
2016 
2017   if (!swMsg.IsEmpty()) {
2018     Alert(pContext, swMsg.c_str());
2019     pEvent->Rc() = FALSE;
2020   }
2021   return TRUE;
2022 }
2023 
AFExtractNums(IJS_Context * cc,const std::vector<CJS_Value> & params,CJS_Value & vRet,CFX_WideString & sError)2024 FX_BOOL CJS_PublicMethods::AFExtractNums(IJS_Context* cc,
2025                                          const std::vector<CJS_Value>& params,
2026                                          CJS_Value& vRet,
2027                                          CFX_WideString& sError) {
2028   CJS_Context* pContext = (CJS_Context*)cc;
2029   if (params.size() != 1) {
2030     sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
2031     return FALSE;
2032   }
2033 
2034   CJS_Runtime* pRuntime = CJS_Runtime::FromContext(cc);
2035   CJS_Array nums(pRuntime);
2036 
2037   CFX_WideString str = params[0].ToCFXWideString();
2038   CFX_WideString sPart;
2039 
2040   if (str.GetAt(0) == L'.' || str.GetAt(0) == L',')
2041     str = L"0" + str;
2042 
2043   int nIndex = 0;
2044   for (int i = 0, sz = str.GetLength(); i < sz; i++) {
2045     FX_WCHAR wc = str.GetAt(i);
2046     if (FXSYS_iswdigit(wc)) {
2047       sPart += wc;
2048     } else {
2049       if (sPart.GetLength() > 0) {
2050         nums.SetElement(nIndex, CJS_Value(pRuntime, sPart.c_str()));
2051         sPart = L"";
2052         nIndex++;
2053       }
2054     }
2055   }
2056 
2057   if (sPart.GetLength() > 0) {
2058     nums.SetElement(nIndex, CJS_Value(pRuntime, sPart.c_str()));
2059   }
2060 
2061   if (nums.GetLength() > 0)
2062     vRet = nums;
2063   else
2064     vRet.SetNull();
2065 
2066   return TRUE;
2067 }
2068