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