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