a615d4409b592be5c690b19a9780f8c98b498b0e
[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) return FALSE;
101
102                         p++;
103                         c = *p;
104                         if (c == '+' || c == '-')
105                         {
106                                 bKXJS = TRUE;
107                         }
108                         else
109                         {
110                                 return FALSE;
111                         }
112                 }
113                 else if (!IsDigit(c))
114                 {
115                         return FALSE;
116                 }
117                 p++;
118         }
119
120         return TRUE;
121 }
122
123 FX_BOOL CJS_PublicMethods::IsDigit(wchar_t ch)
124 {
125         return (ch >= L'0' && ch <= L'9');
126 }
127
128 FX_BOOL CJS_PublicMethods::IsDigit(char ch)
129 {
130         return (ch >= '0' && ch <= '9');
131 }
132
133 FX_BOOL CJS_PublicMethods::IsAlphabetic(wchar_t ch)
134 {
135         return ((ch >= L'a' && ch <= L'z') || (ch >= L'A' && ch <= L'Z'));
136 }
137
138 FX_BOOL CJS_PublicMethods::IsAlphaNumeric(wchar_t ch)
139 {
140         return (IsDigit(ch) || IsAlphabetic(ch));
141 }
142
143 FX_BOOL CJS_PublicMethods::maskSatisfied(wchar_t c_Change,wchar_t c_Mask)
144 {
145         switch (c_Mask)
146         {
147         case L'9':
148         return IsDigit(c_Change);
149     case L'A':
150         return IsAlphabetic(c_Change);
151     case L'O':
152         return IsAlphaNumeric(c_Change);
153     case L'X':
154         return TRUE;
155         default:
156         return (c_Change == c_Mask);
157         }
158 }
159
160 FX_BOOL CJS_PublicMethods::isReservedMaskChar(wchar_t ch)
161 {
162         return ch == L'9' || ch == L'A' || ch == L'O' || ch == L'X';
163 }
164
165 double CJS_PublicMethods::AF_Simple(const FX_WCHAR* sFuction, double dValue1, double dValue2)
166 {
167         if (FXSYS_wcsicmp(sFuction,L"AVG") == 0 || FXSYS_wcsicmp(sFuction,L"SUM") == 0)
168         {
169                 return dValue1 + dValue2;
170         }
171         else if (FXSYS_wcsicmp(sFuction, L"PRD") == 0)
172         {
173                 return dValue1 * dValue2;
174         }
175         else if (FXSYS_wcsicmp(sFuction,L"MIN") == 0)
176         {
177                 return FX_MIN(dValue1, dValue2);
178         }
179         else if (FXSYS_wcsicmp(sFuction,L"MAX") == 0)
180         {
181                 return FX_MAX(dValue1, dValue2);
182         }
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                         else
1312                         {
1313                                 bHasSep = TRUE;
1314                                 continue;
1315                         }
1316                 }
1317                 if (*it == L'-')
1318                 {
1319                         if (bHasSign)
1320                         {
1321                                 FX_BOOL &bRc = pEvent->Rc();
1322                                 bRc = FALSE;
1323                                 return TRUE;
1324                         }
1325                         else if (it != w_strChange2.begin()) //sign's position is not correct
1326                         {
1327                                 FX_BOOL &bRc = pEvent->Rc();
1328                                 bRc = FALSE;
1329                                 return TRUE;
1330                         }
1331                         else if (pEvent->SelStart() != 0)
1332                         {
1333                                 FX_BOOL &bRc = pEvent->Rc();
1334                                 bRc = FALSE;
1335                                 return TRUE;
1336                         }
1337                         bHasSign = TRUE;
1338                         continue;
1339                 }
1340
1341                 if (!IsDigit(*it))
1342                 {
1343                         FX_BOOL &bRc = pEvent->Rc();
1344                         bRc = FALSE;
1345                         return TRUE;
1346                 }
1347         }
1348
1349
1350         std::wstring w_prefix = w_strValue2.substr(0,pEvent->SelStart());
1351         std::wstring w_postfix;
1352         if (pEvent->SelEnd()<(int)w_strValue2.length())
1353                 w_postfix  = w_strValue2.substr(pEvent->SelEnd());
1354         w_strValue2 = w_prefix + w_strChange2 + w_postfix;
1355         w_strValue = w_strValue2.c_str();
1356         val = w_strValue;
1357         return TRUE;
1358
1359 }
1360
1361 //function AFPercent_Format(nDec, sepStyle)
1362 FX_BOOL CJS_PublicMethods::AFPercent_Format(IFXJS_Context* cc, const CJS_Parameters& params, CJS_Value& vRet, CFX_WideString& sError)
1363 {
1364 #if _FX_OS_ != _FX_ANDROID_
1365         CJS_Context* pContext = (CJS_Context *)cc;
1366         ASSERT(pContext != NULL);
1367         CJS_EventHandler* pEvent = pContext->GetEventHandler();
1368         ASSERT(pEvent != NULL);
1369
1370     if (params.size() != 2)
1371         {
1372                 sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
1373                 return FALSE;
1374         }
1375         if(!pEvent->m_pValue)
1376                 return FALSE;
1377
1378         CFX_WideString& Value = pEvent->Value();
1379         CFX_ByteString strValue = StrTrim(CFX_ByteString::FromUnicode(Value));
1380         if (strValue.IsEmpty())
1381                 return TRUE;
1382
1383         int iDec = params[0].ToInt();
1384         if (iDec < 0)
1385                 iDec = -iDec;
1386
1387         int iSepStyle = params[1].ToInt();
1388         if (iSepStyle < 0 || iSepStyle > 3)
1389                 iSepStyle = 0;
1390
1391         //////////////////////////////////////////////////////
1392         //for processing decimal places
1393         double dValue = atof(strValue);
1394         dValue *= 100;
1395         if (iDec > 0)
1396                 dValue += DOUBLE_CORRECT;//УÕý
1397
1398         int iDec2;
1399         FX_BOOL bNegative = FALSE;
1400         strValue = fcvt(dValue,iDec,&iDec2,&bNegative);
1401     if (strValue.IsEmpty())
1402         {
1403                 dValue = 0;
1404                 strValue = fcvt(dValue,iDec,&iDec2,&bNegative);
1405         }
1406
1407         if (iDec2 < 0)
1408         {
1409                 for (int iNum = 0; iNum < abs(iDec2); iNum++)
1410                 {
1411                         strValue = "0" + strValue;
1412                 }
1413                 iDec2 = 0;
1414
1415         }
1416         int iMax = strValue.GetLength();
1417         if (iDec2 > iMax)
1418         {
1419                 for (int iNum = 0; iNum <= iDec2 - iMax; iNum++)
1420                 {
1421                         strValue += "0";
1422                 }
1423                 iMax = iDec2+1;
1424         }
1425         ///////////////////////////////////////////////////////
1426     //for processing seperator style
1427         if (iDec2 < iMax)
1428         {
1429                 if (iSepStyle == 0 || iSepStyle == 1)
1430                 {
1431                         strValue.Insert(iDec2, '.');
1432                         iMax++;
1433                 }
1434                 else if (iSepStyle == 2 || iSepStyle == 3)
1435                 {
1436                         strValue.Insert(iDec2, ',');
1437                         iMax++;
1438                 }
1439
1440                 if (iDec2 == 0)
1441                         strValue.Insert(iDec2, '0');
1442         }
1443         if (iSepStyle == 0 || iSepStyle == 2)
1444         {
1445                 char cSeperator;
1446                 if (iSepStyle == 0)
1447                         cSeperator = ',';
1448                 else
1449                         cSeperator = '.';
1450
1451                 int iDecPositive;
1452                 iDecPositive = iDec2;
1453
1454                 for (iDecPositive = iDec2 -3; iDecPositive > 0; iDecPositive -= 3)
1455                 {
1456                         strValue.Insert(iDecPositive,cSeperator);
1457                         iMax++;
1458                 }
1459         }
1460         ////////////////////////////////////////////////////////////////////
1461         //negative mark
1462         if(bNegative)
1463                 strValue = "-" + strValue;
1464         strValue += "%";
1465         Value = CFX_WideString::FromLocal(strValue);
1466 #endif
1467         return TRUE;
1468 }
1469 //AFPercent_Keystroke(nDec, sepStyle)
1470 FX_BOOL CJS_PublicMethods::AFPercent_Keystroke(IFXJS_Context* cc, const CJS_Parameters& params, CJS_Value& vRet, CFX_WideString& sError)
1471 {
1472         return AFNumber_Keystroke(cc,params,vRet,sError);
1473 }
1474
1475 //function AFDate_FormatEx(cFormat)
1476 FX_BOOL CJS_PublicMethods::AFDate_FormatEx(IFXJS_Context* cc, const CJS_Parameters& params, CJS_Value& vRet, CFX_WideString& sError)
1477 {
1478         CJS_Context* pContext = (CJS_Context *)cc;
1479         ASSERT(pContext != NULL);
1480         CJS_EventHandler* pEvent = pContext->GetEventHandler();
1481         ASSERT(pEvent != NULL);
1482
1483         if (params.size() != 1)
1484         {
1485                 sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
1486                 return FALSE;
1487         }
1488         if(!pEvent->m_pValue)
1489                 return FALSE;
1490
1491         CFX_WideString& val = pEvent->Value();
1492         CFX_WideString strValue = val;
1493         if (strValue.IsEmpty())
1494                 return TRUE;
1495
1496         CFX_WideString sFormat = params[0].ToCFXWideString();
1497         FX_BOOL bWrongFormat = FALSE;
1498         double dDate = 0.0f;
1499
1500         if(strValue.Find(L"GMT") != -1)
1501         {
1502                 //for GMT format time
1503                 //such as "Tue Aug 11 14:24:16 GMT+08002009"
1504                 dDate = MakeInterDate(strValue);
1505         }
1506         else
1507         {
1508                 dDate = MakeRegularDate(strValue,sFormat,bWrongFormat);
1509         }
1510
1511         if (JS_PortIsNan(dDate))
1512         {
1513                 CFX_WideString swMsg;
1514                 swMsg.Format(JSGetStringFromID(pContext, IDS_STRING_JSPARSEDATE).c_str(), sFormat.c_str());
1515                 Alert(pContext, swMsg.c_str());
1516                 return FALSE;
1517         }
1518
1519         val =  MakeFormatDate(dDate,sFormat);
1520         return TRUE;
1521 }
1522
1523 double CJS_PublicMethods::MakeInterDate(CFX_WideString strValue)
1524 {
1525         int nHour;
1526         int nMin;
1527         int nSec;
1528         int nYear;
1529         int nMonth;
1530         int nDay;
1531
1532         CFX_WideStringArray wsArray;
1533         CFX_WideString sMonth = L"";
1534         CFX_WideString sTemp = L"";
1535         int nSize = strValue.GetLength();
1536
1537         for(int i = 0; i < nSize; i++)
1538         {
1539                 FX_WCHAR c = strValue.GetAt(i);
1540                 if(c == L' ' || c == L':')
1541                 {
1542                         wsArray.Add(sTemp);
1543                         sTemp = L"";
1544                         continue;
1545                 }
1546
1547                 sTemp += c;
1548         }
1549
1550         wsArray.Add(sTemp);
1551         if(wsArray.GetSize() != 8)return 0;
1552
1553         sTemp = wsArray[1];
1554         if(sTemp.Compare(L"Jan") == 0) nMonth = 1;
1555         if(sTemp.Compare(L"Feb") == 0) nMonth = 2;
1556         if(sTemp.Compare(L"Mar") == 0) nMonth = 3;
1557         if(sTemp.Compare(L"Apr") == 0) nMonth = 4;
1558         if(sTemp.Compare(L"May") == 0) nMonth = 5;
1559         if(sTemp.Compare(L"Jun") == 0) nMonth = 6;
1560         if(sTemp.Compare(L"Jul") == 0) nMonth = 7;
1561         if(sTemp.Compare(L"Aug") == 0) nMonth = 8;
1562         if(sTemp.Compare(L"Sep") == 0) nMonth = 9;
1563         if(sTemp.Compare(L"Oct") == 0) nMonth = 10;
1564         if(sTemp.Compare(L"Nov") == 0) nMonth = 11;
1565         if(sTemp.Compare(L"Dec") == 0) nMonth = 12;
1566
1567         nDay = (int)ParseStringToNumber(wsArray[2].c_str());
1568         nHour = (int)ParseStringToNumber(wsArray[3].c_str());
1569         nMin = (int)ParseStringToNumber(wsArray[4].c_str());
1570         nSec = (int)ParseStringToNumber(wsArray[5].c_str());
1571         nYear = (int)ParseStringToNumber(wsArray[7].c_str());
1572
1573         double dRet = JS_MakeDate(JS_MakeDay(nYear,nMonth - 1,nDay),JS_MakeTime(nHour, nMin, nSec, 0));
1574
1575         if (JS_PortIsNan(dRet))
1576         {
1577                 dRet = JS_DateParse(strValue.c_str());
1578         }
1579
1580         return dRet;
1581 }
1582
1583 //AFDate_KeystrokeEx(cFormat)
1584 FX_BOOL CJS_PublicMethods::AFDate_KeystrokeEx(IFXJS_Context* cc, const CJS_Parameters& params, CJS_Value& vRet, CFX_WideString& sError)
1585 {
1586         CJS_Context* pContext = (CJS_Context *)cc;
1587         ASSERT(pContext != NULL);
1588         CJS_EventHandler* pEvent = pContext->GetEventHandler();
1589         ASSERT(pEvent != NULL);
1590
1591         if (params.size() != 1)
1592         {
1593                 sError = L"AFDate_KeystrokeEx's parameters' size r not correct";
1594                 return FALSE;
1595         }
1596
1597         if (pEvent->WillCommit())
1598         {
1599                 if(!pEvent->m_pValue)
1600                         return FALSE;
1601                 CFX_WideString strValue = pEvent->Value();
1602                 if (strValue.IsEmpty())
1603                         return TRUE;
1604
1605                 CFX_WideString sFormat = params[0].ToCFXWideString();
1606                 FX_BOOL bWrongFormat = FALSE;
1607                 double dRet = MakeRegularDate(strValue,sFormat,bWrongFormat);
1608                 if (bWrongFormat || JS_PortIsNan(dRet))
1609                 {
1610                         CFX_WideString swMsg;
1611                         swMsg.Format(JSGetStringFromID(pContext, IDS_STRING_JSPARSEDATE).c_str(), sFormat.c_str());
1612                         Alert(pContext, swMsg.c_str());
1613                         pEvent->Rc() = FALSE;
1614                         return TRUE;
1615                 }
1616         }
1617         return TRUE;
1618 }
1619
1620 FX_BOOL CJS_PublicMethods::AFDate_Format(IFXJS_Context* cc, const CJS_Parameters& params, CJS_Value& vRet, CFX_WideString& sError)
1621 {
1622         v8::Isolate* isolate = ::GetIsolate(cc);
1623
1624         if (params.size() != 1)
1625         {
1626                 CJS_Context* pContext = (CJS_Context*)cc;
1627                 ASSERT(pContext != NULL);
1628
1629                 sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
1630                 return FALSE;
1631         }
1632
1633         int iIndex = params[0].ToInt();
1634         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",
1635                 L"yy-mm-dd", L"mmm-yy", L"mmmm-yy", L"mmm d, yyyy", L"mmmm d, yyyy",
1636                 L"m/d/yy h:MM tt", L"m/d/yy HH:MM" };
1637
1638         ASSERT(iIndex < FX_ArraySize(cFormats));
1639
1640         if (iIndex < 0)
1641                 iIndex = 0;
1642         if (iIndex >= FX_ArraySize(cFormats))
1643                 iIndex = 0;
1644         CJS_Parameters newParams;
1645         CJS_Value val(isolate,cFormats[iIndex]);
1646         newParams.push_back(val);
1647         return AFDate_FormatEx(cc,newParams,vRet,sError);
1648 }
1649
1650 //AFDate_KeystrokeEx(cFormat)
1651 FX_BOOL CJS_PublicMethods::AFDate_Keystroke(IFXJS_Context* cc, const CJS_Parameters& params, CJS_Value& vRet, CFX_WideString& sError)
1652 {
1653         v8::Isolate* isolate = ::GetIsolate(cc);
1654
1655         if (params.size() != 1)
1656         {
1657                 CJS_Context* pContext = (CJS_Context*)cc;
1658                 ASSERT(pContext != NULL);
1659
1660                 sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
1661                 return FALSE;
1662         }
1663
1664         int iIndex = params[0].ToInt();
1665         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",
1666                 L"yy-mm-dd", L"mmm-yy", L"mmmm-yy", L"mmm d, yyyy", L"mmmm d, yyyy",
1667                 L"m/d/yy h:MM tt", L"m/d/yy HH:MM" };
1668
1669         ASSERT(iIndex<FX_ArraySize(cFormats));
1670
1671         if (iIndex < 0)
1672                 iIndex = 0;
1673         if (iIndex >= FX_ArraySize(cFormats))
1674                 iIndex = 0;
1675         CJS_Parameters newParams;
1676         CJS_Value val(isolate,cFormats[iIndex]);
1677         newParams.push_back(val);
1678         return AFDate_KeystrokeEx(cc,newParams,vRet,sError);
1679 }
1680
1681 //function AFTime_Format(ptf)
1682 FX_BOOL CJS_PublicMethods::AFTime_Format(IFXJS_Context* cc, const CJS_Parameters& params, CJS_Value& vRet, CFX_WideString& sError)
1683 {
1684         v8::Isolate* isolate = ::GetIsolate(cc);
1685
1686         if (params.size() != 1)
1687         {
1688                 CJS_Context* pContext = (CJS_Context*)cc;
1689                 ASSERT(pContext != NULL);
1690                 sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
1691                 return FALSE;
1692         }
1693
1694         int iIndex = params[0].ToInt();
1695         const FX_WCHAR* cFormats[] = {L"HH:MM", L"h:MM tt", L"HH:MM:ss", L"h:MM:ss tt"};
1696
1697         ASSERT(iIndex<FX_ArraySize(cFormats));
1698
1699         if (iIndex < 0)
1700                 iIndex = 0;
1701         if (iIndex >= FX_ArraySize(cFormats))
1702                 iIndex = 0;
1703         CJS_Parameters newParams;
1704         CJS_Value val(isolate,cFormats[iIndex]);
1705         newParams.push_back(val);
1706         return AFDate_FormatEx(cc,newParams,vRet,sError);
1707 }
1708
1709 FX_BOOL CJS_PublicMethods::AFTime_Keystroke(IFXJS_Context* cc, const CJS_Parameters& params, CJS_Value& vRet, CFX_WideString& sError)
1710 {
1711         v8::Isolate* isolate = ::GetIsolate(cc);
1712         if (params.size() != 1)
1713         {
1714                 CJS_Context* pContext = (CJS_Context*)cc;
1715                 ASSERT(pContext != NULL);
1716                 sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
1717                 return FALSE;
1718         }
1719
1720         int iIndex = params[0].ToInt();
1721         const FX_WCHAR* cFormats[] = {L"HH:MM", L"h:MM tt", L"HH:MM:ss", L"h:MM:ss tt"};
1722
1723         ASSERT(iIndex<FX_ArraySize(cFormats));
1724
1725         if (iIndex < 0)
1726                 iIndex = 0;
1727         if (iIndex >= FX_ArraySize(cFormats))
1728                 iIndex = 0;
1729         CJS_Parameters newParams;
1730         CJS_Value val(isolate,cFormats[iIndex]);
1731         newParams.push_back(val);
1732         return AFDate_KeystrokeEx(cc,newParams,vRet,sError);
1733 }
1734
1735 FX_BOOL CJS_PublicMethods::AFTime_FormatEx(IFXJS_Context* cc, const CJS_Parameters& params, CJS_Value& vRet, CFX_WideString& sError)
1736 {
1737         return AFDate_FormatEx(cc,params,vRet,sError);
1738 }
1739
1740 FX_BOOL CJS_PublicMethods::AFTime_KeystrokeEx(IFXJS_Context* cc, const CJS_Parameters& params, CJS_Value& vRet, CFX_WideString& sError)
1741 {
1742         return AFDate_KeystrokeEx(cc,params,vRet,sError);
1743 }
1744
1745 //function AFSpecial_Format(psf)
1746 FX_BOOL CJS_PublicMethods::AFSpecial_Format(IFXJS_Context* cc, const CJS_Parameters& params, CJS_Value& vRet, CFX_WideString& sError)
1747 {
1748         CJS_Context* pContext = (CJS_Context *)cc;
1749         ASSERT(pContext != NULL);
1750
1751         if (params.size() != 1)
1752         {
1753                 sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
1754                 return FALSE;
1755         }
1756
1757         std::string cFormat;
1758         int iIndex = params[0].ToInt();
1759
1760         CJS_EventHandler* pEvent = pContext->GetEventHandler();
1761         ASSERT(pEvent != NULL);
1762
1763         if(!pEvent->m_pValue)
1764                 return FALSE;
1765         CFX_WideString& Value = pEvent->Value();
1766         std::string strSrc = CFX_ByteString::FromUnicode(Value).c_str();
1767
1768         switch (iIndex)
1769         {
1770         case 0:
1771                 cFormat = "99999";
1772                 break;
1773         case 1:
1774                 cFormat = "99999-9999";
1775                 break;
1776         case 2:
1777                 {
1778                         std::string NumberStr;
1779                         util::printx("9999999999", strSrc,NumberStr);
1780                         if (NumberStr.length() >= 10 )
1781                                 cFormat = "(999) 999-9999";
1782                         else
1783                                 cFormat = "999-9999";
1784                         break;
1785                 }
1786         case 3:
1787                 cFormat = "999-99-9999";
1788                 break;
1789         }
1790
1791         std::string strDes;
1792         util::printx(cFormat,strSrc,strDes);
1793         Value = CFX_WideString::FromLocal(strDes.c_str());
1794         return TRUE;
1795 }
1796
1797
1798 //function AFSpecial_KeystrokeEx(mask)
1799 FX_BOOL CJS_PublicMethods::AFSpecial_KeystrokeEx(IFXJS_Context* cc, const CJS_Parameters& params, CJS_Value& vRet, CFX_WideString& sError)
1800 {
1801         CJS_Context* pContext = (CJS_Context *)cc;
1802         ASSERT(pContext != NULL);
1803         CJS_EventHandler* pEvent = pContext->GetEventHandler();
1804
1805         ASSERT(pEvent != NULL);
1806
1807         if (params.size() < 1)
1808         {
1809                 sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
1810                 return FALSE;
1811         }
1812
1813         if(!pEvent->m_pValue)
1814                 return FALSE;
1815         CFX_WideString& valEvent = pEvent->Value();
1816
1817         CFX_WideString wstrMask = params[0].ToCFXWideString();
1818         if (wstrMask.IsEmpty())
1819                 return TRUE;
1820
1821         std::wstring wstrValue = valEvent.c_str();
1822
1823         if (pEvent->WillCommit())
1824         {
1825                 if (wstrValue.empty())
1826                         return TRUE;
1827                 int iIndexMask = 0;
1828                 for (std::wstring::iterator it = wstrValue.begin(); it != wstrValue.end(); it++)
1829                 {
1830                         wchar_t w_Value = *it;
1831                         if (!maskSatisfied(w_Value,wstrMask[iIndexMask]))
1832                                 break;
1833                         iIndexMask++;
1834                 }
1835
1836                 if (iIndexMask != wstrMask.GetLength() || (iIndexMask != wstrValue.size() && wstrMask.GetLength() != 0))
1837                 {
1838                         Alert(pContext, JSGetStringFromID(pContext, IDS_STRING_JSAFNUMBER_KEYSTROKE).c_str());
1839                         pEvent->Rc() = FALSE;
1840                 }
1841                 return TRUE;
1842         }
1843
1844         CFX_WideString &wideChange = pEvent->Change();
1845         std::wstring wChange = wideChange.c_str();
1846         if (wChange.empty())
1847                 return TRUE;
1848
1849         int iIndexMask = pEvent->SelStart();
1850
1851         if (wstrValue.length() - (pEvent->SelEnd()-pEvent->SelStart()) + wChange.length() > (FX_DWORD)wstrMask.GetLength())
1852         {
1853                 Alert(pContext, JSGetStringFromID(pContext, IDS_STRING_JSPARAM_TOOLONG).c_str());
1854                 pEvent->Rc() = FALSE;
1855                 return TRUE;
1856         }
1857
1858         if (iIndexMask >= wstrMask.GetLength() && (!wChange.empty()))
1859         {
1860                 Alert(pContext, JSGetStringFromID(pContext, IDS_STRING_JSPARAM_TOOLONG).c_str());
1861                 pEvent->Rc() = FALSE;
1862                 return TRUE;
1863         }
1864
1865         for (std::wstring::iterator it = wChange.begin(); it != wChange.end(); it++)
1866         {
1867                 if (iIndexMask >= wstrMask.GetLength())
1868                 {
1869                         Alert(pContext, JSGetStringFromID(pContext, IDS_STRING_JSPARAM_TOOLONG).c_str());
1870                         pEvent->Rc() = FALSE;
1871                         return TRUE;
1872                 }
1873                 wchar_t w_Mask = wstrMask[iIndexMask];
1874                 if (!isReservedMaskChar(w_Mask))
1875                 {
1876                         *it = w_Mask;
1877                 }
1878                 wchar_t w_Change = *it;
1879                 if (!maskSatisfied(w_Change,w_Mask))
1880                 {
1881                         pEvent->Rc() = FALSE;
1882                         return TRUE;
1883                 }
1884                 iIndexMask++;
1885         }
1886
1887         wideChange = wChange.c_str();
1888         return TRUE;
1889 }
1890
1891
1892 //function AFSpecial_Keystroke(psf)
1893 FX_BOOL CJS_PublicMethods::AFSpecial_Keystroke(IFXJS_Context* cc, const CJS_Parameters& params, CJS_Value& vRet, CFX_WideString& sError)
1894 {
1895         v8::Isolate* isolate = ::GetIsolate(cc);
1896
1897         CJS_Context* pContext = (CJS_Context *)cc;
1898         ASSERT(pContext != NULL);
1899         CJS_EventHandler* pEvent = pContext->GetEventHandler();
1900         ASSERT(pEvent != NULL);
1901
1902         if (params.size() != 1)
1903         {
1904                 sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
1905                 return FALSE;
1906         }
1907
1908         std::string cFormat;
1909         int iIndex = params[0].ToInt();
1910
1911         if(!pEvent->m_pValue)
1912                 return FALSE;
1913         //CJS_Value val = pEvent->Value();
1914         CFX_WideString& val = pEvent->Value();
1915         std::string strSrc = CFX_ByteString::FromUnicode(val).c_str();
1916         std::wstring wstrChange = pEvent->Change().c_str();
1917
1918         switch (iIndex)
1919         {
1920         case 0:
1921                 cFormat = "99999";
1922                 break;
1923         case 1:
1924                 //cFormat = "99999-9999";
1925                 cFormat = "999999999";
1926                 break;
1927         case 2:
1928                 {
1929                         std::string NumberStr;
1930                         util::printx("9999999999", strSrc,NumberStr);
1931                         if (strSrc.length() + wstrChange.length() > 7 )
1932                                 //cFormat = "(999) 999-9999";
1933                                 cFormat = "9999999999";
1934                         else
1935                                 //cFormat = "999-9999";
1936                                 cFormat = "9999999";
1937                         break;
1938                 }
1939         case 3:
1940                 //cFormat = "999-99-9999";
1941                 cFormat = "999999999";
1942                 break;
1943         }
1944
1945         CJS_Parameters params2;
1946         CJS_Value vMask(isolate, cFormat.c_str());
1947         params2.push_back(vMask);
1948
1949     return AFSpecial_KeystrokeEx(cc,params2,vRet,sError);
1950 }
1951
1952 FX_BOOL CJS_PublicMethods::AFMergeChange(IFXJS_Context* cc, const CJS_Parameters& params, CJS_Value& vRet, CFX_WideString& sError)
1953 {
1954         CJS_Context* pContext = (CJS_Context *)cc;
1955         ASSERT(pContext != NULL);
1956         CJS_EventHandler* pEventHandler = pContext->GetEventHandler();
1957         ASSERT(pEventHandler != NULL);
1958
1959         if (params.size() != 1)
1960         {
1961                 sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
1962                 return FALSE;
1963         }
1964
1965         CFX_WideString swValue;
1966         if (pEventHandler->m_pValue != NULL)
1967                 swValue = pEventHandler->Value();
1968
1969         if (pEventHandler->WillCommit())
1970         {
1971                 vRet = swValue.c_str();
1972                 return TRUE;
1973         }
1974
1975         CFX_WideString prefix,postfix;
1976
1977         if (pEventHandler->SelStart() >= 0)
1978                 prefix = swValue.Mid(0,pEventHandler->SelStart());
1979         else
1980                 prefix = L"";
1981
1982
1983         if (pEventHandler->SelEnd() >= 0 && pEventHandler->SelEnd() <= swValue.GetLength())
1984                 postfix = swValue.Mid(pEventHandler->SelEnd(), swValue.GetLength() - pEventHandler->SelEnd());
1985         else postfix = L"";
1986
1987         vRet = (prefix + pEventHandler->Change() + postfix).c_str();
1988
1989         return TRUE;
1990 }
1991
1992 FX_BOOL CJS_PublicMethods::AFParseDateEx(IFXJS_Context* cc, const CJS_Parameters& params, CJS_Value& vRet, CFX_WideString& sError)
1993 {
1994         CJS_Context* pContext = (CJS_Context *)cc;
1995         ASSERT(pContext != NULL);
1996
1997         if (params.size() != 2)
1998         {
1999                 sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
2000                 return FALSE;
2001         }
2002
2003         CFX_WideString sValue = params[0].ToCFXWideString();
2004         CFX_WideString sFormat = params[1].ToCFXWideString();
2005
2006         FX_BOOL bWrongFormat = FALSE;
2007         double dDate = MakeRegularDate(sValue,sFormat,bWrongFormat);
2008
2009         if (JS_PortIsNan(dDate))
2010         {
2011                 CFX_WideString swMsg;
2012                 swMsg.Format(JSGetStringFromID(pContext, IDS_STRING_JSPARSEDATE).c_str(), sFormat.c_str());
2013                 Alert((CJS_Context *)cc, swMsg.c_str());
2014                 return FALSE;
2015         }
2016
2017         vRet = dDate;
2018         return TRUE;
2019 }
2020
2021 FX_BOOL CJS_PublicMethods::AFSimple(IFXJS_Context* cc, const CJS_Parameters& params, CJS_Value& vRet, CFX_WideString& sError)
2022 {
2023         if (params.size() != 3)
2024         {
2025                 CJS_Context* pContext = (CJS_Context *)cc;
2026                 ASSERT(pContext != NULL);
2027
2028                 sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
2029                 return FALSE;
2030         }
2031
2032         vRet = (double)AF_Simple(params[0].ToCFXWideString().c_str(), params[1].ToDouble(), params[2].ToDouble());
2033         return TRUE;
2034 }
2035
2036 FX_BOOL CJS_PublicMethods::AFMakeNumber(IFXJS_Context* cc, const CJS_Parameters& params, CJS_Value& vRet, CFX_WideString& sError)
2037 {
2038         if (params.size() != 1)
2039         {
2040                 CJS_Context* pContext = (CJS_Context *)cc;
2041                 ASSERT(pContext != NULL);
2042
2043                 sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
2044                 return FALSE;
2045         }
2046         vRet = ParseStringToNumber(params[0].ToCFXWideString().c_str());
2047         return TRUE;
2048 }
2049
2050 FX_BOOL CJS_PublicMethods::AFSimple_Calculate(IFXJS_Context* cc, const CJS_Parameters& params, CJS_Value& vRet, CFX_WideString& sError)
2051 {
2052         v8::Isolate* isolate = ::GetIsolate(cc);
2053
2054         CJS_Context* pContext = (CJS_Context *)cc;
2055         ASSERT(pContext != NULL);
2056
2057         if (params.size() != 2)
2058         {
2059                 sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
2060                 return FALSE;
2061         }
2062
2063         CJS_Value params1 = params[1];
2064
2065         if (!params1.IsArrayObject() && params1.GetType() != VT_string)
2066         {
2067                 sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
2068                 return FALSE;
2069         }
2070
2071         CPDFSDK_Document* pReaderDoc = pContext->GetReaderDocument();
2072     ASSERT(pReaderDoc != NULL);
2073
2074         CPDFSDK_InterForm* pReaderInterForm = pReaderDoc->GetInterForm();
2075         ASSERT(pReaderInterForm != NULL);
2076
2077         CPDF_InterForm* pInterForm = pReaderInterForm->GetInterForm();
2078         ASSERT(pInterForm != NULL);
2079
2080         double dValue;
2081         CFX_WideString sFunction = params[0].ToCFXWideString();
2082         if (wcscmp(sFunction.c_str(), L"PRD") == 0)
2083         dValue = 1.0;
2084         else
2085                 dValue = 0.0;
2086
2087         CJS_Array FieldNameArray = AF_MakeArrayFromList(isolate,params1);
2088
2089         int nFieldsCount = 0;
2090
2091         for (int i=0,isz=FieldNameArray.GetLength(); i<isz; i++)
2092         {
2093                 CJS_Value jsValue(isolate);
2094                 FieldNameArray.GetElement(i,jsValue);
2095                 CFX_WideString wsFieldName = jsValue.ToCFXWideString();
2096
2097         for (int j=0,jsz=pInterForm->CountFields(wsFieldName); j<jsz; j++)
2098                 {
2099                         if (CPDF_FormField* pFormField = pInterForm->GetField(j, wsFieldName))
2100                         {
2101                                 double dTemp = 0.0;
2102
2103                                 switch (pFormField->GetFieldType())
2104                                 {
2105                                 case FIELDTYPE_TEXTFIELD:
2106                                 case FIELDTYPE_COMBOBOX:
2107                                         {
2108                                                 dTemp = ParseStringToNumber(pFormField->GetValue().c_str());
2109                                                 break;
2110                                         }
2111                                 case FIELDTYPE_PUSHBUTTON:
2112                                         {
2113                                                 dTemp = 0.0;
2114                                                 break;
2115                                         }
2116                                 case FIELDTYPE_CHECKBOX:
2117                                 case FIELDTYPE_RADIOBUTTON:
2118                                         {
2119                                                 dTemp = 0.0;
2120                                                 for (int c=0,csz=pFormField->CountControls(); c<csz; c++)
2121                                                 {
2122                                                         if (CPDF_FormControl* pFormCtrl = pFormField->GetControl(c))
2123                                                         {
2124                                                                 if (pFormCtrl->IsChecked())
2125                                                                 {
2126                                                                         dTemp += ParseStringToNumber(pFormCtrl->GetExportValue().c_str());
2127                                                                         break;
2128                                                                 }
2129                                                                 else
2130                                                                         continue;
2131                                                         }
2132                                                 }
2133                                                 break;
2134                                         }
2135                                 case FIELDTYPE_LISTBOX:
2136                                         {
2137                                                 dTemp = 0.0;
2138                                                 if (pFormField->CountSelectedItems() > 1)
2139                                                         break;
2140                                                 else
2141                                                 {
2142                                                         dTemp = ParseStringToNumber(pFormField->GetValue().c_str());
2143                                                         break;
2144                                                 }
2145                                         }
2146                                 default:
2147                                         break;
2148                                 }
2149
2150                                 if (i == 0 && j == 0 && (wcscmp(sFunction.c_str(), L"MIN") == 0 || wcscmp(sFunction.c_str(), L"MAX") == 0))
2151                                         dValue = dTemp;
2152
2153                                 dValue = AF_Simple(sFunction.c_str(), dValue, dTemp);
2154
2155                                 nFieldsCount++;
2156                         }
2157                 }
2158         }
2159
2160         if (wcscmp(sFunction.c_str(), L"AVG") == 0 && nFieldsCount > 0)
2161                 dValue /= nFieldsCount;
2162
2163         dValue = (double)floor(dValue * FXSYS_pow((double)10,(double)6) + 0.49) / FXSYS_pow((double)10,(double)6);
2164         CJS_Value jsValue(isolate,dValue);
2165         if((CJS_EventHandler*)pContext->GetEventHandler()->m_pValue)
2166                 ((CJS_EventHandler*)pContext->GetEventHandler())->Value() = jsValue.ToCFXWideString();
2167
2168         return TRUE;
2169 }
2170
2171 /* This function validates the current event to ensure that its value is
2172 ** within the specified range. */
2173
2174 FX_BOOL CJS_PublicMethods::AFRange_Validate(IFXJS_Context* cc, const CJS_Parameters& params, CJS_Value& vRet, CFX_WideString& sError)
2175 {
2176         CJS_Context* pContext = (CJS_Context *)cc;
2177         ASSERT(pContext != NULL);
2178         CJS_EventHandler* pEvent = pContext->GetEventHandler();
2179         ASSERT(pEvent != NULL);
2180
2181         if (params.size() != 4)
2182         {
2183                 sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
2184                 return FALSE;
2185         }
2186
2187         if(!pEvent->m_pValue)
2188                 return FALSE;
2189         if (pEvent->Value().IsEmpty() )
2190                 return TRUE;
2191         double dEentValue = atof(CFX_ByteString::FromUnicode(pEvent->Value()));
2192         FX_BOOL bGreaterThan = params[0].ToBool();
2193         double dGreaterThan = params[1].ToDouble();
2194         FX_BOOL bLessThan = params[2].ToBool();
2195         double dLessThan = params[3].ToDouble();
2196         CFX_WideString swMsg;
2197
2198         if (bGreaterThan && bLessThan)
2199         {
2200                 if (dEentValue < dGreaterThan || dEentValue > dLessThan)
2201                         swMsg.Format(JSGetStringFromID(pContext, IDS_STRING_JSRANGE1).c_str(),
2202                                                  params[1].ToCFXWideString().c_str(),
2203                                                  params[3].ToCFXWideString().c_str());
2204         }
2205         else if (bGreaterThan)
2206         {
2207                 if (dEentValue < dGreaterThan)
2208                         swMsg.Format(JSGetStringFromID(pContext, IDS_STRING_JSRANGE2).c_str(),
2209                                                  params[1].ToCFXWideString().c_str());
2210         }
2211         else if (bLessThan)
2212         {
2213                 if (dEentValue > dLessThan)
2214                         swMsg.Format(JSGetStringFromID(pContext, IDS_STRING_JSRANGE3).c_str(),
2215                                                  params[3].ToCFXWideString().c_str());
2216         }
2217
2218         if (!swMsg.IsEmpty())
2219         {
2220                 Alert(pContext, swMsg.c_str());
2221                 pEvent->Rc() = FALSE;
2222         }
2223         return TRUE;
2224 }
2225
2226 FX_BOOL CJS_PublicMethods::AFExtractNums(IFXJS_Context* cc, const CJS_Parameters& params, CJS_Value& vRet, CFX_WideString& sError)
2227 {
2228         v8::Isolate* isolate = ::GetIsolate(cc);
2229         CJS_Context* pContext = (CJS_Context*)cc;
2230         ASSERT(pContext != NULL);
2231
2232         if (params.size() != 1)
2233         {
2234                 sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
2235                 return FALSE;
2236         }
2237
2238         CJS_Array nums(isolate);
2239
2240         CFX_WideString str = params[0].ToCFXWideString();
2241         CFX_WideString sPart;
2242
2243         if (str.GetAt(0) == L'.' || str.GetAt(0) == L',')
2244                 str = L"0" + str;
2245
2246         int nIndex = 0;
2247         for (int i=0, sz=str.GetLength(); i<sz; i++)
2248         {
2249                 FX_WCHAR wc = str.GetAt(i);
2250                 if (IsDigit((wchar_t)wc))
2251                 {
2252                         sPart += wc;
2253                 }
2254                 else
2255                 {
2256                         if (sPart.GetLength() > 0)
2257                         {
2258                                 nums.SetElement(nIndex,CJS_Value(isolate,sPart.c_str()));
2259                                 sPart = L"";
2260                                 nIndex ++;
2261                         }
2262                 }
2263         }
2264
2265         if (sPart.GetLength() > 0)
2266         {
2267                 nums.SetElement(nIndex,CJS_Value(isolate,sPart.c_str()));
2268         }
2269
2270         if (nums.GetLength() > 0)
2271                 vRet = nums;
2272         else
2273                 vRet.SetNull();
2274
2275         return TRUE;
2276 }