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