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