Home | History | Annotate | Download | only in javascript
      1 // Copyright 2014 PDFium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
      6 
      7 #include "PublicMethods.h"
      8 
      9 #include <algorithm>
     10 
     11 #include "Field.h"
     12 #include "JS_Context.h"
     13 #include "JS_Define.h"
     14 #include "JS_EventHandler.h"
     15 #include "JS_Object.h"
     16 #include "JS_Runtime.h"
     17 #include "JS_Value.h"
     18 #include "color.h"
     19 #include "core/include/fxcrt/fx_ext.h"
     20 #include "fpdfsdk/include/fsdk_mgr.h"  // For CPDFDoc_Environment.
     21 #include "fpdfsdk/include/javascript/IJavaScript.h"
     22 #include "resource.h"
     23 #include "util.h"
     24 
     25 #define DOUBLE_CORRECT 0.000000000000001
     26 
     27 BEGIN_JS_STATIC_GLOBAL_FUN(CJS_PublicMethods)
     28 JS_STATIC_GLOBAL_FUN_ENTRY(AFNumber_Format)
     29 JS_STATIC_GLOBAL_FUN_ENTRY(AFNumber_Keystroke)
     30 JS_STATIC_GLOBAL_FUN_ENTRY(AFPercent_Format)
     31 JS_STATIC_GLOBAL_FUN_ENTRY(AFPercent_Keystroke)
     32 JS_STATIC_GLOBAL_FUN_ENTRY(AFDate_FormatEx)
     33 JS_STATIC_GLOBAL_FUN_ENTRY(AFDate_KeystrokeEx)
     34 JS_STATIC_GLOBAL_FUN_ENTRY(AFDate_Format)
     35 JS_STATIC_GLOBAL_FUN_ENTRY(AFDate_Keystroke)
     36 JS_STATIC_GLOBAL_FUN_ENTRY(AFTime_FormatEx)
     37 JS_STATIC_GLOBAL_FUN_ENTRY(AFTime_KeystrokeEx)
     38 JS_STATIC_GLOBAL_FUN_ENTRY(AFTime_Format)
     39 JS_STATIC_GLOBAL_FUN_ENTRY(AFTime_Keystroke)
     40 JS_STATIC_GLOBAL_FUN_ENTRY(AFSpecial_Format)
     41 JS_STATIC_GLOBAL_FUN_ENTRY(AFSpecial_Keystroke)
     42 JS_STATIC_GLOBAL_FUN_ENTRY(AFSpecial_KeystrokeEx)
     43 JS_STATIC_GLOBAL_FUN_ENTRY(AFSimple)
     44 JS_STATIC_GLOBAL_FUN_ENTRY(AFMakeNumber)
     45 JS_STATIC_GLOBAL_FUN_ENTRY(AFSimple_Calculate)
     46 JS_STATIC_GLOBAL_FUN_ENTRY(AFRange_Validate)
     47 JS_STATIC_GLOBAL_FUN_ENTRY(AFMergeChange)
     48 JS_STATIC_GLOBAL_FUN_ENTRY(AFParseDateEx)
     49 JS_STATIC_GLOBAL_FUN_ENTRY(AFExtractNums)
     50 END_JS_STATIC_GLOBAL_FUN()
     51 
     52 IMPLEMENT_JS_STATIC_GLOBAL_FUN(CJS_PublicMethods)
     53 
     54 static const FX_WCHAR* const months[] = {L"Jan",
     55                                          L"Feb",
     56                                          L"Mar",
     57                                          L"Apr",
     58                                          L"May",
     59                                          L"Jun",
     60                                          L"Jul",
     61                                          L"Aug",
     62                                          L"Sep",
     63                                          L"Oct",
     64                                          L"Nov",
     65                                          L"Dec"};
     66 
     67 static const FX_WCHAR* const fullmonths[] = {L"January",
     68                                              L"February",
     69                                              L"March",
     70                                              L"April",
     71                                              L"May",
     72                                              L"June",
     73                                              L"July",
     74                                              L"August",
     75                                              L"September",
     76                                              L"October",
     77                                              L"November",
     78                                              L"December"};
     79 
     80 FX_BOOL CJS_PublicMethods::IsNumber(const FX_WCHAR* string) {
     81   CFX_WideString sTrim = StrTrim(string);
     82   const FX_WCHAR* pTrim = sTrim.c_str();
     83   const FX_WCHAR* p = pTrim;
     84 
     85   FX_BOOL bDot = FALSE;
     86   FX_BOOL bKXJS = FALSE;
     87 
     88   wchar_t c;
     89   while ((c = *p)) {
     90     if (c == '.' || c == ',') {
     91       if (bDot)
     92         return FALSE;
     93       bDot = TRUE;
     94     } else if (c == '-' || c == '+') {
     95       if (p != pTrim)
     96         return FALSE;
     97     } else if (c == 'e' || c == 'E') {
     98       if (bKXJS)
     99         return FALSE;
    100 
    101       p++;
    102       c = *p;
    103       if (c == '+' || c == '-') {
    104         bKXJS = TRUE;
    105       } else {
    106         return FALSE;
    107       }
    108     } else if (!FXSYS_iswdigit(c)) {
    109       return FALSE;
    110     }
    111     p++;
    112   }
    113 
    114   return TRUE;
    115 }
    116 
    117 FX_BOOL CJS_PublicMethods::maskSatisfied(wchar_t c_Change, wchar_t c_Mask) {
    118   switch (c_Mask) {
    119     case L'9':
    120       return FXSYS_iswdigit(c_Change);
    121     case L'A':
    122       return FXSYS_iswalpha(c_Change);
    123     case L'O':
    124       return FXSYS_iswalnum(c_Change);
    125     case L'X':
    126       return TRUE;
    127     default:
    128       return (c_Change == c_Mask);
    129   }
    130 }
    131 
    132 FX_BOOL CJS_PublicMethods::isReservedMaskChar(wchar_t ch) {
    133   return ch == L'9' || ch == L'A' || ch == L'O' || ch == L'X';
    134 }
    135 
    136 double CJS_PublicMethods::AF_Simple(const FX_WCHAR* sFuction,
    137                                     double dValue1,
    138                                     double dValue2) {
    139   if (FXSYS_wcsicmp(sFuction, L"AVG") == 0 ||
    140       FXSYS_wcsicmp(sFuction, L"SUM") == 0) {
    141     return dValue1 + dValue2;
    142   }
    143   if (FXSYS_wcsicmp(sFuction, L"PRD") == 0) {
    144     return dValue1 * dValue2;
    145   }
    146   if (FXSYS_wcsicmp(sFuction, L"MIN") == 0) {
    147     return std::min(dValue1, dValue2);
    148   }
    149   if (FXSYS_wcsicmp(sFuction, L"MAX") == 0) {
    150     return std::max(dValue1, dValue2);
    151   }
    152   return dValue1;
    153 }
    154 
    155 CFX_WideString CJS_PublicMethods::StrLTrim(const FX_WCHAR* pStr) {
    156   while (*pStr && *pStr == L' ')
    157     pStr++;
    158 
    159   return pStr;
    160 }
    161 
    162 CFX_WideString CJS_PublicMethods::StrRTrim(const FX_WCHAR* pStr) {
    163   const FX_WCHAR* p = pStr;
    164   while (*p)
    165     p++;
    166   while (p > pStr && *(p - 1) == L' ')
    167     p--;
    168 
    169   return CFX_WideString(pStr, p - pStr);
    170 }
    171 
    172 CFX_WideString CJS_PublicMethods::StrTrim(const FX_WCHAR* pStr) {
    173   return StrRTrim(StrLTrim(pStr).c_str());
    174 }
    175 
    176 CFX_ByteString CJS_PublicMethods::StrLTrim(const FX_CHAR* pStr) {
    177   while (*pStr && *pStr == ' ')
    178     pStr++;
    179 
    180   return pStr;
    181 }
    182 
    183 CFX_ByteString CJS_PublicMethods::StrRTrim(const FX_CHAR* pStr) {
    184   const FX_CHAR* p = pStr;
    185   while (*p)
    186     p++;
    187   while (p > pStr && *(p - 1) == L' ')
    188     p--;
    189 
    190   return CFX_ByteString(pStr, p - pStr);
    191 }
    192 
    193 CFX_ByteString CJS_PublicMethods::StrTrim(const FX_CHAR* pStr) {
    194   return StrRTrim(StrLTrim(pStr));
    195 }
    196 
    197 double CJS_PublicMethods::ParseNumber(const FX_WCHAR* swSource,
    198                                       FX_BOOL& bAllDigits,
    199                                       FX_BOOL& bDot,
    200                                       FX_BOOL& bSign,
    201                                       FX_BOOL& bKXJS) {
    202   bDot = FALSE;
    203   bSign = FALSE;
    204   bKXJS = FALSE;
    205 
    206   FX_BOOL bDigitExist = FALSE;
    207 
    208   const FX_WCHAR* p = swSource;
    209   wchar_t c;
    210 
    211   const FX_WCHAR* pStart = NULL;
    212   const FX_WCHAR* pEnd = NULL;
    213 
    214   while ((c = *p)) {
    215     if (!pStart && c != L' ') {
    216       pStart = p;
    217     }
    218 
    219     pEnd = p;
    220     p++;
    221   }
    222 
    223   if (!pStart) {
    224     bAllDigits = FALSE;
    225     return 0;
    226   }
    227 
    228   while (pEnd != pStart) {
    229     if (*pEnd == L' ')
    230       pEnd--;
    231     else
    232       break;
    233   }
    234 
    235   double dRet = 0;
    236   p = pStart;
    237   bAllDigits = TRUE;
    238   CFX_WideString swDigits;
    239 
    240   while (p <= pEnd) {
    241     c = *p;
    242 
    243     if (FXSYS_iswdigit(c)) {
    244       swDigits += c;
    245       bDigitExist = TRUE;
    246     } else {
    247       switch (c) {
    248         case L' ':
    249           bAllDigits = FALSE;
    250           break;
    251         case L'.':
    252         case L',':
    253           if (!bDot) {
    254             if (bDigitExist) {
    255               swDigits += L'.';
    256             } else {
    257               swDigits += L'0';
    258               swDigits += L'.';
    259               bDigitExist = TRUE;
    260             }
    261 
    262             bDot = TRUE;
    263             break;
    264           }
    265         case 'e':
    266         case 'E':
    267           if (!bKXJS) {
    268             p++;
    269             c = *p;
    270             if (c == '+' || c == '-') {
    271               bKXJS = TRUE;
    272               swDigits += 'e';
    273               swDigits += c;
    274             }
    275             break;
    276           }
    277         case L'-':
    278           if (!bDigitExist && !bSign) {
    279             swDigits += c;
    280             bSign = TRUE;
    281             break;
    282           }
    283         default:
    284           bAllDigits = FALSE;
    285 
    286           if (p != pStart && !bDot && bDigitExist) {
    287             swDigits += L'.';
    288             bDot = TRUE;
    289           } else {
    290             bDot = FALSE;
    291             bDigitExist = FALSE;
    292             swDigits = L"";
    293           }
    294           break;
    295       }
    296     }
    297 
    298     p++;
    299   }
    300 
    301   if (swDigits.GetLength() > 0 && swDigits.GetLength() < 17) {
    302     CFX_ByteString sDigits = swDigits.UTF8Encode();
    303 
    304     if (bKXJS) {
    305       dRet = atof(sDigits);
    306     } else {
    307       if (bDot) {
    308         char* pStopString;
    309         dRet = ::strtod(sDigits, &pStopString);
    310       } else {
    311         dRet = atol(sDigits);
    312       }
    313     }
    314   }
    315 
    316   return dRet;
    317 }
    318 
    319 double CJS_PublicMethods::ParseStringToNumber(const FX_WCHAR* swSource) {
    320   FX_BOOL bAllDigits = FALSE;
    321   FX_BOOL bDot = FALSE;
    322   FX_BOOL bSign = FALSE;
    323   FX_BOOL bKXJS = FALSE;
    324 
    325   return ParseNumber(swSource, bAllDigits, bDot, bSign, bKXJS);
    326 }
    327 
    328 FX_BOOL CJS_PublicMethods::ConvertStringToNumber(const FX_WCHAR* swSource,
    329                                                  double& dRet,
    330                                                  FX_BOOL& bDot) {
    331   FX_BOOL bAllDigits = FALSE;
    332   FX_BOOL bSign = FALSE;
    333   FX_BOOL bKXJS = FALSE;
    334 
    335   dRet = ParseNumber(swSource, bAllDigits, bDot, bSign, bKXJS);
    336 
    337   return bAllDigits;
    338 }
    339 
    340 CJS_Array CJS_PublicMethods::AF_MakeArrayFromList(CJS_Runtime* pRuntime,
    341                                                   CJS_Value val) {
    342   CJS_Array StrArray(pRuntime);
    343   if (val.IsArrayObject()) {
    344     val.ConvertToArray(StrArray);
    345     return StrArray;
    346   }
    347   CFX_WideString wsStr = val.ToCFXWideString();
    348   CFX_ByteString t = CFX_ByteString::FromUnicode(wsStr);
    349   const char* p = (const char*)t;
    350 
    351   int ch = ',';
    352   int nIndex = 0;
    353 
    354   while (*p) {
    355     const char* pTemp = strchr(p, ch);
    356     if (!pTemp) {
    357       StrArray.SetElement(nIndex, CJS_Value(pRuntime, StrTrim(p).c_str()));
    358       break;
    359     }
    360 
    361     char* pSub = new char[pTemp - p + 1];
    362     strncpy(pSub, p, pTemp - p);
    363     *(pSub + (pTemp - p)) = '\0';
    364 
    365     StrArray.SetElement(nIndex, CJS_Value(pRuntime, StrTrim(pSub).c_str()));
    366     delete[] pSub;
    367 
    368     nIndex++;
    369     p = ++pTemp;
    370   }
    371   return StrArray;
    372 }
    373 
    374 int CJS_PublicMethods::ParseStringInteger(const CFX_WideString& string,
    375                                           int nStart,
    376                                           int& nSkip,
    377                                           int nMaxStep) {
    378   int nRet = 0;
    379   nSkip = 0;
    380   for (int i = nStart, sz = string.GetLength(); i < sz; i++) {
    381     if (i - nStart > 10)
    382       break;
    383 
    384     FX_WCHAR c = string.GetAt(i);
    385     if (!FXSYS_iswdigit(c))
    386       break;
    387 
    388     nRet = nRet * 10 + FXSYS_toDecimalDigitWide(c);
    389     nSkip = i - nStart + 1;
    390     if (nSkip >= nMaxStep)
    391       break;
    392   }
    393 
    394   return nRet;
    395 }
    396 
    397 CFX_WideString CJS_PublicMethods::ParseStringString(
    398     const CFX_WideString& string,
    399     int nStart,
    400     int& nSkip) {
    401   CFX_WideString swRet;
    402   nSkip = 0;
    403   for (int i = nStart, sz = string.GetLength(); i < sz; i++) {
    404     FX_WCHAR c = string.GetAt(i);
    405     if (!FXSYS_iswdigit(c))
    406       break;
    407 
    408     swRet += c;
    409     nSkip = i - nStart + 1;
    410   }
    411 
    412   return swRet;
    413 }
    414 
    415 double CJS_PublicMethods::ParseNormalDate(const CFX_WideString& value,
    416                                           bool* bWrongFormat) {
    417   double dt = JS_GetDateTime();
    418 
    419   int nYear = JS_GetYearFromTime(dt);
    420   int nMonth = JS_GetMonthFromTime(dt) + 1;
    421   int nDay = JS_GetDayFromTime(dt);
    422   int nHour = JS_GetHourFromTime(dt);
    423   int nMin = JS_GetMinFromTime(dt);
    424   int nSec = JS_GetSecFromTime(dt);
    425 
    426   int number[3];
    427 
    428   int nSkip = 0;
    429   int nLen = value.GetLength();
    430   int nIndex = 0;
    431   int i = 0;
    432   while (i < nLen) {
    433     if (nIndex > 2)
    434       break;
    435 
    436     FX_WCHAR c = value.GetAt(i);
    437     if (FXSYS_iswdigit(c)) {
    438       number[nIndex++] = ParseStringInteger(value, i, nSkip, 4);
    439       i += nSkip;
    440     } else {
    441       i++;
    442     }
    443   }
    444 
    445   if (nIndex == 2) {
    446     // case2: month/day
    447     // case3: day/month
    448     if ((number[0] >= 1 && number[0] <= 12) &&
    449         (number[1] >= 1 && number[1] <= 31)) {
    450       nMonth = number[0];
    451       nDay = number[1];
    452     } else if ((number[0] >= 1 && number[0] <= 31) &&
    453                (number[1] >= 1 && number[1] <= 12)) {
    454       nDay = number[0];
    455       nMonth = number[1];
    456     }
    457 
    458     if (bWrongFormat)
    459       *bWrongFormat = false;
    460   } else if (nIndex == 3) {
    461     // case1: year/month/day
    462     // case2: month/day/year
    463     // case3: day/month/year
    464 
    465     if (number[0] > 12 && (number[1] >= 1 && number[1] <= 12) &&
    466         (number[2] >= 1 && number[2] <= 31)) {
    467       nYear = number[0];
    468       nMonth = number[1];
    469       nDay = number[2];
    470     } else if ((number[0] >= 1 && number[0] <= 12) &&
    471                (number[1] >= 1 && number[1] <= 31) && number[2] > 31) {
    472       nMonth = number[0];
    473       nDay = number[1];
    474       nYear = number[2];
    475     } else if ((number[0] >= 1 && number[0] <= 31) &&
    476                (number[1] >= 1 && number[1] <= 12) && number[2] > 31) {
    477       nDay = number[0];
    478       nMonth = number[1];
    479       nYear = number[2];
    480     }
    481 
    482     if (bWrongFormat)
    483       *bWrongFormat = false;
    484   } else {
    485     if (bWrongFormat)
    486       *bWrongFormat = true;
    487     return dt;
    488   }
    489 
    490   CFX_WideString swTemp;
    491   swTemp.Format(L"%d/%d/%d %d:%d:%d", nMonth, nDay, nYear, nHour, nMin, nSec);
    492   return JS_DateParse(swTemp.c_str());
    493 }
    494 
    495 double CJS_PublicMethods::MakeRegularDate(const CFX_WideString& value,
    496                                           const CFX_WideString& format,
    497                                           bool* bWrongFormat) {
    498   double dt = JS_GetDateTime();
    499 
    500   if (format.IsEmpty() || value.IsEmpty())
    501     return dt;
    502 
    503   int nYear = JS_GetYearFromTime(dt);
    504   int nMonth = JS_GetMonthFromTime(dt) + 1;
    505   int nDay = JS_GetDayFromTime(dt);
    506   int nHour = JS_GetHourFromTime(dt);
    507   int nMin = JS_GetMinFromTime(dt);
    508   int nSec = JS_GetSecFromTime(dt);
    509 
    510   int nYearSub = 99;  // nYear - 2000;
    511 
    512   FX_BOOL bPm = FALSE;
    513   FX_BOOL bExit = FALSE;
    514   bool bBadFormat = false;
    515 
    516   int i = 0;
    517   int j = 0;
    518 
    519   while (i < format.GetLength()) {
    520     if (bExit)
    521       break;
    522 
    523     FX_WCHAR c = format.GetAt(i);
    524     switch (c) {
    525       case ':':
    526       case '.':
    527       case '-':
    528       case '\\':
    529       case '/':
    530         i++;
    531         j++;
    532         break;
    533 
    534       case 'y':
    535       case 'm':
    536       case 'd':
    537       case 'H':
    538       case 'h':
    539       case 'M':
    540       case 's':
    541       case 't': {
    542         int oldj = j;
    543         int nSkip = 0;
    544         int remaining = format.GetLength() - i - 1;
    545 
    546         if (remaining == 0 || format.GetAt(i + 1) != c) {
    547           switch (c) {
    548             case 'y':
    549               i++;
    550               j++;
    551               break;
    552             case 'm':
    553               nMonth = ParseStringInteger(value, j, nSkip, 2);
    554               i++;
    555               j += nSkip;
    556               break;
    557             case 'd':
    558               nDay = ParseStringInteger(value, j, nSkip, 2);
    559               i++;
    560               j += nSkip;
    561               break;
    562             case 'H':
    563               nHour = ParseStringInteger(value, j, nSkip, 2);
    564               i++;
    565               j += nSkip;
    566               break;
    567             case 'h':
    568               nHour = ParseStringInteger(value, j, nSkip, 2);
    569               i++;
    570               j += nSkip;
    571               break;
    572             case 'M':
    573               nMin = ParseStringInteger(value, j, nSkip, 2);
    574               i++;
    575               j += nSkip;
    576               break;
    577             case 's':
    578               nSec = ParseStringInteger(value, j, nSkip, 2);
    579               i++;
    580               j += nSkip;
    581               break;
    582             case 't':
    583               bPm = (j < value.GetLength() && value.GetAt(j) == 'p');
    584               i++;
    585               j++;
    586               break;
    587           }
    588         } else if (remaining == 1 || format.GetAt(i + 2) != c) {
    589           switch (c) {
    590             case 'y':
    591               nYear = ParseStringInteger(value, j, nSkip, 4);
    592               i += 2;
    593               j += nSkip;
    594               break;
    595             case 'm':
    596               nMonth = ParseStringInteger(value, j, nSkip, 2);
    597               i += 2;
    598               j += nSkip;
    599               break;
    600             case 'd':
    601               nDay = ParseStringInteger(value, j, nSkip, 2);
    602               i += 2;
    603               j += nSkip;
    604               break;
    605             case 'H':
    606               nHour = 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 'M':
    616               nMin = ParseStringInteger(value, j, nSkip, 2);
    617               i += 2;
    618               j += nSkip;
    619               break;
    620             case 's':
    621               nSec = ParseStringInteger(value, j, nSkip, 2);
    622               i += 2;
    623               j += nSkip;
    624               break;
    625             case 't':
    626               bPm = (j + 1 < value.GetLength() && value.GetAt(j) == 'p' &&
    627                      value.GetAt(j + 1) == 'm');
    628               i += 2;
    629               j += 2;
    630               break;
    631           }
    632         } else if (remaining == 2 || format.GetAt(i + 3) != c) {
    633           switch (c) {
    634             case 'm': {
    635               CFX_WideString sMonth = ParseStringString(value, j, nSkip);
    636               FX_BOOL bFind = FALSE;
    637               for (int m = 0; m < 12; m++) {
    638                 if (sMonth.CompareNoCase(months[m]) == 0) {
    639                   nMonth = m + 1;
    640                   i += 3;
    641                   j += nSkip;
    642                   bFind = TRUE;
    643                   break;
    644                 }
    645               }
    646 
    647               if (!bFind) {
    648                 nMonth = ParseStringInteger(value, j, nSkip, 3);
    649                 i += 3;
    650                 j += nSkip;
    651               }
    652             } break;
    653             case 'y':
    654               break;
    655             default:
    656               i += 3;
    657               j += 3;
    658               break;
    659           }
    660         } else if (remaining == 3 || format.GetAt(i + 4) != c) {
    661           switch (c) {
    662             case 'y':
    663               nYear = ParseStringInteger(value, j, nSkip, 4);
    664               j += nSkip;
    665               i += 4;
    666               break;
    667             case 'm': {
    668               FX_BOOL bFind = FALSE;
    669 
    670               CFX_WideString sMonth = ParseStringString(value, j, nSkip);
    671               sMonth.MakeLower();
    672 
    673               for (int m = 0; m < 12; m++) {
    674                 CFX_WideString sFullMonths = fullmonths[m];
    675                 sFullMonths.MakeLower();
    676 
    677                 if (sFullMonths.Find(sMonth.c_str(), 0) != -1) {
    678                   nMonth = m + 1;
    679                   i += 4;
    680                   j += nSkip;
    681                   bFind = TRUE;
    682                   break;
    683                 }
    684               }
    685 
    686               if (!bFind) {
    687                 nMonth = ParseStringInteger(value, j, nSkip, 4);
    688                 i += 4;
    689                 j += nSkip;
    690               }
    691             } break;
    692             default:
    693               i += 4;
    694               j += 4;
    695               break;
    696           }
    697         } else {
    698           if (j >= value.GetLength() || format.GetAt(i) != value.GetAt(j)) {
    699             bBadFormat = true;
    700             bExit = TRUE;
    701           }
    702           i++;
    703           j++;
    704         }
    705 
    706         if (oldj == j) {
    707           bBadFormat = true;
    708           bExit = TRUE;
    709         }
    710       }
    711 
    712       break;
    713       default:
    714         if (value.GetLength() <= j) {
    715           bExit = TRUE;
    716         } else if (format.GetAt(i) != value.GetAt(j)) {
    717           bBadFormat = true;
    718           bExit = TRUE;
    719         }
    720 
    721         i++;
    722         j++;
    723         break;
    724     }
    725   }
    726 
    727   if (bPm)
    728     nHour += 12;
    729 
    730   if (nYear >= 0 && nYear <= nYearSub)
    731     nYear += 2000;
    732 
    733   if (nMonth < 1 || nMonth > 12)
    734     bBadFormat = true;
    735 
    736   if (nDay < 1 || nDay > 31)
    737     bBadFormat = true;
    738 
    739   if (nHour < 0 || nHour > 24)
    740     bBadFormat = true;
    741 
    742   if (nMin < 0 || nMin > 60)
    743     bBadFormat = true;
    744 
    745   if (nSec < 0 || nSec > 60)
    746     bBadFormat = true;
    747 
    748   double dRet = 0;
    749 
    750   if (bBadFormat) {
    751     dRet = ParseNormalDate(value, &bBadFormat);
    752   } else {
    753     dRet = JS_MakeDate(JS_MakeDay(nYear, nMonth - 1, nDay),
    754                        JS_MakeTime(nHour, nMin, nSec, 0));
    755 
    756     if (JS_PortIsNan(dRet)) {
    757       dRet = JS_DateParse(value.c_str());
    758     }
    759   }
    760 
    761   if (JS_PortIsNan(dRet)) {
    762     dRet = ParseNormalDate(value, &bBadFormat);
    763   }
    764 
    765   if (bWrongFormat)
    766     *bWrongFormat = bBadFormat;
    767   return dRet;
    768 }
    769 
    770 CFX_WideString CJS_PublicMethods::MakeFormatDate(double dDate,
    771                                                  const CFX_WideString& format) {
    772   CFX_WideString sRet = L"", sPart = L"";
    773 
    774   int nYear = JS_GetYearFromTime(dDate);
    775   int nMonth = JS_GetMonthFromTime(dDate) + 1;
    776   int nDay = JS_GetDayFromTime(dDate);
    777   int nHour = JS_GetHourFromTime(dDate);
    778   int nMin = JS_GetMinFromTime(dDate);
    779   int nSec = JS_GetSecFromTime(dDate);
    780 
    781   int i = 0;
    782   while (i < format.GetLength()) {
    783     FX_WCHAR c = format.GetAt(i);
    784     int remaining = format.GetLength() - i - 1;
    785     sPart = L"";
    786     switch (c) {
    787       case 'y':
    788       case 'm':
    789       case 'd':
    790       case 'H':
    791       case 'h':
    792       case 'M':
    793       case 's':
    794       case 't':
    795         if (remaining == 0 || format.GetAt(i + 1) != c) {
    796           switch (c) {
    797             case 'y':
    798               sPart += c;
    799               break;
    800             case 'm':
    801               sPart.Format(L"%d", nMonth);
    802               break;
    803             case 'd':
    804               sPart.Format(L"%d", nDay);
    805               break;
    806             case 'H':
    807               sPart.Format(L"%d", nHour);
    808               break;
    809             case 'h':
    810               sPart.Format(L"%d", nHour > 12 ? nHour - 12 : nHour);
    811               break;
    812             case 'M':
    813               sPart.Format(L"%d", nMin);
    814               break;
    815             case 's':
    816               sPart.Format(L"%d", nSec);
    817               break;
    818             case 't':
    819               sPart += nHour > 12 ? 'p' : 'a';
    820               break;
    821           }
    822           i++;
    823         } else if (remaining == 1 || format.GetAt(i + 2) != c) {
    824           switch (c) {
    825             case 'y':
    826               sPart.Format(L"%02d", nYear - (nYear / 100) * 100);
    827               break;
    828             case 'm':
    829               sPart.Format(L"%02d", nMonth);
    830               break;
    831             case 'd':
    832               sPart.Format(L"%02d", nDay);
    833               break;
    834             case 'H':
    835               sPart.Format(L"%02d", nHour);
    836               break;
    837             case 'h':
    838               sPart.Format(L"%02d", nHour > 12 ? nHour - 12 : nHour);
    839               break;
    840             case 'M':
    841               sPart.Format(L"%02d", nMin);
    842               break;
    843             case 's':
    844               sPart.Format(L"%02d", nSec);
    845               break;
    846             case 't':
    847               sPart = nHour > 12 ? L"pm" : L"am";
    848               break;
    849           }
    850           i += 2;
    851         } else if (remaining == 2 || format.GetAt(i + 3) != c) {
    852           switch (c) {
    853             case 'm':
    854               i += 3;
    855               if (nMonth > 0 && nMonth <= 12)
    856                 sPart += months[nMonth - 1];
    857               break;
    858             default:
    859               i += 3;
    860               sPart += c;
    861               sPart += c;
    862               sPart += c;
    863               break;
    864           }
    865         } else if (remaining == 3 || format.GetAt(i + 4) != c) {
    866           switch (c) {
    867             case 'y':
    868               sPart.Format(L"%04d", nYear);
    869               i += 4;
    870               break;
    871             case 'm':
    872               i += 4;
    873               if (nMonth > 0 && nMonth <= 12)
    874                 sPart += fullmonths[nMonth - 1];
    875               break;
    876             default:
    877               i += 4;
    878               sPart += c;
    879               sPart += c;
    880               sPart += c;
    881               sPart += c;
    882               break;
    883           }
    884         } else {
    885           i++;
    886           sPart += c;
    887         }
    888         break;
    889       default:
    890         i++;
    891         sPart += c;
    892         break;
    893     }
    894 
    895     sRet += sPart;
    896   }
    897 
    898   return sRet;
    899 }
    900 
    901 /* -------------------------------------------------------------------------- */
    902 
    903 // function AFNumber_Format(nDec, sepStyle, negStyle, currStyle, strCurrency,
    904 // bCurrencyPrepend)
    905 FX_BOOL CJS_PublicMethods::AFNumber_Format(IJS_Context* cc,
    906                                            const std::vector<CJS_Value>& params,
    907                                            CJS_Value& vRet,
    908                                            CFX_WideString& sError) {
    909 #if _FX_OS_ != _FX_ANDROID_
    910   CJS_Context* pContext = (CJS_Context*)cc;
    911   if (params.size() != 6) {
    912     sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
    913     return FALSE;
    914   }
    915 
    916   CJS_Runtime* pRuntime = CJS_Runtime::FromContext(cc);
    917   CJS_EventHandler* pEvent = pContext->GetEventHandler();
    918   if (!pEvent->m_pValue)
    919     return FALSE;
    920 
    921   CFX_WideString& Value = pEvent->Value();
    922   CFX_ByteString strValue = StrTrim(CFX_ByteString::FromUnicode(Value));
    923   if (strValue.IsEmpty())
    924     return TRUE;
    925 
    926   int iDec = params[0].ToInt();
    927   int iSepStyle = params[1].ToInt();
    928   int iNegStyle = params[2].ToInt();
    929   // params[3] is iCurrStyle, it's not used.
    930   std::wstring wstrCurrency(params[4].ToCFXWideString().c_str());
    931   FX_BOOL bCurrencyPrepend = params[5].ToBool();
    932 
    933   if (iDec < 0)
    934     iDec = -iDec;
    935 
    936   if (iSepStyle < 0 || iSepStyle > 3)
    937     iSepStyle = 0;
    938 
    939   if (iNegStyle < 0 || iNegStyle > 3)
    940     iNegStyle = 0;
    941 
    942   //////////////////////////////////////////////////////
    943   // for processing decimal places
    944   strValue.Replace(",", ".");
    945   double dValue = atof(strValue);
    946   if (iDec > 0)
    947     dValue += DOUBLE_CORRECT;
    948 
    949   int iDec2;
    950   int iNegative = 0;
    951 
    952   strValue = fcvt(dValue, iDec, &iDec2, &iNegative);
    953   if (strValue.IsEmpty()) {
    954     dValue = 0;
    955     strValue = fcvt(dValue, iDec, &iDec2, &iNegative);
    956     if (strValue.IsEmpty()) {
    957       strValue = "0";
    958       iDec2 = 1;
    959     }
    960   }
    961 
    962   if (iDec2 < 0) {
    963     for (int iNum = 0; iNum < abs(iDec2); iNum++) {
    964       strValue = "0" + strValue;
    965     }
    966     iDec2 = 0;
    967   }
    968   int iMax = strValue.GetLength();
    969   if (iDec2 > iMax) {
    970     for (int iNum = 0; iNum <= iDec2 - iMax; iNum++) {
    971       strValue += "0";
    972     }
    973     iMax = iDec2 + 1;
    974   }
    975   ///////////////////////////////////////////////////////
    976   // for processing seperator style
    977   if (iDec2 < iMax) {
    978     if (iSepStyle == 0 || iSepStyle == 1) {
    979       strValue.Insert(iDec2, '.');
    980       iMax++;
    981     } else if (iSepStyle == 2 || iSepStyle == 3) {
    982       strValue.Insert(iDec2, ',');
    983       iMax++;
    984     }
    985 
    986     if (iDec2 == 0)
    987       strValue.Insert(iDec2, '0');
    988   }
    989   if (iSepStyle == 0 || iSepStyle == 2) {
    990     char cSeperator;
    991     if (iSepStyle == 0)
    992       cSeperator = ',';
    993     else
    994       cSeperator = '.';
    995 
    996     for (int iDecPositive = iDec2 - 3; iDecPositive > 0; iDecPositive -= 3) {
    997       strValue.Insert(iDecPositive, cSeperator);
    998       iMax++;
    999     }
   1000   }
   1001 
   1002   //////////////////////////////////////////////////////////////////////
   1003   // for processing currency string
   1004 
   1005   Value = CFX_WideString::FromLocal(strValue);
   1006   std::wstring strValue2 = Value.c_str();
   1007 
   1008   if (bCurrencyPrepend)
   1009     strValue2 = wstrCurrency + strValue2;
   1010   else
   1011     strValue2 = strValue2 + wstrCurrency;
   1012 
   1013   /////////////////////////////////////////////////////////////////////////
   1014   // for processing negative style
   1015   if (iNegative) {
   1016     if (iNegStyle == 0) {
   1017       strValue2.insert(0, L"-");
   1018     }
   1019     if (iNegStyle == 2 || iNegStyle == 3) {
   1020       strValue2.insert(0, L"(");
   1021       strValue2.insert(strValue2.length(), L")");
   1022     }
   1023     if (iNegStyle == 1 || iNegStyle == 3) {
   1024       if (Field* fTarget = pEvent->Target_Field()) {
   1025         CJS_Array arColor(pRuntime);
   1026         CJS_Value vColElm(pRuntime);
   1027         vColElm = L"RGB";
   1028         arColor.SetElement(0, vColElm);
   1029         vColElm = 1;
   1030         arColor.SetElement(1, vColElm);
   1031         vColElm = 0;
   1032         arColor.SetElement(2, vColElm);
   1033 
   1034         arColor.SetElement(3, vColElm);
   1035 
   1036         CJS_PropValue vProp(pRuntime);
   1037         vProp.StartGetting();
   1038         vProp << arColor;
   1039         vProp.StartSetting();
   1040         fTarget->textColor(cc, vProp, sError);  // red
   1041       }
   1042     }
   1043   } else {
   1044     if (iNegStyle == 1 || iNegStyle == 3) {
   1045       if (Field* fTarget = pEvent->Target_Field()) {
   1046         CJS_Array arColor(pRuntime);
   1047         CJS_Value vColElm(pRuntime);
   1048         vColElm = L"RGB";
   1049         arColor.SetElement(0, vColElm);
   1050         vColElm = 0;
   1051         arColor.SetElement(1, vColElm);
   1052         arColor.SetElement(2, vColElm);
   1053         arColor.SetElement(3, vColElm);
   1054 
   1055         CJS_PropValue vProp(pRuntime);
   1056         vProp.StartGetting();
   1057         fTarget->textColor(cc, vProp, sError);
   1058 
   1059         CJS_Array aProp(pRuntime);
   1060         vProp.ConvertToArray(aProp);
   1061 
   1062         CPWL_Color crProp;
   1063         CPWL_Color crColor;
   1064         color::ConvertArrayToPWLColor(aProp, crProp);
   1065         color::ConvertArrayToPWLColor(arColor, crColor);
   1066 
   1067         if (crColor != crProp) {
   1068           CJS_PropValue vProp2(pRuntime);
   1069           vProp2.StartGetting();
   1070           vProp2 << arColor;
   1071           vProp2.StartSetting();
   1072           fTarget->textColor(cc, vProp2, sError);
   1073         }
   1074       }
   1075     }
   1076   }
   1077   Value = strValue2.c_str();
   1078 #endif
   1079   return TRUE;
   1080 }
   1081 
   1082 // function AFNumber_Keystroke(nDec, sepStyle, negStyle, currStyle, strCurrency,
   1083 // bCurrencyPrepend)
   1084 FX_BOOL CJS_PublicMethods::AFNumber_Keystroke(
   1085     IJS_Context* cc,
   1086     const std::vector<CJS_Value>& params,
   1087     CJS_Value& vRet,
   1088     CFX_WideString& sError) {
   1089   CJS_Context* pContext = (CJS_Context*)cc;
   1090   CJS_EventHandler* pEvent = pContext->GetEventHandler();
   1091 
   1092   if (params.size() < 2)
   1093     return FALSE;
   1094   int iSepStyle = params[1].ToInt();
   1095 
   1096   if (iSepStyle < 0 || iSepStyle > 3)
   1097     iSepStyle = 0;
   1098   if (!pEvent->m_pValue)
   1099     return FALSE;
   1100   CFX_WideString& val = pEvent->Value();
   1101   CFX_WideString& w_strChange = pEvent->Change();
   1102   CFX_WideString w_strValue = val;
   1103 
   1104   if (pEvent->WillCommit()) {
   1105     CFX_WideString wstrChange = w_strChange;
   1106     CFX_WideString wstrValue = StrLTrim(w_strValue.c_str());
   1107     if (wstrValue.IsEmpty())
   1108       return TRUE;
   1109 
   1110     CFX_WideString swTemp = wstrValue;
   1111     swTemp.Replace(L",", L".");
   1112     if (!IsNumber(swTemp.c_str())) {
   1113       pEvent->Rc() = FALSE;
   1114       sError = JSGetStringFromID(pContext, IDS_STRING_JSAFNUMBER_KEYSTROKE);
   1115       Alert(pContext, sError.c_str());
   1116       return TRUE;
   1117     }
   1118     return TRUE;  // it happens after the last keystroke and before validating,
   1119   }
   1120 
   1121   std::wstring w_strValue2 = w_strValue.c_str();
   1122   std::wstring w_strChange2 = w_strChange.c_str();
   1123   std::wstring w_strSelected;
   1124   if (-1 != pEvent->SelStart())
   1125     w_strSelected = w_strValue2.substr(pEvent->SelStart(),
   1126                                        (pEvent->SelEnd() - pEvent->SelStart()));
   1127   bool bHasSign = (w_strValue2.find('-') != std::wstring::npos) &&
   1128                   (w_strSelected.find('-') == std::wstring::npos);
   1129   if (bHasSign) {
   1130     // can't insert "change" in front to sign postion.
   1131     if (pEvent->SelStart() == 0) {
   1132       FX_BOOL& bRc = pEvent->Rc();
   1133       bRc = FALSE;
   1134       return TRUE;
   1135     }
   1136   }
   1137 
   1138   char cSep = L'.';
   1139 
   1140   switch (iSepStyle) {
   1141     case 0:
   1142     case 1:
   1143       cSep = L'.';
   1144       break;
   1145     case 2:
   1146     case 3:
   1147       cSep = L',';
   1148       break;
   1149   }
   1150 
   1151   bool bHasSep = (w_strValue2.find(cSep) != std::wstring::npos);
   1152   for (std::wstring::iterator it = w_strChange2.begin();
   1153        it != w_strChange2.end(); it++) {
   1154     if (*it == cSep) {
   1155       if (bHasSep) {
   1156         FX_BOOL& bRc = pEvent->Rc();
   1157         bRc = FALSE;
   1158         return TRUE;
   1159       }
   1160       bHasSep = TRUE;
   1161       continue;
   1162     }
   1163     if (*it == L'-') {
   1164       if (bHasSign) {
   1165         FX_BOOL& bRc = pEvent->Rc();
   1166         bRc = FALSE;
   1167         return TRUE;
   1168       }
   1169       // sign's position is not correct
   1170       if (it != w_strChange2.begin()) {
   1171         FX_BOOL& bRc = pEvent->Rc();
   1172         bRc = FALSE;
   1173         return TRUE;
   1174       }
   1175       if (pEvent->SelStart() != 0) {
   1176         FX_BOOL& bRc = pEvent->Rc();
   1177         bRc = FALSE;
   1178         return TRUE;
   1179       }
   1180       bHasSign = TRUE;
   1181       continue;
   1182     }
   1183 
   1184     if (!FXSYS_iswdigit(*it)) {
   1185       FX_BOOL& bRc = pEvent->Rc();
   1186       bRc = FALSE;
   1187       return TRUE;
   1188     }
   1189   }
   1190 
   1191   std::wstring w_prefix = w_strValue2.substr(0, pEvent->SelStart());
   1192   std::wstring w_postfix;
   1193   if (pEvent->SelEnd() < (int)w_strValue2.length())
   1194     w_postfix = w_strValue2.substr(pEvent->SelEnd());
   1195   w_strValue2 = w_prefix + w_strChange2 + w_postfix;
   1196   w_strValue = w_strValue2.c_str();
   1197   val = w_strValue;
   1198   return TRUE;
   1199 }
   1200 
   1201 // function AFPercent_Format(nDec, sepStyle)
   1202 FX_BOOL CJS_PublicMethods::AFPercent_Format(
   1203     IJS_Context* cc,
   1204     const std::vector<CJS_Value>& params,
   1205     CJS_Value& vRet,
   1206     CFX_WideString& sError) {
   1207 #if _FX_OS_ != _FX_ANDROID_
   1208   CJS_Context* pContext = (CJS_Context*)cc;
   1209   CJS_EventHandler* pEvent = pContext->GetEventHandler();
   1210 
   1211   if (params.size() != 2) {
   1212     sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
   1213     return FALSE;
   1214   }
   1215   if (!pEvent->m_pValue)
   1216     return FALSE;
   1217 
   1218   CFX_WideString& Value = pEvent->Value();
   1219   CFX_ByteString strValue = StrTrim(CFX_ByteString::FromUnicode(Value));
   1220   if (strValue.IsEmpty())
   1221     return TRUE;
   1222 
   1223   int iDec = params[0].ToInt();
   1224   if (iDec < 0)
   1225     iDec = -iDec;
   1226 
   1227   int iSepStyle = params[1].ToInt();
   1228   if (iSepStyle < 0 || iSepStyle > 3)
   1229     iSepStyle = 0;
   1230 
   1231   //////////////////////////////////////////////////////
   1232   // for processing decimal places
   1233   double dValue = atof(strValue);
   1234   dValue *= 100;
   1235   if (iDec > 0)
   1236     dValue += DOUBLE_CORRECT;
   1237 
   1238   int iDec2;
   1239   int iNegative = 0;
   1240   strValue = fcvt(dValue, iDec, &iDec2, &iNegative);
   1241   if (strValue.IsEmpty()) {
   1242     dValue = 0;
   1243     strValue = fcvt(dValue, iDec, &iDec2, &iNegative);
   1244   }
   1245 
   1246   if (iDec2 < 0) {
   1247     for (int iNum = 0; iNum < abs(iDec2); iNum++) {
   1248       strValue = "0" + strValue;
   1249     }
   1250     iDec2 = 0;
   1251   }
   1252   int iMax = strValue.GetLength();
   1253   if (iDec2 > iMax) {
   1254     for (int iNum = 0; iNum <= iDec2 - iMax; iNum++) {
   1255       strValue += "0";
   1256     }
   1257     iMax = iDec2 + 1;
   1258   }
   1259   ///////////////////////////////////////////////////////
   1260   // for processing seperator style
   1261   if (iDec2 < iMax) {
   1262     if (iSepStyle == 0 || iSepStyle == 1) {
   1263       strValue.Insert(iDec2, '.');
   1264       iMax++;
   1265     } else if (iSepStyle == 2 || iSepStyle == 3) {
   1266       strValue.Insert(iDec2, ',');
   1267       iMax++;
   1268     }
   1269 
   1270     if (iDec2 == 0)
   1271       strValue.Insert(iDec2, '0');
   1272   }
   1273   if (iSepStyle == 0 || iSepStyle == 2) {
   1274     char cSeperator;
   1275     if (iSepStyle == 0)
   1276       cSeperator = ',';
   1277     else
   1278       cSeperator = '.';
   1279 
   1280     for (int iDecPositive = iDec2 - 3; iDecPositive > 0; iDecPositive -= 3) {
   1281       strValue.Insert(iDecPositive, cSeperator);
   1282       iMax++;
   1283     }
   1284   }
   1285   ////////////////////////////////////////////////////////////////////
   1286   // negative mark
   1287   if (iNegative)
   1288     strValue = "-" + strValue;
   1289   strValue += "%";
   1290   Value = CFX_WideString::FromLocal(strValue);
   1291 #endif
   1292   return TRUE;
   1293 }
   1294 // AFPercent_Keystroke(nDec, sepStyle)
   1295 FX_BOOL CJS_PublicMethods::AFPercent_Keystroke(
   1296     IJS_Context* cc,
   1297     const std::vector<CJS_Value>& params,
   1298     CJS_Value& vRet,
   1299     CFX_WideString& sError) {
   1300   return AFNumber_Keystroke(cc, params, vRet, sError);
   1301 }
   1302 
   1303 // function AFDate_FormatEx(cFormat)
   1304 FX_BOOL CJS_PublicMethods::AFDate_FormatEx(IJS_Context* cc,
   1305                                            const std::vector<CJS_Value>& params,
   1306                                            CJS_Value& vRet,
   1307                                            CFX_WideString& sError) {
   1308   CJS_Context* pContext = (CJS_Context*)cc;
   1309   CJS_EventHandler* pEvent = pContext->GetEventHandler();
   1310 
   1311   if (params.size() != 1) {
   1312     sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
   1313     return FALSE;
   1314   }
   1315   if (!pEvent->m_pValue)
   1316     return FALSE;
   1317 
   1318   CFX_WideString& val = pEvent->Value();
   1319   CFX_WideString strValue = val;
   1320   if (strValue.IsEmpty())
   1321     return TRUE;
   1322 
   1323   CFX_WideString sFormat = params[0].ToCFXWideString();
   1324   double dDate = 0.0f;
   1325 
   1326   if (strValue.Find(L"GMT") != -1) {
   1327     // for GMT format time
   1328     // such as "Tue Aug 11 14:24:16 GMT+08002009"
   1329     dDate = MakeInterDate(strValue);
   1330   } else {
   1331     dDate = MakeRegularDate(strValue, sFormat, nullptr);
   1332   }
   1333 
   1334   if (JS_PortIsNan(dDate)) {
   1335     CFX_WideString swMsg;
   1336     swMsg.Format(JSGetStringFromID(pContext, IDS_STRING_JSPARSEDATE).c_str(),
   1337                  sFormat.c_str());
   1338     Alert(pContext, swMsg.c_str());
   1339     return FALSE;
   1340   }
   1341 
   1342   val = MakeFormatDate(dDate, sFormat);
   1343   return TRUE;
   1344 }
   1345 
   1346 double CJS_PublicMethods::MakeInterDate(CFX_WideString strValue) {
   1347   int nHour;
   1348   int nMin;
   1349   int nSec;
   1350   int nYear;
   1351   int nMonth;
   1352   int nDay;
   1353 
   1354   CFX_WideStringArray wsArray;
   1355   CFX_WideString sMonth = L"";
   1356   CFX_WideString sTemp = L"";
   1357   int nSize = strValue.GetLength();
   1358 
   1359   for (int i = 0; i < nSize; i++) {
   1360     FX_WCHAR c = strValue.GetAt(i);
   1361     if (c == L' ' || c == L':') {
   1362       wsArray.Add(sTemp);
   1363       sTemp = L"";
   1364       continue;
   1365     }
   1366 
   1367     sTemp += c;
   1368   }
   1369 
   1370   wsArray.Add(sTemp);
   1371   if (wsArray.GetSize() != 8)
   1372     return 0;
   1373 
   1374   sTemp = wsArray[1];
   1375   if (sTemp.Compare(L"Jan") == 0)
   1376     nMonth = 1;
   1377   if (sTemp.Compare(L"Feb") == 0)
   1378     nMonth = 2;
   1379   if (sTemp.Compare(L"Mar") == 0)
   1380     nMonth = 3;
   1381   if (sTemp.Compare(L"Apr") == 0)
   1382     nMonth = 4;
   1383   if (sTemp.Compare(L"May") == 0)
   1384     nMonth = 5;
   1385   if (sTemp.Compare(L"Jun") == 0)
   1386     nMonth = 6;
   1387   if (sTemp.Compare(L"Jul") == 0)
   1388     nMonth = 7;
   1389   if (sTemp.Compare(L"Aug") == 0)
   1390     nMonth = 8;
   1391   if (sTemp.Compare(L"Sep") == 0)
   1392     nMonth = 9;
   1393   if (sTemp.Compare(L"Oct") == 0)
   1394     nMonth = 10;
   1395   if (sTemp.Compare(L"Nov") == 0)
   1396     nMonth = 11;
   1397   if (sTemp.Compare(L"Dec") == 0)
   1398     nMonth = 12;
   1399 
   1400   nDay = (int)ParseStringToNumber(wsArray[2].c_str());
   1401   nHour = (int)ParseStringToNumber(wsArray[3].c_str());
   1402   nMin = (int)ParseStringToNumber(wsArray[4].c_str());
   1403   nSec = (int)ParseStringToNumber(wsArray[5].c_str());
   1404   nYear = (int)ParseStringToNumber(wsArray[7].c_str());
   1405 
   1406   double dRet = JS_MakeDate(JS_MakeDay(nYear, nMonth - 1, nDay),
   1407                             JS_MakeTime(nHour, nMin, nSec, 0));
   1408 
   1409   if (JS_PortIsNan(dRet)) {
   1410     dRet = JS_DateParse(strValue.c_str());
   1411   }
   1412 
   1413   return dRet;
   1414 }
   1415 
   1416 // AFDate_KeystrokeEx(cFormat)
   1417 FX_BOOL CJS_PublicMethods::AFDate_KeystrokeEx(
   1418     IJS_Context* cc,
   1419     const std::vector<CJS_Value>& params,
   1420     CJS_Value& vRet,
   1421     CFX_WideString& sError) {
   1422   CJS_Context* pContext = (CJS_Context*)cc;
   1423   CJS_EventHandler* pEvent = pContext->GetEventHandler();
   1424 
   1425   if (params.size() != 1) {
   1426     sError = L"AFDate_KeystrokeEx's parameters' size r not correct";
   1427     return FALSE;
   1428   }
   1429 
   1430   if (pEvent->WillCommit()) {
   1431     if (!pEvent->m_pValue)
   1432       return FALSE;
   1433     CFX_WideString strValue = pEvent->Value();
   1434     if (strValue.IsEmpty())
   1435       return TRUE;
   1436 
   1437     CFX_WideString sFormat = params[0].ToCFXWideString();
   1438     bool bWrongFormat = FALSE;
   1439     double dRet = MakeRegularDate(strValue, sFormat, &bWrongFormat);
   1440     if (bWrongFormat || JS_PortIsNan(dRet)) {
   1441       CFX_WideString swMsg;
   1442       swMsg.Format(JSGetStringFromID(pContext, IDS_STRING_JSPARSEDATE).c_str(),
   1443                    sFormat.c_str());
   1444       Alert(pContext, swMsg.c_str());
   1445       pEvent->Rc() = FALSE;
   1446       return TRUE;
   1447     }
   1448   }
   1449   return TRUE;
   1450 }
   1451 
   1452 FX_BOOL CJS_PublicMethods::AFDate_Format(IJS_Context* cc,
   1453                                          const std::vector<CJS_Value>& params,
   1454                                          CJS_Value& vRet,
   1455                                          CFX_WideString& sError) {
   1456   CJS_Context* pContext = (CJS_Context*)cc;
   1457   if (params.size() != 1) {
   1458     sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
   1459     return FALSE;
   1460   }
   1461 
   1462   int iIndex = params[0].ToInt();
   1463   const FX_WCHAR* cFormats[] = {L"m/d",
   1464                                 L"m/d/yy",
   1465                                 L"mm/dd/yy",
   1466                                 L"mm/yy",
   1467                                 L"d-mmm",
   1468                                 L"d-mmm-yy",
   1469                                 L"dd-mmm-yy",
   1470                                 L"yy-mm-dd",
   1471                                 L"mmm-yy",
   1472                                 L"mmmm-yy",
   1473                                 L"mmm d, yyyy",
   1474                                 L"mmmm d, yyyy",
   1475                                 L"m/d/yy h:MM tt",
   1476                                 L"m/d/yy HH:MM"};
   1477 
   1478   if (iIndex < 0 || (static_cast<size_t>(iIndex) >= FX_ArraySize(cFormats)))
   1479     iIndex = 0;
   1480 
   1481   std::vector<CJS_Value> newParams;
   1482   newParams.push_back(
   1483       CJS_Value(CJS_Runtime::FromContext(cc), cFormats[iIndex]));
   1484   return AFDate_FormatEx(cc, newParams, vRet, sError);
   1485 }
   1486 
   1487 // AFDate_KeystrokeEx(cFormat)
   1488 FX_BOOL CJS_PublicMethods::AFDate_Keystroke(
   1489     IJS_Context* cc,
   1490     const std::vector<CJS_Value>& params,
   1491     CJS_Value& vRet,
   1492     CFX_WideString& sError) {
   1493   CJS_Context* pContext = (CJS_Context*)cc;
   1494   if (params.size() != 1) {
   1495     sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
   1496     return FALSE;
   1497   }
   1498 
   1499   int iIndex = params[0].ToInt();
   1500   const FX_WCHAR* cFormats[] = {L"m/d",
   1501                                 L"m/d/yy",
   1502                                 L"mm/dd/yy",
   1503                                 L"mm/yy",
   1504                                 L"d-mmm",
   1505                                 L"d-mmm-yy",
   1506                                 L"dd-mmm-yy",
   1507                                 L"yy-mm-dd",
   1508                                 L"mmm-yy",
   1509                                 L"mmmm-yy",
   1510                                 L"mmm d, yyyy",
   1511                                 L"mmmm d, yyyy",
   1512                                 L"m/d/yy h:MM tt",
   1513                                 L"m/d/yy HH:MM"};
   1514 
   1515   if (iIndex < 0 || (static_cast<size_t>(iIndex) >= FX_ArraySize(cFormats)))
   1516     iIndex = 0;
   1517 
   1518   std::vector<CJS_Value> newParams;
   1519   newParams.push_back(
   1520       CJS_Value(CJS_Runtime::FromContext(cc), cFormats[iIndex]));
   1521   return AFDate_KeystrokeEx(cc, newParams, vRet, sError);
   1522 }
   1523 
   1524 // function AFTime_Format(ptf)
   1525 FX_BOOL CJS_PublicMethods::AFTime_Format(IJS_Context* cc,
   1526                                          const std::vector<CJS_Value>& params,
   1527                                          CJS_Value& vRet,
   1528                                          CFX_WideString& sError) {
   1529   CJS_Context* pContext = (CJS_Context*)cc;
   1530   if (params.size() != 1) {
   1531     sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
   1532     return FALSE;
   1533   }
   1534 
   1535   int iIndex = params[0].ToInt();
   1536   const FX_WCHAR* cFormats[] = {L"HH:MM", L"h:MM tt", L"HH:MM:ss",
   1537                                 L"h:MM:ss tt"};
   1538 
   1539   if (iIndex < 0 || (static_cast<size_t>(iIndex) >= FX_ArraySize(cFormats)))
   1540     iIndex = 0;
   1541 
   1542   std::vector<CJS_Value> newParams;
   1543   newParams.push_back(
   1544       CJS_Value(CJS_Runtime::FromContext(cc), cFormats[iIndex]));
   1545   return AFDate_FormatEx(cc, newParams, vRet, sError);
   1546 }
   1547 
   1548 FX_BOOL CJS_PublicMethods::AFTime_Keystroke(
   1549     IJS_Context* cc,
   1550     const std::vector<CJS_Value>& params,
   1551     CJS_Value& vRet,
   1552     CFX_WideString& sError) {
   1553   CJS_Context* pContext = (CJS_Context*)cc;
   1554   if (params.size() != 1) {
   1555     sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
   1556     return FALSE;
   1557   }
   1558 
   1559   int iIndex = params[0].ToInt();
   1560   const FX_WCHAR* cFormats[] = {L"HH:MM", L"h:MM tt", L"HH:MM:ss",
   1561                                 L"h:MM:ss tt"};
   1562 
   1563   if (iIndex < 0 || (static_cast<size_t>(iIndex) >= FX_ArraySize(cFormats)))
   1564     iIndex = 0;
   1565 
   1566   std::vector<CJS_Value> newParams;
   1567   newParams.push_back(
   1568       CJS_Value(CJS_Runtime::FromContext(cc), cFormats[iIndex]));
   1569   return AFDate_KeystrokeEx(cc, newParams, vRet, sError);
   1570 }
   1571 
   1572 FX_BOOL CJS_PublicMethods::AFTime_FormatEx(IJS_Context* cc,
   1573                                            const std::vector<CJS_Value>& params,
   1574                                            CJS_Value& vRet,
   1575                                            CFX_WideString& sError) {
   1576   return AFDate_FormatEx(cc, params, vRet, sError);
   1577 }
   1578 
   1579 FX_BOOL CJS_PublicMethods::AFTime_KeystrokeEx(
   1580     IJS_Context* cc,
   1581     const std::vector<CJS_Value>& params,
   1582     CJS_Value& vRet,
   1583     CFX_WideString& sError) {
   1584   return AFDate_KeystrokeEx(cc, params, vRet, sError);
   1585 }
   1586 
   1587 // function AFSpecial_Format(psf)
   1588 FX_BOOL CJS_PublicMethods::AFSpecial_Format(
   1589     IJS_Context* cc,
   1590     const std::vector<CJS_Value>& params,
   1591     CJS_Value& vRet,
   1592     CFX_WideString& sError) {
   1593   CJS_Context* pContext = (CJS_Context*)cc;
   1594 
   1595   if (params.size() != 1) {
   1596     sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
   1597     return FALSE;
   1598   }
   1599 
   1600   std::string cFormat;
   1601   int iIndex = params[0].ToInt();
   1602 
   1603   CJS_EventHandler* pEvent = pContext->GetEventHandler();
   1604   if (!pEvent->m_pValue)
   1605     return FALSE;
   1606   CFX_WideString& Value = pEvent->Value();
   1607   std::string strSrc = CFX_ByteString::FromUnicode(Value).c_str();
   1608 
   1609   switch (iIndex) {
   1610     case 0:
   1611       cFormat = "99999";
   1612       break;
   1613     case 1:
   1614       cFormat = "99999-9999";
   1615       break;
   1616     case 2: {
   1617       std::string NumberStr;
   1618       util::printx("9999999999", strSrc, NumberStr);
   1619       if (NumberStr.length() >= 10)
   1620         cFormat = "(999) 999-9999";
   1621       else
   1622         cFormat = "999-9999";
   1623       break;
   1624     }
   1625     case 3:
   1626       cFormat = "999-99-9999";
   1627       break;
   1628   }
   1629 
   1630   std::string strDes;
   1631   util::printx(cFormat, strSrc, strDes);
   1632   Value = CFX_WideString::FromLocal(strDes.c_str());
   1633   return TRUE;
   1634 }
   1635 
   1636 // function AFSpecial_KeystrokeEx(mask)
   1637 FX_BOOL CJS_PublicMethods::AFSpecial_KeystrokeEx(
   1638     IJS_Context* cc,
   1639     const std::vector<CJS_Value>& params,
   1640     CJS_Value& vRet,
   1641     CFX_WideString& sError) {
   1642   CJS_Context* pContext = (CJS_Context*)cc;
   1643   CJS_EventHandler* pEvent = pContext->GetEventHandler();
   1644 
   1645   if (params.size() < 1) {
   1646     sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
   1647     return FALSE;
   1648   }
   1649 
   1650   if (!pEvent->m_pValue)
   1651     return FALSE;
   1652   CFX_WideString& valEvent = pEvent->Value();
   1653 
   1654   CFX_WideString wstrMask = params[0].ToCFXWideString();
   1655   if (wstrMask.IsEmpty())
   1656     return TRUE;
   1657 
   1658   const size_t wstrMaskLen = wstrMask.GetLength();
   1659   const std::wstring wstrValue = valEvent.c_str();
   1660 
   1661   if (pEvent->WillCommit()) {
   1662     if (wstrValue.empty())
   1663       return TRUE;
   1664     size_t iIndexMask = 0;
   1665     for (const auto& w_Value : wstrValue) {
   1666       if (!maskSatisfied(w_Value, wstrMask[iIndexMask]))
   1667         break;
   1668       iIndexMask++;
   1669     }
   1670 
   1671     if (iIndexMask != wstrMaskLen ||
   1672         (iIndexMask != wstrValue.size() && wstrMaskLen != 0)) {
   1673       Alert(
   1674           pContext,
   1675           JSGetStringFromID(pContext, IDS_STRING_JSAFNUMBER_KEYSTROKE).c_str());
   1676       pEvent->Rc() = FALSE;
   1677     }
   1678     return TRUE;
   1679   }
   1680 
   1681   CFX_WideString& wideChange = pEvent->Change();
   1682   std::wstring wChange = wideChange.c_str();
   1683   if (wChange.empty())
   1684     return TRUE;
   1685 
   1686   int iIndexMask = pEvent->SelStart();
   1687 
   1688   size_t combined_len = wstrValue.length() + wChange.length() -
   1689                         (pEvent->SelEnd() - pEvent->SelStart());
   1690   if (combined_len > wstrMaskLen) {
   1691     Alert(pContext,
   1692           JSGetStringFromID(pContext, IDS_STRING_JSPARAM_TOOLONG).c_str());
   1693     pEvent->Rc() = FALSE;
   1694     return TRUE;
   1695   }
   1696 
   1697   if (iIndexMask >= wstrMaskLen && (!wChange.empty())) {
   1698     Alert(pContext,
   1699           JSGetStringFromID(pContext, IDS_STRING_JSPARAM_TOOLONG).c_str());
   1700     pEvent->Rc() = FALSE;
   1701     return TRUE;
   1702   }
   1703 
   1704   for (std::wstring::iterator it = wChange.begin(); it != wChange.end(); it++) {
   1705     if (iIndexMask >= wstrMaskLen) {
   1706       Alert(pContext,
   1707             JSGetStringFromID(pContext, IDS_STRING_JSPARAM_TOOLONG).c_str());
   1708       pEvent->Rc() = FALSE;
   1709       return TRUE;
   1710     }
   1711     wchar_t w_Mask = wstrMask[iIndexMask];
   1712     if (!isReservedMaskChar(w_Mask)) {
   1713       *it = w_Mask;
   1714     }
   1715     wchar_t w_Change = *it;
   1716     if (!maskSatisfied(w_Change, w_Mask)) {
   1717       pEvent->Rc() = FALSE;
   1718       return TRUE;
   1719     }
   1720     iIndexMask++;
   1721   }
   1722 
   1723   wideChange = wChange.c_str();
   1724   return TRUE;
   1725 }
   1726 
   1727 // function AFSpecial_Keystroke(psf)
   1728 FX_BOOL CJS_PublicMethods::AFSpecial_Keystroke(
   1729     IJS_Context* cc,
   1730     const std::vector<CJS_Value>& params,
   1731     CJS_Value& vRet,
   1732     CFX_WideString& sError) {
   1733   CJS_Context* pContext = (CJS_Context*)cc;
   1734   if (params.size() != 1) {
   1735     sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
   1736     return FALSE;
   1737   }
   1738 
   1739   CJS_EventHandler* pEvent = pContext->GetEventHandler();
   1740   if (!pEvent->m_pValue)
   1741     return FALSE;
   1742 
   1743   std::string cFormat;
   1744   int iIndex = params[0].ToInt();
   1745   CFX_WideString& val = pEvent->Value();
   1746   std::string strSrc = CFX_ByteString::FromUnicode(val).c_str();
   1747   std::wstring wstrChange = pEvent->Change().c_str();
   1748 
   1749   switch (iIndex) {
   1750     case 0:
   1751       cFormat = "99999";
   1752       break;
   1753     case 1:
   1754       // cFormat = "99999-9999";
   1755       cFormat = "999999999";
   1756       break;
   1757     case 2: {
   1758       std::string NumberStr;
   1759       util::printx("9999999999", strSrc, NumberStr);
   1760       if (strSrc.length() + wstrChange.length() > 7)
   1761         // cFormat = "(999) 999-9999";
   1762         cFormat = "9999999999";
   1763       else
   1764         // cFormat = "999-9999";
   1765         cFormat = "9999999";
   1766       break;
   1767     }
   1768     case 3:
   1769       // cFormat = "999-99-9999";
   1770       cFormat = "999999999";
   1771       break;
   1772   }
   1773 
   1774   std::vector<CJS_Value> params2;
   1775   params2.push_back(CJS_Value(CJS_Runtime::FromContext(cc), cFormat.c_str()));
   1776   return AFSpecial_KeystrokeEx(cc, params2, vRet, sError);
   1777 }
   1778 
   1779 FX_BOOL CJS_PublicMethods::AFMergeChange(IJS_Context* cc,
   1780                                          const std::vector<CJS_Value>& params,
   1781                                          CJS_Value& vRet,
   1782                                          CFX_WideString& sError) {
   1783   CJS_Context* pContext = (CJS_Context*)cc;
   1784   CJS_EventHandler* pEventHandler = pContext->GetEventHandler();
   1785 
   1786   if (params.size() != 1) {
   1787     sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
   1788     return FALSE;
   1789   }
   1790 
   1791   CFX_WideString swValue;
   1792   if (pEventHandler->m_pValue)
   1793     swValue = pEventHandler->Value();
   1794 
   1795   if (pEventHandler->WillCommit()) {
   1796     vRet = swValue.c_str();
   1797     return TRUE;
   1798   }
   1799 
   1800   CFX_WideString prefix, postfix;
   1801 
   1802   if (pEventHandler->SelStart() >= 0)
   1803     prefix = swValue.Mid(0, pEventHandler->SelStart());
   1804   else
   1805     prefix = L"";
   1806 
   1807   if (pEventHandler->SelEnd() >= 0 &&
   1808       pEventHandler->SelEnd() <= swValue.GetLength())
   1809     postfix = swValue.Mid(pEventHandler->SelEnd(),
   1810                           swValue.GetLength() - pEventHandler->SelEnd());
   1811   else
   1812     postfix = L"";
   1813 
   1814   vRet = (prefix + pEventHandler->Change() + postfix).c_str();
   1815 
   1816   return TRUE;
   1817 }
   1818 
   1819 FX_BOOL CJS_PublicMethods::AFParseDateEx(IJS_Context* cc,
   1820                                          const std::vector<CJS_Value>& params,
   1821                                          CJS_Value& vRet,
   1822                                          CFX_WideString& sError) {
   1823   CJS_Context* pContext = (CJS_Context*)cc;
   1824   ASSERT(pContext);
   1825 
   1826   if (params.size() != 2) {
   1827     sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
   1828     return FALSE;
   1829   }
   1830 
   1831   CFX_WideString sValue = params[0].ToCFXWideString();
   1832   CFX_WideString sFormat = params[1].ToCFXWideString();
   1833 
   1834   double dDate = MakeRegularDate(sValue, sFormat, nullptr);
   1835 
   1836   if (JS_PortIsNan(dDate)) {
   1837     CFX_WideString swMsg;
   1838     swMsg.Format(JSGetStringFromID(pContext, IDS_STRING_JSPARSEDATE).c_str(),
   1839                  sFormat.c_str());
   1840     Alert((CJS_Context*)cc, swMsg.c_str());
   1841     return FALSE;
   1842   }
   1843 
   1844   vRet = dDate;
   1845   return TRUE;
   1846 }
   1847 
   1848 FX_BOOL CJS_PublicMethods::AFSimple(IJS_Context* cc,
   1849                                     const std::vector<CJS_Value>& params,
   1850                                     CJS_Value& vRet,
   1851                                     CFX_WideString& sError) {
   1852   if (params.size() != 3) {
   1853     CJS_Context* pContext = (CJS_Context*)cc;
   1854     ASSERT(pContext);
   1855 
   1856     sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
   1857     return FALSE;
   1858   }
   1859 
   1860   vRet = (double)AF_Simple(params[0].ToCFXWideString().c_str(),
   1861                            params[1].ToDouble(), params[2].ToDouble());
   1862   return TRUE;
   1863 }
   1864 
   1865 FX_BOOL CJS_PublicMethods::AFMakeNumber(IJS_Context* cc,
   1866                                         const std::vector<CJS_Value>& params,
   1867                                         CJS_Value& vRet,
   1868                                         CFX_WideString& sError) {
   1869   if (params.size() != 1) {
   1870     CJS_Context* pContext = (CJS_Context*)cc;
   1871     ASSERT(pContext);
   1872 
   1873     sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
   1874     return FALSE;
   1875   }
   1876   vRet = ParseStringToNumber(params[0].ToCFXWideString().c_str());
   1877   return TRUE;
   1878 }
   1879 
   1880 FX_BOOL CJS_PublicMethods::AFSimple_Calculate(
   1881     IJS_Context* cc,
   1882     const std::vector<CJS_Value>& params,
   1883     CJS_Value& vRet,
   1884     CFX_WideString& sError) {
   1885   CJS_Context* pContext = (CJS_Context*)cc;
   1886   if (params.size() != 2) {
   1887     sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
   1888     return FALSE;
   1889   }
   1890 
   1891   CJS_Value params1 = params[1];
   1892   if (!params1.IsArrayObject() && params1.GetType() != CJS_Value::VT_string) {
   1893     sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
   1894     return FALSE;
   1895   }
   1896 
   1897   CPDFSDK_Document* pReaderDoc = pContext->GetReaderDocument();
   1898   CPDFSDK_InterForm* pReaderInterForm = pReaderDoc->GetInterForm();
   1899   CPDF_InterForm* pInterForm = pReaderInterForm->GetInterForm();
   1900 
   1901   CFX_WideString sFunction = params[0].ToCFXWideString();
   1902   double dValue = wcscmp(sFunction.c_str(), L"PRD") == 0 ? 1.0 : 0.0;
   1903 
   1904   CJS_Runtime* pRuntime = CJS_Runtime::FromContext(cc);
   1905   CJS_Array FieldNameArray = AF_MakeArrayFromList(pRuntime, params1);
   1906   int nFieldsCount = 0;
   1907 
   1908   for (int i = 0, isz = FieldNameArray.GetLength(); i < isz; i++) {
   1909     CJS_Value jsValue(pRuntime);
   1910     FieldNameArray.GetElement(i, jsValue);
   1911     CFX_WideString wsFieldName = jsValue.ToCFXWideString();
   1912 
   1913     for (int j = 0, jsz = pInterForm->CountFields(wsFieldName); j < jsz; j++) {
   1914       if (CPDF_FormField* pFormField = pInterForm->GetField(j, wsFieldName)) {
   1915         double dTemp = 0.0;
   1916 
   1917         switch (pFormField->GetFieldType()) {
   1918           case FIELDTYPE_TEXTFIELD:
   1919           case FIELDTYPE_COMBOBOX: {
   1920             dTemp = ParseStringToNumber(pFormField->GetValue().c_str());
   1921             break;
   1922           }
   1923           case FIELDTYPE_PUSHBUTTON: {
   1924             dTemp = 0.0;
   1925             break;
   1926           }
   1927           case FIELDTYPE_CHECKBOX:
   1928           case FIELDTYPE_RADIOBUTTON: {
   1929             dTemp = 0.0;
   1930             for (int c = 0, csz = pFormField->CountControls(); c < csz; c++) {
   1931               if (CPDF_FormControl* pFormCtrl = pFormField->GetControl(c)) {
   1932                 if (pFormCtrl->IsChecked()) {
   1933                   dTemp +=
   1934                       ParseStringToNumber(pFormCtrl->GetExportValue().c_str());
   1935                   break;
   1936                 }
   1937               }
   1938             }
   1939             break;
   1940           }
   1941           case FIELDTYPE_LISTBOX: {
   1942             if (pFormField->CountSelectedItems() > 1)
   1943               break;
   1944 
   1945             dTemp = ParseStringToNumber(pFormField->GetValue().c_str());
   1946             break;
   1947           }
   1948           default:
   1949             break;
   1950         }
   1951 
   1952         if (i == 0 && j == 0 && (wcscmp(sFunction.c_str(), L"MIN") == 0 ||
   1953                                  wcscmp(sFunction.c_str(), L"MAX") == 0))
   1954           dValue = dTemp;
   1955 
   1956         dValue = AF_Simple(sFunction.c_str(), dValue, dTemp);
   1957 
   1958         nFieldsCount++;
   1959       }
   1960     }
   1961   }
   1962 
   1963   if (wcscmp(sFunction.c_str(), L"AVG") == 0 && nFieldsCount > 0)
   1964     dValue /= nFieldsCount;
   1965 
   1966   dValue = (double)floor(dValue * FXSYS_pow((double)10, (double)6) + 0.49) /
   1967            FXSYS_pow((double)10, (double)6);
   1968   CJS_Value jsValue(pRuntime, dValue);
   1969   if (pContext->GetEventHandler()->m_pValue)
   1970     pContext->GetEventHandler()->Value() = jsValue.ToCFXWideString();
   1971 
   1972   return TRUE;
   1973 }
   1974 
   1975 /* This function validates the current event to ensure that its value is
   1976 ** within the specified range. */
   1977 
   1978 FX_BOOL CJS_PublicMethods::AFRange_Validate(
   1979     IJS_Context* cc,
   1980     const std::vector<CJS_Value>& params,
   1981     CJS_Value& vRet,
   1982     CFX_WideString& sError) {
   1983   CJS_Context* pContext = (CJS_Context*)cc;
   1984   CJS_EventHandler* pEvent = pContext->GetEventHandler();
   1985 
   1986   if (params.size() != 4) {
   1987     sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
   1988     return FALSE;
   1989   }
   1990 
   1991   if (!pEvent->m_pValue)
   1992     return FALSE;
   1993   if (pEvent->Value().IsEmpty())
   1994     return TRUE;
   1995   double dEentValue = atof(CFX_ByteString::FromUnicode(pEvent->Value()));
   1996   FX_BOOL bGreaterThan = params[0].ToBool();
   1997   double dGreaterThan = params[1].ToDouble();
   1998   FX_BOOL bLessThan = params[2].ToBool();
   1999   double dLessThan = params[3].ToDouble();
   2000   CFX_WideString swMsg;
   2001 
   2002   if (bGreaterThan && bLessThan) {
   2003     if (dEentValue < dGreaterThan || dEentValue > dLessThan)
   2004       swMsg.Format(JSGetStringFromID(pContext, IDS_STRING_JSRANGE1).c_str(),
   2005                    params[1].ToCFXWideString().c_str(),
   2006                    params[3].ToCFXWideString().c_str());
   2007   } else if (bGreaterThan) {
   2008     if (dEentValue < dGreaterThan)
   2009       swMsg.Format(JSGetStringFromID(pContext, IDS_STRING_JSRANGE2).c_str(),
   2010                    params[1].ToCFXWideString().c_str());
   2011   } else if (bLessThan) {
   2012     if (dEentValue > dLessThan)
   2013       swMsg.Format(JSGetStringFromID(pContext, IDS_STRING_JSRANGE3).c_str(),
   2014                    params[3].ToCFXWideString().c_str());
   2015   }
   2016 
   2017   if (!swMsg.IsEmpty()) {
   2018     Alert(pContext, swMsg.c_str());
   2019     pEvent->Rc() = FALSE;
   2020   }
   2021   return TRUE;
   2022 }
   2023 
   2024 FX_BOOL CJS_PublicMethods::AFExtractNums(IJS_Context* cc,
   2025                                          const std::vector<CJS_Value>& params,
   2026                                          CJS_Value& vRet,
   2027                                          CFX_WideString& sError) {
   2028   CJS_Context* pContext = (CJS_Context*)cc;
   2029   if (params.size() != 1) {
   2030     sError = JSGetStringFromID(pContext, IDS_STRING_JSPARAMERROR);
   2031     return FALSE;
   2032   }
   2033 
   2034   CJS_Runtime* pRuntime = CJS_Runtime::FromContext(cc);
   2035   CJS_Array nums(pRuntime);
   2036 
   2037   CFX_WideString str = params[0].ToCFXWideString();
   2038   CFX_WideString sPart;
   2039 
   2040   if (str.GetAt(0) == L'.' || str.GetAt(0) == L',')
   2041     str = L"0" + str;
   2042 
   2043   int nIndex = 0;
   2044   for (int i = 0, sz = str.GetLength(); i < sz; i++) {
   2045     FX_WCHAR wc = str.GetAt(i);
   2046     if (FXSYS_iswdigit(wc)) {
   2047       sPart += wc;
   2048     } else {
   2049       if (sPart.GetLength() > 0) {
   2050         nums.SetElement(nIndex, CJS_Value(pRuntime, sPart.c_str()));
   2051         sPart = L"";
   2052         nIndex++;
   2053       }
   2054     }
   2055   }
   2056 
   2057   if (sPart.GetLength() > 0) {
   2058     nums.SetElement(nIndex, CJS_Value(pRuntime, sPart.c_str()));
   2059   }
   2060 
   2061   if (nums.GetLength() > 0)
   2062     vRet = nums;
   2063   else
   2064     vRet.SetNull();
   2065 
   2066   return TRUE;
   2067 }
   2068