blob: f71ea37c20b764e1f93cad85f73adca4be224c8c [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
7#include "../../include/javascript/JavaScript.h"
8#include "../../include/javascript/IJavaScript.h"
9#include "../../include/javascript/JS_Define.h"
10#include "../../include/javascript/JS_Object.h"
11#include "../../include/javascript/JS_Value.h"
12#include "../../include/javascript/PublicMethods.h"
13#include "../../include/javascript/JS_EventHandler.h"
14#include "../../include/javascript/resource.h"
15#include "../../include/javascript/JS_Context.h"
16#include "../../include/javascript/JS_Value.h"
17#include "../../include/javascript/util.h"
18#include "../../include/javascript/Field.h"
19#include "../../include/javascript/color.h"
20#include "../../include/javascript/JS_Runtime.h"
21
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
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001501 ASSERT(iIndex < FX_ArraySize(cFormats));
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001502
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001503 if (iIndex < 0)
1504 iIndex = 0;
1505 if (iIndex >= FX_ArraySize(cFormats))
1506 iIndex = 0;
1507 CJS_Parameters newParams;
1508 CJS_Value val(isolate, cFormats[iIndex]);
1509 newParams.push_back(val);
1510 return AFDate_FormatEx(cc, newParams, vRet, sError);
1511}
Lei Zhanga6d9f0e2015-06-13 00:48:38 -07001512
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001513// AFDate_KeystrokeEx(cFormat)
1514FX_BOOL CJS_PublicMethods::AFDate_Keystroke(IFXJS_Context* cc,
1515 const CJS_Parameters& params,
1516 CJS_Value& vRet,
1517 CFX_WideString& sError) {
1518 v8::Isolate* isolate = ::GetIsolate(cc);
1519
1520 if (params.size() != 1) {
1521 CJS_Context* pContext = (CJS_Context*)cc;
1522 ASSERT(pContext != NULL);
1523
1524 sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
1525 return FALSE;
1526 }
1527
1528 int iIndex = params[0].ToInt();
1529 const FX_WCHAR* cFormats[] = {L"m/d",
1530 L"m/d/yy",
1531 L"mm/dd/yy",
1532 L"mm/yy",
1533 L"d-mmm",
1534 L"d-mmm-yy",
1535 L"dd-mmm-yy",
1536 L"yy-mm-dd",
1537 L"mmm-yy",
1538 L"mmmm-yy",
1539 L"mmm d, yyyy",
1540 L"mmmm d, yyyy",
1541 L"m/d/yy h:MM tt",
1542 L"m/d/yy HH:MM"};
1543
1544 ASSERT(iIndex < FX_ArraySize(cFormats));
1545
1546 if (iIndex < 0)
1547 iIndex = 0;
1548 if (iIndex >= FX_ArraySize(cFormats))
1549 iIndex = 0;
1550 CJS_Parameters newParams;
1551 CJS_Value val(isolate, cFormats[iIndex]);
1552 newParams.push_back(val);
1553 return AFDate_KeystrokeEx(cc, newParams, vRet, sError);
1554}
1555
1556// function AFTime_Format(ptf)
1557FX_BOOL CJS_PublicMethods::AFTime_Format(IFXJS_Context* cc,
1558 const CJS_Parameters& params,
1559 CJS_Value& vRet,
1560 CFX_WideString& sError) {
1561 v8::Isolate* isolate = ::GetIsolate(cc);
1562
1563 if (params.size() != 1) {
1564 CJS_Context* pContext = (CJS_Context*)cc;
1565 ASSERT(pContext != NULL);
1566 sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
1567 return FALSE;
1568 }
1569
1570 int iIndex = params[0].ToInt();
1571 const FX_WCHAR* cFormats[] = {L"HH:MM", L"h:MM tt", L"HH:MM:ss",
1572 L"h:MM:ss tt"};
1573
1574 ASSERT(iIndex < FX_ArraySize(cFormats));
1575
1576 if (iIndex < 0)
1577 iIndex = 0;
1578 if (iIndex >= FX_ArraySize(cFormats))
1579 iIndex = 0;
1580 CJS_Parameters newParams;
1581 CJS_Value val(isolate, cFormats[iIndex]);
1582 newParams.push_back(val);
1583 return AFDate_FormatEx(cc, newParams, vRet, sError);
1584}
1585
1586FX_BOOL CJS_PublicMethods::AFTime_Keystroke(IFXJS_Context* cc,
1587 const CJS_Parameters& params,
1588 CJS_Value& vRet,
1589 CFX_WideString& sError) {
1590 v8::Isolate* isolate = ::GetIsolate(cc);
1591 if (params.size() != 1) {
1592 CJS_Context* pContext = (CJS_Context*)cc;
1593 ASSERT(pContext != NULL);
1594 sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
1595 return FALSE;
1596 }
1597
1598 int iIndex = params[0].ToInt();
1599 const FX_WCHAR* cFormats[] = {L"HH:MM", L"h:MM tt", L"HH:MM:ss",
1600 L"h:MM:ss tt"};
1601
1602 ASSERT(iIndex < FX_ArraySize(cFormats));
1603
1604 if (iIndex < 0)
1605 iIndex = 0;
1606 if (iIndex >= FX_ArraySize(cFormats))
1607 iIndex = 0;
1608 CJS_Parameters newParams;
1609 CJS_Value val(isolate, cFormats[iIndex]);
1610 newParams.push_back(val);
1611 return AFDate_KeystrokeEx(cc, newParams, vRet, sError);
1612}
1613
1614FX_BOOL CJS_PublicMethods::AFTime_FormatEx(IFXJS_Context* cc,
1615 const CJS_Parameters& params,
1616 CJS_Value& vRet,
1617 CFX_WideString& sError) {
1618 return AFDate_FormatEx(cc, params, vRet, sError);
1619}
1620
1621FX_BOOL CJS_PublicMethods::AFTime_KeystrokeEx(IFXJS_Context* cc,
1622 const CJS_Parameters& params,
1623 CJS_Value& vRet,
1624 CFX_WideString& sError) {
1625 return AFDate_KeystrokeEx(cc, params, vRet, sError);
1626}
1627
1628// function AFSpecial_Format(psf)
1629FX_BOOL CJS_PublicMethods::AFSpecial_Format(IFXJS_Context* cc,
1630 const CJS_Parameters& params,
1631 CJS_Value& vRet,
1632 CFX_WideString& sError) {
1633 CJS_Context* pContext = (CJS_Context*)cc;
1634 ASSERT(pContext != NULL);
1635
1636 if (params.size() != 1) {
1637 sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
1638 return FALSE;
1639 }
1640
1641 std::string cFormat;
1642 int iIndex = params[0].ToInt();
1643
1644 CJS_EventHandler* pEvent = pContext->GetEventHandler();
1645 ASSERT(pEvent != NULL);
1646
1647 if (!pEvent->m_pValue)
1648 return FALSE;
1649 CFX_WideString& Value = pEvent->Value();
1650 std::string strSrc = CFX_ByteString::FromUnicode(Value).c_str();
1651
1652 switch (iIndex) {
Tom Sepez2f2ffec2015-07-23 14:42:09 -07001653 case 0:
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001654 cFormat = "99999";
1655 break;
Tom Sepez2f2ffec2015-07-23 14:42:09 -07001656 case 1:
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001657 cFormat = "99999-9999";
1658 break;
1659 case 2: {
1660 std::string NumberStr;
1661 util::printx("9999999999", strSrc, NumberStr);
1662 if (NumberStr.length() >= 10)
1663 cFormat = "(999) 999-9999";
1664 else
1665 cFormat = "999-9999";
1666 break;
1667 }
Tom Sepez2f2ffec2015-07-23 14:42:09 -07001668 case 3:
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001669 cFormat = "999-99-9999";
1670 break;
1671 }
1672
1673 std::string strDes;
1674 util::printx(cFormat, strSrc, strDes);
1675 Value = CFX_WideString::FromLocal(strDes.c_str());
1676 return TRUE;
1677}
1678
1679// function AFSpecial_KeystrokeEx(mask)
1680FX_BOOL CJS_PublicMethods::AFSpecial_KeystrokeEx(IFXJS_Context* cc,
1681 const CJS_Parameters& params,
1682 CJS_Value& vRet,
1683 CFX_WideString& sError) {
1684 CJS_Context* pContext = (CJS_Context*)cc;
1685 ASSERT(pContext != NULL);
1686 CJS_EventHandler* pEvent = pContext->GetEventHandler();
1687
1688 ASSERT(pEvent != NULL);
1689
1690 if (params.size() < 1) {
1691 sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
1692 return FALSE;
1693 }
1694
1695 if (!pEvent->m_pValue)
1696 return FALSE;
1697 CFX_WideString& valEvent = pEvent->Value();
1698
1699 CFX_WideString wstrMask = params[0].ToCFXWideString();
1700 if (wstrMask.IsEmpty())
1701 return TRUE;
1702
1703 std::wstring wstrValue = valEvent.c_str();
1704
1705 if (pEvent->WillCommit()) {
1706 if (wstrValue.empty())
1707 return TRUE;
1708 int iIndexMask = 0;
1709 for (std::wstring::iterator it = wstrValue.begin(); it != wstrValue.end();
1710 it++) {
1711 wchar_t w_Value = *it;
1712 if (!maskSatisfied(w_Value, wstrMask[iIndexMask]))
Tom Sepez2f2ffec2015-07-23 14:42:09 -07001713 break;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001714 iIndexMask++;
Tom Sepez2f2ffec2015-07-23 14:42:09 -07001715 }
Lei Zhanga6d9f0e2015-06-13 00:48:38 -07001716
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001717 if (iIndexMask != wstrMask.GetLength() ||
1718 (iIndexMask != wstrValue.size() && wstrMask.GetLength() != 0)) {
1719 Alert(
1720 pContext,
1721 JSGetStringFromID(pContext, IDS_STRING_JSAFNUMBER_KEYSTROKE).c_str());
1722 pEvent->Rc() = FALSE;
1723 }
Tom Sepez2f2ffec2015-07-23 14:42:09 -07001724 return TRUE;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001725 }
1726
1727 CFX_WideString& wideChange = pEvent->Change();
1728 std::wstring wChange = wideChange.c_str();
1729 if (wChange.empty())
1730 return TRUE;
1731
1732 int iIndexMask = pEvent->SelStart();
1733
1734 if (wstrValue.length() - (pEvent->SelEnd() - pEvent->SelStart()) +
1735 wChange.length() >
1736 (FX_DWORD)wstrMask.GetLength()) {
1737 Alert(pContext,
1738 JSGetStringFromID(pContext, IDS_STRING_JSPARAM_TOOLONG).c_str());
1739 pEvent->Rc() = FALSE;
1740 return TRUE;
1741 }
1742
1743 if (iIndexMask >= wstrMask.GetLength() && (!wChange.empty())) {
1744 Alert(pContext,
1745 JSGetStringFromID(pContext, IDS_STRING_JSPARAM_TOOLONG).c_str());
1746 pEvent->Rc() = FALSE;
1747 return TRUE;
1748 }
1749
1750 for (std::wstring::iterator it = wChange.begin(); it != wChange.end(); it++) {
1751 if (iIndexMask >= wstrMask.GetLength()) {
1752 Alert(pContext,
1753 JSGetStringFromID(pContext, IDS_STRING_JSPARAM_TOOLONG).c_str());
1754 pEvent->Rc() = FALSE;
1755 return TRUE;
1756 }
1757 wchar_t w_Mask = wstrMask[iIndexMask];
1758 if (!isReservedMaskChar(w_Mask)) {
1759 *it = w_Mask;
1760 }
1761 wchar_t w_Change = *it;
1762 if (!maskSatisfied(w_Change, w_Mask)) {
1763 pEvent->Rc() = FALSE;
1764 return TRUE;
1765 }
1766 iIndexMask++;
1767 }
1768
1769 wideChange = wChange.c_str();
1770 return TRUE;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001771}
1772
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001773// function AFSpecial_Keystroke(psf)
1774FX_BOOL CJS_PublicMethods::AFSpecial_Keystroke(IFXJS_Context* cc,
1775 const CJS_Parameters& params,
1776 CJS_Value& vRet,
1777 CFX_WideString& sError) {
1778 v8::Isolate* isolate = ::GetIsolate(cc);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001779
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001780 CJS_Context* pContext = (CJS_Context*)cc;
1781 ASSERT(pContext != NULL);
1782 CJS_EventHandler* pEvent = pContext->GetEventHandler();
1783 ASSERT(pEvent != NULL);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001784
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001785 if (params.size() != 1) {
1786 sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
1787 return FALSE;
1788 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001789
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001790 std::string cFormat;
1791 int iIndex = params[0].ToInt();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001792
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001793 if (!pEvent->m_pValue)
1794 return FALSE;
1795 // CJS_Value val = pEvent->Value();
1796 CFX_WideString& val = pEvent->Value();
1797 std::string strSrc = CFX_ByteString::FromUnicode(val).c_str();
1798 std::wstring wstrChange = pEvent->Change().c_str();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001799
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001800 switch (iIndex) {
Tom Sepez2f2ffec2015-07-23 14:42:09 -07001801 case 0:
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001802 cFormat = "99999";
1803 break;
Tom Sepez2f2ffec2015-07-23 14:42:09 -07001804 case 1:
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001805 // cFormat = "99999-9999";
1806 cFormat = "999999999";
1807 break;
1808 case 2: {
1809 std::string NumberStr;
1810 util::printx("9999999999", strSrc, NumberStr);
1811 if (strSrc.length() + wstrChange.length() > 7)
1812 // cFormat = "(999) 999-9999";
1813 cFormat = "9999999999";
1814 else
1815 // cFormat = "999-9999";
1816 cFormat = "9999999";
1817 break;
1818 }
Tom Sepez2f2ffec2015-07-23 14:42:09 -07001819 case 3:
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001820 // cFormat = "999-99-9999";
1821 cFormat = "999999999";
1822 break;
1823 }
Lei Zhanga6d9f0e2015-06-13 00:48:38 -07001824
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001825 CJS_Parameters params2;
1826 CJS_Value vMask(isolate, cFormat.c_str());
1827 params2.push_back(vMask);
Lei Zhanga6d9f0e2015-06-13 00:48:38 -07001828
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001829 return AFSpecial_KeystrokeEx(cc, params2, vRet, sError);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001830}
1831
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001832FX_BOOL CJS_PublicMethods::AFMergeChange(IFXJS_Context* cc,
1833 const CJS_Parameters& params,
1834 CJS_Value& vRet,
1835 CFX_WideString& sError) {
1836 CJS_Context* pContext = (CJS_Context*)cc;
1837 ASSERT(pContext != NULL);
1838 CJS_EventHandler* pEventHandler = pContext->GetEventHandler();
1839 ASSERT(pEventHandler != NULL);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001840
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001841 if (params.size() != 1) {
1842 sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
1843 return FALSE;
1844 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001845
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001846 CFX_WideString swValue;
1847 if (pEventHandler->m_pValue != NULL)
1848 swValue = pEventHandler->Value();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001849
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001850 if (pEventHandler->WillCommit()) {
1851 vRet = swValue.c_str();
Tom Sepez2f2ffec2015-07-23 14:42:09 -07001852 return TRUE;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001853 }
1854
1855 CFX_WideString prefix, postfix;
1856
1857 if (pEventHandler->SelStart() >= 0)
1858 prefix = swValue.Mid(0, pEventHandler->SelStart());
1859 else
1860 prefix = L"";
1861
1862 if (pEventHandler->SelEnd() >= 0 &&
1863 pEventHandler->SelEnd() <= swValue.GetLength())
1864 postfix = swValue.Mid(pEventHandler->SelEnd(),
1865 swValue.GetLength() - pEventHandler->SelEnd());
1866 else
1867 postfix = L"";
1868
1869 vRet = (prefix + pEventHandler->Change() + postfix).c_str();
1870
1871 return TRUE;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001872}
1873
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001874FX_BOOL CJS_PublicMethods::AFParseDateEx(IFXJS_Context* cc,
1875 const CJS_Parameters& params,
1876 CJS_Value& vRet,
1877 CFX_WideString& sError) {
1878 CJS_Context* pContext = (CJS_Context*)cc;
1879 ASSERT(pContext != NULL);
1880
1881 if (params.size() != 2) {
1882 sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
1883 return FALSE;
1884 }
1885
1886 CFX_WideString sValue = params[0].ToCFXWideString();
1887 CFX_WideString sFormat = params[1].ToCFXWideString();
1888
1889 FX_BOOL bWrongFormat = FALSE;
1890 double dDate = MakeRegularDate(sValue, sFormat, bWrongFormat);
1891
1892 if (JS_PortIsNan(dDate)) {
1893 CFX_WideString swMsg;
1894 swMsg.Format(JSGetStringFromID(pContext, IDS_STRING_JSPARSEDATE).c_str(),
1895 sFormat.c_str());
1896 Alert((CJS_Context*)cc, swMsg.c_str());
1897 return FALSE;
1898 }
1899
1900 vRet = dDate;
1901 return TRUE;
1902}
1903
1904FX_BOOL CJS_PublicMethods::AFSimple(IFXJS_Context* cc,
1905 const CJS_Parameters& params,
1906 CJS_Value& vRet,
1907 CFX_WideString& sError) {
1908 if (params.size() != 3) {
1909 CJS_Context* pContext = (CJS_Context*)cc;
Tom Sepez2f2ffec2015-07-23 14:42:09 -07001910 ASSERT(pContext != NULL);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001911
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001912 sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
1913 return FALSE;
1914 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001915
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001916 vRet = (double)AF_Simple(params[0].ToCFXWideString().c_str(),
1917 params[1].ToDouble(), params[2].ToDouble());
1918 return TRUE;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001919}
1920
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001921FX_BOOL CJS_PublicMethods::AFMakeNumber(IFXJS_Context* cc,
1922 const CJS_Parameters& params,
1923 CJS_Value& vRet,
1924 CFX_WideString& sError) {
1925 if (params.size() != 1) {
1926 CJS_Context* pContext = (CJS_Context*)cc;
Tom Sepez2f2ffec2015-07-23 14:42:09 -07001927 ASSERT(pContext != NULL);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001928
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001929 sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
1930 return FALSE;
1931 }
1932 vRet = ParseStringToNumber(params[0].ToCFXWideString().c_str());
1933 return TRUE;
1934}
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001935
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001936FX_BOOL CJS_PublicMethods::AFSimple_Calculate(IFXJS_Context* cc,
1937 const CJS_Parameters& params,
1938 CJS_Value& vRet,
1939 CFX_WideString& sError) {
1940 v8::Isolate* isolate = ::GetIsolate(cc);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001941
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001942 CJS_Context* pContext = (CJS_Context*)cc;
1943 ASSERT(pContext != NULL);
Tom Sepezf4ef3f92015-04-23 11:31:31 -07001944
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001945 if (params.size() != 2) {
1946 sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
1947 return FALSE;
1948 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001949
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001950 CJS_Value params1 = params[1];
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001951
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001952 if (!params1.IsArrayObject() && params1.GetType() != VT_string) {
1953 sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
1954 return FALSE;
1955 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001956
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001957 CPDFSDK_Document* pReaderDoc = pContext->GetReaderDocument();
1958 ASSERT(pReaderDoc != NULL);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001959
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001960 CPDFSDK_InterForm* pReaderInterForm = pReaderDoc->GetInterForm();
1961 ASSERT(pReaderInterForm != NULL);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001962
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001963 CPDF_InterForm* pInterForm = pReaderInterForm->GetInterForm();
1964 ASSERT(pInterForm != NULL);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001965
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001966 double dValue;
1967 CFX_WideString sFunction = params[0].ToCFXWideString();
1968 if (wcscmp(sFunction.c_str(), L"PRD") == 0)
1969 dValue = 1.0;
1970 else
1971 dValue = 0.0;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001972
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001973 CJS_Array FieldNameArray = AF_MakeArrayFromList(isolate, params1);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001974
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001975 int nFieldsCount = 0;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001976
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001977 for (int i = 0, isz = FieldNameArray.GetLength(); i < isz; i++) {
1978 CJS_Value jsValue(isolate);
1979 FieldNameArray.GetElement(i, jsValue);
1980 CFX_WideString wsFieldName = jsValue.ToCFXWideString();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001981
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001982 for (int j = 0, jsz = pInterForm->CountFields(wsFieldName); j < jsz; j++) {
1983 if (CPDF_FormField* pFormField = pInterForm->GetField(j, wsFieldName)) {
1984 double dTemp = 0.0;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001985
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001986 switch (pFormField->GetFieldType()) {
1987 case FIELDTYPE_TEXTFIELD:
1988 case FIELDTYPE_COMBOBOX: {
1989 dTemp = ParseStringToNumber(pFormField->GetValue().c_str());
1990 break;
1991 }
1992 case FIELDTYPE_PUSHBUTTON: {
1993 dTemp = 0.0;
1994 break;
1995 }
1996 case FIELDTYPE_CHECKBOX:
1997 case FIELDTYPE_RADIOBUTTON: {
1998 dTemp = 0.0;
1999 for (int c = 0, csz = pFormField->CountControls(); c < csz; c++) {
2000 if (CPDF_FormControl* pFormCtrl = pFormField->GetControl(c)) {
2001 if (pFormCtrl->IsChecked()) {
2002 dTemp +=
2003 ParseStringToNumber(pFormCtrl->GetExportValue().c_str());
2004 break;
2005 } else
2006 continue;
2007 }
Tom Sepez2f2ffec2015-07-23 14:42:09 -07002008 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -07002009 break;
2010 }
2011 case FIELDTYPE_LISTBOX: {
2012 dTemp = 0.0;
2013 if (pFormField->CountSelectedItems() > 1)
2014 break;
2015 else {
2016 dTemp = ParseStringToNumber(pFormField->GetValue().c_str());
2017 break;
2018 }
2019 }
2020 default:
2021 break;
Tom Sepez2f2ffec2015-07-23 14:42:09 -07002022 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -07002023
2024 if (i == 0 && j == 0 && (wcscmp(sFunction.c_str(), L"MIN") == 0 ||
2025 wcscmp(sFunction.c_str(), L"MAX") == 0))
2026 dValue = dTemp;
2027
2028 dValue = AF_Simple(sFunction.c_str(), dValue, dTemp);
2029
2030 nFieldsCount++;
2031 }
Tom Sepez2f2ffec2015-07-23 14:42:09 -07002032 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -07002033 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07002034
Nico Weber9d8ec5a2015-08-04 13:00:21 -07002035 if (wcscmp(sFunction.c_str(), L"AVG") == 0 && nFieldsCount > 0)
2036 dValue /= nFieldsCount;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07002037
Nico Weber9d8ec5a2015-08-04 13:00:21 -07002038 dValue = (double)floor(dValue * FXSYS_pow((double)10, (double)6) + 0.49) /
2039 FXSYS_pow((double)10, (double)6);
2040 CJS_Value jsValue(isolate, dValue);
2041 if ((CJS_EventHandler*)pContext->GetEventHandler()->m_pValue)
2042 ((CJS_EventHandler*)pContext->GetEventHandler())->Value() =
2043 jsValue.ToCFXWideString();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07002044
Nico Weber9d8ec5a2015-08-04 13:00:21 -07002045 return TRUE;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07002046}
2047
Lei Zhanga6d9f0e2015-06-13 00:48:38 -07002048/* This function validates the current event to ensure that its value is
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07002049** within the specified range. */
2050
Nico Weber9d8ec5a2015-08-04 13:00:21 -07002051FX_BOOL CJS_PublicMethods::AFRange_Validate(IFXJS_Context* cc,
2052 const CJS_Parameters& params,
2053 CJS_Value& vRet,
2054 CFX_WideString& sError) {
2055 CJS_Context* pContext = (CJS_Context*)cc;
2056 ASSERT(pContext != NULL);
2057 CJS_EventHandler* pEvent = pContext->GetEventHandler();
2058 ASSERT(pEvent != NULL);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07002059
Nico Weber9d8ec5a2015-08-04 13:00:21 -07002060 if (params.size() != 4) {
2061 sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
2062 return FALSE;
2063 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07002064
Nico Weber9d8ec5a2015-08-04 13:00:21 -07002065 if (!pEvent->m_pValue)
2066 return FALSE;
2067 if (pEvent->Value().IsEmpty())
Tom Sepez2f2ffec2015-07-23 14:42:09 -07002068 return TRUE;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07002069 double dEentValue = atof(CFX_ByteString::FromUnicode(pEvent->Value()));
2070 FX_BOOL bGreaterThan = params[0].ToBool();
2071 double dGreaterThan = params[1].ToDouble();
2072 FX_BOOL bLessThan = params[2].ToBool();
2073 double dLessThan = params[3].ToDouble();
2074 CFX_WideString swMsg;
2075
2076 if (bGreaterThan && bLessThan) {
2077 if (dEentValue < dGreaterThan || dEentValue > dLessThan)
2078 swMsg.Format(JSGetStringFromID(pContext, IDS_STRING_JSRANGE1).c_str(),
2079 params[1].ToCFXWideString().c_str(),
2080 params[3].ToCFXWideString().c_str());
2081 } else if (bGreaterThan) {
2082 if (dEentValue < dGreaterThan)
2083 swMsg.Format(JSGetStringFromID(pContext, IDS_STRING_JSRANGE2).c_str(),
2084 params[1].ToCFXWideString().c_str());
2085 } else if (bLessThan) {
2086 if (dEentValue > dLessThan)
2087 swMsg.Format(JSGetStringFromID(pContext, IDS_STRING_JSRANGE3).c_str(),
2088 params[3].ToCFXWideString().c_str());
2089 }
2090
2091 if (!swMsg.IsEmpty()) {
2092 Alert(pContext, swMsg.c_str());
2093 pEvent->Rc() = FALSE;
2094 }
2095 return TRUE;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07002096}
2097
Nico Weber9d8ec5a2015-08-04 13:00:21 -07002098FX_BOOL CJS_PublicMethods::AFExtractNums(IFXJS_Context* cc,
2099 const CJS_Parameters& params,
2100 CJS_Value& vRet,
2101 CFX_WideString& sError) {
2102 v8::Isolate* isolate = ::GetIsolate(cc);
2103 CJS_Context* pContext = (CJS_Context*)cc;
2104 ASSERT(pContext != NULL);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07002105
Nico Weber9d8ec5a2015-08-04 13:00:21 -07002106 if (params.size() != 1) {
2107 sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
2108 return FALSE;
2109 }
2110
2111 CJS_Array nums(isolate);
2112
2113 CFX_WideString str = params[0].ToCFXWideString();
2114 CFX_WideString sPart;
2115
2116 if (str.GetAt(0) == L'.' || str.GetAt(0) == L',')
2117 str = L"0" + str;
2118
2119 int nIndex = 0;
2120 for (int i = 0, sz = str.GetLength(); i < sz; i++) {
2121 FX_WCHAR wc = str.GetAt(i);
2122 if (IsDigit((wchar_t)wc)) {
2123 sPart += wc;
2124 } else {
2125 if (sPart.GetLength() > 0) {
2126 nums.SetElement(nIndex, CJS_Value(isolate, sPart.c_str()));
2127 sPart = L"";
2128 nIndex++;
2129 }
Tom Sepez2f2ffec2015-07-23 14:42:09 -07002130 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -07002131 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07002132
Nico Weber9d8ec5a2015-08-04 13:00:21 -07002133 if (sPart.GetLength() > 0) {
2134 nums.SetElement(nIndex, CJS_Value(isolate, sPart.c_str()));
2135 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07002136
Nico Weber9d8ec5a2015-08-04 13:00:21 -07002137 if (nums.GetLength() > 0)
2138 vRet = nums;
2139 else
2140 vRet.SetNull();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07002141
Nico Weber9d8ec5a2015-08-04 13:00:21 -07002142 return TRUE;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07002143}