blob: 490c9e300fd227fde8e5ff0c091af4dae1fbb748 [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
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07007#include "../../include/javascript/IJavaScript.h"
8#include "../../include/javascript/JS_Define.h"
9#include "../../include/javascript/JS_Object.h"
10#include "../../include/javascript/JS_Value.h"
11#include "../../include/javascript/PublicMethods.h"
12#include "../../include/javascript/JS_EventHandler.h"
13#include "../../include/javascript/resource.h"
14#include "../../include/javascript/JS_Context.h"
15#include "../../include/javascript/JS_Value.h"
16#include "../../include/javascript/util.h"
17#include "../../include/javascript/Field.h"
18#include "../../include/javascript/color.h"
19#include "../../include/javascript/JS_Runtime.h"
20
Nico Weber9d8ec5a2015-08-04 13:00:21 -070021static v8::Isolate* GetIsolate(IFXJS_Context* cc) {
22 CJS_Context* pContext = (CJS_Context*)cc;
23 ASSERT(pContext != NULL);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070024
Nico Weber9d8ec5a2015-08-04 13:00:21 -070025 CJS_Runtime* pRuntime = pContext->GetJSRuntime();
26 ASSERT(pRuntime != NULL);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070027
Nico Weber9d8ec5a2015-08-04 13:00:21 -070028 return pRuntime->GetIsolate();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070029}
30
Nico Weber9d8ec5a2015-08-04 13:00:21 -070031/* -------------------------------- CJS_PublicMethods
32 * -------------------------------- */
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070033
Nico Weber9d8ec5a2015-08-04 13:00:21 -070034#define DOUBLE_CORRECT 0.000000000000001
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070035
36BEGIN_JS_STATIC_GLOBAL_FUN(CJS_PublicMethods)
Nico Weber9d8ec5a2015-08-04 13:00:21 -070037JS_STATIC_GLOBAL_FUN_ENTRY(AFNumber_Format)
38JS_STATIC_GLOBAL_FUN_ENTRY(AFNumber_Keystroke)
39JS_STATIC_GLOBAL_FUN_ENTRY(AFPercent_Format)
40JS_STATIC_GLOBAL_FUN_ENTRY(AFPercent_Keystroke)
41JS_STATIC_GLOBAL_FUN_ENTRY(AFDate_FormatEx)
42JS_STATIC_GLOBAL_FUN_ENTRY(AFDate_KeystrokeEx)
43JS_STATIC_GLOBAL_FUN_ENTRY(AFDate_Format)
44JS_STATIC_GLOBAL_FUN_ENTRY(AFDate_Keystroke)
45JS_STATIC_GLOBAL_FUN_ENTRY(AFTime_FormatEx)
46JS_STATIC_GLOBAL_FUN_ENTRY(AFTime_KeystrokeEx)
47JS_STATIC_GLOBAL_FUN_ENTRY(AFTime_Format)
48JS_STATIC_GLOBAL_FUN_ENTRY(AFTime_Keystroke)
49JS_STATIC_GLOBAL_FUN_ENTRY(AFSpecial_Format)
50JS_STATIC_GLOBAL_FUN_ENTRY(AFSpecial_Keystroke)
51JS_STATIC_GLOBAL_FUN_ENTRY(AFSpecial_KeystrokeEx)
52JS_STATIC_GLOBAL_FUN_ENTRY(AFSimple)
53JS_STATIC_GLOBAL_FUN_ENTRY(AFMakeNumber)
54JS_STATIC_GLOBAL_FUN_ENTRY(AFSimple_Calculate)
55JS_STATIC_GLOBAL_FUN_ENTRY(AFRange_Validate)
56JS_STATIC_GLOBAL_FUN_ENTRY(AFMergeChange)
57JS_STATIC_GLOBAL_FUN_ENTRY(AFParseDateEx)
58JS_STATIC_GLOBAL_FUN_ENTRY(AFExtractNums)
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070059END_JS_STATIC_GLOBAL_FUN()
60
61IMPLEMENT_JS_STATIC_GLOBAL_FUN(CJS_PublicMethods)
62
Nico Weber9d8ec5a2015-08-04 13:00:21 -070063static const FX_WCHAR* months[] = {L"Jan", L"Feb", L"Mar", L"Apr",
64 L"May", L"Jun", L"Jul", L"Aug",
65 L"Sep", L"Oct", L"Nov", L"Dec"};
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070066
Nico Weber9d8ec5a2015-08-04 13:00:21 -070067static const FX_WCHAR* const fullmonths[] = {
68 L"January", L"February", L"March", L"April",
69 L"May", L"June", L"July", L"August",
70 L"September", L"October", L"November", L"December"};
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070071
Nico Weber9d8ec5a2015-08-04 13:00:21 -070072FX_BOOL CJS_PublicMethods::IsNumber(const FX_WCHAR* string) {
73 CFX_WideString sTrim = StrTrim(string);
74 const FX_WCHAR* pTrim = sTrim.c_str();
75 const FX_WCHAR* p = pTrim;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070076
Nico Weber9d8ec5a2015-08-04 13:00:21 -070077 FX_BOOL bDot = FALSE;
78 FX_BOOL bKXJS = FALSE;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070079
Nico Weber9d8ec5a2015-08-04 13:00:21 -070080 wchar_t c;
81 while ((c = *p)) {
82 if (c == '.' || c == ',') {
83 if (bDot)
84 return FALSE;
85 bDot = TRUE;
86 } else if (c == '-' || c == '+') {
87 if (p != pTrim)
88 return FALSE;
89 } else if (c == 'e' || c == 'E') {
90 if (bKXJS)
91 return FALSE;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070092
Nico Weber9d8ec5a2015-08-04 13:00:21 -070093 p++;
94 c = *p;
95 if (c == '+' || c == '-') {
96 bKXJS = TRUE;
97 } else {
98 return FALSE;
99 }
100 } else if (!IsDigit(c)) {
101 return FALSE;
102 }
103 p++;
104 }
105
106 return TRUE;
107}
108
109FX_BOOL CJS_PublicMethods::IsDigit(wchar_t ch) {
110 return (ch >= L'0' && ch <= L'9');
111}
112
113FX_BOOL CJS_PublicMethods::IsDigit(char ch) {
114 return (ch >= '0' && ch <= '9');
115}
116
117FX_BOOL CJS_PublicMethods::IsAlphabetic(wchar_t ch) {
118 return ((ch >= L'a' && ch <= L'z') || (ch >= L'A' && ch <= L'Z'));
119}
120
121FX_BOOL CJS_PublicMethods::IsAlphaNumeric(wchar_t ch) {
122 return (IsDigit(ch) || IsAlphabetic(ch));
123}
124
125FX_BOOL CJS_PublicMethods::maskSatisfied(wchar_t c_Change, wchar_t c_Mask) {
126 switch (c_Mask) {
127 case L'9':
128 return IsDigit(c_Change);
129 case L'A':
130 return IsAlphabetic(c_Change);
131 case L'O':
132 return IsAlphaNumeric(c_Change);
133 case L'X':
134 return TRUE;
135 default:
136 return (c_Change == c_Mask);
137 }
138}
139
140FX_BOOL CJS_PublicMethods::isReservedMaskChar(wchar_t ch) {
141 return ch == L'9' || ch == L'A' || ch == L'O' || ch == L'X';
142}
143
144double CJS_PublicMethods::AF_Simple(const FX_WCHAR* sFuction,
145 double dValue1,
146 double dValue2) {
147 if (FXSYS_wcsicmp(sFuction, L"AVG") == 0 ||
148 FXSYS_wcsicmp(sFuction, L"SUM") == 0) {
149 return dValue1 + dValue2;
150 }
151 if (FXSYS_wcsicmp(sFuction, L"PRD") == 0) {
152 return dValue1 * dValue2;
153 }
154 if (FXSYS_wcsicmp(sFuction, L"MIN") == 0) {
155 return FX_MIN(dValue1, dValue2);
156 }
157 if (FXSYS_wcsicmp(sFuction, L"MAX") == 0) {
158 return FX_MAX(dValue1, dValue2);
159 }
160 return dValue1;
161}
162
163CFX_WideString CJS_PublicMethods::StrLTrim(const FX_WCHAR* pStr) {
164 while (*pStr && *pStr == L' ')
165 pStr++;
166
167 return pStr;
168}
169
170CFX_WideString CJS_PublicMethods::StrRTrim(const FX_WCHAR* pStr) {
171 const FX_WCHAR* p = pStr;
172 while (*p)
173 p++;
174 while (p > pStr && *(p - 1) == L' ')
175 p--;
176
177 return CFX_WideString(pStr, p - pStr);
178}
179
180CFX_WideString CJS_PublicMethods::StrTrim(const FX_WCHAR* pStr) {
181 return StrRTrim(StrLTrim(pStr).c_str());
182}
183
184CFX_ByteString CJS_PublicMethods::StrLTrim(const FX_CHAR* pStr) {
185 while (*pStr && *pStr == ' ')
186 pStr++;
187
188 return pStr;
189}
190
191CFX_ByteString CJS_PublicMethods::StrRTrim(const FX_CHAR* pStr) {
192 const FX_CHAR* p = pStr;
193 while (*p)
194 p++;
195 while (p > pStr && *(p - 1) == L' ')
196 p--;
197
198 return CFX_ByteString(pStr, p - pStr);
199}
200
201CFX_ByteString CJS_PublicMethods::StrTrim(const FX_CHAR* pStr) {
202 return StrRTrim(StrLTrim(pStr));
203}
204
205double CJS_PublicMethods::ParseNumber(const FX_WCHAR* swSource,
206 FX_BOOL& bAllDigits,
207 FX_BOOL& bDot,
208 FX_BOOL& bSign,
209 FX_BOOL& bKXJS) {
210 bDot = FALSE;
211 bSign = FALSE;
212 bKXJS = FALSE;
213
214 FX_BOOL bDigitExist = FALSE;
215
216 const FX_WCHAR* p = swSource;
217 wchar_t c;
218
219 const FX_WCHAR* pStart = NULL;
220 const FX_WCHAR* pEnd = NULL;
221
222 while ((c = *p)) {
223 if (!pStart && c != L' ') {
224 pStart = p;
225 }
226
227 pEnd = p;
228 p++;
229 }
230
231 if (!pStart) {
232 bAllDigits = FALSE;
233 return 0;
234 }
235
236 while (pEnd != pStart) {
237 if (*pEnd == L' ')
238 pEnd--;
239 else
240 break;
241 }
242
243 double dRet = 0;
244 p = pStart;
245 bAllDigits = TRUE;
246 CFX_WideString swDigits;
247
248 while (p <= pEnd) {
249 c = *p;
250
251 if (IsDigit(c)) {
252 swDigits += c;
253 bDigitExist = TRUE;
254 } else {
255 switch (c) {
256 case L' ':
257 bAllDigits = FALSE;
258 break;
259 case L'.':
260 case L',':
261 if (!bDot) {
262 if (bDigitExist) {
263 swDigits += L'.';
264 } else {
265 swDigits += L'0';
266 swDigits += L'.';
267 bDigitExist = TRUE;
268 }
269
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700270 bDot = TRUE;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700271 break;
272 }
273 case 'e':
274 case 'E':
275 if (!bKXJS) {
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700276 p++;
277 c = *p;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700278 if (c == '+' || c == '-') {
279 bKXJS = TRUE;
280 swDigits += 'e';
281 swDigits += c;
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700282 }
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700283 break;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700284 }
285 case L'-':
286 if (!bDigitExist && !bSign) {
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700287 swDigits += c;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700288 bSign = TRUE;
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700289 break;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700290 }
291 default:
292 bAllDigits = FALSE;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700293
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700294 if (p != pStart && !bDot && bDigitExist) {
295 swDigits += L'.';
296 bDot = TRUE;
297 } else {
298 bDot = FALSE;
299 bDigitExist = FALSE;
300 swDigits = L"";
301 }
302 break;
303 }
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700304 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700305
306 p++;
307 }
308
309 if (swDigits.GetLength() > 0 && swDigits.GetLength() < 17) {
310 CFX_ByteString sDigits = swDigits.UTF8Encode();
311
312 if (bKXJS) {
313 dRet = atof(sDigits);
314 } else {
315 if (bDot) {
316 char* pStopString;
317 dRet = ::strtod(sDigits, &pStopString);
318 } else {
319 dRet = atol(sDigits);
320 }
321 }
322 }
323
324 return dRet;
325}
326
327double CJS_PublicMethods::ParseStringToNumber(const FX_WCHAR* swSource) {
328 FX_BOOL bAllDigits = FALSE;
329 FX_BOOL bDot = FALSE;
330 FX_BOOL bSign = FALSE;
331 FX_BOOL bKXJS = FALSE;
332
333 return ParseNumber(swSource, bAllDigits, bDot, bSign, bKXJS);
334}
335
336FX_BOOL CJS_PublicMethods::ConvertStringToNumber(const FX_WCHAR* swSource,
337 double& dRet,
338 FX_BOOL& bDot) {
339 FX_BOOL bAllDigits = FALSE;
340 FX_BOOL bSign = FALSE;
341 FX_BOOL bKXJS = FALSE;
342
343 dRet = ParseNumber(swSource, bAllDigits, bDot, bSign, bKXJS);
344
345 return bAllDigits;
346}
347
348CJS_Array CJS_PublicMethods::AF_MakeArrayFromList(v8::Isolate* isolate,
349 CJS_Value val) {
350 CJS_Array StrArray(isolate);
351 if (val.IsArrayObject()) {
352 val.ConvertToArray(StrArray);
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700353 return StrArray;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700354 }
355 CFX_WideString wsStr = val.ToCFXWideString();
356 CFX_ByteString t = CFX_ByteString::FromUnicode(wsStr);
357 const char* p = (const char*)t;
358
359 int ch = ',';
360 int nIndex = 0;
361
362 while (*p) {
363 const char* pTemp = strchr(p, ch);
364 if (pTemp == NULL) {
365 StrArray.SetElement(nIndex, CJS_Value(isolate, StrTrim(p).c_str()));
366 break;
367 } else {
368 char* pSub = new char[pTemp - p + 1];
369 strncpy(pSub, p, pTemp - p);
370 *(pSub + (pTemp - p)) = '\0';
371
372 StrArray.SetElement(nIndex, CJS_Value(isolate, StrTrim(pSub).c_str()));
373 delete[] pSub;
374
375 nIndex++;
376 p = ++pTemp;
377 }
378 }
379 return StrArray;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700380}
381
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700382int CJS_PublicMethods::ParseStringInteger(const CFX_WideString& string,
383 int nStart,
384 int& nSkip,
385 int nMaxStep) {
386 int nRet = 0;
387 nSkip = 0;
388 for (int i = nStart, sz = string.GetLength(); i < sz; i++) {
389 if (i - nStart > 10)
390 break;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700391
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700392 FX_WCHAR c = string.GetAt(i);
393 if (IsDigit((wchar_t)c)) {
394 nRet = nRet * 10 + (c - '0');
395 nSkip = i - nStart + 1;
396 if (nSkip >= nMaxStep)
397 break;
398 } else
399 break;
400 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700401
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700402 return nRet;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700403}
404
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700405CFX_WideString CJS_PublicMethods::ParseStringString(
406 const CFX_WideString& string,
407 int nStart,
408 int& nSkip) {
409 CFX_WideString swRet;
410 nSkip = 0;
411 for (int i = nStart, sz = string.GetLength(); i < sz; i++) {
412 FX_WCHAR c = string.GetAt(i);
413 if ((c >= L'a' && c <= L'z') || (c >= L'A' && c <= L'Z')) {
414 swRet += c;
415 nSkip = i - nStart + 1;
416 } else
417 break;
418 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700419
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700420 return swRet;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700421}
422
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700423double CJS_PublicMethods::ParseNormalDate(const CFX_WideString& value,
424 FX_BOOL& bWrongFormat) {
425 double dt = JS_GetDateTime();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700426
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700427 int nYear = JS_GetYearFromTime(dt);
428 int nMonth = JS_GetMonthFromTime(dt) + 1;
429 int nDay = JS_GetDayFromTime(dt);
430 int nHour = JS_GetHourFromTime(dt);
431 int nMin = JS_GetMinFromTime(dt);
432 int nSec = JS_GetSecFromTime(dt);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700433
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700434 int number[3];
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700435
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700436 int nSkip = 0;
437 int nLen = value.GetLength();
438 int nIndex = 0;
439 int i = 0;
440 while (i < nLen) {
441 if (nIndex > 2)
442 break;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700443
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700444 FX_WCHAR c = value.GetAt(i);
445 if (IsDigit((wchar_t)c)) {
446 number[nIndex++] = ParseStringInteger(value, i, nSkip, 4);
447 i += nSkip;
448 } else {
449 i++;
450 }
451 }
452
453 if (nIndex == 2) {
454 // case2: month/day
455 // case3: day/month
456 if ((number[0] >= 1 && number[0] <= 12) &&
457 (number[1] >= 1 && number[1] <= 31)) {
458 nMonth = number[0];
459 nDay = number[1];
460 } else if ((number[0] >= 1 && number[0] <= 31) &&
461 (number[1] >= 1 && number[1] <= 12)) {
462 nDay = number[0];
463 nMonth = number[1];
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700464 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700465
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700466 bWrongFormat = FALSE;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700467 } else if (nIndex == 3) {
468 // case1: year/month/day
469 // case2: month/day/year
470 // case3: day/month/year
Tom Sepez5ffacd62014-07-18 14:42:12 -0700471
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700472 if (number[0] > 12 && (number[1] >= 1 && number[1] <= 12) &&
473 (number[2] >= 1 && number[2] <= 31)) {
474 nYear = number[0];
475 nMonth = number[1];
476 nDay = number[2];
477 } else if ((number[0] >= 1 && number[0] <= 12) &&
478 (number[1] >= 1 && number[1] <= 31) && number[2] > 31) {
479 nMonth = number[0];
480 nDay = number[1];
481 nYear = number[2];
482 } else if ((number[0] >= 1 && number[0] <= 31) &&
483 (number[1] >= 1 && number[1] <= 12) && number[2] > 31) {
484 nDay = number[0];
485 nMonth = number[1];
486 nYear = number[2];
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700487 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700488
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700489 bWrongFormat = FALSE;
490 } else {
491 bWrongFormat = TRUE;
492 return dt;
493 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700494
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700495 CFX_WideString swTemp;
496 swTemp.Format(L"%d/%d/%d %d:%d:%d", nMonth, nDay, nYear, nHour, nMin, nSec);
497 return JS_DateParse(swTemp.c_str());
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700498}
499
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700500double CJS_PublicMethods::MakeRegularDate(const CFX_WideString& value,
501 const CFX_WideString& format,
502 FX_BOOL& bWrongFormat) {
503 double dt = JS_GetDateTime();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700504
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700505 if (format.IsEmpty() || value.IsEmpty())
506 return dt;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700507
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700508 int nYear = JS_GetYearFromTime(dt);
509 int nMonth = JS_GetMonthFromTime(dt) + 1;
510 int nDay = JS_GetDayFromTime(dt);
511 int nHour = JS_GetHourFromTime(dt);
512 int nMin = JS_GetMinFromTime(dt);
513 int nSec = JS_GetSecFromTime(dt);
514
515 int nYearSub = 99; // nYear - 2000;
516
517 FX_BOOL bPm = FALSE;
518 FX_BOOL bExit = FALSE;
519 bWrongFormat = FALSE;
520
521 int i = 0;
522 int j = 0;
523
524 while (i < format.GetLength()) {
525 if (bExit)
526 break;
527
528 FX_WCHAR c = format.GetAt(i);
529 switch (c) {
530 case ':':
531 case '.':
532 case '-':
533 case '\\':
534 case '/':
535 i++;
536 j++;
537 break;
538
539 case 'y':
540 case 'm':
541 case 'd':
542 case 'H':
543 case 'h':
544 case 'M':
545 case 's':
546 case 't': {
547 int oldj = j;
548 int nSkip = 0;
549 int remaining = format.GetLength() - i - 1;
550
551 if (remaining == 0 || format.GetAt(i + 1) != c) {
552 switch (c) {
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700553 case 'y':
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700554 i++;
555 j++;
556 break;
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700557 case 'm':
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700558 nMonth = ParseStringInteger(value, j, nSkip, 2);
559 i++;
560 j += nSkip;
561 break;
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700562 case 'd':
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700563 nDay = ParseStringInteger(value, j, nSkip, 2);
564 i++;
565 j += nSkip;
566 break;
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700567 case 'H':
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700568 nHour = ParseStringInteger(value, j, nSkip, 2);
569 i++;
570 j += nSkip;
571 break;
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700572 case 'h':
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700573 nHour = ParseStringInteger(value, j, nSkip, 2);
574 i++;
575 j += nSkip;
576 break;
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700577 case 'M':
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700578 nMin = ParseStringInteger(value, j, nSkip, 2);
579 i++;
580 j += nSkip;
581 break;
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700582 case 's':
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700583 nSec = ParseStringInteger(value, j, nSkip, 2);
584 i++;
585 j += nSkip;
586 break;
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700587 case 't':
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700588 bPm = (j < value.GetLength() && value.GetAt(j) == 'p');
589 i++;
590 j++;
591 break;
592 }
593 } else if (remaining == 1 || format.GetAt(i + 2) != c) {
594 switch (c) {
595 case 'y':
596 nYear = ParseStringInteger(value, j, nSkip, 4);
597 i += 2;
598 j += nSkip;
599 break;
600 case 'm':
601 nMonth = ParseStringInteger(value, j, nSkip, 2);
602 i += 2;
603 j += nSkip;
604 break;
605 case 'd':
606 nDay = ParseStringInteger(value, j, nSkip, 2);
607 i += 2;
608 j += nSkip;
609 break;
610 case 'H':
611 nHour = ParseStringInteger(value, j, nSkip, 2);
612 i += 2;
613 j += nSkip;
614 break;
615 case 'h':
616 nHour = ParseStringInteger(value, j, nSkip, 2);
617 i += 2;
618 j += nSkip;
619 break;
620 case 'M':
621 nMin = ParseStringInteger(value, j, nSkip, 2);
622 i += 2;
623 j += nSkip;
624 break;
625 case 's':
626 nSec = ParseStringInteger(value, j, nSkip, 2);
627 i += 2;
628 j += nSkip;
629 break;
630 case 't':
631 bPm = (j + 1 < value.GetLength() && value.GetAt(j) == 'p' &&
632 value.GetAt(j + 1) == 'm');
633 i += 2;
634 j += 2;
635 break;
636 }
637 } else if (remaining == 2 || format.GetAt(i + 3) != c) {
638 switch (c) {
639 case 'm': {
640 CFX_WideString sMonth = ParseStringString(value, j, nSkip);
641 FX_BOOL bFind = FALSE;
642 for (int m = 0; m < 12; m++) {
643 if (sMonth.CompareNoCase(months[m]) == 0) {
644 nMonth = m + 1;
645 i += 3;
646 j += nSkip;
647 bFind = TRUE;
648 break;
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700649 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700650 }
651
652 if (!bFind) {
653 nMonth = ParseStringInteger(value, j, nSkip, 3);
654 i += 3;
655 j += nSkip;
656 }
657 } break;
658 case 'y':
659 break;
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700660 default:
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700661 i += 3;
662 j += 3;
663 break;
664 }
665 } else if (remaining == 3 || format.GetAt(i + 4) != c) {
666 switch (c) {
667 case 'y':
668 nYear = ParseStringInteger(value, j, nSkip, 4);
669 j += nSkip;
670 i += 4;
671 break;
672 case 'm': {
673 FX_BOOL bFind = FALSE;
674
675 CFX_WideString sMonth = ParseStringString(value, j, nSkip);
676 sMonth.MakeLower();
677
678 for (int m = 0; m < 12; m++) {
679 CFX_WideString sFullMonths = fullmonths[m];
680 sFullMonths.MakeLower();
681
682 if (sFullMonths.Find(sMonth.c_str(), 0) != -1) {
683 nMonth = m + 1;
684 i += 4;
685 j += nSkip;
686 bFind = TRUE;
687 break;
688 }
689 }
690
691 if (!bFind) {
692 nMonth = ParseStringInteger(value, j, nSkip, 4);
693 i += 4;
694 j += nSkip;
695 }
696 } break;
697 default:
698 i += 4;
699 j += 4;
700 break;
701 }
702 } else {
703 if (j >= value.GetLength() || format.GetAt(i) != value.GetAt(j)) {
704 bWrongFormat = TRUE;
705 bExit = TRUE;
706 }
707 i++;
708 j++;
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700709 }
Tom Sepez85386422014-07-23 10:28:37 -0700710
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700711 if (oldj == j) {
712 bWrongFormat = TRUE;
713 bExit = TRUE;
714 }
715 }
716
717 break;
718 default:
719 if (value.GetLength() <= j) {
720 bExit = TRUE;
721 } else if (format.GetAt(i) != value.GetAt(j)) {
722 bWrongFormat = TRUE;
723 bExit = TRUE;
724 }
725
726 i++;
727 j++;
728 break;
729 }
730 }
731
732 if (bPm)
733 nHour += 12;
734
735 if (nYear >= 0 && nYear <= nYearSub)
736 nYear += 2000;
737
738 if (nMonth < 1 || nMonth > 12)
739 bWrongFormat = TRUE;
740
741 if (nDay < 1 || nDay > 31)
742 bWrongFormat = TRUE;
743
744 if (nHour < 0 || nHour > 24)
745 bWrongFormat = TRUE;
746
747 if (nMin < 0 || nMin > 60)
748 bWrongFormat = TRUE;
749
750 if (nSec < 0 || nSec > 60)
751 bWrongFormat = TRUE;
752
753 double dRet = 0;
754
755 if (bWrongFormat) {
756 dRet = ParseNormalDate(value, bWrongFormat);
757 } else {
758 dRet = JS_MakeDate(JS_MakeDay(nYear, nMonth - 1, nDay),
759 JS_MakeTime(nHour, nMin, nSec, 0));
760
761 if (JS_PortIsNan(dRet)) {
762 dRet = JS_DateParse(value.c_str());
763 }
764 }
765
766 if (JS_PortIsNan(dRet)) {
767 dRet = ParseNormalDate(value, bWrongFormat);
768 }
769
770 return dRet;
771}
772
773CFX_WideString CJS_PublicMethods::MakeFormatDate(double dDate,
774 const CFX_WideString& format) {
775 CFX_WideString sRet = L"", sPart = L"";
776
777 int nYear = JS_GetYearFromTime(dDate);
778 int nMonth = JS_GetMonthFromTime(dDate) + 1;
779 int nDay = JS_GetDayFromTime(dDate);
780 int nHour = JS_GetHourFromTime(dDate);
781 int nMin = JS_GetMinFromTime(dDate);
782 int nSec = JS_GetSecFromTime(dDate);
783
784 int i = 0;
785 while (i < format.GetLength()) {
786 FX_WCHAR c = format.GetAt(i);
787 int remaining = format.GetLength() - i - 1;
788 sPart = L"";
789 switch (c) {
790 case 'y':
791 case 'm':
792 case 'd':
793 case 'H':
794 case 'h':
795 case 'M':
796 case 's':
797 case 't':
798 if (remaining == 0 || format.GetAt(i + 1) != c) {
799 switch (c) {
800 case 'y':
801 sPart += c;
802 break;
803 case 'm':
804 sPart.Format(L"%d", nMonth);
805 break;
806 case 'd':
807 sPart.Format(L"%d", nDay);
808 break;
809 case 'H':
810 sPart.Format(L"%d", nHour);
811 break;
812 case 'h':
813 sPart.Format(L"%d", nHour > 12 ? nHour - 12 : nHour);
814 break;
815 case 'M':
816 sPart.Format(L"%d", nMin);
817 break;
818 case 's':
819 sPart.Format(L"%d", nSec);
820 break;
821 case 't':
822 sPart += nHour > 12 ? 'p' : 'a';
823 break;
824 }
825 i++;
826 } else if (remaining == 1 || format.GetAt(i + 2) != c) {
827 switch (c) {
828 case 'y':
829 sPart.Format(L"%02d", nYear - (nYear / 100) * 100);
830 break;
831 case 'm':
832 sPart.Format(L"%02d", nMonth);
833 break;
834 case 'd':
835 sPart.Format(L"%02d", nDay);
836 break;
837 case 'H':
838 sPart.Format(L"%02d", nHour);
839 break;
840 case 'h':
841 sPart.Format(L"%02d", nHour > 12 ? nHour - 12 : nHour);
842 break;
843 case 'M':
844 sPart.Format(L"%02d", nMin);
845 break;
846 case 's':
847 sPart.Format(L"%02d", nSec);
848 break;
849 case 't':
850 sPart = nHour > 12 ? L"pm" : L"am";
851 break;
852 }
853 i += 2;
854 } else if (remaining == 2 || format.GetAt(i + 3) != c) {
855 switch (c) {
856 case 'm':
857 i += 3;
858 if (nMonth > 0 && nMonth <= 12)
859 sPart += months[nMonth - 1];
860 break;
861 default:
862 i += 3;
863 sPart += c;
864 sPart += c;
865 sPart += c;
866 break;
867 }
868 } else if (remaining == 3 || format.GetAt(i + 4) != c) {
869 switch (c) {
870 case 'y':
871 sPart.Format(L"%04d", nYear);
872 i += 4;
873 break;
874 case 'm':
875 i += 4;
876 if (nMonth > 0 && nMonth <= 12)
877 sPart += fullmonths[nMonth - 1];
878 break;
879 default:
880 i += 4;
881 sPart += c;
882 sPart += c;
883 sPart += c;
884 sPart += c;
885 break;
886 }
887 } else {
888 i++;
889 sPart += c;
890 }
891 break;
892 default:
893 i++;
894 sPart += c;
895 break;
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700896 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700897
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700898 sRet += sPart;
899 }
900
901 return sRet;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700902}
903
904/* -------------------------------------------------------------------------- */
905
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700906// function AFNumber_Format(nDec, sepStyle, negStyle, currStyle, strCurrency,
907// bCurrencyPrepend)
908FX_BOOL CJS_PublicMethods::AFNumber_Format(IFXJS_Context* cc,
909 const CJS_Parameters& params,
910 CJS_Value& vRet,
911 CFX_WideString& sError) {
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700912#if _FX_OS_ != _FX_ANDROID_
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700913 v8::Isolate* isolate = ::GetIsolate(cc);
914 CJS_Context* pContext = (CJS_Context*)cc;
915 ASSERT(pContext != NULL);
916 CJS_EventHandler* pEvent = pContext->GetEventHandler();
917 ASSERT(pEvent != NULL);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700918
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700919 if (params.size() != 6) {
920 sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
921 return FALSE;
922 }
923 if (!pEvent->m_pValue)
924 return FALSE;
925 CFX_WideString& Value = pEvent->Value();
926 CFX_ByteString strValue = StrTrim(CFX_ByteString::FromUnicode(Value));
Lei Zhanga6d9f0e2015-06-13 00:48:38 -0700927
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700928 if (strValue.IsEmpty())
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700929 return TRUE;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700930
931 int iDec = params[0].ToInt();
932 int iSepStyle = params[1].ToInt();
933 int iNegStyle = params[2].ToInt();
934 // params[3] is iCurrStyle, it's not used.
935 std::wstring wstrCurrency(params[4].ToCFXWideString().c_str());
936 FX_BOOL bCurrencyPrepend = params[5].ToBool();
937
938 if (iDec < 0)
939 iDec = -iDec;
940
941 if (iSepStyle < 0 || iSepStyle > 3)
942 iSepStyle = 0;
943
944 if (iNegStyle < 0 || iNegStyle > 3)
945 iNegStyle = 0;
946
947 //////////////////////////////////////////////////////
948 // for processing decimal places
949 strValue.Replace(",", ".");
950 double dValue = atof(strValue);
951 if (iDec > 0)
952 dValue += DOUBLE_CORRECT; //
953
954 int iDec2;
955 int iNegative = 0;
956
957 strValue = fcvt(dValue, iDec, &iDec2, &iNegative);
958 if (strValue.IsEmpty()) {
959 dValue = 0;
960 strValue = fcvt(dValue, iDec, &iDec2, &iNegative);
961 if (strValue.IsEmpty()) {
962 strValue = "0";
963 iDec2 = 1;
964 }
965 }
966
967 if (iDec2 < 0) {
968 for (int iNum = 0; iNum < abs(iDec2); iNum++) {
969 strValue = "0" + strValue;
970 }
971 iDec2 = 0;
972 }
973 int iMax = strValue.GetLength();
974 if (iDec2 > iMax) {
975 for (int iNum = 0; iNum <= iDec2 - iMax; iNum++) {
976 strValue += "0";
977 }
978 iMax = iDec2 + 1;
979 }
980 ///////////////////////////////////////////////////////
981 // for processing seperator style
982 if (iDec2 < iMax) {
983 if (iSepStyle == 0 || iSepStyle == 1) {
984 strValue.Insert(iDec2, '.');
985 iMax++;
986 } else if (iSepStyle == 2 || iSepStyle == 3) {
987 strValue.Insert(iDec2, ',');
988 iMax++;
989 }
990
991 if (iDec2 == 0)
992 strValue.Insert(iDec2, '0');
993 }
994 if (iSepStyle == 0 || iSepStyle == 2) {
995 char cSeperator;
996 if (iSepStyle == 0)
997 cSeperator = ',';
998 else
999 cSeperator = '.';
1000
1001 int iDecPositive, iDecNegative;
1002 iDecPositive = iDec2;
1003 iDecNegative = iDec2;
1004
1005 for (iDecPositive = iDec2 - 3; iDecPositive > 0; iDecPositive -= 3) {
1006 strValue.Insert(iDecPositive, cSeperator);
1007 iMax++;
1008 }
1009 }
1010
1011 //////////////////////////////////////////////////////////////////////
1012 // for processing currency string
1013
1014 Value = CFX_WideString::FromLocal(strValue);
1015 std::wstring strValue2 = Value.c_str();
1016
1017 if (bCurrencyPrepend)
1018 strValue2 = wstrCurrency + strValue2;
1019 else
1020 strValue2 = strValue2 + wstrCurrency;
1021
1022 /////////////////////////////////////////////////////////////////////////
1023 // for processing negative style
1024 if (iNegative) {
1025 if (iNegStyle == 0) {
1026 strValue2.insert(0, L"-");
1027 }
1028 if (iNegStyle == 2 || iNegStyle == 3) {
1029 strValue2.insert(0, L"(");
1030 strValue2.insert(strValue2.length(), L")");
1031 }
1032 if (iNegStyle == 1 || iNegStyle == 3) {
1033 if (Field* fTarget = pEvent->Target_Field()) {
1034 CJS_Array arColor(isolate);
1035 CJS_Value vColElm(isolate);
1036 vColElm = L"RGB";
1037 arColor.SetElement(0, vColElm);
1038 vColElm = 1;
1039 arColor.SetElement(1, vColElm);
1040 vColElm = 0;
1041 arColor.SetElement(2, vColElm);
1042
1043 arColor.SetElement(3, vColElm);
1044
1045 CJS_PropValue vProp(isolate);
1046 vProp.StartGetting();
1047 vProp << arColor;
1048 vProp.StartSetting();
1049 fTarget->textColor(cc, vProp, sError); // red
1050 }
1051 }
1052 } else {
1053 if (iNegStyle == 1 || iNegStyle == 3) {
1054 if (Field* fTarget = pEvent->Target_Field()) {
1055 CJS_Array arColor(isolate);
1056 CJS_Value vColElm(isolate);
1057 vColElm = L"RGB";
1058 arColor.SetElement(0, vColElm);
1059 vColElm = 0;
1060 arColor.SetElement(1, vColElm);
1061 arColor.SetElement(2, vColElm);
1062 arColor.SetElement(3, vColElm);
1063
1064 CJS_PropValue vProp(isolate);
1065 vProp.StartGetting();
1066 fTarget->textColor(cc, vProp, sError);
1067
1068 CJS_Array aProp(isolate);
1069 vProp.ConvertToArray(aProp);
1070
1071 CPWL_Color crProp;
1072 CPWL_Color crColor;
1073 color::ConvertArrayToPWLColor(aProp, crProp);
1074 color::ConvertArrayToPWLColor(arColor, crColor);
1075
1076 if (crColor != crProp) {
1077 CJS_PropValue vProp2(isolate);
1078 vProp2.StartGetting();
1079 vProp2 << arColor;
1080 vProp2.StartSetting();
1081 fTarget->textColor(cc, vProp2, sError);
1082 }
1083 }
1084 }
1085 }
1086 Value = strValue2.c_str();
1087#endif
1088 return TRUE;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001089}
1090
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001091// function AFNumber_Keystroke(nDec, sepStyle, negStyle, currStyle, strCurrency,
1092// bCurrencyPrepend)
1093FX_BOOL CJS_PublicMethods::AFNumber_Keystroke(IFXJS_Context* cc,
1094 const CJS_Parameters& params,
1095 CJS_Value& vRet,
1096 CFX_WideString& sError) {
1097 CJS_Context* pContext = (CJS_Context*)cc;
1098 ASSERT(pContext != NULL);
1099 CJS_EventHandler* pEvent = pContext->GetEventHandler();
1100 ASSERT(pEvent != NULL);
Lei Zhanga6d9f0e2015-06-13 00:48:38 -07001101
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001102 if (params.size() < 2)
1103 return FALSE;
1104 int iSepStyle = params[1].ToInt();
Lei Zhanga6d9f0e2015-06-13 00:48:38 -07001105
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001106 if (iSepStyle < 0 || iSepStyle > 3)
1107 iSepStyle = 0;
1108 if (!pEvent->m_pValue)
1109 return FALSE;
1110 CFX_WideString& val = pEvent->Value();
1111 CFX_WideString& w_strChange = pEvent->Change();
1112 CFX_WideString w_strValue = val;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001113
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001114 if (pEvent->WillCommit()) {
1115 CFX_WideString wstrChange = w_strChange;
1116 CFX_WideString wstrValue = StrLTrim(w_strValue.c_str());
1117 if (wstrValue.IsEmpty())
1118 return TRUE;
Lei Zhanga6d9f0e2015-06-13 00:48:38 -07001119
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001120 CFX_WideString swTemp = wstrValue;
1121 swTemp.Replace(L",", L".");
1122 if (!IsNumber(swTemp.c_str())) {
1123 pEvent->Rc() = FALSE;
1124 sError = JSGetStringFromID(pContext, IDS_STRING_JSAFNUMBER_KEYSTROKE);
1125 Alert(pContext, sError.c_str());
1126 return TRUE;
Tom Sepez2f2ffec2015-07-23 14:42:09 -07001127 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001128 return TRUE; // it happens after the last keystroke and before validating,
1129 }
Tom Sepez4f7bc042015-04-27 12:06:58 -07001130
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001131 std::wstring w_strValue2 = w_strValue.c_str();
1132 std::wstring w_strChange2 = w_strChange.c_str();
1133 std::wstring w_strSelected;
1134 if (-1 != pEvent->SelStart())
1135 w_strSelected = w_strValue2.substr(pEvent->SelStart(),
1136 (pEvent->SelEnd() - pEvent->SelStart()));
Lei Zhangb9c31972015-08-11 14:09:35 -07001137 bool bHasSign = (w_strValue2.find('-') != std::wstring::npos) &&
1138 (w_strSelected.find('-') == std::wstring::npos);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001139 if (bHasSign) {
1140 // can't insert "change" in front to sign postion.
1141 if (pEvent->SelStart() == 0) {
1142 FX_BOOL& bRc = pEvent->Rc();
1143 bRc = FALSE;
1144 return TRUE;
Tom Sepez2f2ffec2015-07-23 14:42:09 -07001145 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001146 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001147
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001148 char cSep = L'.';
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001149
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001150 switch (iSepStyle) {
Tom Sepez2f2ffec2015-07-23 14:42:09 -07001151 case 0:
1152 case 1:
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001153 cSep = L'.';
1154 break;
Tom Sepez2f2ffec2015-07-23 14:42:09 -07001155 case 2:
1156 case 3:
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001157 cSep = L',';
1158 break;
1159 }
Lei Zhanga6d9f0e2015-06-13 00:48:38 -07001160
Lei Zhangb9c31972015-08-11 14:09:35 -07001161 bool bHasSep = (w_strValue2.find(cSep) != std::wstring::npos);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001162 for (std::wstring::iterator it = w_strChange2.begin();
1163 it != w_strChange2.end(); it++) {
1164 if (*it == cSep) {
1165 if (bHasSep) {
1166 FX_BOOL& bRc = pEvent->Rc();
1167 bRc = FALSE;
Tom Sepez2f2ffec2015-07-23 14:42:09 -07001168 return TRUE;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001169 }
1170 bHasSep = TRUE;
1171 continue;
1172 }
1173 if (*it == L'-') {
1174 if (bHasSign) {
1175 FX_BOOL& bRc = pEvent->Rc();
1176 bRc = FALSE;
1177 return TRUE;
1178 }
1179 if (it != w_strChange2.begin()) // sign's position is not correct
1180 {
1181 FX_BOOL& bRc = pEvent->Rc();
1182 bRc = FALSE;
1183 return TRUE;
1184 }
1185 if (pEvent->SelStart() != 0) {
1186 FX_BOOL& bRc = pEvent->Rc();
1187 bRc = FALSE;
1188 return TRUE;
1189 }
1190 bHasSign = TRUE;
1191 continue;
1192 }
1193
1194 if (!IsDigit(*it)) {
1195 FX_BOOL& bRc = pEvent->Rc();
1196 bRc = FALSE;
1197 return TRUE;
1198 }
1199 }
1200
1201 std::wstring w_prefix = w_strValue2.substr(0, pEvent->SelStart());
1202 std::wstring w_postfix;
1203 if (pEvent->SelEnd() < (int)w_strValue2.length())
1204 w_postfix = w_strValue2.substr(pEvent->SelEnd());
1205 w_strValue2 = w_prefix + w_strChange2 + w_postfix;
1206 w_strValue = w_strValue2.c_str();
1207 val = w_strValue;
1208 return TRUE;
1209}
1210
1211// function AFPercent_Format(nDec, sepStyle)
1212FX_BOOL CJS_PublicMethods::AFPercent_Format(IFXJS_Context* cc,
1213 const CJS_Parameters& params,
1214 CJS_Value& vRet,
1215 CFX_WideString& sError) {
1216#if _FX_OS_ != _FX_ANDROID_
1217 CJS_Context* pContext = (CJS_Context*)cc;
1218 ASSERT(pContext != NULL);
1219 CJS_EventHandler* pEvent = pContext->GetEventHandler();
1220 ASSERT(pEvent != NULL);
1221
1222 if (params.size() != 2) {
1223 sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
1224 return FALSE;
1225 }
1226 if (!pEvent->m_pValue)
1227 return FALSE;
1228
1229 CFX_WideString& Value = pEvent->Value();
1230 CFX_ByteString strValue = StrTrim(CFX_ByteString::FromUnicode(Value));
1231 if (strValue.IsEmpty())
1232 return TRUE;
1233
1234 int iDec = params[0].ToInt();
1235 if (iDec < 0)
1236 iDec = -iDec;
1237
1238 int iSepStyle = params[1].ToInt();
1239 if (iSepStyle < 0 || iSepStyle > 3)
1240 iSepStyle = 0;
1241
1242 //////////////////////////////////////////////////////
1243 // for processing decimal places
1244 double dValue = atof(strValue);
1245 dValue *= 100;
1246 if (iDec > 0)
1247 dValue += DOUBLE_CORRECT; //УÕý
1248
1249 int iDec2;
1250 int iNegative = 0;
1251 strValue = fcvt(dValue, iDec, &iDec2, &iNegative);
1252 if (strValue.IsEmpty()) {
1253 dValue = 0;
1254 strValue = fcvt(dValue, iDec, &iDec2, &iNegative);
1255 }
1256
1257 if (iDec2 < 0) {
1258 for (int iNum = 0; iNum < abs(iDec2); iNum++) {
1259 strValue = "0" + strValue;
1260 }
1261 iDec2 = 0;
1262 }
1263 int iMax = strValue.GetLength();
1264 if (iDec2 > iMax) {
1265 for (int iNum = 0; iNum <= iDec2 - iMax; iNum++) {
1266 strValue += "0";
1267 }
1268 iMax = iDec2 + 1;
1269 }
1270 ///////////////////////////////////////////////////////
1271 // for processing seperator style
1272 if (iDec2 < iMax) {
1273 if (iSepStyle == 0 || iSepStyle == 1) {
1274 strValue.Insert(iDec2, '.');
1275 iMax++;
1276 } else if (iSepStyle == 2 || iSepStyle == 3) {
1277 strValue.Insert(iDec2, ',');
1278 iMax++;
1279 }
1280
1281 if (iDec2 == 0)
1282 strValue.Insert(iDec2, '0');
1283 }
1284 if (iSepStyle == 0 || iSepStyle == 2) {
1285 char cSeperator;
1286 if (iSepStyle == 0)
1287 cSeperator = ',';
1288 else
1289 cSeperator = '.';
1290
1291 int iDecPositive, iDecNegative;
1292 iDecPositive = iDec2;
1293 iDecNegative = iDec2;
1294
1295 for (iDecPositive = iDec2 - 3; iDecPositive > 0; iDecPositive -= 3) {
1296 strValue.Insert(iDecPositive, cSeperator);
1297 iMax++;
1298 }
1299 }
1300 ////////////////////////////////////////////////////////////////////
1301 // negative mark
1302 if (iNegative)
1303 strValue = "-" + strValue;
1304 strValue += "%";
1305 Value = CFX_WideString::FromLocal(strValue);
1306#endif
1307 return TRUE;
1308}
1309// AFPercent_Keystroke(nDec, sepStyle)
1310FX_BOOL CJS_PublicMethods::AFPercent_Keystroke(IFXJS_Context* cc,
1311 const CJS_Parameters& params,
1312 CJS_Value& vRet,
1313 CFX_WideString& sError) {
1314 return AFNumber_Keystroke(cc, params, vRet, sError);
1315}
1316
1317// function AFDate_FormatEx(cFormat)
1318FX_BOOL CJS_PublicMethods::AFDate_FormatEx(IFXJS_Context* cc,
1319 const CJS_Parameters& params,
1320 CJS_Value& vRet,
1321 CFX_WideString& sError) {
1322 CJS_Context* pContext = (CJS_Context*)cc;
1323 ASSERT(pContext != NULL);
1324 CJS_EventHandler* pEvent = pContext->GetEventHandler();
1325 ASSERT(pEvent != NULL);
1326
1327 if (params.size() != 1) {
1328 sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
1329 return FALSE;
1330 }
1331 if (!pEvent->m_pValue)
1332 return FALSE;
1333
1334 CFX_WideString& val = pEvent->Value();
1335 CFX_WideString strValue = val;
1336 if (strValue.IsEmpty())
1337 return TRUE;
1338
1339 CFX_WideString sFormat = params[0].ToCFXWideString();
1340 FX_BOOL bWrongFormat = FALSE;
1341 double dDate = 0.0f;
1342
1343 if (strValue.Find(L"GMT") != -1) {
1344 // for GMT format time
1345 // such as "Tue Aug 11 14:24:16 GMT+08002009"
1346 dDate = MakeInterDate(strValue);
1347 } else {
1348 dDate = MakeRegularDate(strValue, sFormat, bWrongFormat);
1349 }
1350
1351 if (JS_PortIsNan(dDate)) {
1352 CFX_WideString swMsg;
1353 swMsg.Format(JSGetStringFromID(pContext, IDS_STRING_JSPARSEDATE).c_str(),
1354 sFormat.c_str());
1355 Alert(pContext, swMsg.c_str());
1356 return FALSE;
1357 }
1358
1359 val = MakeFormatDate(dDate, sFormat);
1360 return TRUE;
1361}
1362
1363double CJS_PublicMethods::MakeInterDate(CFX_WideString strValue) {
1364 int nHour;
1365 int nMin;
1366 int nSec;
1367 int nYear;
1368 int nMonth;
1369 int nDay;
1370
1371 CFX_WideStringArray wsArray;
1372 CFX_WideString sMonth = L"";
1373 CFX_WideString sTemp = L"";
1374 int nSize = strValue.GetLength();
1375
1376 for (int i = 0; i < nSize; i++) {
1377 FX_WCHAR c = strValue.GetAt(i);
1378 if (c == L' ' || c == L':') {
1379 wsArray.Add(sTemp);
1380 sTemp = L"";
1381 continue;
1382 }
1383
1384 sTemp += c;
1385 }
1386
1387 wsArray.Add(sTemp);
1388 if (wsArray.GetSize() != 8)
1389 return 0;
1390
1391 sTemp = wsArray[1];
1392 if (sTemp.Compare(L"Jan") == 0)
1393 nMonth = 1;
1394 if (sTemp.Compare(L"Feb") == 0)
1395 nMonth = 2;
1396 if (sTemp.Compare(L"Mar") == 0)
1397 nMonth = 3;
1398 if (sTemp.Compare(L"Apr") == 0)
1399 nMonth = 4;
1400 if (sTemp.Compare(L"May") == 0)
1401 nMonth = 5;
1402 if (sTemp.Compare(L"Jun") == 0)
1403 nMonth = 6;
1404 if (sTemp.Compare(L"Jul") == 0)
1405 nMonth = 7;
1406 if (sTemp.Compare(L"Aug") == 0)
1407 nMonth = 8;
1408 if (sTemp.Compare(L"Sep") == 0)
1409 nMonth = 9;
1410 if (sTemp.Compare(L"Oct") == 0)
1411 nMonth = 10;
1412 if (sTemp.Compare(L"Nov") == 0)
1413 nMonth = 11;
1414 if (sTemp.Compare(L"Dec") == 0)
1415 nMonth = 12;
1416
1417 nDay = (int)ParseStringToNumber(wsArray[2].c_str());
1418 nHour = (int)ParseStringToNumber(wsArray[3].c_str());
1419 nMin = (int)ParseStringToNumber(wsArray[4].c_str());
1420 nSec = (int)ParseStringToNumber(wsArray[5].c_str());
1421 nYear = (int)ParseStringToNumber(wsArray[7].c_str());
1422
1423 double dRet = JS_MakeDate(JS_MakeDay(nYear, nMonth - 1, nDay),
1424 JS_MakeTime(nHour, nMin, nSec, 0));
1425
1426 if (JS_PortIsNan(dRet)) {
1427 dRet = JS_DateParse(strValue.c_str());
1428 }
1429
1430 return dRet;
1431}
1432
1433// AFDate_KeystrokeEx(cFormat)
1434FX_BOOL CJS_PublicMethods::AFDate_KeystrokeEx(IFXJS_Context* cc,
1435 const CJS_Parameters& params,
1436 CJS_Value& vRet,
1437 CFX_WideString& sError) {
1438 CJS_Context* pContext = (CJS_Context*)cc;
1439 ASSERT(pContext != NULL);
1440 CJS_EventHandler* pEvent = pContext->GetEventHandler();
1441 ASSERT(pEvent != NULL);
1442
1443 if (params.size() != 1) {
1444 sError = L"AFDate_KeystrokeEx's parameters' size r not correct";
1445 return FALSE;
1446 }
1447
1448 if (pEvent->WillCommit()) {
1449 if (!pEvent->m_pValue)
1450 return FALSE;
1451 CFX_WideString strValue = pEvent->Value();
1452 if (strValue.IsEmpty())
1453 return TRUE;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001454
Tom Sepez2f2ffec2015-07-23 14:42:09 -07001455 CFX_WideString sFormat = params[0].ToCFXWideString();
1456 FX_BOOL bWrongFormat = FALSE;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001457 double dRet = MakeRegularDate(strValue, sFormat, bWrongFormat);
1458 if (bWrongFormat || JS_PortIsNan(dRet)) {
1459 CFX_WideString swMsg;
1460 swMsg.Format(JSGetStringFromID(pContext, IDS_STRING_JSPARSEDATE).c_str(),
1461 sFormat.c_str());
1462 Alert(pContext, swMsg.c_str());
1463 pEvent->Rc() = FALSE;
1464 return TRUE;
Tom Sepez2f2ffec2015-07-23 14:42:09 -07001465 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001466 }
1467 return TRUE;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001468}
1469
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001470FX_BOOL CJS_PublicMethods::AFDate_Format(IFXJS_Context* cc,
1471 const CJS_Parameters& params,
1472 CJS_Value& vRet,
1473 CFX_WideString& sError) {
1474 v8::Isolate* isolate = ::GetIsolate(cc);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001475
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001476 if (params.size() != 1) {
1477 CJS_Context* pContext = (CJS_Context*)cc;
Tom Sepez2f2ffec2015-07-23 14:42:09 -07001478 ASSERT(pContext != NULL);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001479
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001480 sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
1481 return FALSE;
1482 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001483
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001484 int iIndex = params[0].ToInt();
1485 const FX_WCHAR* cFormats[] = {L"m/d",
1486 L"m/d/yy",
1487 L"mm/dd/yy",
1488 L"mm/yy",
1489 L"d-mmm",
1490 L"d-mmm-yy",
1491 L"dd-mmm-yy",
1492 L"yy-mm-dd",
1493 L"mmm-yy",
1494 L"mmmm-yy",
1495 L"mmm d, yyyy",
1496 L"mmmm d, yyyy",
1497 L"m/d/yy h:MM tt",
1498 L"m/d/yy HH:MM"};
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001499
Lei Zhanga0f67242015-08-17 15:39:30 -07001500 if (iIndex < 0 || (static_cast<size_t>(iIndex) >= FX_ArraySize(cFormats)))
1501 iIndex = 0;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001502
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001503 CJS_Parameters newParams;
1504 CJS_Value val(isolate, cFormats[iIndex]);
1505 newParams.push_back(val);
1506 return AFDate_FormatEx(cc, newParams, vRet, sError);
1507}
Lei Zhanga6d9f0e2015-06-13 00:48:38 -07001508
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001509// AFDate_KeystrokeEx(cFormat)
1510FX_BOOL CJS_PublicMethods::AFDate_Keystroke(IFXJS_Context* cc,
1511 const CJS_Parameters& params,
1512 CJS_Value& vRet,
1513 CFX_WideString& sError) {
1514 v8::Isolate* isolate = ::GetIsolate(cc);
1515
1516 if (params.size() != 1) {
1517 CJS_Context* pContext = (CJS_Context*)cc;
1518 ASSERT(pContext != NULL);
1519
1520 sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
1521 return FALSE;
1522 }
1523
1524 int iIndex = params[0].ToInt();
1525 const FX_WCHAR* cFormats[] = {L"m/d",
1526 L"m/d/yy",
1527 L"mm/dd/yy",
1528 L"mm/yy",
1529 L"d-mmm",
1530 L"d-mmm-yy",
1531 L"dd-mmm-yy",
1532 L"yy-mm-dd",
1533 L"mmm-yy",
1534 L"mmmm-yy",
1535 L"mmm d, yyyy",
1536 L"mmmm d, yyyy",
1537 L"m/d/yy h:MM tt",
1538 L"m/d/yy HH:MM"};
1539
Lei Zhanga0f67242015-08-17 15:39:30 -07001540 if (iIndex < 0 || (static_cast<size_t>(iIndex) >= FX_ArraySize(cFormats)))
1541 iIndex = 0;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001542
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001543 CJS_Parameters newParams;
1544 CJS_Value val(isolate, cFormats[iIndex]);
1545 newParams.push_back(val);
1546 return AFDate_KeystrokeEx(cc, newParams, vRet, sError);
1547}
1548
1549// function AFTime_Format(ptf)
1550FX_BOOL CJS_PublicMethods::AFTime_Format(IFXJS_Context* cc,
1551 const CJS_Parameters& params,
1552 CJS_Value& vRet,
1553 CFX_WideString& sError) {
1554 v8::Isolate* isolate = ::GetIsolate(cc);
1555
1556 if (params.size() != 1) {
1557 CJS_Context* pContext = (CJS_Context*)cc;
1558 ASSERT(pContext != NULL);
1559 sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
1560 return FALSE;
1561 }
1562
1563 int iIndex = params[0].ToInt();
1564 const FX_WCHAR* cFormats[] = {L"HH:MM", L"h:MM tt", L"HH:MM:ss",
1565 L"h:MM:ss tt"};
1566
Lei Zhanga0f67242015-08-17 15:39:30 -07001567 if (iIndex < 0 || (static_cast<size_t>(iIndex) >= FX_ArraySize(cFormats)))
1568 iIndex = 0;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001569
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001570 CJS_Parameters newParams;
1571 CJS_Value val(isolate, cFormats[iIndex]);
1572 newParams.push_back(val);
1573 return AFDate_FormatEx(cc, newParams, vRet, sError);
1574}
1575
1576FX_BOOL CJS_PublicMethods::AFTime_Keystroke(IFXJS_Context* cc,
1577 const CJS_Parameters& params,
1578 CJS_Value& vRet,
1579 CFX_WideString& sError) {
1580 v8::Isolate* isolate = ::GetIsolate(cc);
1581 if (params.size() != 1) {
1582 CJS_Context* pContext = (CJS_Context*)cc;
1583 ASSERT(pContext != NULL);
1584 sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
1585 return FALSE;
1586 }
1587
1588 int iIndex = params[0].ToInt();
1589 const FX_WCHAR* cFormats[] = {L"HH:MM", L"h:MM tt", L"HH:MM:ss",
1590 L"h:MM:ss tt"};
1591
Lei Zhanga0f67242015-08-17 15:39:30 -07001592 if (iIndex < 0 || (static_cast<size_t>(iIndex) >= FX_ArraySize(cFormats)))
1593 iIndex = 0;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001594
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001595 CJS_Parameters newParams;
1596 CJS_Value val(isolate, cFormats[iIndex]);
1597 newParams.push_back(val);
1598 return AFDate_KeystrokeEx(cc, newParams, vRet, sError);
1599}
1600
1601FX_BOOL CJS_PublicMethods::AFTime_FormatEx(IFXJS_Context* cc,
1602 const CJS_Parameters& params,
1603 CJS_Value& vRet,
1604 CFX_WideString& sError) {
1605 return AFDate_FormatEx(cc, params, vRet, sError);
1606}
1607
1608FX_BOOL CJS_PublicMethods::AFTime_KeystrokeEx(IFXJS_Context* cc,
1609 const CJS_Parameters& params,
1610 CJS_Value& vRet,
1611 CFX_WideString& sError) {
1612 return AFDate_KeystrokeEx(cc, params, vRet, sError);
1613}
1614
1615// function AFSpecial_Format(psf)
1616FX_BOOL CJS_PublicMethods::AFSpecial_Format(IFXJS_Context* cc,
1617 const CJS_Parameters& params,
1618 CJS_Value& vRet,
1619 CFX_WideString& sError) {
1620 CJS_Context* pContext = (CJS_Context*)cc;
1621 ASSERT(pContext != NULL);
1622
1623 if (params.size() != 1) {
1624 sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
1625 return FALSE;
1626 }
1627
1628 std::string cFormat;
1629 int iIndex = params[0].ToInt();
1630
1631 CJS_EventHandler* pEvent = pContext->GetEventHandler();
1632 ASSERT(pEvent != NULL);
1633
1634 if (!pEvent->m_pValue)
1635 return FALSE;
1636 CFX_WideString& Value = pEvent->Value();
1637 std::string strSrc = CFX_ByteString::FromUnicode(Value).c_str();
1638
1639 switch (iIndex) {
Tom Sepez2f2ffec2015-07-23 14:42:09 -07001640 case 0:
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001641 cFormat = "99999";
1642 break;
Tom Sepez2f2ffec2015-07-23 14:42:09 -07001643 case 1:
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001644 cFormat = "99999-9999";
1645 break;
1646 case 2: {
1647 std::string NumberStr;
1648 util::printx("9999999999", strSrc, NumberStr);
1649 if (NumberStr.length() >= 10)
1650 cFormat = "(999) 999-9999";
1651 else
1652 cFormat = "999-9999";
1653 break;
1654 }
Tom Sepez2f2ffec2015-07-23 14:42:09 -07001655 case 3:
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001656 cFormat = "999-99-9999";
1657 break;
1658 }
1659
1660 std::string strDes;
1661 util::printx(cFormat, strSrc, strDes);
1662 Value = CFX_WideString::FromLocal(strDes.c_str());
1663 return TRUE;
1664}
1665
1666// function AFSpecial_KeystrokeEx(mask)
1667FX_BOOL CJS_PublicMethods::AFSpecial_KeystrokeEx(IFXJS_Context* cc,
1668 const CJS_Parameters& params,
1669 CJS_Value& vRet,
1670 CFX_WideString& sError) {
1671 CJS_Context* pContext = (CJS_Context*)cc;
1672 ASSERT(pContext != NULL);
1673 CJS_EventHandler* pEvent = pContext->GetEventHandler();
1674
1675 ASSERT(pEvent != NULL);
1676
1677 if (params.size() < 1) {
1678 sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
1679 return FALSE;
1680 }
1681
1682 if (!pEvent->m_pValue)
1683 return FALSE;
1684 CFX_WideString& valEvent = pEvent->Value();
1685
1686 CFX_WideString wstrMask = params[0].ToCFXWideString();
1687 if (wstrMask.IsEmpty())
1688 return TRUE;
1689
Lei Zhanga0f67242015-08-17 15:39:30 -07001690 const size_t wstrMaskLen = wstrMask.GetLength();
1691 const std::wstring wstrValue = valEvent.c_str();
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001692
1693 if (pEvent->WillCommit()) {
1694 if (wstrValue.empty())
1695 return TRUE;
Lei Zhanga0f67242015-08-17 15:39:30 -07001696 size_t iIndexMask = 0;
1697 for (const auto& w_Value : wstrValue) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001698 if (!maskSatisfied(w_Value, wstrMask[iIndexMask]))
Tom Sepez2f2ffec2015-07-23 14:42:09 -07001699 break;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001700 iIndexMask++;
Tom Sepez2f2ffec2015-07-23 14:42:09 -07001701 }
Lei Zhanga6d9f0e2015-06-13 00:48:38 -07001702
Lei Zhanga0f67242015-08-17 15:39:30 -07001703 if (iIndexMask != wstrMaskLen ||
1704 (iIndexMask != wstrValue.size() && wstrMaskLen != 0)) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001705 Alert(
1706 pContext,
1707 JSGetStringFromID(pContext, IDS_STRING_JSAFNUMBER_KEYSTROKE).c_str());
1708 pEvent->Rc() = FALSE;
1709 }
Tom Sepez2f2ffec2015-07-23 14:42:09 -07001710 return TRUE;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001711 }
1712
1713 CFX_WideString& wideChange = pEvent->Change();
1714 std::wstring wChange = wideChange.c_str();
1715 if (wChange.empty())
1716 return TRUE;
1717
1718 int iIndexMask = pEvent->SelStart();
1719
Lei Zhanga0f67242015-08-17 15:39:30 -07001720 size_t combined_len = wstrValue.length() + wChange.length() -
1721 (pEvent->SelEnd() - pEvent->SelStart());
1722 if (combined_len > wstrMaskLen) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001723 Alert(pContext,
1724 JSGetStringFromID(pContext, IDS_STRING_JSPARAM_TOOLONG).c_str());
1725 pEvent->Rc() = FALSE;
1726 return TRUE;
1727 }
1728
Lei Zhanga0f67242015-08-17 15:39:30 -07001729 if (iIndexMask >= wstrMaskLen && (!wChange.empty())) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001730 Alert(pContext,
1731 JSGetStringFromID(pContext, IDS_STRING_JSPARAM_TOOLONG).c_str());
1732 pEvent->Rc() = FALSE;
1733 return TRUE;
1734 }
1735
1736 for (std::wstring::iterator it = wChange.begin(); it != wChange.end(); it++) {
Lei Zhanga0f67242015-08-17 15:39:30 -07001737 if (iIndexMask >= wstrMaskLen) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001738 Alert(pContext,
1739 JSGetStringFromID(pContext, IDS_STRING_JSPARAM_TOOLONG).c_str());
1740 pEvent->Rc() = FALSE;
1741 return TRUE;
1742 }
1743 wchar_t w_Mask = wstrMask[iIndexMask];
1744 if (!isReservedMaskChar(w_Mask)) {
1745 *it = w_Mask;
1746 }
1747 wchar_t w_Change = *it;
1748 if (!maskSatisfied(w_Change, w_Mask)) {
1749 pEvent->Rc() = FALSE;
1750 return TRUE;
1751 }
1752 iIndexMask++;
1753 }
1754
1755 wideChange = wChange.c_str();
1756 return TRUE;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001757}
1758
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001759// function AFSpecial_Keystroke(psf)
1760FX_BOOL CJS_PublicMethods::AFSpecial_Keystroke(IFXJS_Context* cc,
1761 const CJS_Parameters& params,
1762 CJS_Value& vRet,
1763 CFX_WideString& sError) {
1764 v8::Isolate* isolate = ::GetIsolate(cc);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001765
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001766 CJS_Context* pContext = (CJS_Context*)cc;
1767 ASSERT(pContext != NULL);
1768 CJS_EventHandler* pEvent = pContext->GetEventHandler();
1769 ASSERT(pEvent != NULL);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001770
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001771 if (params.size() != 1) {
1772 sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
1773 return FALSE;
1774 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001775
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001776 std::string cFormat;
1777 int iIndex = params[0].ToInt();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001778
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001779 if (!pEvent->m_pValue)
1780 return FALSE;
1781 // CJS_Value val = pEvent->Value();
1782 CFX_WideString& val = pEvent->Value();
1783 std::string strSrc = CFX_ByteString::FromUnicode(val).c_str();
1784 std::wstring wstrChange = pEvent->Change().c_str();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001785
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001786 switch (iIndex) {
Tom Sepez2f2ffec2015-07-23 14:42:09 -07001787 case 0:
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001788 cFormat = "99999";
1789 break;
Tom Sepez2f2ffec2015-07-23 14:42:09 -07001790 case 1:
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001791 // cFormat = "99999-9999";
1792 cFormat = "999999999";
1793 break;
1794 case 2: {
1795 std::string NumberStr;
1796 util::printx("9999999999", strSrc, NumberStr);
1797 if (strSrc.length() + wstrChange.length() > 7)
1798 // cFormat = "(999) 999-9999";
1799 cFormat = "9999999999";
1800 else
1801 // cFormat = "999-9999";
1802 cFormat = "9999999";
1803 break;
1804 }
Tom Sepez2f2ffec2015-07-23 14:42:09 -07001805 case 3:
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001806 // cFormat = "999-99-9999";
1807 cFormat = "999999999";
1808 break;
1809 }
Lei Zhanga6d9f0e2015-06-13 00:48:38 -07001810
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001811 CJS_Parameters params2;
1812 CJS_Value vMask(isolate, cFormat.c_str());
1813 params2.push_back(vMask);
Lei Zhanga6d9f0e2015-06-13 00:48:38 -07001814
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001815 return AFSpecial_KeystrokeEx(cc, params2, vRet, sError);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001816}
1817
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001818FX_BOOL CJS_PublicMethods::AFMergeChange(IFXJS_Context* cc,
1819 const CJS_Parameters& params,
1820 CJS_Value& vRet,
1821 CFX_WideString& sError) {
1822 CJS_Context* pContext = (CJS_Context*)cc;
1823 ASSERT(pContext != NULL);
1824 CJS_EventHandler* pEventHandler = pContext->GetEventHandler();
1825 ASSERT(pEventHandler != NULL);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001826
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001827 if (params.size() != 1) {
1828 sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
1829 return FALSE;
1830 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001831
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001832 CFX_WideString swValue;
1833 if (pEventHandler->m_pValue != NULL)
1834 swValue = pEventHandler->Value();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001835
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001836 if (pEventHandler->WillCommit()) {
1837 vRet = swValue.c_str();
Tom Sepez2f2ffec2015-07-23 14:42:09 -07001838 return TRUE;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001839 }
1840
1841 CFX_WideString prefix, postfix;
1842
1843 if (pEventHandler->SelStart() >= 0)
1844 prefix = swValue.Mid(0, pEventHandler->SelStart());
1845 else
1846 prefix = L"";
1847
1848 if (pEventHandler->SelEnd() >= 0 &&
1849 pEventHandler->SelEnd() <= swValue.GetLength())
1850 postfix = swValue.Mid(pEventHandler->SelEnd(),
1851 swValue.GetLength() - pEventHandler->SelEnd());
1852 else
1853 postfix = L"";
1854
1855 vRet = (prefix + pEventHandler->Change() + postfix).c_str();
1856
1857 return TRUE;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001858}
1859
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001860FX_BOOL CJS_PublicMethods::AFParseDateEx(IFXJS_Context* cc,
1861 const CJS_Parameters& params,
1862 CJS_Value& vRet,
1863 CFX_WideString& sError) {
1864 CJS_Context* pContext = (CJS_Context*)cc;
1865 ASSERT(pContext != NULL);
1866
1867 if (params.size() != 2) {
1868 sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
1869 return FALSE;
1870 }
1871
1872 CFX_WideString sValue = params[0].ToCFXWideString();
1873 CFX_WideString sFormat = params[1].ToCFXWideString();
1874
1875 FX_BOOL bWrongFormat = FALSE;
1876 double dDate = MakeRegularDate(sValue, sFormat, bWrongFormat);
1877
1878 if (JS_PortIsNan(dDate)) {
1879 CFX_WideString swMsg;
1880 swMsg.Format(JSGetStringFromID(pContext, IDS_STRING_JSPARSEDATE).c_str(),
1881 sFormat.c_str());
1882 Alert((CJS_Context*)cc, swMsg.c_str());
1883 return FALSE;
1884 }
1885
1886 vRet = dDate;
1887 return TRUE;
1888}
1889
1890FX_BOOL CJS_PublicMethods::AFSimple(IFXJS_Context* cc,
1891 const CJS_Parameters& params,
1892 CJS_Value& vRet,
1893 CFX_WideString& sError) {
1894 if (params.size() != 3) {
1895 CJS_Context* pContext = (CJS_Context*)cc;
Tom Sepez2f2ffec2015-07-23 14:42:09 -07001896 ASSERT(pContext != NULL);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001897
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001898 sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
1899 return FALSE;
1900 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001901
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001902 vRet = (double)AF_Simple(params[0].ToCFXWideString().c_str(),
1903 params[1].ToDouble(), params[2].ToDouble());
1904 return TRUE;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001905}
1906
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001907FX_BOOL CJS_PublicMethods::AFMakeNumber(IFXJS_Context* cc,
1908 const CJS_Parameters& params,
1909 CJS_Value& vRet,
1910 CFX_WideString& sError) {
1911 if (params.size() != 1) {
1912 CJS_Context* pContext = (CJS_Context*)cc;
Tom Sepez2f2ffec2015-07-23 14:42:09 -07001913 ASSERT(pContext != NULL);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001914
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001915 sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
1916 return FALSE;
1917 }
1918 vRet = ParseStringToNumber(params[0].ToCFXWideString().c_str());
1919 return TRUE;
1920}
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001921
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001922FX_BOOL CJS_PublicMethods::AFSimple_Calculate(IFXJS_Context* cc,
1923 const CJS_Parameters& params,
1924 CJS_Value& vRet,
1925 CFX_WideString& sError) {
1926 v8::Isolate* isolate = ::GetIsolate(cc);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001927
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001928 CJS_Context* pContext = (CJS_Context*)cc;
1929 ASSERT(pContext != NULL);
Tom Sepezf4ef3f92015-04-23 11:31:31 -07001930
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001931 if (params.size() != 2) {
1932 sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
1933 return FALSE;
1934 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001935
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001936 CJS_Value params1 = params[1];
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001937
Tom Sepez39bfe122015-09-17 15:25:23 -07001938 if (!params1.IsArrayObject() && params1.GetType() != CJS_Value::VT_string) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001939 sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
1940 return FALSE;
1941 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001942
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001943 CPDFSDK_Document* pReaderDoc = pContext->GetReaderDocument();
1944 ASSERT(pReaderDoc != NULL);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001945
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001946 CPDFSDK_InterForm* pReaderInterForm = pReaderDoc->GetInterForm();
1947 ASSERT(pReaderInterForm != NULL);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001948
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001949 CPDF_InterForm* pInterForm = pReaderInterForm->GetInterForm();
1950 ASSERT(pInterForm != NULL);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001951
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001952 double dValue;
1953 CFX_WideString sFunction = params[0].ToCFXWideString();
1954 if (wcscmp(sFunction.c_str(), L"PRD") == 0)
1955 dValue = 1.0;
1956 else
1957 dValue = 0.0;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001958
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001959 CJS_Array FieldNameArray = AF_MakeArrayFromList(isolate, params1);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001960
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001961 int nFieldsCount = 0;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001962
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001963 for (int i = 0, isz = FieldNameArray.GetLength(); i < isz; i++) {
1964 CJS_Value jsValue(isolate);
1965 FieldNameArray.GetElement(i, jsValue);
1966 CFX_WideString wsFieldName = jsValue.ToCFXWideString();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001967
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001968 for (int j = 0, jsz = pInterForm->CountFields(wsFieldName); j < jsz; j++) {
1969 if (CPDF_FormField* pFormField = pInterForm->GetField(j, wsFieldName)) {
1970 double dTemp = 0.0;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001971
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001972 switch (pFormField->GetFieldType()) {
1973 case FIELDTYPE_TEXTFIELD:
1974 case FIELDTYPE_COMBOBOX: {
1975 dTemp = ParseStringToNumber(pFormField->GetValue().c_str());
1976 break;
1977 }
1978 case FIELDTYPE_PUSHBUTTON: {
1979 dTemp = 0.0;
1980 break;
1981 }
1982 case FIELDTYPE_CHECKBOX:
1983 case FIELDTYPE_RADIOBUTTON: {
1984 dTemp = 0.0;
1985 for (int c = 0, csz = pFormField->CountControls(); c < csz; c++) {
1986 if (CPDF_FormControl* pFormCtrl = pFormField->GetControl(c)) {
1987 if (pFormCtrl->IsChecked()) {
1988 dTemp +=
1989 ParseStringToNumber(pFormCtrl->GetExportValue().c_str());
1990 break;
1991 } else
1992 continue;
1993 }
Tom Sepez2f2ffec2015-07-23 14:42:09 -07001994 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001995 break;
1996 }
1997 case FIELDTYPE_LISTBOX: {
1998 dTemp = 0.0;
1999 if (pFormField->CountSelectedItems() > 1)
2000 break;
2001 else {
2002 dTemp = ParseStringToNumber(pFormField->GetValue().c_str());
2003 break;
2004 }
2005 }
2006 default:
2007 break;
Tom Sepez2f2ffec2015-07-23 14:42:09 -07002008 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -07002009
2010 if (i == 0 && j == 0 && (wcscmp(sFunction.c_str(), L"MIN") == 0 ||
2011 wcscmp(sFunction.c_str(), L"MAX") == 0))
2012 dValue = dTemp;
2013
2014 dValue = AF_Simple(sFunction.c_str(), dValue, dTemp);
2015
2016 nFieldsCount++;
2017 }
Tom Sepez2f2ffec2015-07-23 14:42:09 -07002018 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -07002019 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07002020
Nico Weber9d8ec5a2015-08-04 13:00:21 -07002021 if (wcscmp(sFunction.c_str(), L"AVG") == 0 && nFieldsCount > 0)
2022 dValue /= nFieldsCount;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07002023
Nico Weber9d8ec5a2015-08-04 13:00:21 -07002024 dValue = (double)floor(dValue * FXSYS_pow((double)10, (double)6) + 0.49) /
2025 FXSYS_pow((double)10, (double)6);
2026 CJS_Value jsValue(isolate, dValue);
foxit8b544ed2015-09-10 14:57:54 +08002027 if (pContext->GetEventHandler()->m_pValue)
2028 pContext->GetEventHandler()->Value() = jsValue.ToCFXWideString();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07002029
Nico Weber9d8ec5a2015-08-04 13:00:21 -07002030 return TRUE;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07002031}
2032
Lei Zhanga6d9f0e2015-06-13 00:48:38 -07002033/* This function validates the current event to ensure that its value is
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07002034** within the specified range. */
2035
Nico Weber9d8ec5a2015-08-04 13:00:21 -07002036FX_BOOL CJS_PublicMethods::AFRange_Validate(IFXJS_Context* cc,
2037 const CJS_Parameters& params,
2038 CJS_Value& vRet,
2039 CFX_WideString& sError) {
2040 CJS_Context* pContext = (CJS_Context*)cc;
2041 ASSERT(pContext != NULL);
2042 CJS_EventHandler* pEvent = pContext->GetEventHandler();
2043 ASSERT(pEvent != NULL);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07002044
Nico Weber9d8ec5a2015-08-04 13:00:21 -07002045 if (params.size() != 4) {
2046 sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
2047 return FALSE;
2048 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07002049
Nico Weber9d8ec5a2015-08-04 13:00:21 -07002050 if (!pEvent->m_pValue)
2051 return FALSE;
2052 if (pEvent->Value().IsEmpty())
Tom Sepez2f2ffec2015-07-23 14:42:09 -07002053 return TRUE;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07002054 double dEentValue = atof(CFX_ByteString::FromUnicode(pEvent->Value()));
2055 FX_BOOL bGreaterThan = params[0].ToBool();
2056 double dGreaterThan = params[1].ToDouble();
2057 FX_BOOL bLessThan = params[2].ToBool();
2058 double dLessThan = params[3].ToDouble();
2059 CFX_WideString swMsg;
2060
2061 if (bGreaterThan && bLessThan) {
2062 if (dEentValue < dGreaterThan || dEentValue > dLessThan)
2063 swMsg.Format(JSGetStringFromID(pContext, IDS_STRING_JSRANGE1).c_str(),
2064 params[1].ToCFXWideString().c_str(),
2065 params[3].ToCFXWideString().c_str());
2066 } else if (bGreaterThan) {
2067 if (dEentValue < dGreaterThan)
2068 swMsg.Format(JSGetStringFromID(pContext, IDS_STRING_JSRANGE2).c_str(),
2069 params[1].ToCFXWideString().c_str());
2070 } else if (bLessThan) {
2071 if (dEentValue > dLessThan)
2072 swMsg.Format(JSGetStringFromID(pContext, IDS_STRING_JSRANGE3).c_str(),
2073 params[3].ToCFXWideString().c_str());
2074 }
2075
2076 if (!swMsg.IsEmpty()) {
2077 Alert(pContext, swMsg.c_str());
2078 pEvent->Rc() = FALSE;
2079 }
2080 return TRUE;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07002081}
2082
Nico Weber9d8ec5a2015-08-04 13:00:21 -07002083FX_BOOL CJS_PublicMethods::AFExtractNums(IFXJS_Context* cc,
2084 const CJS_Parameters& params,
2085 CJS_Value& vRet,
2086 CFX_WideString& sError) {
2087 v8::Isolate* isolate = ::GetIsolate(cc);
2088 CJS_Context* pContext = (CJS_Context*)cc;
2089 ASSERT(pContext != NULL);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07002090
Nico Weber9d8ec5a2015-08-04 13:00:21 -07002091 if (params.size() != 1) {
2092 sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
2093 return FALSE;
2094 }
2095
2096 CJS_Array nums(isolate);
2097
2098 CFX_WideString str = params[0].ToCFXWideString();
2099 CFX_WideString sPart;
2100
2101 if (str.GetAt(0) == L'.' || str.GetAt(0) == L',')
2102 str = L"0" + str;
2103
2104 int nIndex = 0;
2105 for (int i = 0, sz = str.GetLength(); i < sz; i++) {
2106 FX_WCHAR wc = str.GetAt(i);
2107 if (IsDigit((wchar_t)wc)) {
2108 sPart += wc;
2109 } else {
2110 if (sPart.GetLength() > 0) {
2111 nums.SetElement(nIndex, CJS_Value(isolate, sPart.c_str()));
2112 sPart = L"";
2113 nIndex++;
2114 }
Tom Sepez2f2ffec2015-07-23 14:42:09 -07002115 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -07002116 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07002117
Nico Weber9d8ec5a2015-08-04 13:00:21 -07002118 if (sPart.GetLength() > 0) {
2119 nums.SetElement(nIndex, CJS_Value(isolate, sPart.c_str()));
2120 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07002121
Nico Weber9d8ec5a2015-08-04 13:00:21 -07002122 if (nums.GetLength() > 0)
2123 vRet = nums;
2124 else
2125 vRet.SetNull();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07002126
Nico Weber9d8ec5a2015-08-04 13:00:21 -07002127 return TRUE;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07002128}