diff options
Diffstat (limited to 'source/pdf/pdf-js-util.js')
-rw-r--r-- | source/pdf/pdf-js-util.js | 874 |
1 files changed, 874 insertions, 0 deletions
diff --git a/source/pdf/pdf-js-util.js b/source/pdf/pdf-js-util.js new file mode 100644 index 00000000..299f80ac --- /dev/null +++ b/source/pdf/pdf-js-util.js @@ -0,0 +1,874 @@ +var MuPDF = { + monthName: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'], + shortMonthName: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], + monthPattern: /Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec/, + dayName: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], + + padZeros: function(num, places) { + var s = String(num) + while (s.length < places) + s = '0' + s + return s; + }, + + convertCase: function(str, cmd) { + switch (cmd) { + case '>': return str.toUpperCase(); + case '<': return str.toLowerCase(); + default: return str; + } + }, +}; + +/* display must be kept in sync with an enum in pdf_form.c */ +var display = { + visible: 0, + hidden: 1, + noPrint: 2, + noView: 3, +}; + +var border = { + s: "Solid", + d: "Dashed", + b: "Beveled", + i: "Inset", + u: "Underline", +}; + +var color = { + transparent: [ "T" ], + black: [ "G", 0 ], + white: [ "G", 1 ], + red: [ "RGB", 1,0,0 ], + green: [ "RGB", 0,1,0 ], + blue: [ "RGB", 0,0,1 ], + cyan: [ "CMYK", 1,0,0,0 ], + magenta: [ "CMYK", 0,1,0,0 ], + yellow: [ "CMYK", 0,0,1,0 ], + dkGray: [ "G", 0.25 ], + gray: [ "G", 0.5 ], + ltGray: [ "G", 0.75 ], +}; + +var util = {}; + +util.printd = function(fmt, d) +{ + var regexp = /(m+|d+|y+|H+|h+|M+|s+|t+|[^mdyHhMst]+)/g; + var res = ''; + var i; + + if (!d) + return null; + + var tokens = fmt.match(regexp); + var length = tokens ? tokens.length : 0; + + for (i = 0; i < length; i++) + { + switch(tokens[i]) + { + case 'mmmm': res += MuPDF.monthName[d.getMonth()]; break; + case 'mmm': res += MuPDF.monthName[d.getMonth()].substring(0,3); break; + case 'mm': res += MuPDF.padZeros(d.getMonth()+1, 2); break; + case 'm': res += d.getMonth()+1; break; + case 'dddd': res += MuPDF.dayName[d.getDay()]; break; + case 'ddd': res += MuPDF.dayName[d.getDay()].substring(0,3); break; + case 'dd': res += MuPDF.padZeros(d.getDate(), 2); break; + case 'd': res += d.getDate(); break; + case 'yyyy': res += d.getFullYear(); break; + case 'yy': res += d.getFullYear()%100; break; + case 'HH': res += MuPDF.padZeros(d.getHours(), 2); break; + case 'H': res += d.getHours(); break; + case 'hh': res += MuPDF.padZeros((d.getHours()+11)%12+1, 2); break; + case 'h': res += (d.getHours()+11)%12+1; break; + case 'MM': res += MuPDF.padZeros(d.getMinutes(), 2); break; + case 'M': res += d.getMinutes(); break; + case 'ss': res += MuPDF.padZeros(d.getSeconds(), 2); break; + case 's': res += d.getSeconds(); break; + case 'tt': res += d.getHours() < 12 ? 'am' : 'pm'; break; + case 't': res += d.getHours() < 12 ? 'a' : 'p'; break; + default: res += tokens[i]; + } + } + + return res; +} + +util.printx = function(fmt, val) +{ + var cs = '='; + var res = ''; + var i = 0; + var m; + var length = fmt ? fmt.length : 0; + + while (i < length) + { + switch (fmt.charAt(i)) + { + case '\\': + i++; + if (i >= length) return res; + res += fmt.charAt(i); + break; + + case 'X': + m = val.match(/\w/); + if (!m) return res; + res += MuPDF.convertCase(m[0],cs); + val = val.replace(/^\W*\w/,''); + break; + + case 'A': + m = val.match(/[A-Za-z]/); + if (!m) return res; + res += MuPDF.convertCase(m[0],cs); + val = val.replace(/^[^A-Za-z]*[A-Za-z]/,''); + break; + + case '9': + m = val.match(/\d/); + if (!m) return res; + res += m[0]; + val = val.replace(/^\D*\d/,''); + break; + + case '*': + res += val; + val = ''; + break; + + case '?': + if (!val) return res; + res += MuPDF.convertCase(val.charAt(0),cs); + val = val.substring(1); + break; + + case '=': + case '>': + case '<': + cs = fmt.charAt(i); + break; + + default: + res += MuPDF.convertCase(fmt.charAt(i),cs); + break; + } + + i++; + } + + return res; +} + +util.printf = function() +{ + var i; + + if (arguments.length < 1) + return ""; + + var res = ""; + var arg_i = 1; + var regexp = /%[^dfsx]*[dfsx]|[^%]*/g; + var tokens = arguments[0].match(regexp); + var length = tokens ? tokens.length : 0; + + for (i = 0; i < length; i++) + { + var tok = tokens[i]; + if (tok.match(/^%/)) + { + if (arg_i < arguments.length) + { + var val = arguments[arg_i++]; + var fval = ''; + var neg = false; + var decsep_re = /^,[0123]/; + var flags_re = /^[+ 0#]+/; + var width_re = /^\d+/; + var prec_re = /^\.\d+/; + var conv_re = /^[dfsx]/; + + tok = tok.replace(/^%/, ""); + var decsep = tok.match(decsep_re); + if (decsep) decsep = decsep[0]; + tok = tok.replace(decsep_re, ""); + var flags = tok.match(flags_re); + if (flags) flags = flags[0]; + tok = tok.replace(flags_re, ""); + var width = tok.match(width_re); + if (width) width = width[0]; + tok = tok.replace(width_re, ""); + var prec = tok.match(prec_re); + if (prec) prec = prec[0]; + tok = tok.replace(prec_re, ""); + var conv = tok.match(conv_re); + if (conv) conv = conv[0]; + + prec = prec ? Number(prec.replace(/^\./, '')) : 0; + var poschar = (flags && flags.match(/[+ ]/)) ? flags.match(/[+ ]/)[0] : ''; + var pad = (flags && flags.match(/0/)) ? '0' : ' '; + + var point = '.'; + var thou = ''; + + if (decsep) + { + switch(decsep) + { + case ',0': thou = ','; break; + case ',1': break; + case ',2': thou = '.'; point = ','; break; + case ',3': point = ','; break; + } + } + + switch(conv) + { + case 'x': + val = Math.floor(val); + neg = (val < 0); + if (neg) + val = -val; + + // Convert to hex + while (val) + { + fval = '0123456789ABCDEF'.charAt(val%16) + fval; + val = Math.floor(val/16); + } + + if (neg) + fval = '-' + fval; + else + fval = poschar + fval; + break; + + case 'd': + fval = String(Math.floor(val)); + break; + + case 's': + // Always pad strings with space + pad = ' '; + fval = String(val); + break; + + case 'f': + fval = String(val); + + if (prec) + { + var frac = fval.match(/\.\d+/); + if (frac) + { + frac = frac[0]; + // Matched string includes the dot, so make it + // prec+1 in length + if (frac.length > prec+1) + frac = frac.substring(0, prec+1); + else if(frac.length < prec+1) + frac += new Array(prec+1-frac.length+1).join('0'); + + fval = fval.replace(/\.\d+/, frac); + } + } + break; + } + + if (conv.match(/[fd]/)) + { + if (fval >= 0) + fval = poschar + fval; + + if (point !== '.') + fval.replace(/\./, point); + + if (thou) + { + var intpart = fval.match(/\d+/)[0]; + intpart = new Array(2-(intpart.length+2)%3+1).join('0') + intpart; + intpart = intpart.match(/.../g).join(thou).replace(/^0*[,.]?/,''); + fval = fval.replace(/\d+/, intpart); + } + } + + if (width && fval.length < width) + fval = new Array(width - fval.length + 1).join(pad) + fval; + + res += fval; + } + } + else + { + res += tok; + } + } + + return res; +} + +function AFMergeChange(event) +{ + return event.value; +} + +function AFMakeNumber(str) +{ + var nums = str.match(/\d+/g); + + if (!nums) + return null; + + var res = nums.join('.'); + + if (str.match(/^[^0-9]*\./)) + res = '0.'+res; + + return res * (str.match(/-/) ? -1.0 : 1.0); +} + +function AFExtractTime(dt) +{ + var ampm = dt.match(/(am|pm)/); + dt = dt.replace(/(am|pm)/, ''); + var t = dt.match(/\d{1,2}:\d{1,2}:\d{1,2}/); + dt = dt.replace(/\d{1,2}:\d{1,2}:\d{1,2}/, ''); + if (!t) + { + t = dt.match(/\d{1,2}:\d{1,2}/); + dt = dt.replace(/\d{1,2}:\d{1,2}/, ''); + } + + return [dt, t?t[0]+(ampm?ampm[0]:''):'']; +} + +function AFParseDateOrder(fmt) +{ + var i; + var order = ''; + + // Ensure all present with those not added in default order + fmt += "mdy"; + + for (i = 0; i < fmt.length; i++) + { + var c = fmt.charAt(i); + + if ('ymd'.indexOf(c) !== -1 && order.indexOf(c) === -1) + order += c; + } + + return order; +} + +function AFMatchMonth(d) +{ + var m = d.match(MuPDF.monthPattern); + + return m ? MuPDF.shortMonthName.indexOf(m[0]) : null; +} + +function AFParseTime(str, d) +{ + if (!str) + return d; + + if (!d) + d = new Date(); + + var ampm = str.match(/(am|pm)/); + var nums = str.match(/\d+/g); + var hour, min, sec; + + if (!nums) + return null; + + sec = 0; + + switch (nums.length) + { + case 3: + sec = parseInt(nums[2]); + case 2: + hour = parseInt(nums[0]); + min = parseInt(nums[1]); + break; + + default: + return null; + } + + ampm = ampm && ampm[0] + + if (ampm === 'am' && hour < 12) + hour = 12 + hour; + if (ampm === 'pm' && hour >= 12) + hour = 0 + hour - 12; + + d.setHours(hour, min, sec); + + if (d.getHours() !== hour || d.getMinutes() !== min || d.getSeconds() !== sec) + return null; + + return d; +} + +function AFParseDateEx(d, fmt) +{ + var i; + var dt = AFExtractTime(d); + var nums = dt[0].match(/\d+/g); + var order = AFParseDateOrder(fmt); + var text_month = AFMatchMonth(dt[0]); + var dout = new Date(); + var year = dout.getFullYear(); + var month = dout.getMonth(); + var date = dout.getDate(); + + dout.setHours(12,0,0); + + if (!nums || nums.length < 1 || nums.length > 3) + return null; + + if (nums.length < 3 && text_month) + { + // Use the text month rather than one of the numbers + month = text_month; + order = order.replace('m',''); + } + + order = order.substring(0, nums.length); + + // If year and month specified but not date then use the 1st + if (order === "ym" || (order === "y" && text_month)) + date = 1; + + for (i = 0; i < nums.length; i++) + { + switch (order.charAt(i)) + { + case 'y': year = parseInt(nums[i]); break; + case 'm': month = parseInt(nums[i]) - 1; break; + case 'd': date = parseInt(nums[i]); break; + } + } + + if (year < 100) + { + if (fmt.search("yyyy") !== -1) + return null; + + if (year >= 50) + year = 1900 + year; + else if (year >= 0) + year = 2000 + year; + } + + dout.setFullYear(year, month, date); + + if (dout.getFullYear() !== year || dout.getMonth() !== month || dout.getDate() !== date) + return null; + + return AFParseTime(dt[1], dout); +} + +function AFDate_KeystrokeEx(fmt) +{ + if (event.willCommit && !AFParseDateEx(event.value, fmt)) + { + app.alert("The date/time entered ("+event.value+") does not match the format ("+fmt+") of the field [ "+event.target.name+" ]"); + event.rc = false; + } +} + +function AFDate_Keystroke(index) +{ + var formats = ['m/d','m/d/yy','mm/dd/yy','mm/yy','d-mmm','d-mmm-yy','dd-mm-yy','yy-mm-dd', + 'mmm-yy','mmmm-yy','mmm d, yyyy','mmmm d, yyyy','m/d/yy h:MM tt','m/d/yy HH:MM']; + AFDate_KeystrokeEx(formats[index]); +} + +function AFDate_FormatEx(fmt) +{ + var d = AFParseDateEx(event.value, fmt); + + event.value = d ? util.printd(fmt, d) : ""; +} + +function AFDate_Format(index) +{ + var formats = ['m/d','m/d/yy','mm/dd/yy','mm/yy','d-mmm','d-mmm-yy','dd-mm-yy','yy-mm-dd', + 'mmm-yy','mmmm-yy','mmm d, yyyy','mmmm d, yyyy','m/d/yy h:MM tt','m/d/yy HH:MM']; + AFDate_FormatEx(formats[index]); +} + +function AFTime_Keystroke(index) +{ + if (event.willCommit && !AFParseTime(event.value, null)) + { + app.alert("The value entered ("+event.value+") does not match the format of the field [ "+event.target.name+" ]"); + event.rc = false; + } +} + +function AFTime_FormatEx(fmt) +{ + var d = AFParseTime(event.value, null); + + event.value = d ? util.printd(fmt, d) : ''; +} + +function AFTime_Format(index) +{ + var formats = ['HH:MM','h:MM tt','HH:MM:ss','h:MM:ss tt']; + + AFTime_FormatEx(formats[index]); +} + +function AFSpecial_KeystrokeEx(fmt) +{ + var cs = '='; + var val = event.value; + var res = ''; + var i = 0; + var m; + var length = fmt ? fmt.length : 0; + + while (i < length) + { + switch (fmt.charAt(i)) + { + case '\\': + i++; + if (i >= length) + break; + res += fmt.charAt(i); + if (val && val.charAt(0) === fmt.charAt(i)) + val = val.substring(1); + break; + + case 'X': + m = val.match(/^\w/); + if (!m) + { + event.rc = false; + break; + } + res += MuPDF.convertCase(m[0],cs); + val = val.substring(1); + break; + + case 'A': + m = val.match(/^[A-Za-z]/); + if (!m) + { + event.rc = false; + break; + } + res += MuPDF.convertCase(m[0],cs); + val = val.substring(1); + break; + + case '9': + m = val.match(/^\d/); + if (!m) + { + event.rc = false; + break; + } + res += m[0]; + val = val.substring(1); + break; + + case '*': + res += val; + val = ''; + break; + + case '?': + if (!val) + { + event.rc = false; + break; + } + res += MuPDF.convertCase(val.charAt(0),cs); + val = val.substring(1); + break; + + case '=': + case '>': + case '<': + cs = fmt.charAt(i); + break; + + default: + res += fmt.charAt(i); + if (val && val.charAt(0) === fmt.charAt(i)) + val = val.substring(1); + break; + } + + i++; + } + + if (event.rc) + event.value = res; + else if (event.willCommit) + app.alert("The value entered ("+event.value+") does not match the format of the field [ "+event.target.name+" ] should be "+fmt); +} + +function AFSpecial_Keystroke(index) +{ + if (event.willCommit) + { + switch (index) + { + case 0: + if (!event.value.match(/^\d{5}$/)) + event.rc = false; + break; + case 1: + if (!event.value.match(/^\d{5}[-. ]?\d{4}$/)) + event.rc = false; + break; + case 2: + if (!event.value.match(/^((\(\d{3}\)|\d{3})[-. ]?)?\d{3}[-. ]?\d{4}$/)) + event.rc = false; + break; + case 3: + if (!event.value.match(/^\d{3}[-. ]?\d{2}[-. ]?\d{4}$/)) + event.rc = false; + break; + } + + if (!event.rc) + app.alert("The value entered ("+event.value+") does not match the format of the field [ "+event.target.name+" ]"); + } +} + +function AFSpecial_Format(index) +{ + var res; + + switch (index) + { + case 0: + res = util.printx('99999', event.value); + break; + case 1: + res = util.printx('99999-9999', event.value); + break; + case 2: + res = util.printx('9999999999', event.value); + res = util.printx(res.length >= 10 ? '(999) 999-9999' : '999-9999', event.value); + break; + case 3: + res = util.printx('999-99-9999', event.value); + break; + } + + event.value = res ? res : ''; +} + +function AFNumber_Keystroke(nDec, sepStyle, negStyle, currStyle, strCurrency, bCurrencyPrepend) +{ + if (sepStyle & 2) + { + if (!event.value.match(/^[+-]?\d*[,.]?\d*$/)) + event.rc = false; + } + else + { + if (!event.value.match(/^[+-]?\d*\.?\d*$/)) + event.rc = false; + } + + if (event.willCommit) + { + if (!event.value.match(/\d/)) + event.rc = false; + + if (!event.rc) + app.alert("The value entered ("+event.value+") does not match the format of the field [ "+event.target.name+" ]"); + } +} + +function AFNumber_Format(nDec,sepStyle,negStyle,currStyle,strCurrency,bCurrencyPrepend) +{ + var val = event.value; + var fracpart; + var intpart; + var point = sepStyle&2 ? ',' : '.'; + var separator = sepStyle&2 ? '.' : ','; + + if (/^\D*\./.test(val)) + val = '0'+val; + + var groups = val.match(/\d+/g); + + if (!groups) + return; + + switch (groups.length) + { + case 0: + return; + case 1: + fracpart = ''; + intpart = groups[0]; + break; + default: + fracpart = groups.pop(); + intpart = groups.join(''); + break; + } + + // Remove leading zeros + intpart = intpart.replace(/^0*/,''); + if (!intpart) + intpart = '0'; + + if ((sepStyle & 1) === 0) + { + // Add the thousands sepearators: pad to length multiple of 3 with zeros, + // split into 3s, join with separator, and remove the leading zeros + intpart = new Array(2-(intpart.length+2)%3+1).join('0') + intpart; + intpart = intpart.match(/.../g).join(separator).replace(/^0*/,''); + } + + if (!intpart) + intpart = '0'; + + // Adjust fractional part to correct number of decimal places + fracpart += new Array(nDec+1).join('0'); + fracpart = fracpart.substring(0,nDec); + + if (fracpart) + intpart += point+fracpart; + + if (bCurrencyPrepend) + intpart = strCurrency+intpart; + else + intpart += strCurrency; + + if (/-/.test(val)) + { + switch (negStyle) + { + case 0: + intpart = '-'+intpart; + break; + case 1: + break; + case 2: + case 3: + intpart = '('+intpart+')'; + break; + } + } + + if (negStyle&1) + event.target.textColor = /-/.test(val) ? color.red : color.black; + + event.value = intpart; +} + +function AFPercent_Keystroke(nDec, sepStyle) +{ + AFNumber_Keystroke(nDec, sepStyle, 0, 0, "", true); +} + +function AFPercent_Format(nDec, sepStyle) +{ + var val = AFMakeNumber(event.value); + + if (!val) + { + event.value = ''; + return; + } + + event.value = (val * 100) + ''; + + AFNumber_Format(nDec, sepStyle, 0, 0, "%", false); +} + +function AFSimple_Calculate(op, list) +{ + var i, res; + + switch (op) + { + case 'SUM': + res = 0; + break; + case 'PRD': + res = 1; + break; + case 'AVG': + res = 0; + break; + } + + if (typeof list === 'string') + list = list.split(/ *, */); + + for (i = 0; i < list.length; i++) + { + var field = MuPDF_Doc.getField(list[i]); + var value = Number(field.value); + + switch (op) + { + case 'SUM': + res += value; + break; + case 'PRD': + res *= value; + break; + case 'AVG': + res += value; + break; + case 'MIN': + if (i === 0 || value < res) + res = value; + break; + case 'MAX': + if (i === 0 || value > res) + res = value; + break; + } + } + + if (op === 'AVG') + res /= list.length; + + event.value = res; +} + +function AFRange_Validate(lowerCheck, lowerLimit, upperCheck, upperLimit) +{ + if (upperCheck && event.value > upperLimit) + { + event.rc = false; + } + + if (lowerCheck && event.value < lowerLimit) + { + event.rc = false; + } + + if (!event.rc) + { + if (lowerCheck && upperCheck) + app.alert(util.printf("The entered value ("+event.value+") must be greater than or equal to %s and less than or equal to %s", lowerLimit, upperLimit)); + else if (lowerCheck) + app.alert(util.printf("The entered value ("+event.value+") must be greater than or equal to %s", lowerLimit)); + else + app.alert(util.printf("The entered value ("+event.value+") must be less than or equal to %s", upperLimit)); + } +} |