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