blob: f5686a7129d1823a458c7904156f6607c328634b [file] [log] [blame]
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001// 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.
Lei Zhanga6d9f0e2015-06-13 00:48:38 -07004
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07005// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
Tom Sepez37458412015-10-06 11:33:46 -07007#include "PublicMethods.h"
8
9#include "../../include/fsdk_mgr.h" // For CPDFDoc_Environment.
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070010#include "../../include/javascript/IJavaScript.h"
Tom Sepez37458412015-10-06 11:33:46 -070011#include "Field.h"
12#include "JS_Context.h"
13#include "JS_Define.h"
14#include "JS_EventHandler.h"
15#include "JS_Object.h"
16#include "JS_Runtime.h"
17#include "JS_Value.h"
18#include "color.h"
19#include "resource.h"
20#include "util.h"
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070021
Nico Weber9d8ec5a2015-08-04 13:00:21 -070022static v8::Isolate* GetIsolate(IFXJS_Context* cc) {
23 CJS_Context* pContext = (CJS_Context*)cc;
24 ASSERT(pContext != NULL);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070025
Nico Weber9d8ec5a2015-08-04 13:00:21 -070026 CJS_Runtime* pRuntime = pContext->GetJSRuntime();
27 ASSERT(pRuntime != NULL);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070028
Nico Weber9d8ec5a2015-08-04 13:00:21 -070029 return pRuntime->GetIsolate();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070030}
31
Nico Weber9d8ec5a2015-08-04 13:00:21 -070032/* -------------------------------- CJS_PublicMethods
33 * -------------------------------- */
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070034
Nico Weber9d8ec5a2015-08-04 13:00:21 -070035#define DOUBLE_CORRECT 0.000000000000001
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070036
37BEGIN_JS_STATIC_GLOBAL_FUN(CJS_PublicMethods)
Nico Weber9d8ec5a2015-08-04 13:00:21 -070038JS_STATIC_GLOBAL_FUN_ENTRY(AFNumber_Format)
39JS_STATIC_GLOBAL_FUN_ENTRY(AFNumber_Keystroke)
40JS_STATIC_GLOBAL_FUN_ENTRY(AFPercent_Format)
41JS_STATIC_GLOBAL_FUN_ENTRY(AFPercent_Keystroke)
42JS_STATIC_GLOBAL_FUN_ENTRY(AFDate_FormatEx)
43JS_STATIC_GLOBAL_FUN_ENTRY(AFDate_KeystrokeEx)
44JS_STATIC_GLOBAL_FUN_ENTRY(AFDate_Format)
45JS_STATIC_GLOBAL_FUN_ENTRY(AFDate_Keystroke)
46JS_STATIC_GLOBAL_FUN_ENTRY(AFTime_FormatEx)
47JS_STATIC_GLOBAL_FUN_ENTRY(AFTime_KeystrokeEx)
48JS_STATIC_GLOBAL_FUN_ENTRY(AFTime_Format)
49JS_STATIC_GLOBAL_FUN_ENTRY(AFTime_Keystroke)
50JS_STATIC_GLOBAL_FUN_ENTRY(AFSpecial_Format)
51JS_STATIC_GLOBAL_FUN_ENTRY(AFSpecial_Keystroke)
52JS_STATIC_GLOBAL_FUN_ENTRY(AFSpecial_KeystrokeEx)
53JS_STATIC_GLOBAL_FUN_ENTRY(AFSimple)
54JS_STATIC_GLOBAL_FUN_ENTRY(AFMakeNumber)
55JS_STATIC_GLOBAL_FUN_ENTRY(AFSimple_Calculate)
56JS_STATIC_GLOBAL_FUN_ENTRY(AFRange_Validate)
57JS_STATIC_GLOBAL_FUN_ENTRY(AFMergeChange)
58JS_STATIC_GLOBAL_FUN_ENTRY(AFParseDateEx)
59JS_STATIC_GLOBAL_FUN_ENTRY(AFExtractNums)
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070060END_JS_STATIC_GLOBAL_FUN()
61
62IMPLEMENT_JS_STATIC_GLOBAL_FUN(CJS_PublicMethods)
63
Nico Weber9d8ec5a2015-08-04 13:00:21 -070064static const FX_WCHAR* months[] = {L"Jan", L"Feb", L"Mar", L"Apr",
65 L"May", L"Jun", L"Jul", L"Aug",
66 L"Sep", L"Oct", L"Nov", L"Dec"};
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070067
Nico Weber9d8ec5a2015-08-04 13:00:21 -070068static const FX_WCHAR* const fullmonths[] = {
69 L"January", L"February", L"March", L"April",
70 L"May", L"June", L"July", L"August",
71 L"September", L"October", L"November", L"December"};
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070072
Nico Weber9d8ec5a2015-08-04 13:00:21 -070073FX_BOOL CJS_PublicMethods::IsNumber(const FX_WCHAR* string) {
74 CFX_WideString sTrim = StrTrim(string);
75 const FX_WCHAR* pTrim = sTrim.c_str();
76 const FX_WCHAR* p = pTrim;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070077
Nico Weber9d8ec5a2015-08-04 13:00:21 -070078 FX_BOOL bDot = FALSE;
79 FX_BOOL bKXJS = FALSE;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070080
Nico Weber9d8ec5a2015-08-04 13:00:21 -070081 wchar_t c;
82 while ((c = *p)) {
83 if (c == '.' || c == ',') {
84 if (bDot)
85 return FALSE;
86 bDot = TRUE;
87 } else if (c == '-' || c == '+') {
88 if (p != pTrim)
89 return FALSE;
90 } else if (c == 'e' || c == 'E') {
91 if (bKXJS)
92 return FALSE;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070093
Nico Weber9d8ec5a2015-08-04 13:00:21 -070094 p++;
95 c = *p;
96 if (c == '+' || c == '-') {
97 bKXJS = TRUE;
98 } else {
99 return FALSE;
100 }
101 } else if (!IsDigit(c)) {
102 return FALSE;
103 }
104 p++;
105 }
106
107 return TRUE;
108}
109
110FX_BOOL CJS_PublicMethods::IsDigit(wchar_t ch) {
111 return (ch >= L'0' && ch <= L'9');
112}
113
114FX_BOOL CJS_PublicMethods::IsDigit(char ch) {
115 return (ch >= '0' && ch <= '9');
116}
117
118FX_BOOL CJS_PublicMethods::IsAlphabetic(wchar_t ch) {
119 return ((ch >= L'a' && ch <= L'z') || (ch >= L'A' && ch <= L'Z'));
120}
121
122FX_BOOL CJS_PublicMethods::IsAlphaNumeric(wchar_t ch) {
123 return (IsDigit(ch) || IsAlphabetic(ch));
124}
125
126FX_BOOL CJS_PublicMethods::maskSatisfied(wchar_t c_Change, wchar_t c_Mask) {
127 switch (c_Mask) {
128 case L'9':
129 return IsDigit(c_Change);
130 case L'A':
131 return IsAlphabetic(c_Change);
132 case L'O':
133 return IsAlphaNumeric(c_Change);
134 case L'X':
135 return TRUE;
136 default:
137 return (c_Change == c_Mask);
138 }
139}
140
141FX_BOOL CJS_PublicMethods::isReservedMaskChar(wchar_t ch) {
142 return ch == L'9' || ch == L'A' || ch == L'O' || ch == L'X';
143}
144
145double CJS_PublicMethods::AF_Simple(const FX_WCHAR* sFuction,
146 double dValue1,
147 double dValue2) {
148 if (FXSYS_wcsicmp(sFuction, L"AVG") == 0 ||
149 FXSYS_wcsicmp(sFuction, L"SUM") == 0) {
150 return dValue1 + dValue2;
151 }
152 if (FXSYS_wcsicmp(sFuction, L"PRD") == 0) {
153 return dValue1 * dValue2;
154 }
155 if (FXSYS_wcsicmp(sFuction, L"MIN") == 0) {
156 return FX_MIN(dValue1, dValue2);
157 }
158 if (FXSYS_wcsicmp(sFuction, L"MAX") == 0) {
159 return FX_MAX(dValue1, dValue2);
160 }
161 return dValue1;
162}
163
164CFX_WideString CJS_PublicMethods::StrLTrim(const FX_WCHAR* pStr) {
165 while (*pStr && *pStr == L' ')
166 pStr++;
167
168 return pStr;
169}
170
171CFX_WideString CJS_PublicMethods::StrRTrim(const FX_WCHAR* pStr) {
172 const FX_WCHAR* p = pStr;
173 while (*p)
174 p++;
175 while (p > pStr && *(p - 1) == L' ')
176 p--;
177
178 return CFX_WideString(pStr, p - pStr);
179}
180
181CFX_WideString CJS_PublicMethods::StrTrim(const FX_WCHAR* pStr) {
182 return StrRTrim(StrLTrim(pStr).c_str());
183}
184
185CFX_ByteString CJS_PublicMethods::StrLTrim(const FX_CHAR* pStr) {
186 while (*pStr && *pStr == ' ')
187 pStr++;
188
189 return pStr;
190}
191
192CFX_ByteString CJS_PublicMethods::StrRTrim(const FX_CHAR* pStr) {
193 const FX_CHAR* p = pStr;
194 while (*p)
195 p++;
196 while (p > pStr && *(p - 1) == L' ')
197 p--;
198
199 return CFX_ByteString(pStr, p - pStr);
200}
201
202CFX_ByteString CJS_PublicMethods::StrTrim(const FX_CHAR* pStr) {
203 return StrRTrim(StrLTrim(pStr));
204}
205
206double CJS_PublicMethods::ParseNumber(const FX_WCHAR* swSource,
207 FX_BOOL& bAllDigits,
208 FX_BOOL& bDot,
209 FX_BOOL& bSign,
210 FX_BOOL& bKXJS) {
211 bDot = FALSE;
212 bSign = FALSE;
213 bKXJS = FALSE;
214
215 FX_BOOL bDigitExist = FALSE;
216
217 const FX_WCHAR* p = swSource;
218 wchar_t c;
219
220 const FX_WCHAR* pStart = NULL;
221 const FX_WCHAR* pEnd = NULL;
222
223 while ((c = *p)) {
224 if (!pStart && c != L' ') {
225 pStart = p;
226 }
227
228 pEnd = p;
229 p++;
230 }
231
232 if (!pStart) {
233 bAllDigits = FALSE;
234 return 0;
235 }
236
237 while (pEnd != pStart) {
238 if (*pEnd == L' ')
239 pEnd--;
240 else
241 break;
242 }
243
244 double dRet = 0;
245 p = pStart;
246 bAllDigits = TRUE;
247 CFX_WideString swDigits;
248
249 while (p <= pEnd) {
250 c = *p;
251
252 if (IsDigit(c)) {
253 swDigits += c;
254 bDigitExist = TRUE;
255 } else {
256 switch (c) {
257 case L' ':
258 bAllDigits = FALSE;
259 break;
260 case L'.':
261 case L',':
262 if (!bDot) {
263 if (bDigitExist) {
264 swDigits += L'.';
265 } else {
266 swDigits += L'0';
267 swDigits += L'.';
268 bDigitExist = TRUE;
269 }
270
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700271 bDot = TRUE;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700272 break;
273 }
274 case 'e':
275 case 'E':
276 if (!bKXJS) {
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700277 p++;
278 c = *p;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700279 if (c == '+' || c == '-') {
280 bKXJS = TRUE;
281 swDigits += 'e';
282 swDigits += c;
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700283 }
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700284 break;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700285 }
286 case L'-':
287 if (!bDigitExist && !bSign) {
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700288 swDigits += c;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700289 bSign = TRUE;
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700290 break;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700291 }
292 default:
293 bAllDigits = FALSE;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700294
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700295 if (p != pStart && !bDot && bDigitExist) {
296 swDigits += L'.';
297 bDot = TRUE;
298 } else {
299 bDot = FALSE;
300 bDigitExist = FALSE;
301 swDigits = L"";
302 }
303 break;
304 }
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700305 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700306
307 p++;
308 }
309
310 if (swDigits.GetLength() > 0 && swDigits.GetLength() < 17) {
311 CFX_ByteString sDigits = swDigits.UTF8Encode();
312
313 if (bKXJS) {
314 dRet = atof(sDigits);
315 } else {
316 if (bDot) {
317 char* pStopString;
318 dRet = ::strtod(sDigits, &pStopString);
319 } else {
320 dRet = atol(sDigits);
321 }
322 }
323 }
324
325 return dRet;
326}
327
328double CJS_PublicMethods::ParseStringToNumber(const FX_WCHAR* swSource) {
329 FX_BOOL bAllDigits = FALSE;
330 FX_BOOL bDot = FALSE;
331 FX_BOOL bSign = FALSE;
332 FX_BOOL bKXJS = FALSE;
333
334 return ParseNumber(swSource, bAllDigits, bDot, bSign, bKXJS);
335}
336
337FX_BOOL CJS_PublicMethods::ConvertStringToNumber(const FX_WCHAR* swSource,
338 double& dRet,
339 FX_BOOL& bDot) {
340 FX_BOOL bAllDigits = FALSE;
341 FX_BOOL bSign = FALSE;
342 FX_BOOL bKXJS = FALSE;
343
344 dRet = ParseNumber(swSource, bAllDigits, bDot, bSign, bKXJS);
345
346 return bAllDigits;
347}
348
349CJS_Array CJS_PublicMethods::AF_MakeArrayFromList(v8::Isolate* isolate,
350 CJS_Value val) {
351 CJS_Array StrArray(isolate);
352 if (val.IsArrayObject()) {
353 val.ConvertToArray(StrArray);
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700354 return StrArray;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700355 }
356 CFX_WideString wsStr = val.ToCFXWideString();
357 CFX_ByteString t = CFX_ByteString::FromUnicode(wsStr);
358 const char* p = (const char*)t;
359
360 int ch = ',';
361 int nIndex = 0;
362
363 while (*p) {
364 const char* pTemp = strchr(p, ch);
365 if (pTemp == NULL) {
366 StrArray.SetElement(nIndex, CJS_Value(isolate, StrTrim(p).c_str()));
367 break;
368 } else {
369 char* pSub = new char[pTemp - p + 1];
370 strncpy(pSub, p, pTemp - p);
371 *(pSub + (pTemp - p)) = '\0';
372
373 StrArray.SetElement(nIndex, CJS_Value(isolate, StrTrim(pSub).c_str()));
374 delete[] pSub;
375
376 nIndex++;
377 p = ++pTemp;
378 }
379 }
380 return StrArray;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700381}
382
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700383int CJS_PublicMethods::ParseStringInteger(const CFX_WideString& string,
384 int nStart,
385 int& nSkip,
386 int nMaxStep) {
387 int nRet = 0;
388 nSkip = 0;
389 for (int i = nStart, sz = string.GetLength(); i < sz; i++) {
390 if (i - nStart > 10)
391 break;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700392
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700393 FX_WCHAR c = string.GetAt(i);
394 if (IsDigit((wchar_t)c)) {
395 nRet = nRet * 10 + (c - '0');
396 nSkip = i - nStart + 1;
397 if (nSkip >= nMaxStep)
398 break;
399 } else
400 break;
401 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700402
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700403 return nRet;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700404}
405
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700406CFX_WideString CJS_PublicMethods::ParseStringString(
407 const CFX_WideString& string,
408 int nStart,
409 int& nSkip) {
410 CFX_WideString swRet;
411 nSkip = 0;
412 for (int i = nStart, sz = string.GetLength(); i < sz; i++) {
413 FX_WCHAR c = string.GetAt(i);
414 if ((c >= L'a' && c <= L'z') || (c >= L'A' && c <= L'Z')) {
415 swRet += c;
416 nSkip = i - nStart + 1;
417 } else
418 break;
419 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700420
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700421 return swRet;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700422}
423
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700424double CJS_PublicMethods::ParseNormalDate(const CFX_WideString& value,
425 FX_BOOL& bWrongFormat) {
426 double dt = JS_GetDateTime();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700427
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700428 int nYear = JS_GetYearFromTime(dt);
429 int nMonth = JS_GetMonthFromTime(dt) + 1;
430 int nDay = JS_GetDayFromTime(dt);
431 int nHour = JS_GetHourFromTime(dt);
432 int nMin = JS_GetMinFromTime(dt);
433 int nSec = JS_GetSecFromTime(dt);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700434
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700435 int number[3];
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700436
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700437 int nSkip = 0;
438 int nLen = value.GetLength();
439 int nIndex = 0;
440 int i = 0;
441 while (i < nLen) {
442 if (nIndex > 2)
443 break;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700444
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700445 FX_WCHAR c = value.GetAt(i);
446 if (IsDigit((wchar_t)c)) {
447 number[nIndex++] = ParseStringInteger(value, i, nSkip, 4);
448 i += nSkip;
449 } else {
450 i++;
451 }
452 }
453
454 if (nIndex == 2) {
455 // case2: month/day
456 // case3: day/month
457 if ((number[0] >= 1 && number[0] <= 12) &&
458 (number[1] >= 1 && number[1] <= 31)) {
459 nMonth = number[0];
460 nDay = number[1];
461 } else if ((number[0] >= 1 && number[0] <= 31) &&
462 (number[1] >= 1 && number[1] <= 12)) {
463 nDay = number[0];
464 nMonth = number[1];
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700465 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700466
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700467 bWrongFormat = FALSE;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700468 } else if (nIndex == 3) {
469 // case1: year/month/day
470 // case2: month/day/year
471 // case3: day/month/year
Tom Sepez5ffacd62014-07-18 14:42:12 -0700472
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700473 if (number[0] > 12 && (number[1] >= 1 && number[1] <= 12) &&
474 (number[2] >= 1 && number[2] <= 31)) {
475 nYear = number[0];
476 nMonth = number[1];
477 nDay = number[2];
478 } else if ((number[0] >= 1 && number[0] <= 12) &&
479 (number[1] >= 1 && number[1] <= 31) && number[2] > 31) {
480 nMonth = number[0];
481 nDay = number[1];
482 nYear = number[2];
483 } else if ((number[0] >= 1 && number[0] <= 31) &&
484 (number[1] >= 1 && number[1] <= 12) && number[2] > 31) {
485 nDay = number[0];
486 nMonth = number[1];
487 nYear = number[2];
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700488 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700489
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700490 bWrongFormat = FALSE;
491 } else {
492 bWrongFormat = TRUE;
493 return dt;
494 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700495
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700496 CFX_WideString swTemp;
497 swTemp.Format(L"%d/%d/%d %d:%d:%d", nMonth, nDay, nYear, nHour, nMin, nSec);
498 return JS_DateParse(swTemp.c_str());
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700499}
500
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700501double CJS_PublicMethods::MakeRegularDate(const CFX_WideString& value,
502 const CFX_WideString& format,
503 FX_BOOL& bWrongFormat) {
504 double dt = JS_GetDateTime();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700505
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700506 if (format.IsEmpty() || value.IsEmpty())
507 return dt;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700508
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700509 int nYear = JS_GetYearFromTime(dt);
510 int nMonth = JS_GetMonthFromTime(dt) + 1;
511 int nDay = JS_GetDayFromTime(dt);
512 int nHour = JS_GetHourFromTime(dt);
513 int nMin = JS_GetMinFromTime(dt);
514 int nSec = JS_GetSecFromTime(dt);
515
516 int nYearSub = 99; // nYear - 2000;
517
518 FX_BOOL bPm = FALSE;
519 FX_BOOL bExit = FALSE;
520 bWrongFormat = FALSE;
521
522 int i = 0;
523 int j = 0;
524
525 while (i < format.GetLength()) {
526 if (bExit)
527 break;
528
529 FX_WCHAR c = format.GetAt(i);
530 switch (c) {
531 case ':':
532 case '.':
533 case '-':
534 case '\\':
535 case '/':
536 i++;
537 j++;
538 break;
539
540 case 'y':
541 case 'm':
542 case 'd':
543 case 'H':
544 case 'h':
545 case 'M':
546 case 's':
547 case 't': {
548 int oldj = j;
549 int nSkip = 0;
550 int remaining = format.GetLength() - i - 1;
551
552 if (remaining == 0 || format.GetAt(i + 1) != c) {
553 switch (c) {
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700554 case 'y':
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700555 i++;
556 j++;
557 break;
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700558 case 'm':
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700559 nMonth = ParseStringInteger(value, j, nSkip, 2);
560 i++;
561 j += nSkip;
562 break;
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700563 case 'd':
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700564 nDay = ParseStringInteger(value, j, nSkip, 2);
565 i++;
566 j += nSkip;
567 break;
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700568 case 'H':
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700569 nHour = ParseStringInteger(value, j, nSkip, 2);
570 i++;
571 j += nSkip;
572 break;
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700573 case 'h':
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700574 nHour = ParseStringInteger(value, j, nSkip, 2);
575 i++;
576 j += nSkip;
577 break;
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700578 case 'M':
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700579 nMin = ParseStringInteger(value, j, nSkip, 2);
580 i++;
581 j += nSkip;
582 break;
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700583 case 's':
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700584 nSec = ParseStringInteger(value, j, nSkip, 2);
585 i++;
586 j += nSkip;
587 break;
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700588 case 't':
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700589 bPm = (j < value.GetLength() && value.GetAt(j) == 'p');
590 i++;
591 j++;
592 break;
593 }
594 } else if (remaining == 1 || format.GetAt(i + 2) != c) {
595 switch (c) {
596 case 'y':
597 nYear = ParseStringInteger(value, j, nSkip, 4);
598 i += 2;
599 j += nSkip;
600 break;
601 case 'm':
602 nMonth = ParseStringInteger(value, j, nSkip, 2);
603 i += 2;
604 j += nSkip;
605 break;
606 case 'd':
607 nDay = ParseStringInteger(value, j, nSkip, 2);
608 i += 2;
609 j += nSkip;
610 break;
611 case 'H':
612 nHour = ParseStringInteger(value, j, nSkip, 2);
613 i += 2;
614 j += nSkip;
615 break;
616 case 'h':
617 nHour = ParseStringInteger(value, j, nSkip, 2);
618 i += 2;
619 j += nSkip;
620 break;
621 case 'M':
622 nMin = ParseStringInteger(value, j, nSkip, 2);
623 i += 2;
624 j += nSkip;
625 break;
626 case 's':
627 nSec = ParseStringInteger(value, j, nSkip, 2);
628 i += 2;
629 j += nSkip;
630 break;
631 case 't':
632 bPm = (j + 1 < value.GetLength() && value.GetAt(j) == 'p' &&
633 value.GetAt(j + 1) == 'm');
634 i += 2;
635 j += 2;
636 break;
637 }
638 } else if (remaining == 2 || format.GetAt(i + 3) != c) {
639 switch (c) {
640 case 'm': {
641 CFX_WideString sMonth = ParseStringString(value, j, nSkip);
642 FX_BOOL bFind = FALSE;
643 for (int m = 0; m < 12; m++) {
644 if (sMonth.CompareNoCase(months[m]) == 0) {
645 nMonth = m + 1;
646 i += 3;
647 j += nSkip;
648 bFind = TRUE;
649 break;
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700650 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700651 }
652
653 if (!bFind) {
654 nMonth = ParseStringInteger(value, j, nSkip, 3);
655 i += 3;
656 j += nSkip;
657 }
658 } break;
659 case 'y':
660 break;
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700661 default:
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700662 i += 3;
663 j += 3;
664 break;
665 }
666 } else if (remaining == 3 || format.GetAt(i + 4) != c) {
667 switch (c) {
668 case 'y':
669 nYear = ParseStringInteger(value, j, nSkip, 4);
670 j += nSkip;
671 i += 4;
672 break;
673 case 'm': {
674 FX_BOOL bFind = FALSE;
675
676 CFX_WideString sMonth = ParseStringString(value, j, nSkip);
677 sMonth.MakeLower();
678
679 for (int m = 0; m < 12; m++) {
680 CFX_WideString sFullMonths = fullmonths[m];
681 sFullMonths.MakeLower();
682
683 if (sFullMonths.Find(sMonth.c_str(), 0) != -1) {
684 nMonth = m + 1;
685 i += 4;
686 j += nSkip;
687 bFind = TRUE;
688 break;
689 }
690 }
691
692 if (!bFind) {
693 nMonth = ParseStringInteger(value, j, nSkip, 4);
694 i += 4;
695 j += nSkip;
696 }
697 } break;
698 default:
699 i += 4;
700 j += 4;
701 break;
702 }
703 } else {
704 if (j >= value.GetLength() || format.GetAt(i) != value.GetAt(j)) {
705 bWrongFormat = TRUE;
706 bExit = TRUE;
707 }
708 i++;
709 j++;
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700710 }
Tom Sepez85386422014-07-23 10:28:37 -0700711
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700712 if (oldj == j) {
713 bWrongFormat = TRUE;
714 bExit = TRUE;
715 }
716 }
717
718 break;
719 default:
720 if (value.GetLength() <= j) {
721 bExit = TRUE;
722 } else if (format.GetAt(i) != value.GetAt(j)) {
723 bWrongFormat = TRUE;
724 bExit = TRUE;
725 }
726
727 i++;
728 j++;
729 break;
730 }
731 }
732
733 if (bPm)
734 nHour += 12;
735
736 if (nYear >= 0 && nYear <= nYearSub)
737 nYear += 2000;
738
739 if (nMonth < 1 || nMonth > 12)
740 bWrongFormat = TRUE;
741
742 if (nDay < 1 || nDay > 31)
743 bWrongFormat = TRUE;
744
745 if (nHour < 0 || nHour > 24)
746 bWrongFormat = TRUE;
747
748 if (nMin < 0 || nMin > 60)
749 bWrongFormat = TRUE;
750
751 if (nSec < 0 || nSec > 60)
752 bWrongFormat = TRUE;
753
754 double dRet = 0;
755
756 if (bWrongFormat) {
757 dRet = ParseNormalDate(value, bWrongFormat);
758 } else {
759 dRet = JS_MakeDate(JS_MakeDay(nYear, nMonth - 1, nDay),
760 JS_MakeTime(nHour, nMin, nSec, 0));
761
762 if (JS_PortIsNan(dRet)) {
763 dRet = JS_DateParse(value.c_str());
764 }
765 }
766
767 if (JS_PortIsNan(dRet)) {
768 dRet = ParseNormalDate(value, bWrongFormat);
769 }
770
771 return dRet;
772}
773
774CFX_WideString CJS_PublicMethods::MakeFormatDate(double dDate,
775 const CFX_WideString& format) {
776 CFX_WideString sRet = L"", sPart = L"";
777
778 int nYear = JS_GetYearFromTime(dDate);
779 int nMonth = JS_GetMonthFromTime(dDate) + 1;
780 int nDay = JS_GetDayFromTime(dDate);
781 int nHour = JS_GetHourFromTime(dDate);
782 int nMin = JS_GetMinFromTime(dDate);
783 int nSec = JS_GetSecFromTime(dDate);
784
785 int i = 0;
786 while (i < format.GetLength()) {
787 FX_WCHAR c = format.GetAt(i);
788 int remaining = format.GetLength() - i - 1;
789 sPart = L"";
790 switch (c) {
791 case 'y':
792 case 'm':
793 case 'd':
794 case 'H':
795 case 'h':
796 case 'M':
797 case 's':
798 case 't':
799 if (remaining == 0 || format.GetAt(i + 1) != c) {
800 switch (c) {
801 case 'y':
802 sPart += c;
803 break;
804 case 'm':
805 sPart.Format(L"%d", nMonth);
806 break;
807 case 'd':
808 sPart.Format(L"%d", nDay);
809 break;
810 case 'H':
811 sPart.Format(L"%d", nHour);
812 break;
813 case 'h':
814 sPart.Format(L"%d", nHour > 12 ? nHour - 12 : nHour);
815 break;
816 case 'M':
817 sPart.Format(L"%d", nMin);
818 break;
819 case 's':
820 sPart.Format(L"%d", nSec);
821 break;
822 case 't':
823 sPart += nHour > 12 ? 'p' : 'a';
824 break;
825 }
826 i++;
827 } else if (remaining == 1 || format.GetAt(i + 2) != c) {
828 switch (c) {
829 case 'y':
830 sPart.Format(L"%02d", nYear - (nYear / 100) * 100);
831 break;
832 case 'm':
833 sPart.Format(L"%02d", nMonth);
834 break;
835 case 'd':
836 sPart.Format(L"%02d", nDay);
837 break;
838 case 'H':
839 sPart.Format(L"%02d", nHour);
840 break;
841 case 'h':
842 sPart.Format(L"%02d", nHour > 12 ? nHour - 12 : nHour);
843 break;
844 case 'M':
845 sPart.Format(L"%02d", nMin);
846 break;
847 case 's':
848 sPart.Format(L"%02d", nSec);
849 break;
850 case 't':
851 sPart = nHour > 12 ? L"pm" : L"am";
852 break;
853 }
854 i += 2;
855 } else if (remaining == 2 || format.GetAt(i + 3) != c) {
856 switch (c) {
857 case 'm':
858 i += 3;
859 if (nMonth > 0 && nMonth <= 12)
860 sPart += months[nMonth - 1];
861 break;
862 default:
863 i += 3;
864 sPart += c;
865 sPart += c;
866 sPart += c;
867 break;
868 }
869 } else if (remaining == 3 || format.GetAt(i + 4) != c) {
870 switch (c) {
871 case 'y':
872 sPart.Format(L"%04d", nYear);
873 i += 4;
874 break;
875 case 'm':
876 i += 4;
877 if (nMonth > 0 && nMonth <= 12)
878 sPart += fullmonths[nMonth - 1];
879 break;
880 default:
881 i += 4;
882 sPart += c;
883 sPart += c;
884 sPart += c;
885 sPart += c;
886 break;
887 }
888 } else {
889 i++;
890 sPart += c;
891 }
892 break;
893 default:
894 i++;
895 sPart += c;
896 break;
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700897 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700898
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700899 sRet += sPart;
900 }
901
902 return sRet;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700903}
904
905/* -------------------------------------------------------------------------- */
906
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700907// function AFNumber_Format(nDec, sepStyle, negStyle, currStyle, strCurrency,
908// bCurrencyPrepend)
909FX_BOOL CJS_PublicMethods::AFNumber_Format(IFXJS_Context* cc,
910 const CJS_Parameters& params,
911 CJS_Value& vRet,
912 CFX_WideString& sError) {
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700913#if _FX_OS_ != _FX_ANDROID_
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700914 v8::Isolate* isolate = ::GetIsolate(cc);
915 CJS_Context* pContext = (CJS_Context*)cc;
916 ASSERT(pContext != NULL);
917 CJS_EventHandler* pEvent = pContext->GetEventHandler();
918 ASSERT(pEvent != NULL);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700919
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700920 if (params.size() != 6) {
921 sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
922 return FALSE;
923 }
924 if (!pEvent->m_pValue)
925 return FALSE;
926 CFX_WideString& Value = pEvent->Value();
927 CFX_ByteString strValue = StrTrim(CFX_ByteString::FromUnicode(Value));
Lei Zhanga6d9f0e2015-06-13 00:48:38 -0700928
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700929 if (strValue.IsEmpty())
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700930 return TRUE;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700931
932 int iDec = params[0].ToInt();
933 int iSepStyle = params[1].ToInt();
934 int iNegStyle = params[2].ToInt();
935 // params[3] is iCurrStyle, it's not used.
936 std::wstring wstrCurrency(params[4].ToCFXWideString().c_str());
937 FX_BOOL bCurrencyPrepend = params[5].ToBool();
938
939 if (iDec < 0)
940 iDec = -iDec;
941
942 if (iSepStyle < 0 || iSepStyle > 3)
943 iSepStyle = 0;
944
945 if (iNegStyle < 0 || iNegStyle > 3)
946 iNegStyle = 0;
947
948 //////////////////////////////////////////////////////
949 // for processing decimal places
950 strValue.Replace(",", ".");
951 double dValue = atof(strValue);
952 if (iDec > 0)
953 dValue += DOUBLE_CORRECT; //
954
955 int iDec2;
956 int iNegative = 0;
957
958 strValue = fcvt(dValue, iDec, &iDec2, &iNegative);
959 if (strValue.IsEmpty()) {
960 dValue = 0;
961 strValue = fcvt(dValue, iDec, &iDec2, &iNegative);
962 if (strValue.IsEmpty()) {
963 strValue = "0";
964 iDec2 = 1;
965 }
966 }
967
968 if (iDec2 < 0) {
969 for (int iNum = 0; iNum < abs(iDec2); iNum++) {
970 strValue = "0" + strValue;
971 }
972 iDec2 = 0;
973 }
974 int iMax = strValue.GetLength();
975 if (iDec2 > iMax) {
976 for (int iNum = 0; iNum <= iDec2 - iMax; iNum++) {
977 strValue += "0";
978 }
979 iMax = iDec2 + 1;
980 }
981 ///////////////////////////////////////////////////////
982 // for processing seperator style
983 if (iDec2 < iMax) {
984 if (iSepStyle == 0 || iSepStyle == 1) {
985 strValue.Insert(iDec2, '.');
986 iMax++;
987 } else if (iSepStyle == 2 || iSepStyle == 3) {
988 strValue.Insert(iDec2, ',');
989 iMax++;
990 }
991
992 if (iDec2 == 0)
993 strValue.Insert(iDec2, '0');
994 }
995 if (iSepStyle == 0 || iSepStyle == 2) {
996 char cSeperator;
997 if (iSepStyle == 0)
998 cSeperator = ',';
999 else
1000 cSeperator = '.';
1001
1002 int iDecPositive, iDecNegative;
1003 iDecPositive = iDec2;
1004 iDecNegative = iDec2;
1005
1006 for (iDecPositive = iDec2 - 3; iDecPositive > 0; iDecPositive -= 3) {
1007 strValue.Insert(iDecPositive, cSeperator);
1008 iMax++;
1009 }
1010 }
1011
1012 //////////////////////////////////////////////////////////////////////
1013 // for processing currency string
1014
1015 Value = CFX_WideString::FromLocal(strValue);
1016 std::wstring strValue2 = Value.c_str();
1017
1018 if (bCurrencyPrepend)
1019 strValue2 = wstrCurrency + strValue2;
1020 else
1021 strValue2 = strValue2 + wstrCurrency;
1022
1023 /////////////////////////////////////////////////////////////////////////
1024 // for processing negative style
1025 if (iNegative) {
1026 if (iNegStyle == 0) {
1027 strValue2.insert(0, L"-");
1028 }
1029 if (iNegStyle == 2 || iNegStyle == 3) {
1030 strValue2.insert(0, L"(");
1031 strValue2.insert(strValue2.length(), L")");
1032 }
1033 if (iNegStyle == 1 || iNegStyle == 3) {
1034 if (Field* fTarget = pEvent->Target_Field()) {
1035 CJS_Array arColor(isolate);
1036 CJS_Value vColElm(isolate);
1037 vColElm = L"RGB";
1038 arColor.SetElement(0, vColElm);
1039 vColElm = 1;
1040 arColor.SetElement(1, vColElm);
1041 vColElm = 0;
1042 arColor.SetElement(2, vColElm);
1043
1044 arColor.SetElement(3, vColElm);
1045
1046 CJS_PropValue vProp(isolate);
1047 vProp.StartGetting();
1048 vProp << arColor;
1049 vProp.StartSetting();
1050 fTarget->textColor(cc, vProp, sError); // red
1051 }
1052 }
1053 } else {
1054 if (iNegStyle == 1 || iNegStyle == 3) {
1055 if (Field* fTarget = pEvent->Target_Field()) {
1056 CJS_Array arColor(isolate);
1057 CJS_Value vColElm(isolate);
1058 vColElm = L"RGB";
1059 arColor.SetElement(0, vColElm);
1060 vColElm = 0;
1061 arColor.SetElement(1, vColElm);
1062 arColor.SetElement(2, vColElm);
1063 arColor.SetElement(3, vColElm);
1064
1065 CJS_PropValue vProp(isolate);
1066 vProp.StartGetting();
1067 fTarget->textColor(cc, vProp, sError);
1068
1069 CJS_Array aProp(isolate);
1070 vProp.ConvertToArray(aProp);
1071
1072 CPWL_Color crProp;
1073 CPWL_Color crColor;
1074 color::ConvertArrayToPWLColor(aProp, crProp);
1075 color::ConvertArrayToPWLColor(arColor, crColor);
1076
1077 if (crColor != crProp) {
1078 CJS_PropValue vProp2(isolate);
1079 vProp2.StartGetting();
1080 vProp2 << arColor;
1081 vProp2.StartSetting();
1082 fTarget->textColor(cc, vProp2, sError);
1083 }
1084 }
1085 }
1086 }
1087 Value = strValue2.c_str();
1088#endif
1089 return TRUE;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001090}
1091
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001092// function AFNumber_Keystroke(nDec, sepStyle, negStyle, currStyle, strCurrency,
1093// bCurrencyPrepend)
1094FX_BOOL CJS_PublicMethods::AFNumber_Keystroke(IFXJS_Context* cc,
1095 const CJS_Parameters& params,
1096 CJS_Value& vRet,
1097 CFX_WideString& sError) {
1098 CJS_Context* pContext = (CJS_Context*)cc;
1099 ASSERT(pContext != NULL);
1100 CJS_EventHandler* pEvent = pContext->GetEventHandler();
1101 ASSERT(pEvent != NULL);
Lei Zhanga6d9f0e2015-06-13 00:48:38 -07001102
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001103 if (params.size() < 2)
1104 return FALSE;
1105 int iSepStyle = params[1].ToInt();
Lei Zhanga6d9f0e2015-06-13 00:48:38 -07001106
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001107 if (iSepStyle < 0 || iSepStyle > 3)
1108 iSepStyle = 0;
1109 if (!pEvent->m_pValue)
1110 return FALSE;
1111 CFX_WideString& val = pEvent->Value();
1112 CFX_WideString& w_strChange = pEvent->Change();
1113 CFX_WideString w_strValue = val;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001114
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001115 if (pEvent->WillCommit()) {
1116 CFX_WideString wstrChange = w_strChange;
1117 CFX_WideString wstrValue = StrLTrim(w_strValue.c_str());
1118 if (wstrValue.IsEmpty())
1119 return TRUE;
Lei Zhanga6d9f0e2015-06-13 00:48:38 -07001120
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001121 CFX_WideString swTemp = wstrValue;
1122 swTemp.Replace(L",", L".");
1123 if (!IsNumber(swTemp.c_str())) {
1124 pEvent->Rc() = FALSE;
1125 sError = JSGetStringFromID(pContext, IDS_STRING_JSAFNUMBER_KEYSTROKE);
1126 Alert(pContext, sError.c_str());
1127 return TRUE;
Tom Sepez2f2ffec2015-07-23 14:42:09 -07001128 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001129 return TRUE; // it happens after the last keystroke and before validating,
1130 }
Tom Sepez4f7bc042015-04-27 12:06:58 -07001131
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001132 std::wstring w_strValue2 = w_strValue.c_str();
1133 std::wstring w_strChange2 = w_strChange.c_str();
1134 std::wstring w_strSelected;
1135 if (-1 != pEvent->SelStart())
1136 w_strSelected = w_strValue2.substr(pEvent->SelStart(),
1137 (pEvent->SelEnd() - pEvent->SelStart()));
Lei Zhangb9c31972015-08-11 14:09:35 -07001138 bool bHasSign = (w_strValue2.find('-') != std::wstring::npos) &&
1139 (w_strSelected.find('-') == std::wstring::npos);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001140 if (bHasSign) {
1141 // can't insert "change" in front to sign postion.
1142 if (pEvent->SelStart() == 0) {
1143 FX_BOOL& bRc = pEvent->Rc();
1144 bRc = FALSE;
1145 return TRUE;
Tom Sepez2f2ffec2015-07-23 14:42:09 -07001146 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001147 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001148
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001149 char cSep = L'.';
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001150
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001151 switch (iSepStyle) {
Tom Sepez2f2ffec2015-07-23 14:42:09 -07001152 case 0:
1153 case 1:
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001154 cSep = L'.';
1155 break;
Tom Sepez2f2ffec2015-07-23 14:42:09 -07001156 case 2:
1157 case 3:
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001158 cSep = L',';
1159 break;
1160 }
Lei Zhanga6d9f0e2015-06-13 00:48:38 -07001161
Lei Zhangb9c31972015-08-11 14:09:35 -07001162 bool bHasSep = (w_strValue2.find(cSep) != std::wstring::npos);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001163 for (std::wstring::iterator it = w_strChange2.begin();
1164 it != w_strChange2.end(); it++) {
1165 if (*it == cSep) {
1166 if (bHasSep) {
1167 FX_BOOL& bRc = pEvent->Rc();
1168 bRc = FALSE;
Tom Sepez2f2ffec2015-07-23 14:42:09 -07001169 return TRUE;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001170 }
1171 bHasSep = TRUE;
1172 continue;
1173 }
1174 if (*it == L'-') {
1175 if (bHasSign) {
1176 FX_BOOL& bRc = pEvent->Rc();
1177 bRc = FALSE;
1178 return TRUE;
1179 }
1180 if (it != w_strChange2.begin()) // sign's position is not correct
1181 {
1182 FX_BOOL& bRc = pEvent->Rc();
1183 bRc = FALSE;
1184 return TRUE;
1185 }
1186 if (pEvent->SelStart() != 0) {
1187 FX_BOOL& bRc = pEvent->Rc();
1188 bRc = FALSE;
1189 return TRUE;
1190 }
1191 bHasSign = TRUE;
1192 continue;
1193 }
1194
1195 if (!IsDigit(*it)) {
1196 FX_BOOL& bRc = pEvent->Rc();
1197 bRc = FALSE;
1198 return TRUE;
1199 }
1200 }
1201
1202 std::wstring w_prefix = w_strValue2.substr(0, pEvent->SelStart());
1203 std::wstring w_postfix;
1204 if (pEvent->SelEnd() < (int)w_strValue2.length())
1205 w_postfix = w_strValue2.substr(pEvent->SelEnd());
1206 w_strValue2 = w_prefix + w_strChange2 + w_postfix;
1207 w_strValue = w_strValue2.c_str();
1208 val = w_strValue;
1209 return TRUE;
1210}
1211
1212// function AFPercent_Format(nDec, sepStyle)
1213FX_BOOL CJS_PublicMethods::AFPercent_Format(IFXJS_Context* cc,
1214 const CJS_Parameters& params,
1215 CJS_Value& vRet,
1216 CFX_WideString& sError) {
1217#if _FX_OS_ != _FX_ANDROID_
1218 CJS_Context* pContext = (CJS_Context*)cc;
1219 ASSERT(pContext != NULL);
1220 CJS_EventHandler* pEvent = pContext->GetEventHandler();
1221 ASSERT(pEvent != NULL);
1222
1223 if (params.size() != 2) {
1224 sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
1225 return FALSE;
1226 }
1227 if (!pEvent->m_pValue)
1228 return FALSE;
1229
1230 CFX_WideString& Value = pEvent->Value();
1231 CFX_ByteString strValue = StrTrim(CFX_ByteString::FromUnicode(Value));
1232 if (strValue.IsEmpty())
1233 return TRUE;
1234
1235 int iDec = params[0].ToInt();
1236 if (iDec < 0)
1237 iDec = -iDec;
1238
1239 int iSepStyle = params[1].ToInt();
1240 if (iSepStyle < 0 || iSepStyle > 3)
1241 iSepStyle = 0;
1242
1243 //////////////////////////////////////////////////////
1244 // for processing decimal places
1245 double dValue = atof(strValue);
1246 dValue *= 100;
1247 if (iDec > 0)
1248 dValue += DOUBLE_CORRECT; //УÕý
1249
1250 int iDec2;
1251 int iNegative = 0;
1252 strValue = fcvt(dValue, iDec, &iDec2, &iNegative);
1253 if (strValue.IsEmpty()) {
1254 dValue = 0;
1255 strValue = fcvt(dValue, iDec, &iDec2, &iNegative);
1256 }
1257
1258 if (iDec2 < 0) {
1259 for (int iNum = 0; iNum < abs(iDec2); iNum++) {
1260 strValue = "0" + strValue;
1261 }
1262 iDec2 = 0;
1263 }
1264 int iMax = strValue.GetLength();
1265 if (iDec2 > iMax) {
1266 for (int iNum = 0; iNum <= iDec2 - iMax; iNum++) {
1267 strValue += "0";
1268 }
1269 iMax = iDec2 + 1;
1270 }
1271 ///////////////////////////////////////////////////////
1272 // for processing seperator style
1273 if (iDec2 < iMax) {
1274 if (iSepStyle == 0 || iSepStyle == 1) {
1275 strValue.Insert(iDec2, '.');
1276 iMax++;
1277 } else if (iSepStyle == 2 || iSepStyle == 3) {
1278 strValue.Insert(iDec2, ',');
1279 iMax++;
1280 }
1281
1282 if (iDec2 == 0)
1283 strValue.Insert(iDec2, '0');
1284 }
1285 if (iSepStyle == 0 || iSepStyle == 2) {
1286 char cSeperator;
1287 if (iSepStyle == 0)
1288 cSeperator = ',';
1289 else
1290 cSeperator = '.';
1291
1292 int iDecPositive, iDecNegative;
1293 iDecPositive = iDec2;
1294 iDecNegative = iDec2;
1295
1296 for (iDecPositive = iDec2 - 3; iDecPositive > 0; iDecPositive -= 3) {
1297 strValue.Insert(iDecPositive, cSeperator);
1298 iMax++;
1299 }
1300 }
1301 ////////////////////////////////////////////////////////////////////
1302 // negative mark
1303 if (iNegative)
1304 strValue = "-" + strValue;
1305 strValue += "%";
1306 Value = CFX_WideString::FromLocal(strValue);
1307#endif
1308 return TRUE;
1309}
1310// AFPercent_Keystroke(nDec, sepStyle)
1311FX_BOOL CJS_PublicMethods::AFPercent_Keystroke(IFXJS_Context* cc,
1312 const CJS_Parameters& params,
1313 CJS_Value& vRet,
1314 CFX_WideString& sError) {
1315 return AFNumber_Keystroke(cc, params, vRet, sError);
1316}
1317
1318// function AFDate_FormatEx(cFormat)
1319FX_BOOL CJS_PublicMethods::AFDate_FormatEx(IFXJS_Context* cc,
1320 const CJS_Parameters& params,
1321 CJS_Value& vRet,
1322 CFX_WideString& sError) {
1323 CJS_Context* pContext = (CJS_Context*)cc;
1324 ASSERT(pContext != NULL);
1325 CJS_EventHandler* pEvent = pContext->GetEventHandler();
1326 ASSERT(pEvent != NULL);
1327
1328 if (params.size() != 1) {
1329 sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
1330 return FALSE;
1331 }
1332 if (!pEvent->m_pValue)
1333 return FALSE;
1334
1335 CFX_WideString& val = pEvent->Value();
1336 CFX_WideString strValue = val;
1337 if (strValue.IsEmpty())
1338 return TRUE;
1339
1340 CFX_WideString sFormat = params[0].ToCFXWideString();
1341 FX_BOOL bWrongFormat = FALSE;
1342 double dDate = 0.0f;
1343
1344 if (strValue.Find(L"GMT") != -1) {
1345 // for GMT format time
1346 // such as "Tue Aug 11 14:24:16 GMT+08002009"
1347 dDate = MakeInterDate(strValue);
1348 } else {
1349 dDate = MakeRegularDate(strValue, sFormat, bWrongFormat);
1350 }
1351
1352 if (JS_PortIsNan(dDate)) {
1353 CFX_WideString swMsg;
1354 swMsg.Format(JSGetStringFromID(pContext, IDS_STRING_JSPARSEDATE).c_str(),
1355 sFormat.c_str());
1356 Alert(pContext, swMsg.c_str());
1357 return FALSE;
1358 }
1359
1360 val = MakeFormatDate(dDate, sFormat);
1361 return TRUE;
1362}
1363
1364double CJS_PublicMethods::MakeInterDate(CFX_WideString strValue) {
1365 int nHour;
1366 int nMin;
1367 int nSec;
1368 int nYear;
1369 int nMonth;
1370 int nDay;
1371
1372 CFX_WideStringArray wsArray;
1373 CFX_WideString sMonth = L"";
1374 CFX_WideString sTemp = L"";
1375 int nSize = strValue.GetLength();
1376
1377 for (int i = 0; i < nSize; i++) {
1378 FX_WCHAR c = strValue.GetAt(i);
1379 if (c == L' ' || c == L':') {
1380 wsArray.Add(sTemp);
1381 sTemp = L"";
1382 continue;
1383 }
1384
1385 sTemp += c;
1386 }
1387
1388 wsArray.Add(sTemp);
1389 if (wsArray.GetSize() != 8)
1390 return 0;
1391
1392 sTemp = wsArray[1];
1393 if (sTemp.Compare(L"Jan") == 0)
1394 nMonth = 1;
1395 if (sTemp.Compare(L"Feb") == 0)
1396 nMonth = 2;
1397 if (sTemp.Compare(L"Mar") == 0)
1398 nMonth = 3;
1399 if (sTemp.Compare(L"Apr") == 0)
1400 nMonth = 4;
1401 if (sTemp.Compare(L"May") == 0)
1402 nMonth = 5;
1403 if (sTemp.Compare(L"Jun") == 0)
1404 nMonth = 6;
1405 if (sTemp.Compare(L"Jul") == 0)
1406 nMonth = 7;
1407 if (sTemp.Compare(L"Aug") == 0)
1408 nMonth = 8;
1409 if (sTemp.Compare(L"Sep") == 0)
1410 nMonth = 9;
1411 if (sTemp.Compare(L"Oct") == 0)
1412 nMonth = 10;
1413 if (sTemp.Compare(L"Nov") == 0)
1414 nMonth = 11;
1415 if (sTemp.Compare(L"Dec") == 0)
1416 nMonth = 12;
1417
1418 nDay = (int)ParseStringToNumber(wsArray[2].c_str());
1419 nHour = (int)ParseStringToNumber(wsArray[3].c_str());
1420 nMin = (int)ParseStringToNumber(wsArray[4].c_str());
1421 nSec = (int)ParseStringToNumber(wsArray[5].c_str());
1422 nYear = (int)ParseStringToNumber(wsArray[7].c_str());
1423
1424 double dRet = JS_MakeDate(JS_MakeDay(nYear, nMonth - 1, nDay),
1425 JS_MakeTime(nHour, nMin, nSec, 0));
1426
1427 if (JS_PortIsNan(dRet)) {
1428 dRet = JS_DateParse(strValue.c_str());
1429 }
1430
1431 return dRet;
1432}
1433
1434// AFDate_KeystrokeEx(cFormat)
1435FX_BOOL CJS_PublicMethods::AFDate_KeystrokeEx(IFXJS_Context* cc,
1436 const CJS_Parameters& params,
1437 CJS_Value& vRet,
1438 CFX_WideString& sError) {
1439 CJS_Context* pContext = (CJS_Context*)cc;
1440 ASSERT(pContext != NULL);
1441 CJS_EventHandler* pEvent = pContext->GetEventHandler();
1442 ASSERT(pEvent != NULL);
1443
1444 if (params.size() != 1) {
1445 sError = L"AFDate_KeystrokeEx's parameters' size r not correct";
1446 return FALSE;
1447 }
1448
1449 if (pEvent->WillCommit()) {
1450 if (!pEvent->m_pValue)
1451 return FALSE;
1452 CFX_WideString strValue = pEvent->Value();
1453 if (strValue.IsEmpty())
1454 return TRUE;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001455
Tom Sepez2f2ffec2015-07-23 14:42:09 -07001456 CFX_WideString sFormat = params[0].ToCFXWideString();
1457 FX_BOOL bWrongFormat = FALSE;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001458 double dRet = MakeRegularDate(strValue, sFormat, bWrongFormat);
1459 if (bWrongFormat || JS_PortIsNan(dRet)) {
1460 CFX_WideString swMsg;
1461 swMsg.Format(JSGetStringFromID(pContext, IDS_STRING_JSPARSEDATE).c_str(),
1462 sFormat.c_str());
1463 Alert(pContext, swMsg.c_str());
1464 pEvent->Rc() = FALSE;
1465 return TRUE;
Tom Sepez2f2ffec2015-07-23 14:42:09 -07001466 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001467 }
1468 return TRUE;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001469}
1470
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001471FX_BOOL CJS_PublicMethods::AFDate_Format(IFXJS_Context* cc,
1472 const CJS_Parameters& params,
1473 CJS_Value& vRet,
1474 CFX_WideString& sError) {
1475 v8::Isolate* isolate = ::GetIsolate(cc);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001476
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001477 if (params.size() != 1) {
1478 CJS_Context* pContext = (CJS_Context*)cc;
Tom Sepez2f2ffec2015-07-23 14:42:09 -07001479 ASSERT(pContext != NULL);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001480
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001481 sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
1482 return FALSE;
1483 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001484
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001485 int iIndex = params[0].ToInt();
1486 const FX_WCHAR* cFormats[] = {L"m/d",
1487 L"m/d/yy",
1488 L"mm/dd/yy",
1489 L"mm/yy",
1490 L"d-mmm",
1491 L"d-mmm-yy",
1492 L"dd-mmm-yy",
1493 L"yy-mm-dd",
1494 L"mmm-yy",
1495 L"mmmm-yy",
1496 L"mmm d, yyyy",
1497 L"mmmm d, yyyy",
1498 L"m/d/yy h:MM tt",
1499 L"m/d/yy HH:MM"};
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001500
Lei Zhanga0f67242015-08-17 15:39:30 -07001501 if (iIndex < 0 || (static_cast<size_t>(iIndex) >= FX_ArraySize(cFormats)))
1502 iIndex = 0;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001503
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001504 CJS_Parameters newParams;
1505 CJS_Value val(isolate, cFormats[iIndex]);
1506 newParams.push_back(val);
1507 return AFDate_FormatEx(cc, newParams, vRet, sError);
1508}
Lei Zhanga6d9f0e2015-06-13 00:48:38 -07001509
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001510// AFDate_KeystrokeEx(cFormat)
1511FX_BOOL CJS_PublicMethods::AFDate_Keystroke(IFXJS_Context* cc,
1512 const CJS_Parameters& params,
1513 CJS_Value& vRet,
1514 CFX_WideString& sError) {
1515 v8::Isolate* isolate = ::GetIsolate(cc);
1516
1517 if (params.size() != 1) {
1518 CJS_Context* pContext = (CJS_Context*)cc;
1519 ASSERT(pContext != NULL);
1520
1521 sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
1522 return FALSE;
1523 }
1524
1525 int iIndex = params[0].ToInt();
1526 const FX_WCHAR* cFormats[] = {L"m/d",
1527 L"m/d/yy",
1528 L"mm/dd/yy",
1529 L"mm/yy",
1530 L"d-mmm",
1531 L"d-mmm-yy",
1532 L"dd-mmm-yy",
1533 L"yy-mm-dd",
1534 L"mmm-yy",
1535 L"mmmm-yy",
1536 L"mmm d, yyyy",
1537 L"mmmm d, yyyy",
1538 L"m/d/yy h:MM tt",
1539 L"m/d/yy HH:MM"};
1540
Lei Zhanga0f67242015-08-17 15:39:30 -07001541 if (iIndex < 0 || (static_cast<size_t>(iIndex) >= FX_ArraySize(cFormats)))
1542 iIndex = 0;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001543
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001544 CJS_Parameters newParams;
1545 CJS_Value val(isolate, cFormats[iIndex]);
1546 newParams.push_back(val);
1547 return AFDate_KeystrokeEx(cc, newParams, vRet, sError);
1548}
1549
1550// function AFTime_Format(ptf)
1551FX_BOOL CJS_PublicMethods::AFTime_Format(IFXJS_Context* cc,
1552 const CJS_Parameters& params,
1553 CJS_Value& vRet,
1554 CFX_WideString& sError) {
1555 v8::Isolate* isolate = ::GetIsolate(cc);
1556
1557 if (params.size() != 1) {
1558 CJS_Context* pContext = (CJS_Context*)cc;
1559 ASSERT(pContext != NULL);
1560 sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
1561 return FALSE;
1562 }
1563
1564 int iIndex = params[0].ToInt();
1565 const FX_WCHAR* cFormats[] = {L"HH:MM", L"h:MM tt", L"HH:MM:ss",
1566 L"h:MM:ss tt"};
1567
Lei Zhanga0f67242015-08-17 15:39:30 -07001568 if (iIndex < 0 || (static_cast<size_t>(iIndex) >= FX_ArraySize(cFormats)))
1569 iIndex = 0;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001570
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001571 CJS_Parameters newParams;
1572 CJS_Value val(isolate, cFormats[iIndex]);
1573 newParams.push_back(val);
1574 return AFDate_FormatEx(cc, newParams, vRet, sError);
1575}
1576
1577FX_BOOL CJS_PublicMethods::AFTime_Keystroke(IFXJS_Context* cc,
1578 const CJS_Parameters& params,
1579 CJS_Value& vRet,
1580 CFX_WideString& sError) {
1581 v8::Isolate* isolate = ::GetIsolate(cc);
1582 if (params.size() != 1) {
1583 CJS_Context* pContext = (CJS_Context*)cc;
1584 ASSERT(pContext != NULL);
1585 sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
1586 return FALSE;
1587 }
1588
1589 int iIndex = params[0].ToInt();
1590 const FX_WCHAR* cFormats[] = {L"HH:MM", L"h:MM tt", L"HH:MM:ss",
1591 L"h:MM:ss tt"};
1592
Lei Zhanga0f67242015-08-17 15:39:30 -07001593 if (iIndex < 0 || (static_cast<size_t>(iIndex) >= FX_ArraySize(cFormats)))
1594 iIndex = 0;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001595
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001596 CJS_Parameters newParams;
1597 CJS_Value val(isolate, cFormats[iIndex]);
1598 newParams.push_back(val);
1599 return AFDate_KeystrokeEx(cc, newParams, vRet, sError);
1600}
1601
1602FX_BOOL CJS_PublicMethods::AFTime_FormatEx(IFXJS_Context* cc,
1603 const CJS_Parameters& params,
1604 CJS_Value& vRet,
1605 CFX_WideString& sError) {
1606 return AFDate_FormatEx(cc, params, vRet, sError);
1607}
1608
1609FX_BOOL CJS_PublicMethods::AFTime_KeystrokeEx(IFXJS_Context* cc,
1610 const CJS_Parameters& params,
1611 CJS_Value& vRet,
1612 CFX_WideString& sError) {
1613 return AFDate_KeystrokeEx(cc, params, vRet, sError);
1614}
1615
1616// function AFSpecial_Format(psf)
1617FX_BOOL CJS_PublicMethods::AFSpecial_Format(IFXJS_Context* cc,
1618 const CJS_Parameters& params,
1619 CJS_Value& vRet,
1620 CFX_WideString& sError) {
1621 CJS_Context* pContext = (CJS_Context*)cc;
1622 ASSERT(pContext != NULL);
1623
1624 if (params.size() != 1) {
1625 sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
1626 return FALSE;
1627 }
1628
1629 std::string cFormat;
1630 int iIndex = params[0].ToInt();
1631
1632 CJS_EventHandler* pEvent = pContext->GetEventHandler();
1633 ASSERT(pEvent != NULL);
1634
1635 if (!pEvent->m_pValue)
1636 return FALSE;
1637 CFX_WideString& Value = pEvent->Value();
1638 std::string strSrc = CFX_ByteString::FromUnicode(Value).c_str();
1639
1640 switch (iIndex) {
Tom Sepez2f2ffec2015-07-23 14:42:09 -07001641 case 0:
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001642 cFormat = "99999";
1643 break;
Tom Sepez2f2ffec2015-07-23 14:42:09 -07001644 case 1:
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001645 cFormat = "99999-9999";
1646 break;
1647 case 2: {
1648 std::string NumberStr;
1649 util::printx("9999999999", strSrc, NumberStr);
1650 if (NumberStr.length() >= 10)
1651 cFormat = "(999) 999-9999";
1652 else
1653 cFormat = "999-9999";
1654 break;
1655 }
Tom Sepez2f2ffec2015-07-23 14:42:09 -07001656 case 3:
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001657 cFormat = "999-99-9999";
1658 break;
1659 }
1660
1661 std::string strDes;
1662 util::printx(cFormat, strSrc, strDes);
1663 Value = CFX_WideString::FromLocal(strDes.c_str());
1664 return TRUE;
1665}
1666
1667// function AFSpecial_KeystrokeEx(mask)
1668FX_BOOL CJS_PublicMethods::AFSpecial_KeystrokeEx(IFXJS_Context* cc,
1669 const CJS_Parameters& params,
1670 CJS_Value& vRet,
1671 CFX_WideString& sError) {
1672 CJS_Context* pContext = (CJS_Context*)cc;
1673 ASSERT(pContext != NULL);
1674 CJS_EventHandler* pEvent = pContext->GetEventHandler();
1675
1676 ASSERT(pEvent != NULL);
1677
1678 if (params.size() < 1) {
1679 sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
1680 return FALSE;
1681 }
1682
1683 if (!pEvent->m_pValue)
1684 return FALSE;
1685 CFX_WideString& valEvent = pEvent->Value();
1686
1687 CFX_WideString wstrMask = params[0].ToCFXWideString();
1688 if (wstrMask.IsEmpty())
1689 return TRUE;
1690
Lei Zhanga0f67242015-08-17 15:39:30 -07001691 const size_t wstrMaskLen = wstrMask.GetLength();
1692 const std::wstring wstrValue = valEvent.c_str();
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001693
1694 if (pEvent->WillCommit()) {
1695 if (wstrValue.empty())
1696 return TRUE;
Lei Zhanga0f67242015-08-17 15:39:30 -07001697 size_t iIndexMask = 0;
1698 for (const auto& w_Value : wstrValue) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001699 if (!maskSatisfied(w_Value, wstrMask[iIndexMask]))
Tom Sepez2f2ffec2015-07-23 14:42:09 -07001700 break;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001701 iIndexMask++;
Tom Sepez2f2ffec2015-07-23 14:42:09 -07001702 }
Lei Zhanga6d9f0e2015-06-13 00:48:38 -07001703
Lei Zhanga0f67242015-08-17 15:39:30 -07001704 if (iIndexMask != wstrMaskLen ||
1705 (iIndexMask != wstrValue.size() && wstrMaskLen != 0)) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001706 Alert(
1707 pContext,
1708 JSGetStringFromID(pContext, IDS_STRING_JSAFNUMBER_KEYSTROKE).c_str());
1709 pEvent->Rc() = FALSE;
1710 }
Tom Sepez2f2ffec2015-07-23 14:42:09 -07001711 return TRUE;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001712 }
1713
1714 CFX_WideString& wideChange = pEvent->Change();
1715 std::wstring wChange = wideChange.c_str();
1716 if (wChange.empty())
1717 return TRUE;
1718
1719 int iIndexMask = pEvent->SelStart();
1720
Lei Zhanga0f67242015-08-17 15:39:30 -07001721 size_t combined_len = wstrValue.length() + wChange.length() -
1722 (pEvent->SelEnd() - pEvent->SelStart());
1723 if (combined_len > wstrMaskLen) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001724 Alert(pContext,
1725 JSGetStringFromID(pContext, IDS_STRING_JSPARAM_TOOLONG).c_str());
1726 pEvent->Rc() = FALSE;
1727 return TRUE;
1728 }
1729
Lei Zhanga0f67242015-08-17 15:39:30 -07001730 if (iIndexMask >= wstrMaskLen && (!wChange.empty())) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001731 Alert(pContext,
1732 JSGetStringFromID(pContext, IDS_STRING_JSPARAM_TOOLONG).c_str());
1733 pEvent->Rc() = FALSE;
1734 return TRUE;
1735 }
1736
1737 for (std::wstring::iterator it = wChange.begin(); it != wChange.end(); it++) {
Lei Zhanga0f67242015-08-17 15:39:30 -07001738 if (iIndexMask >= wstrMaskLen) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001739 Alert(pContext,
1740 JSGetStringFromID(pContext, IDS_STRING_JSPARAM_TOOLONG).c_str());
1741 pEvent->Rc() = FALSE;
1742 return TRUE;
1743 }
1744 wchar_t w_Mask = wstrMask[iIndexMask];
1745 if (!isReservedMaskChar(w_Mask)) {
1746 *it = w_Mask;
1747 }
1748 wchar_t w_Change = *it;
1749 if (!maskSatisfied(w_Change, w_Mask)) {
1750 pEvent->Rc() = FALSE;
1751 return TRUE;
1752 }
1753 iIndexMask++;
1754 }
1755
1756 wideChange = wChange.c_str();
1757 return TRUE;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001758}
1759
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001760// function AFSpecial_Keystroke(psf)
1761FX_BOOL CJS_PublicMethods::AFSpecial_Keystroke(IFXJS_Context* cc,
1762 const CJS_Parameters& params,
1763 CJS_Value& vRet,
1764 CFX_WideString& sError) {
1765 v8::Isolate* isolate = ::GetIsolate(cc);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001766
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001767 CJS_Context* pContext = (CJS_Context*)cc;
1768 ASSERT(pContext != NULL);
1769 CJS_EventHandler* pEvent = pContext->GetEventHandler();
1770 ASSERT(pEvent != NULL);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001771
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001772 if (params.size() != 1) {
1773 sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
1774 return FALSE;
1775 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001776
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001777 std::string cFormat;
1778 int iIndex = params[0].ToInt();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001779
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001780 if (!pEvent->m_pValue)
1781 return FALSE;
1782 // CJS_Value val = pEvent->Value();
1783 CFX_WideString& val = pEvent->Value();
1784 std::string strSrc = CFX_ByteString::FromUnicode(val).c_str();
1785 std::wstring wstrChange = pEvent->Change().c_str();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001786
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001787 switch (iIndex) {
Tom Sepez2f2ffec2015-07-23 14:42:09 -07001788 case 0:
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001789 cFormat = "99999";
1790 break;
Tom Sepez2f2ffec2015-07-23 14:42:09 -07001791 case 1:
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001792 // cFormat = "99999-9999";
1793 cFormat = "999999999";
1794 break;
1795 case 2: {
1796 std::string NumberStr;
1797 util::printx("9999999999", strSrc, NumberStr);
1798 if (strSrc.length() + wstrChange.length() > 7)
1799 // cFormat = "(999) 999-9999";
1800 cFormat = "9999999999";
1801 else
1802 // cFormat = "999-9999";
1803 cFormat = "9999999";
1804 break;
1805 }
Tom Sepez2f2ffec2015-07-23 14:42:09 -07001806 case 3:
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001807 // cFormat = "999-99-9999";
1808 cFormat = "999999999";
1809 break;
1810 }
Lei Zhanga6d9f0e2015-06-13 00:48:38 -07001811
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001812 CJS_Parameters params2;
1813 CJS_Value vMask(isolate, cFormat.c_str());
1814 params2.push_back(vMask);
Lei Zhanga6d9f0e2015-06-13 00:48:38 -07001815
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001816 return AFSpecial_KeystrokeEx(cc, params2, vRet, sError);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001817}
1818
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001819FX_BOOL CJS_PublicMethods::AFMergeChange(IFXJS_Context* cc,
1820 const CJS_Parameters& params,
1821 CJS_Value& vRet,
1822 CFX_WideString& sError) {
1823 CJS_Context* pContext = (CJS_Context*)cc;
1824 ASSERT(pContext != NULL);
1825 CJS_EventHandler* pEventHandler = pContext->GetEventHandler();
1826 ASSERT(pEventHandler != NULL);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001827
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001828 if (params.size() != 1) {
1829 sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
1830 return FALSE;
1831 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001832
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001833 CFX_WideString swValue;
1834 if (pEventHandler->m_pValue != NULL)
1835 swValue = pEventHandler->Value();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001836
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001837 if (pEventHandler->WillCommit()) {
1838 vRet = swValue.c_str();
Tom Sepez2f2ffec2015-07-23 14:42:09 -07001839 return TRUE;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001840 }
1841
1842 CFX_WideString prefix, postfix;
1843
1844 if (pEventHandler->SelStart() >= 0)
1845 prefix = swValue.Mid(0, pEventHandler->SelStart());
1846 else
1847 prefix = L"";
1848
1849 if (pEventHandler->SelEnd() >= 0 &&
1850 pEventHandler->SelEnd() <= swValue.GetLength())
1851 postfix = swValue.Mid(pEventHandler->SelEnd(),
1852 swValue.GetLength() - pEventHandler->SelEnd());
1853 else
1854 postfix = L"";
1855
1856 vRet = (prefix + pEventHandler->Change() + postfix).c_str();
1857
1858 return TRUE;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001859}
1860
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001861FX_BOOL CJS_PublicMethods::AFParseDateEx(IFXJS_Context* cc,
1862 const CJS_Parameters& params,
1863 CJS_Value& vRet,
1864 CFX_WideString& sError) {
1865 CJS_Context* pContext = (CJS_Context*)cc;
1866 ASSERT(pContext != NULL);
1867
1868 if (params.size() != 2) {
1869 sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
1870 return FALSE;
1871 }
1872
1873 CFX_WideString sValue = params[0].ToCFXWideString();
1874 CFX_WideString sFormat = params[1].ToCFXWideString();
1875
1876 FX_BOOL bWrongFormat = FALSE;
1877 double dDate = MakeRegularDate(sValue, sFormat, bWrongFormat);
1878
1879 if (JS_PortIsNan(dDate)) {
1880 CFX_WideString swMsg;
1881 swMsg.Format(JSGetStringFromID(pContext, IDS_STRING_JSPARSEDATE).c_str(),
1882 sFormat.c_str());
1883 Alert((CJS_Context*)cc, swMsg.c_str());
1884 return FALSE;
1885 }
1886
1887 vRet = dDate;
1888 return TRUE;
1889}
1890
1891FX_BOOL CJS_PublicMethods::AFSimple(IFXJS_Context* cc,
1892 const CJS_Parameters& params,
1893 CJS_Value& vRet,
1894 CFX_WideString& sError) {
1895 if (params.size() != 3) {
1896 CJS_Context* pContext = (CJS_Context*)cc;
Tom Sepez2f2ffec2015-07-23 14:42:09 -07001897 ASSERT(pContext != NULL);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001898
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001899 sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
1900 return FALSE;
1901 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001902
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001903 vRet = (double)AF_Simple(params[0].ToCFXWideString().c_str(),
1904 params[1].ToDouble(), params[2].ToDouble());
1905 return TRUE;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001906}
1907
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001908FX_BOOL CJS_PublicMethods::AFMakeNumber(IFXJS_Context* cc,
1909 const CJS_Parameters& params,
1910 CJS_Value& vRet,
1911 CFX_WideString& sError) {
1912 if (params.size() != 1) {
1913 CJS_Context* pContext = (CJS_Context*)cc;
Tom Sepez2f2ffec2015-07-23 14:42:09 -07001914 ASSERT(pContext != NULL);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001915
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001916 sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
1917 return FALSE;
1918 }
1919 vRet = ParseStringToNumber(params[0].ToCFXWideString().c_str());
1920 return TRUE;
1921}
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001922
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001923FX_BOOL CJS_PublicMethods::AFSimple_Calculate(IFXJS_Context* cc,
1924 const CJS_Parameters& params,
1925 CJS_Value& vRet,
1926 CFX_WideString& sError) {
1927 v8::Isolate* isolate = ::GetIsolate(cc);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001928
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001929 CJS_Context* pContext = (CJS_Context*)cc;
1930 ASSERT(pContext != NULL);
Tom Sepezf4ef3f92015-04-23 11:31:31 -07001931
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001932 if (params.size() != 2) {
1933 sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
1934 return FALSE;
1935 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001936
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001937 CJS_Value params1 = params[1];
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001938
Tom Sepez39bfe122015-09-17 15:25:23 -07001939 if (!params1.IsArrayObject() && params1.GetType() != CJS_Value::VT_string) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001940 sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
1941 return FALSE;
1942 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001943
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001944 CPDFSDK_Document* pReaderDoc = pContext->GetReaderDocument();
1945 ASSERT(pReaderDoc != NULL);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001946
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001947 CPDFSDK_InterForm* pReaderInterForm = pReaderDoc->GetInterForm();
1948 ASSERT(pReaderInterForm != NULL);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001949
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001950 CPDF_InterForm* pInterForm = pReaderInterForm->GetInterForm();
1951 ASSERT(pInterForm != NULL);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001952
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001953 double dValue;
1954 CFX_WideString sFunction = params[0].ToCFXWideString();
1955 if (wcscmp(sFunction.c_str(), L"PRD") == 0)
1956 dValue = 1.0;
1957 else
1958 dValue = 0.0;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001959
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001960 CJS_Array FieldNameArray = AF_MakeArrayFromList(isolate, params1);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001961
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001962 int nFieldsCount = 0;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001963
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001964 for (int i = 0, isz = FieldNameArray.GetLength(); i < isz; i++) {
1965 CJS_Value jsValue(isolate);
1966 FieldNameArray.GetElement(i, jsValue);
1967 CFX_WideString wsFieldName = jsValue.ToCFXWideString();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001968
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001969 for (int j = 0, jsz = pInterForm->CountFields(wsFieldName); j < jsz; j++) {
1970 if (CPDF_FormField* pFormField = pInterForm->GetField(j, wsFieldName)) {
1971 double dTemp = 0.0;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001972
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001973 switch (pFormField->GetFieldType()) {
1974 case FIELDTYPE_TEXTFIELD:
1975 case FIELDTYPE_COMBOBOX: {
1976 dTemp = ParseStringToNumber(pFormField->GetValue().c_str());
1977 break;
1978 }
1979 case FIELDTYPE_PUSHBUTTON: {
1980 dTemp = 0.0;
1981 break;
1982 }
1983 case FIELDTYPE_CHECKBOX:
1984 case FIELDTYPE_RADIOBUTTON: {
1985 dTemp = 0.0;
1986 for (int c = 0, csz = pFormField->CountControls(); c < csz; c++) {
1987 if (CPDF_FormControl* pFormCtrl = pFormField->GetControl(c)) {
1988 if (pFormCtrl->IsChecked()) {
1989 dTemp +=
1990 ParseStringToNumber(pFormCtrl->GetExportValue().c_str());
1991 break;
1992 } else
1993 continue;
1994 }
Tom Sepez2f2ffec2015-07-23 14:42:09 -07001995 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001996 break;
1997 }
1998 case FIELDTYPE_LISTBOX: {
1999 dTemp = 0.0;
2000 if (pFormField->CountSelectedItems() > 1)
2001 break;
2002 else {
2003 dTemp = ParseStringToNumber(pFormField->GetValue().c_str());
2004 break;
2005 }
2006 }
2007 default:
2008 break;
Tom Sepez2f2ffec2015-07-23 14:42:09 -07002009 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -07002010
2011 if (i == 0 && j == 0 && (wcscmp(sFunction.c_str(), L"MIN") == 0 ||
2012 wcscmp(sFunction.c_str(), L"MAX") == 0))
2013 dValue = dTemp;
2014
2015 dValue = AF_Simple(sFunction.c_str(), dValue, dTemp);
2016
2017 nFieldsCount++;
2018 }
Tom Sepez2f2ffec2015-07-23 14:42:09 -07002019 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -07002020 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07002021
Nico Weber9d8ec5a2015-08-04 13:00:21 -07002022 if (wcscmp(sFunction.c_str(), L"AVG") == 0 && nFieldsCount > 0)
2023 dValue /= nFieldsCount;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07002024
Nico Weber9d8ec5a2015-08-04 13:00:21 -07002025 dValue = (double)floor(dValue * FXSYS_pow((double)10, (double)6) + 0.49) /
2026 FXSYS_pow((double)10, (double)6);
2027 CJS_Value jsValue(isolate, dValue);
foxit8b544ed2015-09-10 14:57:54 +08002028 if (pContext->GetEventHandler()->m_pValue)
2029 pContext->GetEventHandler()->Value() = jsValue.ToCFXWideString();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07002030
Nico Weber9d8ec5a2015-08-04 13:00:21 -07002031 return TRUE;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07002032}
2033
Lei Zhanga6d9f0e2015-06-13 00:48:38 -07002034/* This function validates the current event to ensure that its value is
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07002035** within the specified range. */
2036
Nico Weber9d8ec5a2015-08-04 13:00:21 -07002037FX_BOOL CJS_PublicMethods::AFRange_Validate(IFXJS_Context* cc,
2038 const CJS_Parameters& params,
2039 CJS_Value& vRet,
2040 CFX_WideString& sError) {
2041 CJS_Context* pContext = (CJS_Context*)cc;
2042 ASSERT(pContext != NULL);
2043 CJS_EventHandler* pEvent = pContext->GetEventHandler();
2044 ASSERT(pEvent != NULL);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07002045
Nico Weber9d8ec5a2015-08-04 13:00:21 -07002046 if (params.size() != 4) {
2047 sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
2048 return FALSE;
2049 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07002050
Nico Weber9d8ec5a2015-08-04 13:00:21 -07002051 if (!pEvent->m_pValue)
2052 return FALSE;
2053 if (pEvent->Value().IsEmpty())
Tom Sepez2f2ffec2015-07-23 14:42:09 -07002054 return TRUE;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07002055 double dEentValue = atof(CFX_ByteString::FromUnicode(pEvent->Value()));
2056 FX_BOOL bGreaterThan = params[0].ToBool();
2057 double dGreaterThan = params[1].ToDouble();
2058 FX_BOOL bLessThan = params[2].ToBool();
2059 double dLessThan = params[3].ToDouble();
2060 CFX_WideString swMsg;
2061
2062 if (bGreaterThan && bLessThan) {
2063 if (dEentValue < dGreaterThan || dEentValue > dLessThan)
2064 swMsg.Format(JSGetStringFromID(pContext, IDS_STRING_JSRANGE1).c_str(),
2065 params[1].ToCFXWideString().c_str(),
2066 params[3].ToCFXWideString().c_str());
2067 } else if (bGreaterThan) {
2068 if (dEentValue < dGreaterThan)
2069 swMsg.Format(JSGetStringFromID(pContext, IDS_STRING_JSRANGE2).c_str(),
2070 params[1].ToCFXWideString().c_str());
2071 } else if (bLessThan) {
2072 if (dEentValue > dLessThan)
2073 swMsg.Format(JSGetStringFromID(pContext, IDS_STRING_JSRANGE3).c_str(),
2074 params[3].ToCFXWideString().c_str());
2075 }
2076
2077 if (!swMsg.IsEmpty()) {
2078 Alert(pContext, swMsg.c_str());
2079 pEvent->Rc() = FALSE;
2080 }
2081 return TRUE;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07002082}
2083
Nico Weber9d8ec5a2015-08-04 13:00:21 -07002084FX_BOOL CJS_PublicMethods::AFExtractNums(IFXJS_Context* cc,
2085 const CJS_Parameters& params,
2086 CJS_Value& vRet,
2087 CFX_WideString& sError) {
2088 v8::Isolate* isolate = ::GetIsolate(cc);
2089 CJS_Context* pContext = (CJS_Context*)cc;
2090 ASSERT(pContext != NULL);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07002091
Nico Weber9d8ec5a2015-08-04 13:00:21 -07002092 if (params.size() != 1) {
2093 sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
2094 return FALSE;
2095 }
2096
2097 CJS_Array nums(isolate);
2098
2099 CFX_WideString str = params[0].ToCFXWideString();
2100 CFX_WideString sPart;
2101
2102 if (str.GetAt(0) == L'.' || str.GetAt(0) == L',')
2103 str = L"0" + str;
2104
2105 int nIndex = 0;
2106 for (int i = 0, sz = str.GetLength(); i < sz; i++) {
2107 FX_WCHAR wc = str.GetAt(i);
2108 if (IsDigit((wchar_t)wc)) {
2109 sPart += wc;
2110 } else {
2111 if (sPart.GetLength() > 0) {
2112 nums.SetElement(nIndex, CJS_Value(isolate, sPart.c_str()));
2113 sPart = L"";
2114 nIndex++;
2115 }
Tom Sepez2f2ffec2015-07-23 14:42:09 -07002116 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -07002117 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07002118
Nico Weber9d8ec5a2015-08-04 13:00:21 -07002119 if (sPart.GetLength() > 0) {
2120 nums.SetElement(nIndex, CJS_Value(isolate, sPart.c_str()));
2121 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07002122
Nico Weber9d8ec5a2015-08-04 13:00:21 -07002123 if (nums.GetLength() > 0)
2124 vRet = nums;
2125 else
2126 vRet.SetNull();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07002127
Nico Weber9d8ec5a2015-08-04 13:00:21 -07002128 return TRUE;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07002129}