home *** CD-ROM | disk | FTP | other *** search
/ Chip 2004 April / Chip_2004-04_cd2.bin / program / reader / Data1.cab / aform.js < prev    next >
Text File  |  2003-07-17  |  45KB  |  1,691 lines

  1. /*
  2.     ==========================================================================
  3.     Module: AForm.js
  4.     ==========================================================================
  5.     Pre-canned functions to map the user interface into JavaScripts.
  6.     ==========================================================================
  7.     The Software, including this file, is subject to the End User License
  8.     Agreement.
  9.     Copyright (c) 1998-2002, Adobe Systems Incorporated, All Rights Reserved.
  10.     ==========================================================================
  11. */
  12.  
  13. // The following code "exports" any strings in the list into the current scope.
  14. var esStrsToExport = new Array(
  15.     "IDS_GREATER_THAN", 
  16.     "IDS_GT_AND_LT", 
  17.     "IDS_LESS_THAN", 
  18.     "IDS_INVALID_MONTH",
  19.     "IDS_INVALID_DATE",
  20.     "IDS_INVALID_DATE2",
  21.     "IDS_INVALID_VALUE", 
  22.     "IDS_AM", "IDS_PM", 
  23.     "IDS_MONTH_INFO", 
  24.     "IDS_STARTUP_CONSOLE_MSG");
  25.  
  26. for(var nToExport = 0; nToExport < esStrsToExport.length; nToExport++)
  27.     eval(esStrsToExport[nToExport] + " = " + app.getString("EScript", esStrsToExport[nToExport]).toSource());
  28.  
  29. console.println(IDS_STARTUP_CONSOLE_MSG);
  30.  
  31. RE_NUMBER_ENTRY_DOT_SEP = new Array(
  32.     "[+-]?\\d*\\.?\\d*"
  33. );
  34. RE_NUMBER_COMMIT_DOT_SEP = new Array(
  35.     "[+-]?\\d+(\\.\\d+)?",        /* -1.0 or -1 */
  36.     "[+-]?\\.\\d+",                /* -.1 */
  37.     "[+-]?\\d+\\."                /* -1. */
  38. );
  39. RE_NUMBER_ENTRY_COMMA_SEP = new Array(
  40.     "[+-]?\\d*,?\\d*"
  41. );
  42. RE_NUMBER_COMMIT_COMMA_SEP = new Array(
  43.     "[+-]?\\d+([.,]\\d+)?",        /* -1,0 or -1 */
  44.     "[+-]?[.,]\\d+",                /* -,1 */
  45.     "[+-]?\\d+[.,]"                /* -1, */
  46. );
  47. RE_ZIP_ENTRY = new Array(
  48.     "\\d{0,5}"
  49. );
  50. RE_ZIP_COMMIT = new Array(
  51.     "\\d{5}"
  52. );
  53. RE_ZIP4_ENTRY = new Array(
  54.     "\\d{0,5}(\\.|[- ])?\\d{0,4}"
  55. );
  56. RE_ZIP4_COMMIT = new Array(
  57.     "\\d{5}(\\.|[- ])?\\d{4}"
  58. );
  59. RE_PHONE_ENTRY = new Array(
  60.     "\\d{0,3}(\\.|[- ])?\\d{0,3}(\\.|[- ])?\\d{0,4}",        /* 555-1234 or 408 555-1234 */
  61.     "\\(\\d{0,3}",                                            /* (408 */
  62.     "\\(\\d{0,3}\\)(\\.|[- ])?\\d{0,3}(\\.|[- ])?\\d{0,4}",    /* (408) 555-1234 */
  63.         /* (allow the addition of parens as an afterthought) */
  64.     "\\(\\d{0,3}(\\.|[- ])?\\d{0,3}(\\.|[- ])?\\d{0,4}",    /* (408 555-1234 */
  65.     "\\d{0,3}\\)(\\.|[- ])?\\d{0,3}(\\.|[- ])?\\d{0,4}",    /* 408) 555-1234 */
  66.     "011(\\.|[- \\d])*"                                        /* international */
  67. );
  68. RE_PHONE_COMMIT = new Array(
  69.     "\\d{3}(\\.|[- ])?\\d{4}",                            /* 555-1234 */
  70.     "\\d{3}(\\.|[- ])?\\d{3}(\\.|[- ])?\\d{4}",            /* 408 555-1234 */
  71.     "\\(\\d{3}\\)(\\.|[- ])?\\d{3}(\\.|[- ])?\\d{4}",    /* (408) 555-1234 */
  72.     "011(\\.|[- \\d])*"                                    /* international */
  73. );
  74. RE_SSN_ENTRY = new Array(
  75.     "\\d{0,3}(\\.|[- ])?\\d{0,2}(\\.|[- ])?\\d{0,4}"
  76. );
  77. RE_SSN_COMMIT = new Array(
  78.     "\\d{3}(\\.|[- ])?\\d{2}(\\.|[- ])?\\d{4}"
  79. );
  80.  
  81. /* Function definitions for the color object. */
  82.  
  83. function ColorConvert(oColor, cColorspace)
  84. {    // Converts a color to a specific colorspace.
  85.     var oOut = oColor;
  86.  
  87.     switch (cColorspace) {
  88.         case "G":
  89.             // Note that conversion to the DeviceGray colorspace is lossy in the same
  90.             // way that a color signal on a B/W TV is lossy.
  91.             if (oColor[0] == "RGB")
  92.                 oOut = new Array("G", 0.3 * oColor[1] + 0.59 * oColor[2] + 0.11 * oColor[3]);
  93.             else if (oColor[0] == "CMYK")
  94.                 oOut = new Array("G", 1.0 - Math.min(1.0, 
  95.                     0.3 * oColor[1] + 0.59 * oColor[2] + 0.11 * oColor[3] + oColor[4]));
  96.         break;
  97.         case "RGB":
  98.             if (oColor[0] == "G")
  99.                 oOut = new Array("RGB", oColor[1], oColor[1], oColor[1]);
  100.             else if (oColor[0] == "CMYK")
  101.                 oOut = new Array("RGB", 1.0 - Math.min(1.0, oColor[1] + oColor[4]), 
  102.                     1.0 - Math.min(1.0, oColor[2] + oColor[4]),
  103.                     1.0 - Math.min(1.0, oColor[3] + oColor[4]));
  104.         break;
  105.         case "CMYK":
  106.             if (oColor[0] == "G")
  107.                 oOut = new Array("CMYK", 0, 0, 0, 1.0 - oColor[1]);
  108.             else if (oColor[0] == "RGB")
  109.                 oOut = new Array("CMYK", 1.0 - oColor[1], 1.0 - oColor[2], 1.0 - oColor[3], 0); 
  110.         break;
  111.     }
  112.  
  113.     return oOut;
  114. }
  115.  
  116. function ColorEqual(c1, c2)
  117. {    // Compare two colors. 
  118.     /* The gray colorspace conversion is lossy so we avoid if possible. */
  119.     if (c1[0] == "G")
  120.         c1 = color.convert(c1, c2[0]);
  121.     else
  122.         c2 = color.convert(c2, c1[0]);
  123.  
  124.     /* Colorspace must be equal. */
  125.     if (c1[0] != c2[0])    {
  126.         return false;
  127.     }
  128.  
  129.     /* Compare the individual components. */
  130.     var nComponents = 0;
  131.         
  132.     switch (c1[0]) {
  133.         case "G":
  134.             nComponents = 1;
  135.         break;
  136.         case "RGB":
  137.             nComponents = 3;
  138.         break;
  139.         case "CMYK":
  140.             nComponents = 4;
  141.         break;
  142.     }
  143.  
  144.     for (var i = 1; i <= nComponents; i++) {
  145.         if (c1[i] != c2[i])    {
  146.             return false;
  147.         }
  148.     }
  149.  
  150.     return true;
  151. }
  152.  
  153. /* ==== Convenience Objects ==== */
  154.  
  155. /* Stock color definitions for ease of use. */
  156. color = new Object();
  157. color.equal = ColorEqual;
  158. color.convert = ColorConvert;
  159. color.transparent = new Array("T");
  160. color.black = new Array("G", 0);
  161. color.white = new Array("G", 1);
  162. color.dkGray = new Array("G", 0.25);
  163. color.gray = new Array("G", 0.5);
  164. color.ltGray = new Array("G", 0.75);
  165. color.red = new Array("RGB", 1, 0, 0);
  166. color.green = new Array("RGB", 0, 1, 0);
  167. color.blue = new Array("RGB", 0, 0, 1);
  168. color.cyan = new Array("CMYK", 1, 0, 0, 0);
  169. color.magenta = new Array("CMYK", 0, 1, 0, 0);
  170. color.yellow = new Array("CMYK", 0, 0, 1, 0);
  171.     
  172. /* Font definitions for ease of use */
  173. font = new Object();
  174. font.Times = "Times-Roman";
  175. font.TimesB = "Times-Bold";
  176. font.TimesI = "Times-Italic";
  177. font.TimesBI = "Times-BoldItalic";
  178. font.Helv = "Helvetica";
  179. font.HelvB = "Helvetica-Bold";
  180. font.HelvI = "Helvetica-Oblique";
  181. font.HelvBI = "Helvetica-BoldOblique";
  182. font.Cour = "Courier";
  183. font.CourB = "Courier-Bold";
  184. font.CourI = "Courier-Oblique";
  185. font.CourBI = "Courier-BoldOblique";
  186. font.Symbol = "Symbol";
  187. font.ZapfD = "ZapfDingbats";
  188. font.KaGo = "HeiseiKakuGo-W5-UniJIS-UCS2-H";
  189. font.KaMi = "HeiseiMin-W3-UniJIS-UCS2-H";
  190.  
  191. /* #if qWR */
  192. font.MyrProRg = "@MyriadPro-Regular";
  193. font.MyrProBd = "@MyriadPro-Bold";
  194. font.MyrProBdIt = "@MyriadPro-BoldIt";
  195. font.MyrProIt = "@MyriadPro-It";
  196. font.MinProRg = "@MinionPro-Regular"
  197. font.MinProBd = "@MinionPro-Bold"
  198. font.MinProBdIt = "@MinionPro-BoldIt"
  199. font.MinProIt = "@MinionPro-It"
  200.  
  201. font.WSProMe = "@WinSoftSerifPro-Med";
  202. font.WSProBd = "@WinSoftSerifPro-Bold";
  203. font.WSProBdIt = "@WinSoftSerifPro-BItal";
  204. font.WSProIt = "@WinSoftSerifPro-MItal";
  205. font.WProMe = "@WinSoftPro-Med"
  206. font.WProBd = "@WinSoftPro-Bold"
  207. font.WProBdIt = "@WinSoftPro-BItal"
  208. font.WProIt = "@WinSoftPro-MItal"
  209.  
  210. /* Compatibility with previous version */
  211. font.MyCE = "MyCE";
  212. font.MyCEB = "MyCEB";
  213. font.MiCE = "MiCE";
  214. font.MiCEB = "MiCEB";
  215. font.CourCE = "CourCE";
  216. font.CourCEB = "CourCEB";
  217. font.MiCy = "MiCy";
  218. font.MiCyB = "MiCyB";
  219. font.Gr01 = "Gr01";
  220. font.Tu01 = "Tu01";
  221.  
  222. font.WNMe = "WinSoftNaskhMedium"
  223. font.WNBo = "WinSoftNaskhBold"
  224. font.WTLi = "WinSoftThuluthLight"
  225. font.WTBo = "WinSoftThuluthBold"
  226. font.WSMe = "WinSoftSerifMedium"
  227. font.WSBo = "WinSoftSerifBold"
  228. font.WSSM = "WinSoftSansSerifMedium"
  229.  
  230. /* Font encoding */
  231. subset = new Object();
  232. subset.All = 0;
  233. subset.Roman = 1;
  234. subset.Kanji = 2;
  235. subset.ChineseT = 3;
  236. subset.ChineseS = 4;
  237. subset.Korean = 5;
  238. subset.EastEuropean = 6;
  239. subset.Cyrillic = 7;
  240. subset.Greek = 8;
  241. subset.Turkish = 9;
  242. subset.Arabic = 10;
  243. subset.Hebrew = 11;
  244. subset.Baltic = 12;
  245. subset.ExtEastEuropean = 13;
  246. subset.ExtCyrillic = 14;
  247.  
  248. /* #endif qWR */
  249. /* Border style definitions for ease of use */
  250. border = new Object();
  251. border.s = "solid";
  252. border.d = "dashed";
  253. border.b = "beveled";
  254. border.i = "inset";
  255. border.u = "underline";
  256.  
  257. /* Radio/Check button style definitions for ease of use */
  258. style = new Object();
  259. style.ch = "check";
  260. style.cr = "cross";
  261. style.di = "diamond";
  262. style.ci = "circle";
  263. style.st = "star";
  264. style.sq = "square"; 
  265.  
  266. /* highlight modes of on a push button */
  267. highlight = new Object();
  268. highlight.n = "none";
  269. highlight.i = "invert";
  270. highlight.p = "push";
  271. highlight.o = "outline";
  272.  
  273. /* zoom types for a document */
  274. zoomtype = new Object();
  275. zoomtype.none = "NoVary";
  276. zoomtype.fitW = "FitWidth";
  277. zoomtype.fitH = "FitHeight";
  278. zoomtype.fitP = "FitPage";
  279. zoomtype.fitV = "FitVisibleWidth";
  280. zoomtype.pref = "Preferred";
  281. zoomtype.refW = "ReflowWidth";
  282.  
  283. /* Cursor behavior in full screen mode. */
  284. cursor = new Object();
  285. cursor.visible = 0;
  286. cursor.hidden = 1;
  287. cursor.delay = 2;
  288.  
  289. /* Transition definitions. */
  290. trans = new Object();
  291. trans.blindsH        = "BlindsHorizontal";
  292. trans.blindsV        = "BlindsVertical";
  293. trans.boxI            = "BoxIn";
  294. trans.boxO            = "BoxOut";
  295. trans.dissolve        = "Dissolve";
  296. trans.glitterD        = "GlitterDown";
  297. trans.glitterR        = "GlitterRight";
  298. trans.glitterRD        = "GlitterRightDown";
  299. trans.random        = "Random";
  300. trans.replace        = "Replace";
  301. trans.splitHI        = "SplitHorizontalIn";
  302. trans.splitHO        = "SplitHorizontalOut";
  303. trans.splitVI        = "SplitVerticalIn";
  304. trans.splitVO        = "SplitVerticalOut";
  305. trans.wipeD            = "WipeDown";
  306. trans.wipeL            = "WipeLeft";
  307. trans.wipeR            = "WipeRight";
  308. trans.wipeU            = "WipeUp";
  309.  
  310. /* Icon/Text placement. */
  311. position = new Object();
  312. position.textOnly    = 0;
  313. position.iconOnly    = 1;
  314. position.iconTextV    = 2;
  315. position.textIconV    = 3;
  316. position.iconTextH    = 4;
  317. position.textIconH    = 5;
  318. position.overlay    = 6;
  319.  
  320. /* When does icon scale. */
  321. scaleWhen = new Object();
  322. scaleWhen.always    = 0;
  323. scaleWhen.never        = 1;
  324. scaleWhen.tooBig    = 2;
  325. scaleWhen.tooSmall    = 3;
  326.  
  327. /* How does icon scale. */
  328. scaleHow = new Object();
  329. scaleHow.proportional    = 0;
  330. scaleHow.anamorphic        = 1;
  331.  
  332.  
  333. /* Field display. */
  334. display = new Object();
  335. display.visible        = 0;
  336. display.hidden        = 1;
  337. display.noPrint        = 2;
  338. display.noView        = 3;
  339.  
  340. /* Permission values */
  341. permission = new Object();
  342. /* Request Objects */
  343. permission.document     = "Document";
  344. permission.page         = "Page";
  345. permission.link         = "Link";
  346. permission.bookmark     = "Bookmark";
  347. permission.thumbnail     = "Thumbnail";
  348. permission.annot         = "Annot";
  349. permission.form         = "Form";
  350. permission.signature     = "Signature";
  351.  
  352. /* Request Operations */
  353. permission.all             = "All";
  354. permission.any             = "Any";
  355. permission.create         = "Create";
  356. permission.remove         = "Delete";
  357. permission.modify         = "Modify";
  358. permission.copy         = "Copy";
  359. permission.accessible     = "Accessible";
  360. permission.select         = "Select";
  361. permission.open         = "Open";
  362. permission.secure         = "Secure";
  363. permission.print         = "Print";
  364. permission.printLowQuality     = "PrintLowQuality";
  365. permission.fillIn         = "FillIn";
  366. permission.rotate         = "Rotate";
  367. permission.crop         = "Crop";
  368. permission.summarize     = "Summarize";
  369. permission.insert         = "Insert";
  370. permission.replace         = "Replace";
  371. permission.reorder         = "Reorder";
  372. permission.fullSave     = "FullSave";
  373. permission.canImport     = "Import";
  374. permission.canExport     = "Export";
  375.  
  376. /* ==== Functions ==== */
  377.  
  378. /* these may be used a lot -- they are language independent */
  379.  
  380. AFDigitsRegExp = new RegExp();
  381. AFDigitsRegExp.compile("\\d+");
  382. AFPMRegExp = new RegExp();
  383. AFPMRegExp.compile(IDS_PM, "i");
  384. AFAMRegExp = new RegExp();
  385. AFAMRegExp.compile(IDS_AM, "i");
  386. AFTimeLongRegExp = new RegExp();
  387. AFTimeLongRegExp.compile("\\d{1,2}:\\d{1,2}:\\d{1,2}");
  388. AFTimeShortRegExp = new RegExp();
  389. AFTimeShortRegExp.compile("\\d{1,2}:\\d{1,2}");
  390. AFTimeGarbageRegExp = new RegExp();
  391. AFTimeGarbageRegExp.compile("\\d{1,2}:\\d{1,2}(:\\d{1,2})?(\\s)*(am|pm)?", "i");
  392.  
  393. function AFBuildRegExps(array)
  394. /* Takes an array of strings and turns it into an array of compiled regular
  395.  * expressions -- is used for the definitions that follow */
  396. {
  397.     var retVal = new Array();
  398.  
  399.     retVal.length = array.length;
  400.     for(var it = 0; it < array.length; it++)
  401.     {
  402.         retVal[it] = new RegExp();
  403.         retVal[it].compile(array[it], "i");
  404.     }
  405.     return retVal;
  406. }
  407.  
  408. /* these may be used a lot -- they are NOT language independent and are 
  409.  * derived from the localizable (RE_xxx) stuff above */
  410.  
  411. AFNumberDotSepEntryRegExp = AFBuildRegExps(RE_NUMBER_ENTRY_DOT_SEP);
  412. AFNumberDotSepCommitRegExp = AFBuildRegExps(RE_NUMBER_COMMIT_DOT_SEP);
  413. AFNumberCommaSepEntryRegExp = AFBuildRegExps(RE_NUMBER_ENTRY_COMMA_SEP);
  414. AFNumberCommaSepCommitRegExp = AFBuildRegExps(RE_NUMBER_COMMIT_COMMA_SEP);
  415. AFZipEntryRegExp = AFBuildRegExps(RE_ZIP_ENTRY);
  416. AFZipCommitRegExp = AFBuildRegExps(RE_ZIP_COMMIT);
  417. AFZip4EntryRegExp = AFBuildRegExps(RE_ZIP4_ENTRY);
  418. AFZip4CommitRegExp = AFBuildRegExps(RE_ZIP4_COMMIT);
  419. AFPhoneEntryRegExp = AFBuildRegExps(RE_PHONE_ENTRY);
  420. AFPhoneCommitRegExp = AFBuildRegExps(RE_PHONE_COMMIT);
  421. AFSSNEntryRegExp = AFBuildRegExps(RE_SSN_ENTRY);
  422. AFSSNCommitRegExp = AFBuildRegExps(RE_SSN_COMMIT);
  423. AFMonthsRegExp = AFBuildRegExps(IDS_MONTH_INFO.split(/\[\d+\]/));
  424.  
  425. function AFExactMatch(rePatterns, sString)
  426. {    /* match a string against an array of RegExps */
  427.     var it;
  428.  
  429.     if(!rePatterns.length && rePatterns.test(sString) && RegExp.lastMatch == sString)
  430.         return true;
  431.     for(it = 0; it < rePatterns.length; it++)
  432.         if(rePatterns[it].test(sString) && RegExp.lastMatch == sString)
  433.             return it + 1;
  434.     return 0;
  435. }
  436.  
  437. function AFExtractNums(string)
  438. {    /* returns an array of numbers that it managed to extract from the given 
  439.      * string or null on failure */
  440.     var nums = new Array();
  441.  
  442.     if (string.charAt(0) == '.' || string.charAt(0) == ',')
  443.         string = "0" + string;
  444.          
  445.     while(AFDigitsRegExp.test(string)) {
  446.         nums.length++;
  447.         nums[nums.length - 1] = RegExp.lastMatch;
  448.         string = RegExp.rightContext;
  449.     }
  450.     if(nums.length >= 1) return nums;
  451.     return null;
  452. }
  453.  
  454. function AFMakeNumber(string)
  455. {    /* attempts to make a number out of a string that may not use '.' as the
  456.      * seperator; it expects that the number is fairly well-behaved other than
  457.      * possibly having a non-JavaScript friendly separator */
  458.     var type = typeof string;
  459.  
  460.     if (type == "number")
  461.         return string;
  462.     if (type != "string")
  463.         return null;
  464.  
  465.     var array = AFExtractNums(string);
  466.  
  467.     if(array)
  468.     {
  469.         var joined = array.join(".");
  470.  
  471.         if (string.indexOf("-.") >= 0)
  472.             joined = "0." + joined;
  473.         return joined * (string.indexOf("-") >= 0 ? -1.0 : 1.0);
  474.     }
  475.     else
  476.         return null;
  477. }
  478.  
  479. function AFExtractRegExp(rePattern, string)
  480. {    /* attempts to match the pattern given against the string given; on 
  481.      * success, returns an array containing (at index 0) the initial
  482.      * string with the matched text removed and (at index 1) the matched
  483.      * text; on failure, returns null */
  484.     var retVal = new Array();
  485.  
  486.     if(rePattern.test(string))
  487.     {
  488.         retVal.length = 2;
  489.         retVal[0] = RegExp.leftContext + RegExp.rightContext;
  490.         retVal[1] = RegExp.lastMatch;
  491.         return retVal;
  492.     }
  493.     return null;
  494. }
  495.  
  496. function AFMakeArrayFromList(string)
  497. {
  498.   var type = typeof string;
  499.  
  500.   if(type == "string")
  501.   {
  502.      var reSep = new RegExp();
  503.     reSep.compile(",[ ]?");
  504.     return string.split(reSep);
  505.   }
  506.   return string;
  507. }
  508.  
  509. function AFExtractTime(string)
  510. {    /* attempts to extract a WELL FORMED time from a string; returned 
  511.      * is an array in the same vein as AFExtractRegExp or null on
  512.      * failure. a WELL FORMED time looks like 12:23:56pm */
  513.     
  514.     var pm = "";
  515.     var info;
  516.  
  517.     info = AFExtractRegExp(AFPMRegExp, string);
  518.     if(info)
  519.     {
  520.         pm = info[1];
  521.         string = info[0];
  522.     }
  523.     info = AFExtractRegExp(AFAMRegExp, string);
  524.     if(info)
  525.     {
  526.         string = info[0];
  527.     }
  528.     info = AFExtractRegExp(AFTimeLongRegExp, string);
  529.     if(info)
  530.     {
  531.         info[1] += pm;
  532.         return info;
  533.     }
  534.     info = AFExtractRegExp(AFTimeShortRegExp, string);
  535.     if(info)
  536.     {
  537.         info[1] += pm;
  538.         return info;
  539.     }
  540.  
  541.     return null;
  542. }
  543.  
  544. function AFGetMonthIndex(string)
  545. {    /* attempts to identify the given string as a month or a valid abbreviation,
  546.      * it expects the given string to be the valid month from the matced RegExp.
  547.      * returns the month index (January = 1) or zero on failure */
  548.     var monthre = new RegExp(string + "\\[(\\d+)\\]", "i");
  549.     var result = monthre.exec(IDS_MONTH_INFO);
  550.     
  551.     if(string && result) return 1.0 * result[1];
  552.     return 0;
  553. }
  554.  
  555. function AFMatchMonth(string)
  556. {    /* attempts to find a valid month embedded in a string; returns the month
  557.      * index (January = 1) or zero on failure */
  558.  
  559.     for(var it = 0; it < AFMonthsRegExp.length; it++)
  560.         if(AFMonthsRegExp[it].test(string))
  561.             return AFGetMonthIndex(RegExp.lastMatch);
  562.     return 0;
  563. }
  564.  
  565. function AFGetMonthString(index)
  566. {    /* returns the string corresponding to the given month or a string that
  567.      * is indicative of the fact that the index was invalid */
  568.     var monthre = new RegExp("(\\w+)\\[" + index + "\\]");
  569.     var result = monthre.exec(IDS_MONTH_INFO);
  570.  
  571.     if(result) return result[1];
  572.     return IDS_INVALID_MONTH;
  573. }
  574.  
  575. function AFParseTime(string, date)
  576. {    /* attempts to parse a string containing a time; returns null on failure
  577.      * or a Date object on success. Time can be in ugly format. */
  578.     var pm, am;
  579.     var nums = AFExtractNums(string);
  580.     if (!date)
  581.         date = new Date();
  582.     var hour, minutes, seconds;
  583.  
  584.     if(!string) return date;
  585.  
  586.     if(!(AFTimeGarbageRegExp.test(string) && string == RegExp.lastMatch))
  587.         return null;
  588.  
  589.     if(!nums) return null;
  590.     if(nums.length < 2 || nums.length > 3) return null;
  591.     if(AFPMRegExp.test(string)) pm = true;
  592.     else pm = false;
  593.     if(AFAMRegExp.test(string)) am = true;
  594.     else am = false;
  595.     hour = new Number(nums[0]); /* force it to number */
  596.     if(pm)
  597.     {
  598.         if(hour < 12) hour += 12;
  599.     }
  600.     else if (am)
  601.     {
  602.         if(hour >= 12) hour -= 12;
  603.     }
  604.     minutes = nums[1];
  605.     if(nums.length == 3) seconds = nums[2];
  606.     else seconds = 0;
  607.     date.setHours(hour);
  608.     date.setMinutes(minutes);
  609.     date.setSeconds(seconds);
  610.     if(date.getHours() != hour)
  611.         return null;
  612.     if(date.getMinutes() != minutes)
  613.         return null;
  614.     if(date.getSeconds() != seconds)
  615.         return null;
  616.     return date;
  617. }
  618.  
  619. function AFDateFromYMD(nYear, nMonth, nDate)
  620. {    /* Validates the given fields and returns a date based on them */
  621.     var dDate = new Date();
  622.  
  623.     dDate.setFullYear(nYear, nMonth, nDate);
  624.     if(dDate.getFullYear() != nYear)
  625.         return null;
  626.     if(dDate.getMonth() != nMonth)
  627.         return null;
  628.     if(dDate.getDate() != nDate)
  629.         return null;
  630.     return dDate;
  631. }
  632.  
  633. function AFParseDateEx(cString, cFormat)
  634. {    /* Attempts to parse a string containing some form of date; returns null
  635.     ** on failure or a Date object on success.  cFormat should be the format 
  636.     ** in which the date is entered. ( eg y/m/d, ddmmyy, etc ). 
  637.     ** compatibility note: this function used to take cOrder as a paramter,
  638.     ** which was the order in which the date was entered (e.g. ymd, mdy, etc.)
  639.     ** However, if the date is entered numerically with no separators.  ie "121902" 
  640.     ** a cOrder of dmy, could be 1-2-1902 or 12-19-02 etc, so now we require cFormat
  641.     ** to resolve the ambiguity. */
  642.     var nYear;
  643.     var nMonth;
  644.     var nDate;
  645.     var nYCount;
  646.     var cOrder;
  647.     var dDate = new Date();
  648.  
  649.     dDate.setHours(12, 0, 0);
  650.  
  651.     /* Empty string returns current date/time. */
  652.     if (!cString) { 
  653.         return dDate;
  654.     }
  655.  
  656.     nYCount = AFParseDateYCount(cFormat); /* count the number of digits for year in the selected format */
  657.     cOrder = AFParseDateOrder(cFormat); /* make sure its in the "ymd" format */
  658.  
  659.     /* Extract any time information in the string. */
  660.     var info = AFExtractTime(cString);
  661.     if (info)
  662.         cString = info[0];
  663.  
  664.     /* Break down the date into an array of numbers. */
  665.     var aNums = AFExtractNums(cString);
  666.     if(!aNums) 
  667.         return null;    /* No numbers? */
  668.  
  669.     /* User supplied three numbers. */
  670.     if (aNums.length == 3) {
  671.         nYear = 1.0 * aNums[cOrder.indexOf("y")];
  672.         if ((nYCount > 2 && nYear < 100) /* must enter 4 digits for the year to match with the format of the field */
  673.             || nYear > 9999)
  674.             return null; 
  675.         
  676.         nYear = AFDateHorizon(nYear);
  677.  
  678.         dDate = AFDateFromYMD(nYear, aNums[cOrder.indexOf("m")] - 1, aNums[cOrder.indexOf("d")]);
  679.         if (info)
  680.             dDate = AFParseTime(info[1], dDate);
  681.         return dDate;
  682.     }
  683.  
  684.     /* Find text based month, if supplied. */
  685.     nMonth = AFMatchMonth(cString);    
  686.  
  687.     /* User supplied two numbers. */
  688.     if(aNums.length == 2) {
  689.         if (nMonth) {
  690.             /* Easy case, the month was text and we have two numbers. */
  691.             if (cOrder.indexOf("y") < cOrder.indexOf("d")) {
  692.                 nYear = 1.0 * aNums[0];
  693.                 nDate = aNums[1];
  694.             } else {
  695.                 nYear = 1.0 * aNums[1];
  696.                 nDate = aNums[0];
  697.             }
  698.             if ((nYCount > 2 && nYear < 100) /* must enter 4 digits for the year to match with the format of the field */
  699.                 || nYear > 9999)
  700.                 return null; 
  701.         
  702.             nYear = AFDateHorizon(nYear);
  703.             dDate = AFDateFromYMD(nYear, nMonth - 1, nDate);
  704.  
  705.             if (info)
  706.                 dDate = AFParseTime(info[1], dDate);
  707.             return dDate;
  708.         }
  709.  
  710.         /* More difficult case. We have two numbers and three slots, how
  711.         ** to allocate them? */
  712.         if (cOrder.indexOf("y") < cOrder.indexOf("d"))    {
  713.             /* Year comes before date and as such we allocate the two
  714.             ** numbers to the month and the year only. */
  715.             if (cOrder.indexOf("y") < cOrder.indexOf("m")) {
  716.                 nYear = 1.0 * aNums[0];
  717.                 nMonth = aNums[1];
  718.             } else {
  719.                 nYear = 1.0 * aNums[1];
  720.                 nMonth = aNums[0];
  721.             }
  722.             if ((nYCount > 2 && nYear < 100) /* must enter 4 digits for the year to match with the format of the field */
  723.                 || nYear > 9999)
  724.                 return null; 
  725.         
  726.             nYear = AFDateHorizon(nYear);
  727.             dDate = AFDateFromYMD(nYear, nMonth - 1, 1);
  728.         } else {
  729.             /* Date comes before year and so we allocate the two numbers
  730.             ** to the date and the month only. */
  731.             nYear = dDate.getFullYear();
  732.             if (cOrder.indexOf("d") < cOrder.indexOf("m")) {
  733.                 dDate = AFDateFromYMD(nYear, aNums[1] - 1, aNums[0]);
  734.             } else {
  735.                 dDate = AFDateFromYMD(nYear, aNums[0] - 1, aNums[1]);
  736.             }
  737.         }
  738.     
  739.         if (info)
  740.             dDate = AFParseTime(info[1], dDate);
  741.         return dDate;
  742.     }
  743.  
  744.     /* User supplied one number. */
  745.     if(aNums.length == 1)    {
  746.         if (nMonth) {
  747.             /* We have one number and two slots (y/d) and need to allocate
  748.             ** them based on who came first in the format. */
  749.             if(cOrder.indexOf("y") < cOrder.indexOf("d")) {
  750.                 nYear = 1.0 * aNums[0];
  751.                 if ((nYCount > 2 && nYear < 100) /* must enter 4 digits for the year to match with the format of the field */
  752.                     || nYear > 9999)
  753.                     return null; 
  754.             
  755.                 nYear = AFDateHorizon(nYear);
  756.                 dDate = AFDateFromYMD(nYear, nMonth - 1, 1);
  757.             } else {
  758.                 nYear = dDate.getFullYear();
  759.                 dDate = AFDateFromYMD(nYear, nMonth - 1, aNums[0]);
  760.             }
  761.             if (info)
  762.                 dDate = AFParseTime(info[1], date);
  763.             return dDate;
  764.         }
  765.  
  766.         /* We have one number and three slots and need to allocate them
  767.         ** based on who came first in the format. */
  768.         // transcribe the format exactly.  There should be a one to one correspondence.
  769.         if (cFormat.length != cString.length)
  770.             return null;
  771.  
  772.         nYear = "";
  773.         nMonth = "";
  774.         nDate = "";
  775.  
  776.         for (var i = 0; i < cFormat.length; i++) {
  777.             switch (cFormat.charAt(i)) {
  778.                 case "\\":    /* Escape character. */
  779.                     i++;
  780.                     break;
  781.                 case "y":
  782.                     nYear += cString.charAt(i);
  783.                     break;
  784.                 case "m":
  785.                     nMonth += cString.charAt(i);
  786.                     break;
  787.                 case "d":
  788.                     nDate += cString.charAt(i);
  789.                     break;
  790.             }
  791.         }
  792.         
  793.         nYear *= 1.0;
  794.         nMonth *= 1.0;
  795.         nDate *= 1.0
  796.         
  797.         if(nMonth)
  798.             nMonth -= 1.0;  // Month range is [0-11]
  799.         
  800.         if(!nDate)
  801.             nDate += 1.0;   // Date range is [1-31]
  802.  
  803.         if ((nYCount > 2 && nYear < 100) /* must enter 4 digits for the year to match with the format of the field */
  804.             || nYear > 9999)
  805.             return null; 
  806.         
  807.         nYear = AFDateHorizon(nYear);
  808.  
  809.         dDate = AFDateFromYMD(nYear, nMonth, nDate);
  810.  
  811.         if (info)
  812.             dDate = AFParseTime(info[1], date);
  813.         return dDate;
  814.     }
  815.  
  816.     /* No idea how to deal with the other combinations. */
  817.     return null;
  818. }
  819.  
  820. function AFDateHorizon(nYear)
  821. {    /* Takes the year supplied and applies the date horizon heuristic.
  822.     ** All years between 50 and 100 we add 1900. All years less than 50 we add 2000. */
  823.     if (nYear < 100 && nYear >= 50) {
  824.         nYear += 1900;
  825.     } else if (nYear >= 0 && nYear < 50) {
  826.         nYear += 2000;
  827.     }
  828.  
  829.     return nYear;
  830. }
  831.  
  832. function AFParseDate(string, longEntry, shortEntry, wordMonthEntry, monthYearEntry)
  833. {    /* OBSOLETE: Use AFParseDateEx instead. */
  834.     var nums;
  835.     var year, month;
  836.     var date;
  837.     var info = AFExtractTime(string);
  838.  
  839.     if(!string) return new Date();
  840.  
  841.     if(info)
  842.         string = info[0];
  843.  
  844.     date = new Date();
  845.     nums = AFExtractNums(string);
  846.     if(!nums) return null;
  847.     if(nums.length == 3)
  848.     {
  849.         year = 1.0 * nums[eval(longEntry.charAt(0))];
  850.         year = AFDateHorizon(year);
  851.         date = AFDateFromYMD(year, nums[eval(longEntry.charAt(1))] - 1, nums[eval(longEntry.charAt(2))]);
  852.         if (info)
  853.             date = AFParseTime(info[1], date);
  854.         return date;
  855.     }
  856.     month = AFMatchMonth(string);
  857.     if(nums.length == 2)
  858.     {
  859.         if(month)
  860.         {
  861.             year = 1.0 * nums[eval(wordMonthEntry.charAt(0))];
  862.             year = AFDateHorizon(year);
  863.             date = AFDateFromYMD(year, month - 1, nums[eval(wordMonthEntry.charAt(1))]);
  864.             if (info)
  865.                 date = AFParseTime(info[1], date);
  866.             return date;
  867.         }
  868.         if(monthYearEntry)
  869.         {
  870.             year = 1.0 * nums[eval(monthYearEntry.charAt(0))];
  871.             year = AFDateHorizon(year);
  872.             date = AFDateFromYMD(year, nums[eval(monthYearEntry.charAt(1))] - 1, 1);
  873.         }
  874.         else
  875.             date = AFDateFromYMD(date.getFullYear(),
  876.                 nums[eval(shortEntry.charAt(0))] - 1,
  877.                 nums[eval(shortEntry.charAt(1))]);
  878.         if (info)
  879.             date = AFParseTime(info[1], date);
  880.         return date;
  881.     }
  882.     if(month && nums.length == 1)
  883.     {
  884.         if(monthYearEntry)
  885.         {
  886.             year = 1.0 * nums[0];
  887.             year = AFDateHorizon(year);
  888.             date = AFDateFromYMD(year, month - 1, 1);
  889.         }
  890.         else
  891.             date = AFDateFromYMD(date.getFullYear(), month - 1,    nums[0]);
  892.         if (info)
  893.             date = AFParseTime(info[1], date);
  894.         return date;
  895.     }
  896.  
  897.     return null;
  898. }
  899.  
  900. function AFParseDateWithPDF(value, pdf)
  901. { /* OBSOLETE: Use AFParseDateEx instead. */
  902.     var cOldFormats = new Array(
  903.         "m/d", "m/d/yy", "mm/dd/yy", "mm/yy", "d-mmm", "d-mmm-yy", "dd-mmm-yy",
  904.         "yy-mm-dd", "mmm-yy", "mmmm-yy", "mmm d, yyyy", "mmmm d, yyyy",
  905.         "m/d/yy h:MM tt", "m/d/yy HH:MM" );
  906.    
  907.     return AFParseDateEx(value, cOldFormats[pdf]);
  908. }
  909.  
  910. function AFMergeChange(event)
  911. {    /* merges the last change with the uncommitted change */
  912.     var prefix, postfix;
  913.     var value = event.value;
  914.  
  915.     if(event.willCommit) return event.value;
  916.     if(event.selStart >= 0)
  917.         prefix = value.substring(0, event.selStart);
  918.     else prefix = "";
  919.     if(event.selEnd >= 0 && event.selEnd <= value.length)
  920.         postfix = value.substring(event.selEnd, value.length);
  921.     else postfix = "";
  922.     return prefix + event.change + postfix;
  923. }
  924.  
  925. function AFRange_Validate(bGreaterThan, nGreaterThan, bLessThan, nLessThan)
  926. {       /* This function validates the current event to ensure that its value is 
  927.     ** within the specified range. */
  928.     var cError = "";
  929.  
  930.     if (event.value == "")
  931.         return;
  932.  
  933.     if (bGreaterThan && bLessThan) {
  934.         if (event.value < nGreaterThan || event.value > nLessThan)
  935.             cError = util.printf(IDS_GT_AND_LT, nGreaterThan, nLessThan);
  936.     } else if (bGreaterThan) {
  937.         if (event.value < nGreaterThan)
  938.             cError = util.printf(IDS_GREATER_THAN, nGreaterThan);
  939.     } else if (bLessThan) {
  940.         if (event.value > nLessThan)
  941.             cError = util.printf(IDS_LESS_THAN, nLessThan);
  942.     }
  943.     
  944.     if (cError != "") {
  945.         if (!event.silenceErrors)
  946.             app.alert(cError, 0);
  947.         event.rc = false;
  948.     }
  949. }
  950.  
  951. function AFSimpleInit(cFunction)
  952. {    /* Convenience function used by AFSimple_Calculate. */
  953.     switch (cFunction)
  954.     {
  955.         case "PRD":
  956.             return 1.0;
  957.             break;
  958.     }
  959.  
  960.     return 0.0;
  961. }
  962.  
  963. function AFSimple(cFunction, nValue1, nValue2)
  964. {    /* Convenience function used by AFSimple_Calculate. */
  965.     var nValue = 1.0 * nValue1;
  966.  
  967.     /* Have to do this otherwise JavaScript thinks it's dealing with strings. */
  968.     nValue1 = 1.0 * nValue1;
  969.     nValue2 = 1.0 * nValue2;
  970.  
  971.     switch (cFunction)
  972.     {
  973.         case "AVG":
  974.         case "SUM":
  975.             nValue = nValue1 + nValue2;
  976.             break;
  977.         case "PRD":
  978.             nValue = nValue1 * nValue2;
  979.             break;
  980.         case "MIN":
  981.             nValue = Math.min(nValue1,nValue2);
  982.             break;
  983.         case "MAX":
  984.             nValue = Math.max(nValue1, nValue2);
  985.             break;
  986.     }
  987.  
  988.     return nValue;
  989. }
  990.  
  991. function AFSimple_Calculate(cFunction, cFields)
  992. {   /* Calculates the sum, average, product, etc. of the listed field values. */
  993.     var nFields = 0;
  994.     var nValue = AFSimpleInit(cFunction);
  995.  
  996.     /* Field name separator is one or more spaces followed by a comma, 
  997.     ** followed by one or more spaces.
  998.     ** or an array of field names */
  999.      var aFields = AFMakeArrayFromList(cFields);
  1000.  
  1001.     for (var i = 0; i < aFields.length; i++) {
  1002.         /* Found a field, process it's value. */
  1003.         var f = this.getField(aFields[i]);
  1004.         var a = f.getArray();
  1005.  
  1006.         for (var j = 0; j < a.length; j++) {
  1007.             var nTemp = AFMakeNumber(a[j].value); 
  1008.             if (i == 0 && j == 0 && (cFunction == "MIN" || cFunction == "MAX"))
  1009.                 nValue = nTemp;
  1010.             nValue = AFSimple(cFunction, nValue, nTemp);
  1011.             nFields++;
  1012.         }
  1013.     }
  1014.  
  1015.     if (cFunction == "AVG" && nFields > 0)
  1016.         nValue /= nFields;
  1017.  
  1018.     // make sure that the value we put out is actually sane.  Sometimes because
  1019.     // of rounding issues and the binary to decimal conversion we get tiny exponential 
  1020.     // numbers, ex 1.0-.99-.01 will return 8.673617379884035e-18
  1021.     // I chose toFixed(6) since after 6, js starts using the 1.0e-7 notation
  1022.  
  1023.     if( cFunction == "AVG" || cFunction == "SUM" || cFunction == "PRD" )
  1024.         nValue = nValue.toFixed(6) *1.0; 
  1025.  
  1026.     event.value = nValue;
  1027. }
  1028.  
  1029. function AFNumber_Keystroke(nDec, sepStyle, negStyle, currStyle, strCurrency, bCurrencyPrepend)
  1030. {       /* This function validates the current keystroke event to make sure the
  1031.         key pressed is reasonable for a numeric field. */
  1032.  
  1033.     var value = AFMergeChange(event);
  1034.     var commit, noCommit;
  1035.  
  1036.     if(!value) return;
  1037.     if(sepStyle > 1)
  1038.     {
  1039.         commit = AFNumberCommaSepCommitRegExp;
  1040.         noCommit = AFNumberCommaSepEntryRegExp;
  1041.     }
  1042.     else
  1043.     {
  1044.         commit = AFNumberDotSepCommitRegExp;
  1045.         noCommit = AFNumberDotSepEntryRegExp;
  1046.     }
  1047.     if(!AFExactMatch(event.willCommit ? commit : noCommit, value))
  1048.     {
  1049.         if (event.willCommit && !event.silenceErrors) {
  1050.             var cAlert = IDS_INVALID_VALUE;
  1051.             if (event.target != null)
  1052.                 cAlert += " [ " + event.target.name + " ]";
  1053.             app.alert(cAlert);
  1054.         }
  1055.         else
  1056.             app.beep(0);
  1057.         event.rc = false;
  1058.     }
  1059.  
  1060.     if (event.willCommit && sepStyle > 1)
  1061.     {
  1062.         // convert from a string to a number 
  1063.         strval = event.value;
  1064.         commas = new RegExp();
  1065.         commas.compile(",");
  1066.  
  1067.         strval = strval.replace(commas, ".");
  1068.         event.value = strval *1.0;
  1069.     } 
  1070. }
  1071.  
  1072. function AFPercent_Keystroke(nDec, sepStyle)
  1073. {
  1074.         AFNumber_Keystroke(nDec, sepStyle, 0, 0, "", true);
  1075. }
  1076.  
  1077. function isNumber(ch)
  1078. {
  1079.     return (ch >= "0" && ch <= "9");
  1080. }
  1081.  
  1082. function isAlphabetic(ch)
  1083. {
  1084.     return ((ch >= "a" && ch <= "z") ||
  1085.               (ch >= "A" && ch <= "Z"));
  1086. }
  1087.  
  1088. function isAlphaNumeric(ch)
  1089. {
  1090.     return (isNumber(ch) || isAlphabetic(ch));
  1091. }
  1092.  
  1093. function isReservedMaskChar(ch)
  1094. {
  1095.     return (ch == '9' || ch == 'X' || ch == 'A' || ch == 'O');
  1096. }
  1097.  
  1098. function maskSatisfied(vChar, mChar)
  1099. {
  1100.     switch(mChar)
  1101.     {
  1102.         case "9":
  1103.             return isNumber(vChar);
  1104.  
  1105.         case "A":
  1106.             return isAlphabetic(vChar);
  1107.  
  1108.         case "O":
  1109.             return isAlphaNumeric(vChar);
  1110.  
  1111.         case "X":
  1112.             return true;
  1113.  
  1114.         default:
  1115.             return (vChar == mChar);
  1116.     }
  1117. }
  1118.  
  1119. function indexOfNextEssential(mask, startIndex)
  1120. {
  1121.     for(var i = startIndex; i < mask.length; i++)
  1122.     {
  1123.         if(isReservedMaskChar(mask.charAt(i)))
  1124.             return i;
  1125.     }
  1126.     return -1;
  1127. }
  1128.  
  1129. function AFSpecial_KeystrokeEx(mask)
  1130. {
  1131.     var value = AFMergeChange(event);
  1132.     
  1133.     if(!value || !mask.length)
  1134.         return;
  1135.             
  1136.     var cAlert = IDS_INVALID_VALUE + ' = "' + mask + '"';
  1137.  
  1138.     if(event.willCommit)
  1139.     {
  1140.         if(indexOfNextEssential(mask, value.length) != -1)
  1141.         {
  1142.             if (!event.silenceErrors)
  1143.                 app.alert(cAlert);
  1144.                 
  1145.             event.rc = false;
  1146.             return;
  1147.         }
  1148.         else {
  1149.             event.value = event.value + mask.substring(value.length, mask.length);
  1150.             return;
  1151.         }
  1152.     }
  1153.  
  1154.     var nMaskIndex = 0;
  1155.     var nValueIndex = 0;
  1156.     
  1157.     var nOffset = 0;  // number of characters we've added to change to make it legal
  1158.     var nChangeStart = event.selStart;    
  1159.     
  1160.     while(nValueIndex < value.length)
  1161.     {
  1162.         var mChar = mask.charAt(nMaskIndex);
  1163.         var vChar = value.charAt(nValueIndex);
  1164.  
  1165.         if(!maskSatisfied(vChar, mChar)) 
  1166.         {
  1167.             var nextEssential = indexOfNextEssential(mask, nMaskIndex);
  1168.             var nChangeEnd = event.selStart + event.change.length + nOffset;
  1169.             
  1170.             if(((nMaskIndex < mask.length) && !isReservedMaskChar(mChar)) && 
  1171.                 (nextEssential != -1) && maskSatisfied(vChar, mask.charAt(nextEssential)) &&
  1172.                 ( (nValueIndex + nOffset) >= nChangeStart) && ( (nValueIndex + nOffset) <= nChangeEnd) ) // we can only modify values w/in the change range
  1173.             {
  1174.                 var maskSubstring = mask.substring(nMaskIndex, nextEssential);
  1175.                 
  1176.                 event.change = event.change.substring(0, nValueIndex + nOffset - nChangeStart) + maskSubstring + event.change.substring(nValueIndex + nOffset - nChangeStart)
  1177.  
  1178.                 nOffset = nOffset + maskSubstring.length;
  1179.                 nMaskIndex = nextEssential;
  1180.             }
  1181.             else
  1182.             {
  1183.                 if (!event.silenceErrors)
  1184.                     app.alert(cAlert);
  1185.                     
  1186.                 event.rc = false;
  1187.                 
  1188.                 return;
  1189.             }
  1190.         }
  1191.         
  1192.         nValueIndex++;
  1193.         nMaskIndex++;
  1194.     }
  1195. }
  1196.  
  1197.  
  1198.  
  1199. function AFSpecial_Keystroke(psf)
  1200. {       /* This function validates the current keystroke event to make sure the
  1201.         key pressed is reasonable for a "special" field. */
  1202.         
  1203.     /* The special formats, indicated by psf, are:
  1204.     
  1205.     psf             format
  1206.     ---             ------
  1207.     0               zip code
  1208.     1               zip + 4
  1209.     2               phone
  1210.     3                SSN
  1211.     
  1212.     */
  1213.  
  1214.     var value = AFMergeChange(event);
  1215.     var commit, noCommit;
  1216.  
  1217.     if(!value) return;
  1218.     switch (psf)
  1219.     {
  1220.         case 0:
  1221.             commit = AFZipCommitRegExp;
  1222.             noCommit = AFZipEntryRegExp;
  1223.             break;
  1224.         case 1:
  1225.             commit = AFZip4CommitRegExp;
  1226.             noCommit = AFZip4EntryRegExp;
  1227.             break;
  1228.         case 2:
  1229.             commit = AFPhoneCommitRegExp;
  1230.             noCommit = AFPhoneEntryRegExp;
  1231.             break;
  1232.         case 3:
  1233.             commit = AFSSNCommitRegExp;
  1234.             noCommit = AFSSNEntryRegExp;
  1235.             break;
  1236.     }        
  1237.     if(!AFExactMatch(event.willCommit ? commit : noCommit, value))
  1238.     {
  1239.         if (event.willCommit && !event.silenceErrors) {
  1240.             var cAlert = IDS_INVALID_VALUE;
  1241.             if (event.target != null)
  1242.                 cAlert += " [ " + event.target.name + " ]";
  1243.             app.alert(cAlert);
  1244.         }
  1245.         else
  1246.             app.beep(0);
  1247.         event.rc = false;
  1248.     }
  1249. }
  1250.  
  1251. function AFDate_KeystrokeEx(cFormat)
  1252. {    /* This function validates the current keystroke event to make sure the
  1253.     ** key pressed is reasonable for a date field. */
  1254.     if(event.willCommit && !AFParseDateEx(AFMergeChange(event), cFormat)) {
  1255.         /* Dates are only validated on commit */
  1256.         if (event.willCommit && !event.silenceErrors) {
  1257.             var cAlert = IDS_INVALID_DATE;
  1258.             var cAlert2 = IDS_INVALID_DATE2;
  1259.             if (event.target != null)
  1260.                 cAlert += "[ " + event.target.name + " ]";
  1261.                 cAlert += cAlert2 + cFormat;
  1262.             app.alert(cAlert);
  1263.         }
  1264.         else
  1265.             app.beep(0);
  1266.         event.rc = false;
  1267.     }
  1268. }
  1269.  
  1270. function AFDate_Keystroke(pdf)
  1271. {    /* OBSOLETE: Use AFDate_KeystrokeEx. */
  1272.     var cOldFormats = new Array(
  1273.         "m/d", "m/d/yy", "mm/dd/yy", "mm/yy", "d-mmm", "d-mmm-yy", "dd-mmm-yy",
  1274.         "yy-mm-dd", "mmm-yy", "mmmm-yy", "mmm d, yyyy", "mmmm d, yyyy",
  1275.         "m/d/yy h:MM tt", "m/d/yy HH:MM" );
  1276.  
  1277.     AFDate_KeystrokeEx(cOldFormats[pdf]);
  1278. }
  1279.  
  1280. function AFTime_Keystroke(ptf)
  1281. {    /* This function validates the current keystroke event to make sure the
  1282.     key pressed is reasonable for a time field. */
  1283.  
  1284.     if(event.willCommit && !AFParseTime(event.value, null))
  1285.                     /* times are only validated on commit */
  1286.     {
  1287.         if (event.willCommit && !event.silenceErrors) {
  1288.             var cAlert = IDS_INVALID_VALUE;
  1289.             if (event.target != null)
  1290.                 cAlert += " [ " + event.target.name + " ]";
  1291.             app.alert(cAlert);
  1292.         }
  1293.         else
  1294.             app.beep(0);
  1295.         event.rc = false;
  1296.     }
  1297. }
  1298.  
  1299. function AFNumber_Format(nDec, sepStyle, negStyle, currStyle, strCurrency, bCurrencyPrepend)
  1300. {       /* This function formats a numeric value according to the parameters. */
  1301.  
  1302.     var value = AFMakeNumber(event.value);
  1303.     var sign = (value < 0 ? -1 : 1);
  1304.     var f = event.target;
  1305.  
  1306.     if(value == null)
  1307.     {
  1308.         event.value = "";
  1309.         return;
  1310.     }    
  1311.     if ((negStyle == 2 /* ParensBlack */ || negStyle == 3 /* ParensRed */) && value < 0)
  1312.         var formatStr = "(";
  1313.     else 
  1314.         var formatStr = "";
  1315.     
  1316.     if (bCurrencyPrepend)
  1317.         formatStr = formatStr + strCurrency;
  1318.         
  1319.     formatStr = formatStr + "%," + sepStyle + "." + nDec + "f";
  1320.     if (! bCurrencyPrepend)
  1321.         formatStr = formatStr + strCurrency;
  1322.         
  1323.     if ((negStyle == 2 /* ParensBlack */ || negStyle == 3 /* ParensRed */) && value < 0)
  1324.         formatStr = formatStr + ")";
  1325.  
  1326.     if (negStyle != 0 /* MinusBlack */ || bCurrencyPrepend)
  1327.         value = Math.abs(value);
  1328.         
  1329.     if (negStyle == 1 /* Red */ || negStyle == 3 /* ParensRed */) {
  1330.         if (sign > 0 )
  1331.             f.textColor = color.black;
  1332.         else 
  1333.             f.textColor = color.red;
  1334.     }
  1335.  
  1336.     var tmp = util.printf(formatStr, value);
  1337.     if (sign < 0 && bCurrencyPrepend && negStyle == 0)
  1338.         tmp = '-' + tmp; /* prepend the -ve sign */
  1339.     event.value = tmp;
  1340. }
  1341.  
  1342. function AFPercent_Format(nDec, sepStyle)
  1343. {       /* This function formats a percentage value according to the parameters. */
  1344.  
  1345.     var value = AFMakeNumber(event.value) * 100;
  1346.     
  1347.     var formatStr = "%," + sepStyle + "." + nDec + "f";
  1348.         
  1349.     if(value == null)
  1350.     {
  1351.         event.value = "";
  1352.         return;
  1353.     }    
  1354.  
  1355.     value = util.printf(formatStr, value);
  1356.     
  1357.     event.value = value + "%";
  1358. }
  1359.  
  1360. function AFSpecial_Format(psf)
  1361. {   /* This function formats a "special" value according to the "PropsSpecialFormat" parameter psf. */
  1362.     /* The special formats, indicated by psf, are: 0 = zip code, 1 = zip + 4, 2 = phone, 3 = SSN. */
  1363.     var value = event.value;
  1364.  
  1365.     if(!value) return;    
  1366.     switch (psf) {
  1367.     
  1368.         case 0:                         
  1369.             var formatStr = "99999";
  1370.             break;
  1371.         case 1:                         
  1372.             var formatStr = "99999-9999";
  1373.             break;
  1374.         case 2:                         /* must distinguish between 2 styles: with and without area code */
  1375.             var NumbersStr = util.printx("9999999999", value);      /* try to suck out 10 numeric chars */
  1376.             if (NumbersStr.length >= 10 )
  1377.                 var formatStr = "(999) 999-9999";
  1378.             else 
  1379.                 var formatStr = "999-9999";
  1380.             break;
  1381.         case 3:
  1382.             var formatStr = "999-99-9999";
  1383.             break;
  1384.     }
  1385.         
  1386.     event.value = util.printx(formatStr, value);
  1387. }
  1388.  
  1389. function AFParseDateYCount(cFormat)
  1390. {
  1391.     /* Determine the order of the date. */
  1392.     var yCount = 0;
  1393.     for (var i = 0; i < cFormat.length; i++) {
  1394.         switch (cFormat.charAt(i)) {
  1395.             case "\\":    /* Escape character. */
  1396.                 i++;
  1397.             break;
  1398.             case "y":
  1399.                 yCount += 1;
  1400.             break;
  1401.         }
  1402.     }
  1403.     return yCount;
  1404. }
  1405.  
  1406. function AFParseDateOrder(cFormat)
  1407. {
  1408.     /* Determine the order of the date. */
  1409.     var cOrder = "";
  1410.     for (var i = 0; i < cFormat.length; i++) {
  1411.         switch (cFormat.charAt(i)) {
  1412.             case "\\":    /* Escape character. */
  1413.                 i++;
  1414.             break;
  1415.             case "m":
  1416.                 if (cOrder.indexOf("m") == -1)
  1417.                     cOrder += "m";
  1418.             break;
  1419.             case "d":
  1420.                 if (cOrder.indexOf("d") == -1)
  1421.                     cOrder += "d";
  1422.             break;
  1423.             case "j":
  1424.             case "y":
  1425.                 if (cOrder.indexOf("y") == -1)
  1426.                     cOrder += "y";
  1427.             break;
  1428.         }
  1429.     }
  1430.  
  1431.     /* Make sure we have a full complement of 3 chars. */
  1432.     if (cOrder.indexOf("m") == -1)
  1433.         cOrder += "m";
  1434.     if (cOrder.indexOf("d") == -1)
  1435.         cOrder += "d";
  1436.     if (cOrder.indexOf("y") == -1)
  1437.         cOrder += "y";
  1438.  
  1439.     return cOrder;
  1440. }
  1441.  
  1442. function AFDate_FormatEx(cFormat)
  1443. {    /* cFormat is a format string with which the date is to be formatted. */
  1444.     if (!event.value) 
  1445.         return;    /* Blank fields remain blank */
  1446.  
  1447.     var date = AFParseDateEx(event.value, cFormat);
  1448.     if (!date) {
  1449.         event.value = "";
  1450.         return;
  1451.     }
  1452.     
  1453.     event.value = util.printd(cFormat, date);
  1454. }
  1455.  
  1456. function AFDate_Format(pdf)
  1457. {    /* OBSOLETE: Use AFDate_FormatEx. */
  1458.     var cOldFormats = new Array(
  1459.         "m/d", "m/d/yy", "mm/dd/yy", "mm/yy", "d-mmm", "d-mmm-yy", "dd-mmm-yy",
  1460.         "yy-mm-dd", "mmm-yy", "mmmm-yy", "mmm d, yyyy", "mmmm d, yyyy",
  1461.         "m/d/yy h:MM tt", "m/d/yy HH:MM" );
  1462.  
  1463.     AFDate_FormatEx(cOldFormats[pdf]);
  1464. }
  1465.  
  1466. function AFTime_Format(ptf)
  1467. {    /* This function formats a time value according to the "PropsTimeFormat" parameter ptf.
  1468.     ** The time formats, indicated by ptf, are:
  1469.     ** ptf             format                                                          
  1470.     ** ---             ------                                                          
  1471.     ** 0               PTF_24HR_MM     [ 14:30      ]
  1472.     ** 1               PTF_12HR_MM     [ 2:30 PM    ]
  1473.     ** 2               PTF_24HR_MM_SS  [ 14:30:15   ]
  1474.     ** 3               PTF_12HR_MM_SS  [ 2:30:15 PM ] */
  1475.  
  1476.     if(!event.value) return;    /* Blank fields remain blank */
  1477.  
  1478.     var date = AFParseTime(event.value, null);
  1479.     if(!date) {
  1480.         event.value = "";
  1481.         return;
  1482.     }
  1483.  
  1484.     var cFormats = new Array(
  1485.         "HH:MM", "h:MM tt", "HH:MM:ss", "h:MM:ss tt" ); 
  1486.     
  1487.     event.value = util.printd(cFormats[ptf], date);
  1488. }
  1489.  
  1490. function AFTime_FormatEx(cFormat)
  1491. {
  1492.     if(!event.value) return;    /* Blank fields remain blank */
  1493.  
  1494.     var date = AFParseTime(event.value, null);
  1495.     if(!date) {
  1496.         event.value = "";
  1497.         return;
  1498.     }
  1499.  
  1500.     event.value = util.printd(cFormat, date);
  1501. }
  1502.  
  1503. function AFSignatureLock(doc, cOperation, cFields, bLock)
  1504. {    // Locks or unlocks a set of fields according to the specified operation.
  1505.     /* Field name separator is one or more spaces followed by a comma, 
  1506.     ** followed by one or more spaces.
  1507.     ** or an array of field names */
  1508.      var aFields = AFMakeArrayFromList(cFields);
  1509.  
  1510.     /* Three cases: ALL, EXCEPT, THESE for the field name list. */
  1511.     if (cOperation != "THESE") {
  1512.         for (var i = 0; i < doc.numFields; i++) {
  1513.             var f = doc.getField(doc.getNthFieldName(i));
  1514.                 
  1515.             f.readonly = bLock;
  1516.          }
  1517.     }
  1518.     
  1519.     if (cOperation == "EXCEPT")
  1520.         /* EXCEPT = ALL(lock) then THESE(unlock) */
  1521.         bLock = !bLock;
  1522.  
  1523.     if (cOperation == "THESE" || (cOperation == "EXCEPT" && !bLock)) {
  1524.         for (var i = 0; i < aFields.length; i++) {
  1525.             var f = doc.getField(aFields[i]);
  1526.             var a = f.getArray();
  1527.  
  1528.             for (var j = 0; j < a.length; j++) {
  1529.                 a[j].readonly = bLock;
  1530.             }
  1531.         }
  1532.     }
  1533. }
  1534.  
  1535. function AFSignature_Format(cOperation, cFields)
  1536. {    /* This function is invoked at format time but really is used to lock fields
  1537.     ** in the document. We unlock all the specified fields if the value is
  1538.     ** null (which means the signature hasn't been applied). */
  1539.  
  1540.     var bLock = (event.value != "");
  1541.  
  1542.     AFSignatureLock(this, cOperation, cFields, bLock);
  1543. }
  1544. function AFStringReplace(cString, oRegExp, cReplacement)
  1545. {
  1546.     return cString.replace(oRegExp, cReplacement);
  1547. }
  1548.  
  1549.  
  1550. function SearchBuildURL(query, mode, country)
  1551. {/* Builds a URL for google.com.
  1552.  
  1553.     Parameters:
  1554.         query: string to be searched such as "find newport"
  1555.         mode:  one of the search modes, kMatchPhrase, kMatchAllWords, or kMatchAnyWords.
  1556.         country: 3 character string such as "ENU", describing the country.
  1557. */
  1558.     var url, queryStr;
  1559.  
  1560.     if (mode < 0 || mode > 2)
  1561.         return "";
  1562.  
  1563.     if (country == "JPN")
  1564.         url = "http://www.google.co.jp/search?";
  1565.     else
  1566.         url = "http://www.google.com/search?";
  1567.  
  1568.  
  1569.     queryStr = "";
  1570.     for (i=0; i < query.length; i++)
  1571.         if (query.charAt(i) == ' ')
  1572.             queryStr = queryStr + '+';
  1573.         else
  1574.             queryStr = queryStr + query.charAt(i);
  1575.  
  1576.             
  1577.     switch (mode)
  1578.     {
  1579.         case 0: /* kMatchPhrase */
  1580.             url = url + "&as_epq=" + queryStr;
  1581.             break;
  1582.         case 1: /* kMatchAllWords */
  1583.             url = url + "&as_q=" + queryStr;
  1584.             break;
  1585.         case 2: /* kMatchAnyWords */
  1586.             url = url + "&as_oq=" + queryStr;
  1587.             break;
  1588.     }
  1589.  
  1590.     url = url + "&ie=UTF-8&oe=UTF-8&hl=";
  1591.  
  1592.  
  1593.     /* country specific stuff */
  1594.     if (country == "ENU")
  1595.         url = url + "en";
  1596.     else if (country == "DEU")
  1597.         url = url + "de";
  1598.     else if (country == "FRA")         
  1599.         url = url + "fr";
  1600.     else if (country == "ITA")
  1601.         url = url + "it";
  1602.     else if (country == "NLD")
  1603.         url = url + "nl";
  1604.     else if (country == "ESP")
  1605.         url = url + "es";
  1606.     else if (country == "SVE")
  1607.         url = url + "sv";
  1608.     else if (country == "JPN")
  1609.         url = url + "ja";
  1610.     else if (country == "KOR")
  1611.         url = url + "ko";
  1612.     else if (country == "CHT")         
  1613.         url = url + "zh-TW";
  1614.     else if (country == "CHS")
  1615.         url = url + "zh-CN";
  1616.     else if (country == "PTB")
  1617.         url = url + "pt";
  1618.     else if (country == "DAN")
  1619.         url = url + "da";
  1620.     else if (country == "SUO")
  1621.         url = url + "fi";
  1622.     else if (country == "NOR")
  1623.         url = url + "no";
  1624.     else if (country == "ARA")
  1625.         url = url + "ar";
  1626.     else if (country == "HEB")
  1627.         url = url + "iw";
  1628.     else
  1629.         url = url + "en";
  1630.  
  1631.     url = url + "&lr=&safe=images&as_filetype=pdf";
  1632.  
  1633.     return url;
  1634. }
  1635.  
  1636.  
  1637. function LookUpWordEnable(country)
  1638. {/* Check a locatization for Look Up Word definition ability.
  1639.  
  1640.     Parameters:
  1641.         country: 3 character string such as "ENU", describing the country.
  1642. */
  1643.     var bEnable = false;
  1644.  
  1645.     switch (country)
  1646.     {
  1647.         case "ENU": /* English */
  1648.             bEnable = true;
  1649.             break;
  1650.  
  1651.         default: /* unsupported country */
  1652.             break;
  1653.     }
  1654.  
  1655.     return bEnable;
  1656. }
  1657.  
  1658.  
  1659. function LookUpWordDefinitionURL(cWord, country)
  1660. {/* Builds a URL for dictionary.com.
  1661.  
  1662.     Parameters:
  1663.         cWord: word to be defined such as "orthographic"
  1664.         country: 3 character string such as "ENU", describing the country.
  1665. */
  1666.     var wordStr, url = "";
  1667.  
  1668.     switch (country)
  1669.     {
  1670.         case "ENU": /* English */
  1671.         {
  1672.             url = "http://www.dictionary.com/cgi-bin/dict.pl?term=";
  1673.  
  1674.             wordStr = "";
  1675.             for (i=0; i < cWord.length; i++)
  1676.                 if (cWord.charAt(i) == ' ')
  1677.                     wordStr = wordStr + '+';
  1678.                 else
  1679.                     wordStr = wordStr + cWord.charAt(i);
  1680.  
  1681.             url = url + wordStr;
  1682.             break;
  1683.         }
  1684.  
  1685.         default: /* unsupported country */
  1686.             break;
  1687.     }
  1688.  
  1689.     return url;
  1690. }
  1691.