| 
									
										
										
										
											2022-03-12 14:05:57 +00:00
										 |  |  | var WK_ = /*#__PURE__*/(function() { | 
					
						
							| 
									
										
										
										
											2017-04-04 16:09:41 +00:00
										 |  |  | 	function lotushopper(data, cb/*:RecordHopperCB*/, opts/*:any*/) { | 
					
						
							|  |  |  | 		if(!data) return; | 
					
						
							|  |  |  | 		prep_blob(data, data.l || 0); | 
					
						
							|  |  |  | 		var Enum = opts.Enum || WK1Enum; | 
					
						
							|  |  |  | 		while(data.l < data.length) { | 
					
						
							|  |  |  | 			var RT = data.read_shift(2); | 
					
						
							| 
									
										
										
										
											2021-11-08 04:52:18 +00:00
										 |  |  | 			var R = Enum[RT] || Enum[0xFFFF]; | 
					
						
							| 
									
										
										
										
											2017-04-04 16:09:41 +00:00
										 |  |  | 			var length = data.read_shift(2); | 
					
						
							|  |  |  | 			var tgt = data.l + length; | 
					
						
							| 
									
										
										
										
											2021-11-08 04:52:18 +00:00
										 |  |  | 			var d = R.f && R.f(data, length, opts); | 
					
						
							| 
									
										
										
										
											2017-04-04 16:09:41 +00:00
										 |  |  | 			data.l = tgt; | 
					
						
							| 
									
										
										
										
											2021-11-08 04:52:18 +00:00
										 |  |  | 			if(cb(d, R, RT)) return; | 
					
						
							| 
									
										
										
										
											2017-04-04 16:09:41 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	function lotus_to_workbook(d/*:RawData*/, opts) { | 
					
						
							|  |  |  | 		switch(opts.type) { | 
					
						
							| 
									
										
										
										
											2022-03-22 20:08:08 +00:00
										 |  |  | 			case 'base64': return lotus_to_workbook_buf(s2a(Base64_decode(d)), opts); | 
					
						
							| 
									
										
										
										
											2017-04-04 16:09:41 +00:00
										 |  |  | 			case 'binary': return lotus_to_workbook_buf(s2a(d), opts); | 
					
						
							|  |  |  | 			case 'buffer': | 
					
						
							|  |  |  | 			case 'array': return lotus_to_workbook_buf(d, opts); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		throw "Unsupported type " + opts.type; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-23 09:48:47 +00:00
										 |  |  | 	/* NOTE: this list intentionally starts at 1 */ | 
					
						
							|  |  |  | 	var LOTUS_DATE_FMTS = [ | 
					
						
							|  |  |  | 		"mmmm", | 
					
						
							|  |  |  | 		"dd-mmm-yyyy", | 
					
						
							|  |  |  | 		"dd-mmm", | 
					
						
							|  |  |  | 		"mmm-yyyy", | 
					
						
							|  |  |  | 		"@", // "text"?
 | 
					
						
							|  |  |  | 		"mm/dd", | 
					
						
							|  |  |  | 		"hh:mm:ss AM/PM", // 7
 | 
					
						
							|  |  |  | 		"hh:mm AM/PM", | 
					
						
							|  |  |  | 		"mm/dd/yyyy", | 
					
						
							|  |  |  | 		"mm/dd", | 
					
						
							|  |  |  | 		"hh:mm:ss", | 
					
						
							|  |  |  | 		"hh:mm" // 12
 | 
					
						
							|  |  |  | 	]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-06 06:39:48 +00:00
										 |  |  | 	function lotus_to_workbook_buf(d, opts)/*:Workbook*/ { | 
					
						
							| 
									
										
										
										
											2017-04-04 16:09:41 +00:00
										 |  |  | 		if(!d) return d; | 
					
						
							|  |  |  | 		var o = opts || {}; | 
					
						
							| 
									
										
										
										
											2017-04-09 04:03:19 +00:00
										 |  |  | 		if(DENSE != null && o.dense == null) o.dense = DENSE; | 
					
						
							| 
									
										
										
										
											2022-10-24 01:05:59 +00:00
										 |  |  | 		var s/*:Worksheet*/ = ({}/*:any*/), n = "Sheet1", next_n = "", sidx = 0; | 
					
						
							|  |  |  | 		var sheets = {}, snames = [], realnames = [], sdata = []; | 
					
						
							|  |  |  | 		if(o.dense) sdata = s["!data"] = []; | 
					
						
							| 
									
										
										
										
											2017-04-04 16:09:41 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		var refguess = {s: {r:0, c:0}, e: {r:0, c:0} }; | 
					
						
							| 
									
										
										
										
											2018-04-06 06:39:48 +00:00
										 |  |  | 		var sheetRows = o.sheetRows || 0; | 
					
						
							| 
									
										
										
										
											2023-06-23 09:48:47 +00:00
										 |  |  | 		var lastcell = {}; | 
					
						
							| 
									
										
										
										
											2017-04-04 16:09:41 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-25 09:02:14 +00:00
										 |  |  | 		if(d[4] == 0x51 && d[5] == 0x50 && d[6] == 0x57) return qpw_to_workbook_buf(d, opts); | 
					
						
							| 
									
										
										
										
											2021-12-29 09:16:02 +00:00
										 |  |  | 		if(d[2] == 0x00) { | 
					
						
							|  |  |  | 			if(d[3] == 0x08 || d[3] == 0x09) { | 
					
						
							|  |  |  | 				if(d.length >= 16 && d[14] == 0x05 && d[15] === 0x6c) throw new Error("Unsupported Works 3 for Mac file"); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-08 04:52:18 +00:00
										 |  |  | 		if(d[2] == 0x02) { | 
					
						
							|  |  |  | 			o.Enum = WK1Enum; | 
					
						
							|  |  |  | 			lotushopper(d, function(val, R, RT) { switch(RT) { | 
					
						
							| 
									
										
										
										
											2021-11-14 04:38:00 +00:00
										 |  |  | 				case 0x00: /* BOF */ | 
					
						
							| 
									
										
										
										
											2017-04-04 16:09:41 +00:00
										 |  |  | 					o.vers = val; | 
					
						
							|  |  |  | 					if(val >= 0x1000) o.qpro = true; | 
					
						
							|  |  |  | 					break; | 
					
						
							| 
									
										
										
										
											2022-04-20 17:31:11 +00:00
										 |  |  | 				case 0xFF: /* BOF (works 3+) */ | 
					
						
							|  |  |  | 					o.vers = val; | 
					
						
							|  |  |  | 					o.works = true; | 
					
						
							|  |  |  | 					break; | 
					
						
							| 
									
										
										
										
											2017-04-04 16:09:41 +00:00
										 |  |  | 				case 0x06: refguess = val; break; /* RANGE */ | 
					
						
							| 
									
										
										
										
											2021-12-29 09:16:02 +00:00
										 |  |  | 				case 0xCC: if(val) next_n = val; break; /* SHEETNAMECS */ | 
					
						
							|  |  |  | 				case 0xDE: next_n = val; break; /* SHEETNAMELP */ | 
					
						
							| 
									
										
										
										
											2017-04-04 16:09:41 +00:00
										 |  |  | 				case 0x0F: /* LABEL */ | 
					
						
							| 
									
										
										
										
											2021-11-14 04:38:00 +00:00
										 |  |  | 				case 0x33: /* STRING */ | 
					
						
							| 
									
										
										
										
											2022-04-20 17:31:11 +00:00
										 |  |  | 					if((!o.qpro && !o.works || RT == 0x33) && val[1].v.charCodeAt(0) < 0x30) val[1].v = val[1].v.slice(1); | 
					
						
							|  |  |  | 					if(o.works || o.works2) val[1].v = val[1].v.replace(/\r\n/g, "\n"); | 
					
						
							| 
									
										
										
										
											2017-04-04 16:09:41 +00:00
										 |  |  | 					/* falls through */ | 
					
						
							|  |  |  | 				case 0x0D: /* INTEGER */ | 
					
						
							|  |  |  | 				case 0x0E: /* NUMBER */ | 
					
						
							|  |  |  | 				case 0x10: /* FORMULA */ | 
					
						
							| 
									
										
										
										
											2017-05-17 04:23:36 +00:00
										 |  |  | 					/* TODO: actual translation of the format code */ | 
					
						
							| 
									
										
										
										
											2023-06-23 09:48:47 +00:00
										 |  |  | 					if((val[2] & 0x70) == 0x70 && (val[2] & 0x0F) > 1 && (val[2] & 0x0F) < 15) { | 
					
						
							|  |  |  | 						val[1].z = o.dateNF || LOTUS_DATE_FMTS[(val[2] & 0x0F)-1] || table_fmt[14]; | 
					
						
							|  |  |  | 						if(o.cellDates) { val[1].v = numdate(val[1].v); val[1].t = typeof val[1].v == "number" ? 'n' : 'd'; } | 
					
						
							| 
									
										
										
										
											2017-05-17 04:23:36 +00:00
										 |  |  | 					} | 
					
						
							| 
									
										
										
										
											2021-12-29 09:16:02 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 					if(o.qpro) { | 
					
						
							|  |  |  | 						if(val[3] > sidx) { | 
					
						
							|  |  |  | 							s["!ref"] = encode_range(refguess); | 
					
						
							|  |  |  | 							sheets[n] = s; | 
					
						
							|  |  |  | 							snames.push(n); | 
					
						
							| 
									
										
										
										
											2022-10-24 01:05:59 +00:00
										 |  |  | 							s = ({}/*:any*/); if(o.dense) sdata = s["!data"] = []; | 
					
						
							| 
									
										
										
										
											2021-12-29 09:16:02 +00:00
										 |  |  | 							refguess = {s: {r:0, c:0}, e: {r:0, c:0} }; | 
					
						
							|  |  |  | 							sidx = val[3]; n = next_n || "Sheet" + (sidx + 1); next_n = ""; | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-24 01:05:59 +00:00
										 |  |  | 					var tmpcell = o.dense ? (sdata[val[0].r]||[])[val[0].c] : s[encode_cell(val[0])]; | 
					
						
							| 
									
										
										
										
											2021-11-14 04:38:00 +00:00
										 |  |  | 					if(tmpcell) { | 
					
						
							|  |  |  | 						tmpcell.t = val[1].t; tmpcell.v = val[1].v; | 
					
						
							|  |  |  | 						if(val[1].z != null) tmpcell.z = val[1].z; | 
					
						
							|  |  |  | 						if(val[1].f != null) tmpcell.f = val[1].f; | 
					
						
							| 
									
										
										
										
											2023-06-23 09:48:47 +00:00
										 |  |  | 						lastcell = tmpcell; | 
					
						
							| 
									
										
										
										
											2021-11-14 04:38:00 +00:00
										 |  |  | 						break; | 
					
						
							|  |  |  | 					} | 
					
						
							| 
									
										
										
										
											2017-04-08 06:55:35 +00:00
										 |  |  | 					if(o.dense) { | 
					
						
							| 
									
										
										
										
											2022-10-24 01:05:59 +00:00
										 |  |  | 						if(!sdata[val[0].r]) sdata[val[0].r] = []; | 
					
						
							|  |  |  | 						sdata[val[0].r][val[0].c] = val[1]; | 
					
						
							| 
									
										
										
										
											2017-04-08 06:55:35 +00:00
										 |  |  | 					} else s[encode_cell(val[0])] = val[1]; | 
					
						
							| 
									
										
										
										
											2023-06-23 09:48:47 +00:00
										 |  |  | 					lastcell = val[1]; | 
					
						
							| 
									
										
										
										
											2017-04-04 16:09:41 +00:00
										 |  |  | 					break; | 
					
						
							| 
									
										
										
										
											2022-04-20 17:31:11 +00:00
										 |  |  | 				case 0x5405: o.works2 = true; break; | 
					
						
							| 
									
										
										
										
											2023-06-23 09:48:47 +00:00
										 |  |  | 				case 0x5402: { | 
					
						
							|  |  |  | 					/* TODO: enumerate all extended number formats */ | 
					
						
							|  |  |  | 					if(val == 0x14a1) { | 
					
						
							|  |  |  | 						lastcell.z = "hh:mm:ss"; | 
					
						
							|  |  |  | 						if(o.cellDates && lastcell.t == "n") { | 
					
						
							|  |  |  | 							lastcell.v = numdate(lastcell.v); lastcell.t = typeof lastcell.v == "number" ? 'n' : 'd'; | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} break; | 
					
						
							| 
									
										
										
										
											2021-11-08 04:52:18 +00:00
										 |  |  | 			}}, o); | 
					
						
							|  |  |  | 		} else if(d[2] == 0x1A || d[2] == 0x0E) { | 
					
						
							|  |  |  | 			o.Enum = WK3Enum; | 
					
						
							|  |  |  | 			if(d[2] == 0x0E) { o.qpro = true; d.l = 0; } | 
					
						
							|  |  |  | 			lotushopper(d, function(val, R, RT) { switch(RT) { | 
					
						
							| 
									
										
										
										
											2021-12-29 09:16:02 +00:00
										 |  |  | 				case 0xCC: n = val; break; /* SHEETNAMECS */ | 
					
						
							| 
									
										
										
										
											2017-04-04 16:09:41 +00:00
										 |  |  | 				case 0x16: /* LABEL16 */ | 
					
						
							| 
									
										
										
										
											2022-04-20 17:31:11 +00:00
										 |  |  | 					if(val[1].v.charCodeAt(0) < 0x30) val[1].v = val[1].v.slice(1); | 
					
						
							|  |  |  | 					// TODO: R9 appears to encode control codes this way -- verify against other versions
 | 
					
						
							|  |  |  | 					val[1].v = val[1].v.replace(/\x0F./g, function($$) { return String.fromCharCode($$.charCodeAt(1) - 0x20); }).replace(/\r\n/g, "\n"); | 
					
						
							| 
									
										
										
										
											2017-04-04 16:09:41 +00:00
										 |  |  | 					/* falls through */ | 
					
						
							|  |  |  | 				case 0x17: /* NUMBER17 */ | 
					
						
							|  |  |  | 				case 0x18: /* NUMBER18 */ | 
					
						
							|  |  |  | 				case 0x19: /* FORMULA19 */ | 
					
						
							|  |  |  | 				case 0x25: /* NUMBER25 */ | 
					
						
							|  |  |  | 				case 0x27: /* NUMBER27 */ | 
					
						
							|  |  |  | 				case 0x28: /* FORMULA28 */ | 
					
						
							|  |  |  | 					if(val[3] > sidx) { | 
					
						
							|  |  |  | 						s["!ref"] = encode_range(refguess); | 
					
						
							|  |  |  | 						sheets[n] = s; | 
					
						
							| 
									
										
										
										
											2021-12-29 09:16:02 +00:00
										 |  |  | 						snames.push(n); | 
					
						
							| 
									
										
										
										
											2022-10-24 01:05:59 +00:00
										 |  |  | 						s = ({}/*:any*/); if(o.dense) sdata = s["!data"] = []; | 
					
						
							| 
									
										
										
										
											2017-04-04 16:09:41 +00:00
										 |  |  | 						refguess = {s: {r:0, c:0}, e: {r:0, c:0} }; | 
					
						
							|  |  |  | 						sidx = val[3]; n = "Sheet" + (sidx + 1); | 
					
						
							|  |  |  | 					} | 
					
						
							| 
									
										
										
										
											2018-04-06 06:39:48 +00:00
										 |  |  | 					if(sheetRows > 0 && val[0].r >= sheetRows) break; | 
					
						
							| 
									
										
										
										
											2017-11-20 01:51:14 +00:00
										 |  |  | 					if(o.dense) { | 
					
						
							| 
									
										
										
										
											2022-10-24 01:05:59 +00:00
										 |  |  | 						if(!sdata[val[0].r]) sdata[val[0].r] = []; | 
					
						
							|  |  |  | 						sdata[val[0].r][val[0].c] = val[1]; | 
					
						
							| 
									
										
										
										
											2017-11-20 01:51:14 +00:00
										 |  |  | 					} else s[encode_cell(val[0])] = val[1]; | 
					
						
							| 
									
										
										
										
											2017-04-04 16:09:41 +00:00
										 |  |  | 					if(refguess.e.c < val[0].c) refguess.e.c = val[0].c; | 
					
						
							|  |  |  | 					if(refguess.e.r < val[0].r) refguess.e.r = val[0].r; | 
					
						
							|  |  |  | 					break; | 
					
						
							| 
									
										
										
										
											2021-11-14 04:38:00 +00:00
										 |  |  | 				case 0x1B: /* XFORMAT */ | 
					
						
							|  |  |  | 					if(val[0x36b0]) realnames[val[0x36b0][0]] = val[0x36b0][1]; | 
					
						
							|  |  |  | 					break; | 
					
						
							| 
									
										
										
										
											2021-12-29 09:16:02 +00:00
										 |  |  | 				case 0x0601: /* SHEETINFOQP */ | 
					
						
							|  |  |  | 					realnames[val[0]] = val[1]; if(val[0] == sidx) n = val[1]; break; | 
					
						
							| 
									
										
										
										
											2017-04-04 16:09:41 +00:00
										 |  |  | 				default: break; | 
					
						
							| 
									
										
										
										
											2021-11-08 04:52:18 +00:00
										 |  |  | 			}}, o); | 
					
						
							|  |  |  | 		} else throw new Error("Unrecognized LOTUS BOF " + d[2]); | 
					
						
							| 
									
										
										
										
											2017-04-04 16:09:41 +00:00
										 |  |  | 		s["!ref"] = encode_range(refguess); | 
					
						
							| 
									
										
										
										
											2021-12-29 09:16:02 +00:00
										 |  |  | 		sheets[next_n || n] = s; | 
					
						
							|  |  |  | 		snames.push(next_n || n); | 
					
						
							| 
									
										
										
										
											2021-11-14 04:38:00 +00:00
										 |  |  | 		if(!realnames.length) return { SheetNames: snames, Sheets: sheets }; | 
					
						
							|  |  |  | 		var osheets = {}, rnames = []; | 
					
						
							| 
									
										
										
										
											2021-12-29 09:16:02 +00:00
										 |  |  | 		/* TODO: verify no collisions */ | 
					
						
							| 
									
										
										
										
											2021-11-14 04:38:00 +00:00
										 |  |  | 		for(var i = 0; i < realnames.length; ++i) if(sheets[snames[i]]) { | 
					
						
							| 
									
										
										
										
											2021-12-29 09:16:02 +00:00
										 |  |  | 			rnames.push(realnames[i] || snames[i]); | 
					
						
							|  |  |  | 			osheets[realnames[i]] = sheets[realnames[i]] || sheets[snames[i]]; | 
					
						
							|  |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2021-11-14 04:38:00 +00:00
										 |  |  | 			rnames.push(realnames[i]); | 
					
						
							| 
									
										
										
										
											2021-12-29 09:16:02 +00:00
										 |  |  | 			osheets[realnames[i]] = ({ "!ref": "A1" }); | 
					
						
							| 
									
										
										
										
											2021-11-14 04:38:00 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		return { SheetNames: rnames, Sheets: osheets }; | 
					
						
							| 
									
										
										
										
											2017-04-04 16:09:41 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-08 04:52:18 +00:00
										 |  |  | 	function sheet_to_wk1(ws/*:Worksheet*/, opts/*:WriteOpts*/) { | 
					
						
							|  |  |  | 		var o = opts || {}; | 
					
						
							|  |  |  | 		if(+o.codepage >= 0) set_cp(+o.codepage); | 
					
						
							| 
									
										
										
										
											2021-11-14 04:38:00 +00:00
										 |  |  | 		if(o.type == "string") throw new Error("Cannot write WK1 to JS string"); | 
					
						
							| 
									
										
										
										
											2021-11-08 04:52:18 +00:00
										 |  |  | 		var ba = buf_array(); | 
					
						
							|  |  |  | 		var range = safe_decode_range(ws["!ref"]); | 
					
						
							| 
									
										
										
										
											2022-10-24 01:05:59 +00:00
										 |  |  | 		var dense = ws["!data"] != null; | 
					
						
							| 
									
										
										
										
											2021-11-08 04:52:18 +00:00
										 |  |  | 		var cols = []; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		write_biff_rec(ba, 0x00, write_BOF_WK1(0x0406)); | 
					
						
							|  |  |  | 		write_biff_rec(ba, 0x06, write_RANGE(range)); | 
					
						
							| 
									
										
										
										
											2021-12-29 09:16:02 +00:00
										 |  |  | 		var max_R = Math.min(range.e.r, 8191); | 
					
						
							| 
									
										
										
										
											2022-10-24 01:05:59 +00:00
										 |  |  | 		for(var C = range.s.c; C <= range.e.c; ++C) cols[C] = encode_col(C); | 
					
						
							| 
									
										
										
										
											2021-12-29 09:16:02 +00:00
										 |  |  | 		for(var R = range.s.r; R <= max_R; ++R) { | 
					
						
							| 
									
										
										
										
											2021-11-08 04:52:18 +00:00
										 |  |  | 			var rr = encode_row(R); | 
					
						
							| 
									
										
										
										
											2022-10-24 01:05:59 +00:00
										 |  |  | 			for(C = range.s.c; C <= range.e.c; ++C) { | 
					
						
							|  |  |  | 				var cell = dense ? (ws["!data"][R]||[])[C] : ws[cols[C] + rr]; | 
					
						
							| 
									
										
										
										
											2021-11-08 04:52:18 +00:00
										 |  |  | 				if(!cell || cell.t == "z") continue; | 
					
						
							| 
									
										
										
										
											2021-11-14 04:38:00 +00:00
										 |  |  | 				/* TODO: formula records */ | 
					
						
							| 
									
										
										
										
											2023-06-23 09:48:47 +00:00
										 |  |  | 				switch(cell.t) { | 
					
						
							|  |  |  | 				case "n": | 
					
						
							|  |  |  | 					if((cell.v|0)==cell.v && cell.v >= -32768 && cell.v <= 32767) write_biff_rec(ba, 0x0d, write_INTEGER(R, C, cell)); | 
					
						
							|  |  |  | 					else write_biff_rec(ba, 0x0e, write_NUMBER(R, C, cell)); | 
					
						
							|  |  |  | 					break; | 
					
						
							|  |  |  | 				case "d": | 
					
						
							|  |  |  | 					var dc = datenum(cell.v); | 
					
						
							|  |  |  | 					if((dc|0)==dc && dc >= -32768 && dc <= 32767) write_biff_rec(ba, 0x0d, write_INTEGER(R, C, {t:"n", v:dc, z:cell.z || table_fmt[14]})); | 
					
						
							|  |  |  | 					else write_biff_rec(ba, 0x0e, write_NUMBER(R, C, {t:"n", v:dc, z:cell.z || table_fmt[14]})); | 
					
						
							|  |  |  | 					break; | 
					
						
							|  |  |  | 				default: | 
					
						
							| 
									
										
										
										
											2021-11-08 04:52:18 +00:00
										 |  |  | 					var str = format_cell(cell); | 
					
						
							|  |  |  | 					write_biff_rec(ba, 0x0F, write_LABEL(R, C, str.slice(0, 239))); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		write_biff_rec(ba, 0x01); | 
					
						
							|  |  |  | 		return ba.end(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-14 04:38:00 +00:00
										 |  |  | 	function book_to_wk3(wb/*:Workbook*/, opts/*:WriteOpts*/) { | 
					
						
							|  |  |  | 		var o = opts || {}; | 
					
						
							|  |  |  | 		if(+o.codepage >= 0) set_cp(+o.codepage); | 
					
						
							|  |  |  | 		if(o.type == "string") throw new Error("Cannot write WK3 to JS string"); | 
					
						
							|  |  |  | 		var ba = buf_array(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		write_biff_rec(ba, 0x00, write_BOF_WK3(wb)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		for(var i = 0, cnt = 0; i < wb.SheetNames.length; ++i) if((wb.Sheets[wb.SheetNames[i]] || {})["!ref"]) write_biff_rec(ba, 0x1b, write_XFORMAT_SHEETNAME(wb.SheetNames[i], cnt++)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		var wsidx = 0; | 
					
						
							|  |  |  | 		for(i = 0; i < wb.SheetNames.length; ++i) { | 
					
						
							|  |  |  | 			var ws = wb.Sheets[wb.SheetNames[i]]; | 
					
						
							|  |  |  | 			if(!ws || !ws["!ref"]) continue; | 
					
						
							|  |  |  | 			var range = safe_decode_range(ws["!ref"]); | 
					
						
							| 
									
										
										
										
											2022-10-24 01:05:59 +00:00
										 |  |  | 			var dense = ws["!data"] != null; | 
					
						
							| 
									
										
										
										
											2021-11-14 04:38:00 +00:00
										 |  |  | 			var cols = []; | 
					
						
							| 
									
										
										
										
											2021-12-29 09:16:02 +00:00
										 |  |  | 			var max_R = Math.min(range.e.r, 8191); | 
					
						
							|  |  |  | 			for(var R = range.s.r; R <= max_R; ++R) { | 
					
						
							| 
									
										
										
										
											2021-11-14 04:38:00 +00:00
										 |  |  | 				var rr = encode_row(R); | 
					
						
							|  |  |  | 				for(var C = range.s.c; C <= range.e.c; ++C) { | 
					
						
							|  |  |  | 					if(R === range.s.r) cols[C] = encode_col(C); | 
					
						
							|  |  |  | 					var ref = cols[C] + rr; | 
					
						
							| 
									
										
										
										
											2022-10-24 01:05:59 +00:00
										 |  |  | 					var cell = dense ? (ws["!data"][R]||[])[C] : ws[ref]; | 
					
						
							| 
									
										
										
										
											2021-11-14 04:38:00 +00:00
										 |  |  | 					if(!cell || cell.t == "z") continue; | 
					
						
							|  |  |  | 					/* TODO: FORMULA19 NUMBER18 records */ | 
					
						
							|  |  |  | 					if(cell.t == "n") { | 
					
						
							|  |  |  | 						write_biff_rec(ba, 0x17, write_NUMBER_17(R, C, wsidx, cell.v)); | 
					
						
							|  |  |  | 					} else { | 
					
						
							|  |  |  | 						var str = format_cell(cell); | 
					
						
							|  |  |  | 						/* TODO: max len? */ | 
					
						
							|  |  |  | 						write_biff_rec(ba, 0x16, write_LABEL_16(R, C, wsidx, str.slice(0, 239))); | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			++wsidx; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		write_biff_rec(ba, 0x01); | 
					
						
							|  |  |  | 		return ba.end(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-08 04:52:18 +00:00
										 |  |  | 	function write_BOF_WK1(v/*:number*/) { | 
					
						
							|  |  |  | 		var out = new_buf(2); | 
					
						
							|  |  |  | 		out.write_shift(2, v); | 
					
						
							|  |  |  | 		return out; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-14 04:38:00 +00:00
										 |  |  | 	function write_BOF_WK3(wb/*:Workbook*/) { | 
					
						
							|  |  |  | 		var out = new_buf(26); | 
					
						
							|  |  |  | 		out.write_shift(2, 0x1000); | 
					
						
							|  |  |  | 		out.write_shift(2, 0x0004); | 
					
						
							|  |  |  | 		out.write_shift(4, 0x0000); | 
					
						
							|  |  |  | 		var rows = 0, cols = 0, wscnt = 0; | 
					
						
							|  |  |  | 		for(var i = 0; i < wb.SheetNames.length; ++i) { | 
					
						
							|  |  |  | 			var name = wb.SheetNames[i]; | 
					
						
							|  |  |  | 			var ws = wb.Sheets[name]; | 
					
						
							|  |  |  | 			if(!ws || !ws["!ref"]) continue; | 
					
						
							|  |  |  | 			++wscnt; | 
					
						
							|  |  |  | 			var range = decode_range(ws["!ref"]); | 
					
						
							|  |  |  | 			if(rows < range.e.r) rows = range.e.r; | 
					
						
							|  |  |  | 			if(cols < range.e.c) cols = range.e.c; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2021-12-29 09:16:02 +00:00
										 |  |  | 		if(rows > 8191) rows = 8191; | 
					
						
							| 
									
										
										
										
											2021-11-14 04:38:00 +00:00
										 |  |  | 		out.write_shift(2, rows); | 
					
						
							|  |  |  | 		out.write_shift(1, wscnt); | 
					
						
							|  |  |  | 		out.write_shift(1, cols); | 
					
						
							|  |  |  | 		out.write_shift(2, 0x00); | 
					
						
							|  |  |  | 		out.write_shift(2, 0x00); | 
					
						
							|  |  |  | 		out.write_shift(1, 0x01); | 
					
						
							|  |  |  | 		out.write_shift(1, 0x02); | 
					
						
							|  |  |  | 		out.write_shift(4, 0); | 
					
						
							|  |  |  | 		out.write_shift(4, 0); | 
					
						
							|  |  |  | 		return out; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-29 09:16:02 +00:00
										 |  |  | 	function parse_RANGE(blob, length, opts) { | 
					
						
							| 
									
										
										
										
											2017-04-04 16:09:41 +00:00
										 |  |  | 		var o = {s:{c:0,r:0},e:{c:0,r:0}}; | 
					
						
							| 
									
										
										
										
											2021-12-29 09:16:02 +00:00
										 |  |  | 		if(length == 8 && opts.qpro) { | 
					
						
							|  |  |  | 			o.s.c = blob.read_shift(1); | 
					
						
							|  |  |  | 			blob.l++; | 
					
						
							|  |  |  | 			o.s.r = blob.read_shift(2); | 
					
						
							|  |  |  | 			o.e.c = blob.read_shift(1); | 
					
						
							|  |  |  | 			blob.l++; | 
					
						
							|  |  |  | 			o.e.r = blob.read_shift(2); | 
					
						
							|  |  |  | 			return o; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-04-04 16:09:41 +00:00
										 |  |  | 		o.s.c = blob.read_shift(2); | 
					
						
							|  |  |  | 		o.s.r = blob.read_shift(2); | 
					
						
							| 
									
										
										
										
											2021-12-29 09:16:02 +00:00
										 |  |  | 		if(length == 12 && opts.qpro) blob.l += 2; | 
					
						
							| 
									
										
										
										
											2017-04-04 16:09:41 +00:00
										 |  |  | 		o.e.c = blob.read_shift(2); | 
					
						
							|  |  |  | 		o.e.r = blob.read_shift(2); | 
					
						
							| 
									
										
										
										
											2021-12-29 09:16:02 +00:00
										 |  |  | 		if(length == 12 && opts.qpro) blob.l += 2; | 
					
						
							| 
									
										
										
										
											2017-04-04 16:09:41 +00:00
										 |  |  | 		if(o.s.c == 0xFFFF) o.s.c = o.e.c = o.s.r = o.e.r = 0; | 
					
						
							|  |  |  | 		return o; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-11-08 04:52:18 +00:00
										 |  |  | 	function write_RANGE(range) { | 
					
						
							|  |  |  | 		var out = new_buf(8); | 
					
						
							|  |  |  | 		out.write_shift(2, range.s.c); | 
					
						
							|  |  |  | 		out.write_shift(2, range.s.r); | 
					
						
							|  |  |  | 		out.write_shift(2, range.e.c); | 
					
						
							|  |  |  | 		out.write_shift(2, range.e.r); | 
					
						
							|  |  |  | 		return out; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-04-04 16:09:41 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	function parse_cell(blob, length, opts) { | 
					
						
							| 
									
										
										
										
											2021-12-29 09:16:02 +00:00
										 |  |  | 		var o = [{c:0,r:0}, {t:'n',v:0}, 0, 0]; | 
					
						
							| 
									
										
										
										
											2017-04-04 16:09:41 +00:00
										 |  |  | 		if(opts.qpro && opts.vers != 0x5120) { | 
					
						
							|  |  |  | 			o[0].c = blob.read_shift(1); | 
					
						
							| 
									
										
										
										
											2021-12-29 09:16:02 +00:00
										 |  |  | 			o[3] = blob.read_shift(1); | 
					
						
							| 
									
										
										
										
											2017-04-04 16:09:41 +00:00
										 |  |  | 			o[0].r = blob.read_shift(2); | 
					
						
							|  |  |  | 			blob.l+=2; | 
					
						
							| 
									
										
										
										
											2022-04-20 17:31:11 +00:00
										 |  |  | 		} else if(opts.works) { // TODO: verify with more complex works3-4 examples
 | 
					
						
							|  |  |  | 			o[0].c = blob.read_shift(2); o[0].r = blob.read_shift(2); | 
					
						
							|  |  |  | 			o[2] = blob.read_shift(2); | 
					
						
							| 
									
										
										
										
											2017-04-04 16:09:41 +00:00
										 |  |  | 		} else { | 
					
						
							|  |  |  | 			o[2] = blob.read_shift(1); | 
					
						
							|  |  |  | 			o[0].c = blob.read_shift(2); o[0].r = blob.read_shift(2); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return o; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-23 09:48:47 +00:00
										 |  |  | 	function get_wk1_fmt(cell)/*:number*/ { | 
					
						
							|  |  |  | 		/* TODO: some fuzzy matching on the number format */ | 
					
						
							|  |  |  | 		if(cell.z && fmt_is_date(cell.z)) { | 
					
						
							|  |  |  | 			return 0xf0 | (LOTUS_DATE_FMTS.indexOf(cell.z) + 1 || 2); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return 0xFF; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-04-04 16:09:41 +00:00
										 |  |  | 	function parse_LABEL(blob, length, opts) { | 
					
						
							|  |  |  | 		var tgt = blob.l + length; | 
					
						
							|  |  |  | 		var o = parse_cell(blob, length, opts); | 
					
						
							|  |  |  | 		o[1].t = 's'; | 
					
						
							| 
									
										
										
										
											2023-06-23 09:48:47 +00:00
										 |  |  | 		if((opts.vers & 0xFFFE) == 0x5120) { // WQ1 / WQ2
 | 
					
						
							| 
									
										
										
										
											2017-04-04 16:09:41 +00:00
										 |  |  | 			blob.l++; | 
					
						
							|  |  |  | 			var len = blob.read_shift(1); | 
					
						
							|  |  |  | 			o[1].v = blob.read_shift(len, 'utf8'); | 
					
						
							|  |  |  | 			return o; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if(opts.qpro) blob.l++; | 
					
						
							|  |  |  | 		o[1].v = blob.read_shift(tgt - blob.l, 'cstr'); | 
					
						
							|  |  |  | 		return o; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-11-08 04:52:18 +00:00
										 |  |  | 	function write_LABEL(R, C, s) { | 
					
						
							|  |  |  | 		/* TODO: encoding */ | 
					
						
							|  |  |  | 		var o = new_buf(7 + s.length); | 
					
						
							|  |  |  | 		o.write_shift(1, 0xFF); | 
					
						
							|  |  |  | 		o.write_shift(2, C); | 
					
						
							|  |  |  | 		o.write_shift(2, R); | 
					
						
							|  |  |  | 		o.write_shift(1, 0x27); // ??
 | 
					
						
							|  |  |  | 		for(var i = 0; i < o.length; ++i) { | 
					
						
							|  |  |  | 			var cc = s.charCodeAt(i); | 
					
						
							|  |  |  | 			o.write_shift(1, cc >= 0x80 ? 0x5F : cc); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		o.write_shift(1, 0); | 
					
						
							|  |  |  | 		return o; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-04-20 17:31:11 +00:00
										 |  |  | 	function parse_STRING(blob, length, opts) { | 
					
						
							|  |  |  | 		var tgt = blob.l + length; | 
					
						
							|  |  |  | 		var o = parse_cell(blob, length, opts); | 
					
						
							|  |  |  | 		o[1].t = 's'; | 
					
						
							|  |  |  | 		if(opts.vers == 0x5120) { | 
					
						
							|  |  |  | 			var len = blob.read_shift(1); | 
					
						
							|  |  |  | 			o[1].v = blob.read_shift(len, 'utf8'); | 
					
						
							|  |  |  | 			return o; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		o[1].v = blob.read_shift(tgt - blob.l, 'cstr'); | 
					
						
							|  |  |  | 		return o; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-04-04 16:09:41 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	function parse_INTEGER(blob, length, opts) { | 
					
						
							|  |  |  | 		var o = parse_cell(blob, length, opts); | 
					
						
							|  |  |  | 		o[1].v = blob.read_shift(2, 'i'); | 
					
						
							|  |  |  | 		return o; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2023-06-23 09:48:47 +00:00
										 |  |  | 	function write_INTEGER(R, C, cell) { | 
					
						
							| 
									
										
										
										
											2021-11-08 04:52:18 +00:00
										 |  |  | 		var o = new_buf(7); | 
					
						
							| 
									
										
										
										
											2023-06-23 09:48:47 +00:00
										 |  |  | 		o.write_shift(1, get_wk1_fmt(cell)); | 
					
						
							| 
									
										
										
										
											2021-11-08 04:52:18 +00:00
										 |  |  | 		o.write_shift(2, C); | 
					
						
							|  |  |  | 		o.write_shift(2, R); | 
					
						
							| 
									
										
										
										
											2023-06-23 09:48:47 +00:00
										 |  |  | 		o.write_shift(2, cell.v, 'i'); | 
					
						
							| 
									
										
										
										
											2021-11-08 04:52:18 +00:00
										 |  |  | 		return o; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-04-04 16:09:41 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	function parse_NUMBER(blob, length, opts) { | 
					
						
							|  |  |  | 		var o = parse_cell(blob, length, opts); | 
					
						
							|  |  |  | 		o[1].v = blob.read_shift(8, 'f'); | 
					
						
							|  |  |  | 		return o; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2023-06-23 09:48:47 +00:00
										 |  |  | 	function write_NUMBER(R, C, cell) { | 
					
						
							| 
									
										
										
										
											2021-11-08 04:52:18 +00:00
										 |  |  | 		var o = new_buf(13); | 
					
						
							| 
									
										
										
										
											2023-06-23 09:48:47 +00:00
										 |  |  | 		o.write_shift(1, get_wk1_fmt(cell)); | 
					
						
							| 
									
										
										
										
											2021-11-08 04:52:18 +00:00
										 |  |  | 		o.write_shift(2, C); | 
					
						
							|  |  |  | 		o.write_shift(2, R); | 
					
						
							| 
									
										
										
										
											2023-06-23 09:48:47 +00:00
										 |  |  | 		o.write_shift(8, cell.v, 'f'); | 
					
						
							| 
									
										
										
										
											2021-11-08 04:52:18 +00:00
										 |  |  | 		return o; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-04-04 16:09:41 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	function parse_FORMULA(blob, length, opts) { | 
					
						
							|  |  |  | 		var tgt = blob.l + length; | 
					
						
							|  |  |  | 		var o = parse_cell(blob, length, opts); | 
					
						
							|  |  |  | 		/* TODO: formula */ | 
					
						
							|  |  |  | 		o[1].v = blob.read_shift(8, 'f'); | 
					
						
							|  |  |  | 		if(opts.qpro) blob.l = tgt; | 
					
						
							|  |  |  | 		else { | 
					
						
							|  |  |  | 			var flen = blob.read_shift(2); | 
					
						
							| 
									
										
										
										
											2021-11-14 04:38:00 +00:00
										 |  |  | 			wk1_fmla_to_csf(blob.slice(blob.l, blob.l + flen), o); | 
					
						
							| 
									
										
										
										
											2017-04-04 16:09:41 +00:00
										 |  |  | 			blob.l += flen; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return o; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-14 04:38:00 +00:00
										 |  |  | 	function wk1_parse_rc(B, V, col) { | 
					
						
							|  |  |  | 		var rel = V & 0x8000; | 
					
						
							|  |  |  | 		V &= ~0x8000; | 
					
						
							|  |  |  | 		V = (rel ? B : 0) + ((V >= 0x2000) ? V - 0x4000 : V); | 
					
						
							|  |  |  | 		return (rel ? "" : "$") + (col ? encode_col(V) : encode_row(V)); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-03-16 03:18:09 +00:00
										 |  |  | 	/* var oprec = [ | 
					
						
							| 
									
										
										
										
											2021-11-14 04:38:00 +00:00
										 |  |  | 		8, 8, 8, 8, 8, 8, 8, 8, 6, 4, 4, 5, 5, 7, 3, 3, | 
					
						
							|  |  |  | 		3, 3, 3, 3, 1, 1, 2, 6, 8, 8, 8, 8, 8, 8, 8, 8 | 
					
						
							| 
									
										
										
										
											2022-03-16 03:18:09 +00:00
										 |  |  | 	]; */ | 
					
						
							| 
									
										
										
										
											2021-11-14 04:38:00 +00:00
										 |  |  | 	/* TODO: flesh out */ | 
					
						
							|  |  |  | 	var FuncTab = { | 
					
						
							| 
									
										
										
										
											2022-05-10 08:02:52 +00:00
										 |  |  | 		0x1F: ["NA", 0], | 
					
						
							|  |  |  | 		// 0x20: ["ERR", 0],
 | 
					
						
							|  |  |  | 		0x21: ["ABS", 1], | 
					
						
							|  |  |  | 		0x22: ["TRUNC", 1], | 
					
						
							|  |  |  | 		0x23: ["SQRT", 1], | 
					
						
							|  |  |  | 		0x24: ["LOG", 1], | 
					
						
							|  |  |  | 		0x25: ["LN", 1], | 
					
						
							|  |  |  | 		0x26: ["PI", 0], | 
					
						
							|  |  |  | 		0x27: ["SIN", 1], | 
					
						
							|  |  |  | 		0x28: ["COS", 1], | 
					
						
							|  |  |  | 		0x29: ["TAN", 1], | 
					
						
							|  |  |  | 		0x2A: ["ATAN2", 2], | 
					
						
							|  |  |  | 		0x2B: ["ATAN", 1], | 
					
						
							|  |  |  | 		0x2C: ["ASIN", 1], | 
					
						
							|  |  |  | 		0x2D: ["ACOS", 1], | 
					
						
							|  |  |  | 		0x2E: ["EXP", 1], | 
					
						
							|  |  |  | 		0x2F: ["MOD", 2], | 
					
						
							|  |  |  | 		// 0x30
 | 
					
						
							|  |  |  | 		0x31: ["ISNA", 1], | 
					
						
							|  |  |  | 		0x32: ["ISERR", 1], | 
					
						
							| 
									
										
										
										
											2021-11-14 04:38:00 +00:00
										 |  |  | 		0x33: ["FALSE", 0], | 
					
						
							|  |  |  | 		0x34: ["TRUE", 0], | 
					
						
							| 
									
										
										
										
											2022-05-10 08:02:52 +00:00
										 |  |  | 		0x35: ["RAND", 0], | 
					
						
							| 
									
										
										
										
											2023-06-23 09:48:47 +00:00
										 |  |  | 		0x36: ["DATE", 3], | 
					
						
							| 
									
										
										
										
											2022-05-10 08:02:52 +00:00
										 |  |  | 		// 0x37 NOW
 | 
					
						
							|  |  |  | 		// 0x38 PMT
 | 
					
						
							|  |  |  | 		// 0x39 PV
 | 
					
						
							|  |  |  | 		// 0x3A FV
 | 
					
						
							|  |  |  | 		// 0x3B IF
 | 
					
						
							|  |  |  | 		// 0x3C DAY
 | 
					
						
							|  |  |  | 		// 0x3D MONTH
 | 
					
						
							|  |  |  | 		// 0x3E YEAR
 | 
					
						
							|  |  |  | 		0x3F: ["ROUND", 2], | 
					
						
							| 
									
										
										
										
											2023-06-23 09:48:47 +00:00
										 |  |  | 		0x40: ["TIME", 3], | 
					
						
							| 
									
										
										
										
											2022-05-10 08:02:52 +00:00
										 |  |  | 		// 0x41 HOUR
 | 
					
						
							|  |  |  | 		// 0x42 MINUTE
 | 
					
						
							|  |  |  | 		// 0x43 SECOND
 | 
					
						
							|  |  |  | 		0x44: ["ISNUMBER", 1], | 
					
						
							|  |  |  | 		0x45: ["ISTEXT", 1], | 
					
						
							| 
									
										
										
										
											2021-11-14 04:38:00 +00:00
										 |  |  | 		0x46: ["LEN", 1], | 
					
						
							| 
									
										
										
										
											2022-05-10 08:02:52 +00:00
										 |  |  | 		0x47: ["VALUE", 1], | 
					
						
							|  |  |  | 		// 0x48: ["FIXED", ?? 1],
 | 
					
						
							|  |  |  | 		0x49: ["MID", 3], | 
					
						
							| 
									
										
										
										
											2022-04-20 17:31:11 +00:00
										 |  |  | 		0x4A: ["CHAR", 1], | 
					
						
							| 
									
										
										
										
											2022-05-10 08:02:52 +00:00
										 |  |  | 		// 0x4B
 | 
					
						
							|  |  |  | 		// 0x4C FIND
 | 
					
						
							|  |  |  | 		// 0x4D DATEVALUE
 | 
					
						
							|  |  |  | 		// 0x4E TIMEVALUE
 | 
					
						
							|  |  |  | 		// 0x4F CELL
 | 
					
						
							| 
									
										
										
										
											2021-11-14 04:38:00 +00:00
										 |  |  | 		0x50: ["SUM", 69], | 
					
						
							|  |  |  | 		0x51: ["AVERAGEA", 69], | 
					
						
							|  |  |  | 		0x52: ["COUNTA", 69], | 
					
						
							|  |  |  | 		0x53: ["MINA", 69], | 
					
						
							|  |  |  | 		0x54: ["MAXA", 69], | 
					
						
							| 
									
										
										
										
											2022-05-10 08:02:52 +00:00
										 |  |  | 		// 0x55 VLOOKUP
 | 
					
						
							|  |  |  | 		// 0x56 NPV
 | 
					
						
							|  |  |  | 		// 0x57 VAR
 | 
					
						
							|  |  |  | 		// 0x58 STD
 | 
					
						
							|  |  |  | 		// 0x59 IRR
 | 
					
						
							|  |  |  | 		// 0x5A HLOOKUP
 | 
					
						
							|  |  |  | 		// 0x5B DSUM
 | 
					
						
							|  |  |  | 		// 0x5C DAVERAGE
 | 
					
						
							|  |  |  | 		// 0x5D DCOUNTA
 | 
					
						
							|  |  |  | 		// 0x5E DMIN
 | 
					
						
							|  |  |  | 		// 0x5F DMAX
 | 
					
						
							|  |  |  | 		// 0x60 DVARP
 | 
					
						
							|  |  |  | 		// 0x61 DSTDEVP
 | 
					
						
							|  |  |  | 		// 0x62 INDEX
 | 
					
						
							|  |  |  | 		// 0x63 COLS
 | 
					
						
							|  |  |  | 		// 0x64 ROWS
 | 
					
						
							|  |  |  | 		// 0x65 REPEAT
 | 
					
						
							|  |  |  | 		0x66: ["UPPER", 1], | 
					
						
							|  |  |  | 		0x67: ["LOWER", 1], | 
					
						
							|  |  |  | 		// 0x68 LEFT
 | 
					
						
							|  |  |  | 		// 0x69 RIGHT
 | 
					
						
							|  |  |  | 		// 0x6A REPLACE
 | 
					
						
							|  |  |  | 		0x6B: ["PROPER", 1], | 
					
						
							|  |  |  | 		// 0x6C CELL
 | 
					
						
							|  |  |  | 		0x6D: ["TRIM", 1], | 
					
						
							|  |  |  | 		// 0x6E CLEAN
 | 
					
						
							| 
									
										
										
										
											2021-11-14 04:38:00 +00:00
										 |  |  | 		0x6F: ["T", 1] | 
					
						
							| 
									
										
										
										
											2022-05-10 08:02:52 +00:00
										 |  |  | 		// 0x70 V
 | 
					
						
							| 
									
										
										
										
											2021-11-14 04:38:00 +00:00
										 |  |  | 	}; | 
					
						
							|  |  |  | 	var BinOpTab = [ | 
					
						
							| 
									
										
										
										
											2022-03-16 03:18:09 +00:00
										 |  |  | 		  "",   "",   "",   "",   "",   "",   "",   "", // eslint-disable-line no-mixed-spaces-and-tabs
 | 
					
						
							|  |  |  | 		  "",  "+",  "-",  "*",  "/",  "^",  "=", "<>", // eslint-disable-line no-mixed-spaces-and-tabs
 | 
					
						
							|  |  |  | 		"<=", ">=",  "<",  ">",   "",   "",   "",   "", // eslint-disable-line no-mixed-spaces-and-tabs
 | 
					
						
							|  |  |  | 		 "&",   "",   "",   "",   "",   "",   "",   ""  // eslint-disable-line no-mixed-spaces-and-tabs
 | 
					
						
							| 
									
										
										
										
											2021-11-14 04:38:00 +00:00
										 |  |  | 	]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	function wk1_fmla_to_csf(blob, o) { | 
					
						
							|  |  |  | 		prep_blob(blob, 0); | 
					
						
							| 
									
										
										
										
											2021-12-29 09:16:02 +00:00
										 |  |  | 		var out = [], argc = 0, R = "", C = "", argL = "", argR = ""; | 
					
						
							| 
									
										
										
										
											2021-11-14 04:38:00 +00:00
										 |  |  | 		while(blob.l < blob.length) { | 
					
						
							|  |  |  | 			var cc = blob[blob.l++]; | 
					
						
							|  |  |  | 			switch(cc) { | 
					
						
							|  |  |  | 				case 0x00: out.push(blob.read_shift(8, 'f')); break; | 
					
						
							|  |  |  | 				case 0x01: { | 
					
						
							|  |  |  | 					C = wk1_parse_rc(o[0].c, blob.read_shift(2), true); | 
					
						
							|  |  |  | 					R = wk1_parse_rc(o[0].r, blob.read_shift(2), false); | 
					
						
							|  |  |  | 					out.push(C + R); | 
					
						
							|  |  |  | 				} break; | 
					
						
							|  |  |  | 				case 0x02: { | 
					
						
							|  |  |  | 					var c = wk1_parse_rc(o[0].c, blob.read_shift(2), true); | 
					
						
							|  |  |  | 					var r = wk1_parse_rc(o[0].r, blob.read_shift(2), false); | 
					
						
							|  |  |  | 					C = wk1_parse_rc(o[0].c, blob.read_shift(2), true); | 
					
						
							|  |  |  | 					R = wk1_parse_rc(o[0].r, blob.read_shift(2), false); | 
					
						
							|  |  |  | 					out.push(c + r + ":" + C + R); | 
					
						
							|  |  |  | 				} break; | 
					
						
							|  |  |  | 				case 0x03: | 
					
						
							|  |  |  | 					if(blob.l < blob.length) { console.error("WK1 premature formula end"); return; } | 
					
						
							|  |  |  | 					break; | 
					
						
							|  |  |  | 				case 0x04: out.push("(" + out.pop() + ")"); break; | 
					
						
							|  |  |  | 				case 0x05: out.push(blob.read_shift(2)); break; | 
					
						
							|  |  |  | 				case 0x06: { | 
					
						
							|  |  |  | 					/* TODO: text encoding */ | 
					
						
							|  |  |  | 					var Z = ""; while((cc = blob[blob.l++])) Z += String.fromCharCode(cc); | 
					
						
							| 
									
										
										
										
											2022-03-11 05:29:05 +00:00
										 |  |  | 					out.push('"' + Z.replace(/"/g, '""') + '"'); | 
					
						
							| 
									
										
										
										
											2021-11-14 04:38:00 +00:00
										 |  |  | 				} break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				case 0x08: out.push("-" + out.pop()); break; | 
					
						
							|  |  |  | 				case 0x17: out.push("+" + out.pop()); break; | 
					
						
							|  |  |  | 				case 0x16: out.push("NOT(" + out.pop() + ")"); break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				case 0x14: case 0x15: { | 
					
						
							| 
									
										
										
										
											2021-12-29 09:16:02 +00:00
										 |  |  | 					argR = out.pop(); argL = out.pop(); | 
					
						
							| 
									
										
										
										
											2021-11-14 04:38:00 +00:00
										 |  |  | 					out.push(["AND", "OR"][cc - 0x14] + "(" + argL + "," + argR + ")"); | 
					
						
							|  |  |  | 				} break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				default: | 
					
						
							|  |  |  | 					if(cc < 0x20 && BinOpTab[cc]) { | 
					
						
							|  |  |  | 						argR = out.pop(); argL = out.pop(); | 
					
						
							|  |  |  | 						out.push(argL + BinOpTab[cc] + argR); | 
					
						
							|  |  |  | 					} else if(FuncTab[cc]) { | 
					
						
							|  |  |  | 						argc = FuncTab[cc][1]; | 
					
						
							|  |  |  | 						if(argc == 69) argc = blob[blob.l++]; | 
					
						
							|  |  |  | 						if(argc > out.length) { console.error("WK1 bad formula parse 0x" + cc.toString(16) + ":|" + out.join("|") + "|"); return; } | 
					
						
							|  |  |  | 						var args = out.slice(-argc); | 
					
						
							|  |  |  | 						out.length -= argc; | 
					
						
							|  |  |  | 						out.push(FuncTab[cc][0] + "(" + args.join(",") + ")"); | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					else if(cc <= 0x07) return console.error("WK1 invalid opcode " + cc.toString(16)); | 
					
						
							|  |  |  | 					else if(cc <= 0x18) return console.error("WK1 unsupported op " + cc.toString(16)); | 
					
						
							|  |  |  | 					else if(cc <= 0x1E) return console.error("WK1 invalid opcode " + cc.toString(16)); | 
					
						
							|  |  |  | 					else if(cc <= 0x73) return console.error("WK1 unsupported function opcode " + cc.toString(16)); | 
					
						
							|  |  |  | 					// possible future functions ??
 | 
					
						
							|  |  |  | 					else return console.error("WK1 unrecognized opcode " + cc.toString(16)); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if(out.length == 1) o[1].f = "" + out[0]; | 
					
						
							|  |  |  | 		else console.error("WK1 bad formula parse |" + out.join("|") + "|"); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-23 09:07:51 +00:00
										 |  |  | 	function parse_cell_3(blob/*::, length*/) { | 
					
						
							| 
									
										
										
										
											2017-04-04 16:09:41 +00:00
										 |  |  | 		var o = [{c:0,r:0}, {t:'n',v:0}, 0]; | 
					
						
							|  |  |  | 		o[0].r = blob.read_shift(2); o[3] = blob[blob.l++]; o[0].c = blob[blob.l++]; | 
					
						
							|  |  |  | 		return o; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	function parse_LABEL_16(blob, length) { | 
					
						
							|  |  |  | 		var o = parse_cell_3(blob, length); | 
					
						
							|  |  |  | 		o[1].t = 's'; | 
					
						
							|  |  |  | 		o[1].v = blob.read_shift(length - 4, 'cstr'); | 
					
						
							|  |  |  | 		return o; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-11-14 04:38:00 +00:00
										 |  |  | 	function write_LABEL_16(R, C, wsidx, s) { | 
					
						
							|  |  |  | 		/* TODO: encoding */ | 
					
						
							|  |  |  | 		var o = new_buf(6 + s.length); | 
					
						
							|  |  |  | 		o.write_shift(2, R); | 
					
						
							|  |  |  | 		o.write_shift(1, wsidx); | 
					
						
							|  |  |  | 		o.write_shift(1, C); | 
					
						
							|  |  |  | 		o.write_shift(1, 0x27); | 
					
						
							|  |  |  | 		for(var i = 0; i < s.length; ++i) { | 
					
						
							|  |  |  | 			var cc = s.charCodeAt(i); | 
					
						
							|  |  |  | 			o.write_shift(1, cc >= 0x80 ? 0x5F : cc); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		o.write_shift(1, 0); | 
					
						
							|  |  |  | 		return o; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-04-04 16:09:41 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	function parse_NUMBER_18(blob, length) { | 
					
						
							|  |  |  | 		var o = parse_cell_3(blob, length); | 
					
						
							|  |  |  | 		o[1].v = blob.read_shift(2); | 
					
						
							|  |  |  | 		var v = o[1].v >> 1; | 
					
						
							|  |  |  | 		if(o[1].v & 0x1) { | 
					
						
							|  |  |  | 			switch(v & 0x07) { | 
					
						
							| 
									
										
										
										
											2021-11-08 04:52:18 +00:00
										 |  |  | 				case 0: v = (v >> 3) * 5000; break; | 
					
						
							| 
									
										
										
										
											2017-04-04 16:09:41 +00:00
										 |  |  | 				case 1: v = (v >> 3) * 500; break; | 
					
						
							|  |  |  | 				case 2: v = (v >> 3) / 20; break; | 
					
						
							| 
									
										
										
										
											2021-11-08 04:52:18 +00:00
										 |  |  | 				case 3: v = (v >> 3) / 200; break; | 
					
						
							| 
									
										
										
										
											2017-04-04 16:09:41 +00:00
										 |  |  | 				case 4: v = (v >> 3) / 2000; break; | 
					
						
							| 
									
										
										
										
											2021-11-08 04:52:18 +00:00
										 |  |  | 				case 5: v = (v >> 3) / 20000; break; | 
					
						
							| 
									
										
										
										
											2017-04-04 16:09:41 +00:00
										 |  |  | 				case 6: v = (v >> 3) / 16; break; | 
					
						
							|  |  |  | 				case 7: v = (v >> 3) / 64; break; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		o[1].v = v; | 
					
						
							|  |  |  | 		return o; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	function parse_NUMBER_17(blob, length) { | 
					
						
							|  |  |  | 		var o = parse_cell_3(blob, length); | 
					
						
							|  |  |  | 		var v1 = blob.read_shift(4); | 
					
						
							|  |  |  | 		var v2 = blob.read_shift(4); | 
					
						
							|  |  |  | 		var e = blob.read_shift(2); | 
					
						
							| 
									
										
										
										
											2021-11-08 04:52:18 +00:00
										 |  |  | 		if(e == 0xFFFF) { | 
					
						
							|  |  |  | 			if(v1 === 0 && v2 === 0xC0000000) { o[1].t = "e"; o[1].v = 0x0F; } // ERR -> #VALUE!
 | 
					
						
							|  |  |  | 			else if(v1 === 0 && v2 === 0xD0000000) { o[1].t = "e"; o[1].v = 0x2A; } // NA -> #N/A
 | 
					
						
							|  |  |  | 			else o[1].v = 0; | 
					
						
							|  |  |  | 			return o; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-04-04 16:09:41 +00:00
										 |  |  | 		var s = e & 0x8000; e = (e&0x7FFF) - 16446; | 
					
						
							| 
									
										
										
										
											2021-11-14 04:38:00 +00:00
										 |  |  | 		o[1].v = (1 - s*2) * (v2 * Math.pow(2, e+32) + v1 * Math.pow(2, e)); | 
					
						
							|  |  |  | 		return o; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	function write_NUMBER_17(R, C, wsidx, v) { | 
					
						
							|  |  |  | 		var o = new_buf(14); | 
					
						
							|  |  |  | 		o.write_shift(2, R); | 
					
						
							|  |  |  | 		o.write_shift(1, wsidx); | 
					
						
							|  |  |  | 		o.write_shift(1, C); | 
					
						
							|  |  |  | 		if(v == 0) { | 
					
						
							|  |  |  | 			o.write_shift(4, 0); | 
					
						
							|  |  |  | 			o.write_shift(4, 0); | 
					
						
							|  |  |  | 			o.write_shift(2, 0xFFFF); | 
					
						
							|  |  |  | 			return o; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		var s = 0, e = 0, v1 = 0, v2 = 0; | 
					
						
							|  |  |  | 		if(v < 0) { s = 1; v = -v; } | 
					
						
							|  |  |  | 		e = Math.log2(v) | 0; | 
					
						
							|  |  |  | 		v /= Math.pow(2, e-31); | 
					
						
							|  |  |  | 		v2 = (v)>>>0; | 
					
						
							|  |  |  | 		if((v2&0x80000000) == 0) { v/=2; ++e; v2 = v >>> 0; } | 
					
						
							|  |  |  | 		v -= v2; | 
					
						
							|  |  |  | 		v2 |= 0x80000000; | 
					
						
							|  |  |  | 		v2 >>>= 0; | 
					
						
							|  |  |  | 		v *= Math.pow(2, 32); | 
					
						
							|  |  |  | 		v1 = v>>>0; | 
					
						
							|  |  |  | 		o.write_shift(4, v1); | 
					
						
							|  |  |  | 		o.write_shift(4, v2); | 
					
						
							|  |  |  | 		e += 0x3FFF + (s ? 0x8000 : 0); | 
					
						
							|  |  |  | 		o.write_shift(2, e); | 
					
						
							| 
									
										
										
										
											2017-04-04 16:09:41 +00:00
										 |  |  | 		return o; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	function parse_FORMULA_19(blob, length) { | 
					
						
							|  |  |  | 		var o = parse_NUMBER_17(blob, 14); | 
					
						
							| 
									
										
										
										
											2021-11-14 04:38:00 +00:00
										 |  |  | 		blob.l += length - 14; /* TODO: WK3 formula */ | 
					
						
							| 
									
										
										
										
											2017-04-04 16:09:41 +00:00
										 |  |  | 		return o; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	function parse_NUMBER_25(blob, length) { | 
					
						
							|  |  |  | 		var o = parse_cell_3(blob, length); | 
					
						
							|  |  |  | 		var v1 = blob.read_shift(4); | 
					
						
							|  |  |  | 		o[1].v = v1 >> 6; | 
					
						
							|  |  |  | 		return o; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	function parse_NUMBER_27(blob, length) { | 
					
						
							|  |  |  | 		var o = parse_cell_3(blob, length); | 
					
						
							|  |  |  | 		var v1 = blob.read_shift(8,'f'); | 
					
						
							|  |  |  | 		o[1].v = v1; | 
					
						
							|  |  |  | 		return o; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	function parse_FORMULA_28(blob, length) { | 
					
						
							| 
									
										
										
										
											2022-04-20 17:31:11 +00:00
										 |  |  | 		var o = parse_NUMBER_27(blob, 12); | 
					
						
							|  |  |  | 		blob.l += length - 12; /* TODO: formula */ | 
					
						
							| 
									
										
										
										
											2017-04-04 16:09:41 +00:00
										 |  |  | 		return o; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-29 09:16:02 +00:00
										 |  |  | 	function parse_SHEETNAMECS(blob, length) { | 
					
						
							|  |  |  | 		return blob[blob.l + length - 1] == 0 ? blob.read_shift(length, 'cstr') : ""; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	function parse_SHEETNAMELP(blob, length) { | 
					
						
							|  |  |  | 		var len = blob[blob.l++]; | 
					
						
							|  |  |  | 		if(len > length - 1) len = length - 1; | 
					
						
							|  |  |  | 		var o = ""; while(o.length < len) o += String.fromCharCode(blob[blob.l++]); | 
					
						
							|  |  |  | 		return o; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	function parse_SHEETINFOQP(blob, length, opts) { | 
					
						
							|  |  |  | 		if(!opts.qpro || length < 21) return; | 
					
						
							|  |  |  | 		var id = blob.read_shift(1); | 
					
						
							|  |  |  | 		blob.l += 17; | 
					
						
							| 
									
										
										
										
											2022-03-16 03:18:09 +00:00
										 |  |  | 		blob.l += 1; //var len = blob.read_shift(1);
 | 
					
						
							| 
									
										
										
										
											2021-12-29 09:16:02 +00:00
										 |  |  | 		blob.l += 2; | 
					
						
							|  |  |  | 		var nm = blob.read_shift(length - 21, 'cstr'); | 
					
						
							|  |  |  | 		return [id, nm]; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-14 04:38:00 +00:00
										 |  |  | 	function parse_XFORMAT(blob, length) { | 
					
						
							|  |  |  | 		var o = {}, tgt = blob.l + length; | 
					
						
							|  |  |  | 		while(blob.l < tgt) { | 
					
						
							|  |  |  | 			var dt = blob.read_shift(2); | 
					
						
							|  |  |  | 			if(dt == 0x36b0) { | 
					
						
							|  |  |  | 				o[dt] = [0, ""]; | 
					
						
							|  |  |  | 				o[dt][0] = blob.read_shift(2); | 
					
						
							|  |  |  | 				while(blob[blob.l]) { o[dt][1] += String.fromCharCode(blob[blob.l]); blob.l++; } blob.l++; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			// TODO: 0x3a99 ??
 | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return o; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	function write_XFORMAT_SHEETNAME(name, wsidx) { | 
					
						
							|  |  |  | 		var out = new_buf(5 + name.length); | 
					
						
							|  |  |  | 		out.write_shift(2, 0x36b0); | 
					
						
							|  |  |  | 		out.write_shift(2, wsidx); | 
					
						
							|  |  |  | 		for(var i = 0; i < name.length; ++i) { | 
					
						
							|  |  |  | 			var cc = name.charCodeAt(i); | 
					
						
							|  |  |  | 			out[out.l++] = cc > 0x7F ? 0x5F : cc; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		out[out.l++] = 0; | 
					
						
							|  |  |  | 		return out; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-04 16:09:41 +00:00
										 |  |  | 	var WK1Enum = { | 
					
						
							|  |  |  | 		/*::[*/0x0000/*::]*/: { n:"BOF", f:parseuint16 }, | 
					
						
							| 
									
										
										
										
											2017-11-20 01:51:14 +00:00
										 |  |  | 		/*::[*/0x0001/*::]*/: { n:"EOF" }, | 
					
						
							|  |  |  | 		/*::[*/0x0002/*::]*/: { n:"CALCMODE" }, | 
					
						
							|  |  |  | 		/*::[*/0x0003/*::]*/: { n:"CALCORDER" }, | 
					
						
							|  |  |  | 		/*::[*/0x0004/*::]*/: { n:"SPLIT" }, | 
					
						
							|  |  |  | 		/*::[*/0x0005/*::]*/: { n:"SYNC" }, | 
					
						
							| 
									
										
										
										
											2017-04-04 16:09:41 +00:00
										 |  |  | 		/*::[*/0x0006/*::]*/: { n:"RANGE", f:parse_RANGE }, | 
					
						
							| 
									
										
										
										
											2017-11-20 01:51:14 +00:00
										 |  |  | 		/*::[*/0x0007/*::]*/: { n:"WINDOW1" }, | 
					
						
							|  |  |  | 		/*::[*/0x0008/*::]*/: { n:"COLW1" }, | 
					
						
							|  |  |  | 		/*::[*/0x0009/*::]*/: { n:"WINTWO" }, | 
					
						
							|  |  |  | 		/*::[*/0x000A/*::]*/: { n:"COLW2" }, | 
					
						
							|  |  |  | 		/*::[*/0x000B/*::]*/: { n:"NAME" }, | 
					
						
							|  |  |  | 		/*::[*/0x000C/*::]*/: { n:"BLANK" }, | 
					
						
							| 
									
										
										
										
											2017-04-04 16:09:41 +00:00
										 |  |  | 		/*::[*/0x000D/*::]*/: { n:"INTEGER", f:parse_INTEGER }, | 
					
						
							|  |  |  | 		/*::[*/0x000E/*::]*/: { n:"NUMBER", f:parse_NUMBER }, | 
					
						
							|  |  |  | 		/*::[*/0x000F/*::]*/: { n:"LABEL", f:parse_LABEL }, | 
					
						
							|  |  |  | 		/*::[*/0x0010/*::]*/: { n:"FORMULA", f:parse_FORMULA }, | 
					
						
							| 
									
										
										
										
											2017-11-20 01:51:14 +00:00
										 |  |  | 		/*::[*/0x0018/*::]*/: { n:"TABLE" }, | 
					
						
							|  |  |  | 		/*::[*/0x0019/*::]*/: { n:"ORANGE" }, | 
					
						
							|  |  |  | 		/*::[*/0x001A/*::]*/: { n:"PRANGE" }, | 
					
						
							|  |  |  | 		/*::[*/0x001B/*::]*/: { n:"SRANGE" }, | 
					
						
							|  |  |  | 		/*::[*/0x001C/*::]*/: { n:"FRANGE" }, | 
					
						
							|  |  |  | 		/*::[*/0x001D/*::]*/: { n:"KRANGE1" }, | 
					
						
							|  |  |  | 		/*::[*/0x0020/*::]*/: { n:"HRANGE" }, | 
					
						
							|  |  |  | 		/*::[*/0x0023/*::]*/: { n:"KRANGE2" }, | 
					
						
							|  |  |  | 		/*::[*/0x0024/*::]*/: { n:"PROTEC" }, | 
					
						
							|  |  |  | 		/*::[*/0x0025/*::]*/: { n:"FOOTER" }, | 
					
						
							|  |  |  | 		/*::[*/0x0026/*::]*/: { n:"HEADER" }, | 
					
						
							|  |  |  | 		/*::[*/0x0027/*::]*/: { n:"SETUP" }, | 
					
						
							|  |  |  | 		/*::[*/0x0028/*::]*/: { n:"MARGINS" }, | 
					
						
							|  |  |  | 		/*::[*/0x0029/*::]*/: { n:"LABELFMT" }, | 
					
						
							|  |  |  | 		/*::[*/0x002A/*::]*/: { n:"TITLES" }, | 
					
						
							|  |  |  | 		/*::[*/0x002B/*::]*/: { n:"SHEETJS" }, | 
					
						
							|  |  |  | 		/*::[*/0x002D/*::]*/: { n:"GRAPH" }, | 
					
						
							|  |  |  | 		/*::[*/0x002E/*::]*/: { n:"NGRAPH" }, | 
					
						
							|  |  |  | 		/*::[*/0x002F/*::]*/: { n:"CALCCOUNT" }, | 
					
						
							|  |  |  | 		/*::[*/0x0030/*::]*/: { n:"UNFORMATTED" }, | 
					
						
							|  |  |  | 		/*::[*/0x0031/*::]*/: { n:"CURSORW12" }, | 
					
						
							|  |  |  | 		/*::[*/0x0032/*::]*/: { n:"WINDOW" }, | 
					
						
							| 
									
										
										
										
											2022-04-20 17:31:11 +00:00
										 |  |  | 		/*::[*/0x0033/*::]*/: { n:"STRING", f:parse_STRING }, | 
					
						
							| 
									
										
										
										
											2017-11-20 01:51:14 +00:00
										 |  |  | 		/*::[*/0x0037/*::]*/: { n:"PASSWORD" }, | 
					
						
							|  |  |  | 		/*::[*/0x0038/*::]*/: { n:"LOCKED" }, | 
					
						
							|  |  |  | 		/*::[*/0x003C/*::]*/: { n:"QUERY" }, | 
					
						
							|  |  |  | 		/*::[*/0x003D/*::]*/: { n:"QUERYNAME" }, | 
					
						
							|  |  |  | 		/*::[*/0x003E/*::]*/: { n:"PRINT" }, | 
					
						
							|  |  |  | 		/*::[*/0x003F/*::]*/: { n:"PRINTNAME" }, | 
					
						
							|  |  |  | 		/*::[*/0x0040/*::]*/: { n:"GRAPH2" }, | 
					
						
							|  |  |  | 		/*::[*/0x0041/*::]*/: { n:"GRAPHNAME" }, | 
					
						
							|  |  |  | 		/*::[*/0x0042/*::]*/: { n:"ZOOM" }, | 
					
						
							|  |  |  | 		/*::[*/0x0043/*::]*/: { n:"SYMSPLIT" }, | 
					
						
							|  |  |  | 		/*::[*/0x0044/*::]*/: { n:"NSROWS" }, | 
					
						
							|  |  |  | 		/*::[*/0x0045/*::]*/: { n:"NSCOLS" }, | 
					
						
							|  |  |  | 		/*::[*/0x0046/*::]*/: { n:"RULER" }, | 
					
						
							|  |  |  | 		/*::[*/0x0047/*::]*/: { n:"NNAME" }, | 
					
						
							|  |  |  | 		/*::[*/0x0048/*::]*/: { n:"ACOMM" }, | 
					
						
							|  |  |  | 		/*::[*/0x0049/*::]*/: { n:"AMACRO" }, | 
					
						
							|  |  |  | 		/*::[*/0x004A/*::]*/: { n:"PARSE" }, | 
					
						
							| 
									
										
										
										
											2023-06-23 09:48:47 +00:00
										 |  |  | 		// 0x0064
 | 
					
						
							| 
									
										
										
										
											2021-11-08 04:52:18 +00:00
										 |  |  | 		/*::[*/0x0066/*::]*/: { n:"PRANGES??" }, | 
					
						
							|  |  |  | 		/*::[*/0x0067/*::]*/: { n:"RRANGES??" }, | 
					
						
							|  |  |  | 		/*::[*/0x0068/*::]*/: { n:"FNAME??" }, | 
					
						
							|  |  |  | 		/*::[*/0x0069/*::]*/: { n:"MRANGES??" }, | 
					
						
							| 
									
										
										
										
											2023-06-23 09:48:47 +00:00
										 |  |  | 		// 0x0096
 | 
					
						
							|  |  |  | 		// 0x0099
 | 
					
						
							|  |  |  | 		// 0x009A
 | 
					
						
							|  |  |  | 		// 0x009B
 | 
					
						
							|  |  |  | 		// 0x009C
 | 
					
						
							|  |  |  | 		// 0x00C0
 | 
					
						
							|  |  |  | 		// 0x00C7
 | 
					
						
							|  |  |  | 		// 0x00C9
 | 
					
						
							| 
									
										
										
										
											2021-12-29 09:16:02 +00:00
										 |  |  | 		/*::[*/0x00CC/*::]*/: { n:"SHEETNAMECS", f:parse_SHEETNAMECS }, | 
					
						
							| 
									
										
										
										
											2023-06-23 09:48:47 +00:00
										 |  |  | 		// 0x00CD
 | 
					
						
							| 
									
										
										
										
											2021-12-29 09:16:02 +00:00
										 |  |  | 		/*::[*/0x00DE/*::]*/: { n:"SHEETNAMELP", f:parse_SHEETNAMELP }, | 
					
						
							| 
									
										
										
										
											2022-04-20 17:31:11 +00:00
										 |  |  | 		/*::[*/0x00FF/*::]*/: { n:"BOF", f:parseuint16 }, | 
					
						
							| 
									
										
										
										
											2023-06-23 09:48:47 +00:00
										 |  |  | 		/*::[*/0x5402/*::]*/: { n:"WKSNF", f:parseuint16 }, | 
					
						
							| 
									
										
										
										
											2021-11-08 04:52:18 +00:00
										 |  |  | 		/*::[*/0xFFFF/*::]*/: { n:"" } | 
					
						
							| 
									
										
										
										
											2017-04-04 16:09:41 +00:00
										 |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	var WK3Enum = { | 
					
						
							| 
									
										
										
										
											2017-11-20 01:51:14 +00:00
										 |  |  | 		/*::[*/0x0000/*::]*/: { n:"BOF" }, | 
					
						
							|  |  |  | 		/*::[*/0x0001/*::]*/: { n:"EOF" }, | 
					
						
							| 
									
										
										
										
											2021-11-08 04:52:18 +00:00
										 |  |  | 		/*::[*/0x0002/*::]*/: { n:"PASSWORD" }, | 
					
						
							|  |  |  | 		/*::[*/0x0003/*::]*/: { n:"CALCSET" }, | 
					
						
							|  |  |  | 		/*::[*/0x0004/*::]*/: { n:"WINDOWSET" }, | 
					
						
							|  |  |  | 		/*::[*/0x0005/*::]*/: { n:"SHEETCELLPTR" }, | 
					
						
							|  |  |  | 		/*::[*/0x0006/*::]*/: { n:"SHEETLAYOUT" }, | 
					
						
							|  |  |  | 		/*::[*/0x0007/*::]*/: { n:"COLUMNWIDTH" }, | 
					
						
							|  |  |  | 		/*::[*/0x0008/*::]*/: { n:"HIDDENCOLUMN" }, | 
					
						
							|  |  |  | 		/*::[*/0x0009/*::]*/: { n:"USERRANGE" }, | 
					
						
							|  |  |  | 		/*::[*/0x000A/*::]*/: { n:"SYSTEMRANGE" }, | 
					
						
							|  |  |  | 		/*::[*/0x000B/*::]*/: { n:"ZEROFORCE" }, | 
					
						
							|  |  |  | 		/*::[*/0x000C/*::]*/: { n:"SORTKEYDIR" }, | 
					
						
							|  |  |  | 		/*::[*/0x000D/*::]*/: { n:"FILESEAL" }, | 
					
						
							|  |  |  | 		/*::[*/0x000E/*::]*/: { n:"DATAFILLNUMS" }, | 
					
						
							|  |  |  | 		/*::[*/0x000F/*::]*/: { n:"PRINTMAIN" }, | 
					
						
							|  |  |  | 		/*::[*/0x0010/*::]*/: { n:"PRINTSTRING" }, | 
					
						
							|  |  |  | 		/*::[*/0x0011/*::]*/: { n:"GRAPHMAIN" }, | 
					
						
							|  |  |  | 		/*::[*/0x0012/*::]*/: { n:"GRAPHSTRING" }, | 
					
						
							| 
									
										
										
										
											2017-11-20 01:51:14 +00:00
										 |  |  | 		/*::[*/0x0013/*::]*/: { n:"??" }, | 
					
						
							| 
									
										
										
										
											2021-11-08 04:52:18 +00:00
										 |  |  | 		/*::[*/0x0014/*::]*/: { n:"ERRCELL" }, | 
					
						
							|  |  |  | 		/*::[*/0x0015/*::]*/: { n:"NACELL" }, | 
					
						
							| 
									
										
										
										
											2017-04-04 16:09:41 +00:00
										 |  |  | 		/*::[*/0x0016/*::]*/: { n:"LABEL16", f:parse_LABEL_16}, | 
					
						
							|  |  |  | 		/*::[*/0x0017/*::]*/: { n:"NUMBER17", f:parse_NUMBER_17 }, | 
					
						
							|  |  |  | 		/*::[*/0x0018/*::]*/: { n:"NUMBER18", f:parse_NUMBER_18 }, | 
					
						
							|  |  |  | 		/*::[*/0x0019/*::]*/: { n:"FORMULA19", f:parse_FORMULA_19}, | 
					
						
							| 
									
										
										
										
											2021-11-08 04:52:18 +00:00
										 |  |  | 		/*::[*/0x001A/*::]*/: { n:"FORMULA1A" }, | 
					
						
							| 
									
										
										
										
											2021-11-14 04:38:00 +00:00
										 |  |  | 		/*::[*/0x001B/*::]*/: { n:"XFORMAT", f:parse_XFORMAT }, | 
					
						
							| 
									
										
										
										
											2021-11-08 04:52:18 +00:00
										 |  |  | 		/*::[*/0x001C/*::]*/: { n:"DTLABELMISC" }, | 
					
						
							|  |  |  | 		/*::[*/0x001D/*::]*/: { n:"DTLABELCELL" }, | 
					
						
							|  |  |  | 		/*::[*/0x001E/*::]*/: { n:"GRAPHWINDOW" }, | 
					
						
							|  |  |  | 		/*::[*/0x001F/*::]*/: { n:"CPA" }, | 
					
						
							|  |  |  | 		/*::[*/0x0020/*::]*/: { n:"LPLAUTO" }, | 
					
						
							|  |  |  | 		/*::[*/0x0021/*::]*/: { n:"QUERY" }, | 
					
						
							|  |  |  | 		/*::[*/0x0022/*::]*/: { n:"HIDDENSHEET" }, | 
					
						
							|  |  |  | 		/*::[*/0x0023/*::]*/: { n:"??" }, | 
					
						
							| 
									
										
										
										
											2017-04-04 16:09:41 +00:00
										 |  |  | 		/*::[*/0x0025/*::]*/: { n:"NUMBER25", f:parse_NUMBER_25 }, | 
					
						
							| 
									
										
										
										
											2021-11-08 04:52:18 +00:00
										 |  |  | 		/*::[*/0x0026/*::]*/: { n:"??" }, | 
					
						
							| 
									
										
										
										
											2017-04-04 16:09:41 +00:00
										 |  |  | 		/*::[*/0x0027/*::]*/: { n:"NUMBER27", f:parse_NUMBER_27 }, | 
					
						
							|  |  |  | 		/*::[*/0x0028/*::]*/: { n:"FORMULA28", f:parse_FORMULA_28 }, | 
					
						
							| 
									
										
										
										
											2021-11-08 04:52:18 +00:00
										 |  |  | 		/*::[*/0x008E/*::]*/: { n:"??" }, | 
					
						
							|  |  |  | 		/*::[*/0x0093/*::]*/: { n:"??" }, | 
					
						
							|  |  |  | 		/*::[*/0x0096/*::]*/: { n:"??" }, | 
					
						
							|  |  |  | 		/*::[*/0x0097/*::]*/: { n:"??" }, | 
					
						
							|  |  |  | 		/*::[*/0x0098/*::]*/: { n:"??" }, | 
					
						
							|  |  |  | 		/*::[*/0x0099/*::]*/: { n:"??" }, | 
					
						
							|  |  |  | 		/*::[*/0x009A/*::]*/: { n:"??" }, | 
					
						
							|  |  |  | 		/*::[*/0x009B/*::]*/: { n:"??" }, | 
					
						
							|  |  |  | 		/*::[*/0x009C/*::]*/: { n:"??" }, | 
					
						
							|  |  |  | 		/*::[*/0x00A3/*::]*/: { n:"??" }, | 
					
						
							|  |  |  | 		/*::[*/0x00AE/*::]*/: { n:"??" }, | 
					
						
							|  |  |  | 		/*::[*/0x00AF/*::]*/: { n:"??" }, | 
					
						
							|  |  |  | 		/*::[*/0x00B0/*::]*/: { n:"??" }, | 
					
						
							|  |  |  | 		/*::[*/0x00B1/*::]*/: { n:"??" }, | 
					
						
							|  |  |  | 		/*::[*/0x00B8/*::]*/: { n:"??" }, | 
					
						
							|  |  |  | 		/*::[*/0x00B9/*::]*/: { n:"??" }, | 
					
						
							|  |  |  | 		/*::[*/0x00BA/*::]*/: { n:"??" }, | 
					
						
							|  |  |  | 		/*::[*/0x00BB/*::]*/: { n:"??" }, | 
					
						
							|  |  |  | 		/*::[*/0x00BC/*::]*/: { n:"??" }, | 
					
						
							|  |  |  | 		/*::[*/0x00C3/*::]*/: { n:"??" }, | 
					
						
							|  |  |  | 		/*::[*/0x00C9/*::]*/: { n:"??" }, | 
					
						
							| 
									
										
										
										
											2021-12-29 09:16:02 +00:00
										 |  |  | 		/*::[*/0x00CC/*::]*/: { n:"SHEETNAMECS", f:parse_SHEETNAMECS }, | 
					
						
							| 
									
										
										
										
											2021-11-08 04:52:18 +00:00
										 |  |  | 		/*::[*/0x00CD/*::]*/: { n:"??" }, | 
					
						
							|  |  |  | 		/*::[*/0x00CE/*::]*/: { n:"??" }, | 
					
						
							|  |  |  | 		/*::[*/0x00CF/*::]*/: { n:"??" }, | 
					
						
							|  |  |  | 		/*::[*/0x00D0/*::]*/: { n:"??" }, | 
					
						
							|  |  |  | 		/*::[*/0x0100/*::]*/: { n:"??" }, | 
					
						
							|  |  |  | 		/*::[*/0x0103/*::]*/: { n:"??" }, | 
					
						
							|  |  |  | 		/*::[*/0x0104/*::]*/: { n:"??" }, | 
					
						
							|  |  |  | 		/*::[*/0x0105/*::]*/: { n:"??" }, | 
					
						
							|  |  |  | 		/*::[*/0x0106/*::]*/: { n:"??" }, | 
					
						
							|  |  |  | 		/*::[*/0x0107/*::]*/: { n:"??" }, | 
					
						
							|  |  |  | 		/*::[*/0x0109/*::]*/: { n:"??" }, | 
					
						
							|  |  |  | 		/*::[*/0x010A/*::]*/: { n:"??" }, | 
					
						
							|  |  |  | 		/*::[*/0x010B/*::]*/: { n:"??" }, | 
					
						
							|  |  |  | 		/*::[*/0x010C/*::]*/: { n:"??" }, | 
					
						
							|  |  |  | 		/*::[*/0x010E/*::]*/: { n:"??" }, | 
					
						
							|  |  |  | 		/*::[*/0x010F/*::]*/: { n:"??" }, | 
					
						
							|  |  |  | 		/*::[*/0x0180/*::]*/: { n:"??" }, | 
					
						
							|  |  |  | 		/*::[*/0x0185/*::]*/: { n:"??" }, | 
					
						
							|  |  |  | 		/*::[*/0x0186/*::]*/: { n:"??" }, | 
					
						
							|  |  |  | 		/*::[*/0x0189/*::]*/: { n:"??" }, | 
					
						
							|  |  |  | 		/*::[*/0x018C/*::]*/: { n:"??" }, | 
					
						
							|  |  |  | 		/*::[*/0x0200/*::]*/: { n:"??" }, | 
					
						
							|  |  |  | 		/*::[*/0x0202/*::]*/: { n:"??" }, | 
					
						
							|  |  |  | 		/*::[*/0x0201/*::]*/: { n:"??" }, | 
					
						
							|  |  |  | 		/*::[*/0x0204/*::]*/: { n:"??" }, | 
					
						
							|  |  |  | 		/*::[*/0x0205/*::]*/: { n:"??" }, | 
					
						
							|  |  |  | 		/*::[*/0x0280/*::]*/: { n:"??" }, | 
					
						
							|  |  |  | 		/*::[*/0x0281/*::]*/: { n:"??" }, | 
					
						
							|  |  |  | 		/*::[*/0x0282/*::]*/: { n:"??" }, | 
					
						
							|  |  |  | 		/*::[*/0x0283/*::]*/: { n:"??" }, | 
					
						
							|  |  |  | 		/*::[*/0x0284/*::]*/: { n:"??" }, | 
					
						
							|  |  |  | 		/*::[*/0x0285/*::]*/: { n:"??" }, | 
					
						
							|  |  |  | 		/*::[*/0x0286/*::]*/: { n:"??" }, | 
					
						
							|  |  |  | 		/*::[*/0x0287/*::]*/: { n:"??" }, | 
					
						
							|  |  |  | 		/*::[*/0x0288/*::]*/: { n:"??" }, | 
					
						
							|  |  |  | 		/*::[*/0x0292/*::]*/: { n:"??" }, | 
					
						
							|  |  |  | 		/*::[*/0x0293/*::]*/: { n:"??" }, | 
					
						
							|  |  |  | 		/*::[*/0x0294/*::]*/: { n:"??" }, | 
					
						
							|  |  |  | 		/*::[*/0x0295/*::]*/: { n:"??" }, | 
					
						
							|  |  |  | 		/*::[*/0x0296/*::]*/: { n:"??" }, | 
					
						
							|  |  |  | 		/*::[*/0x0299/*::]*/: { n:"??" }, | 
					
						
							|  |  |  | 		/*::[*/0x029A/*::]*/: { n:"??" }, | 
					
						
							|  |  |  | 		/*::[*/0x0300/*::]*/: { n:"??" }, | 
					
						
							|  |  |  | 		/*::[*/0x0304/*::]*/: { n:"??" }, | 
					
						
							| 
									
										
										
										
											2021-12-29 09:16:02 +00:00
										 |  |  | 		/*::[*/0x0601/*::]*/: { n:"SHEETINFOQP", f:parse_SHEETINFOQP }, | 
					
						
							| 
									
										
										
										
											2021-11-08 04:52:18 +00:00
										 |  |  | 		/*::[*/0x0640/*::]*/: { n:"??" }, | 
					
						
							|  |  |  | 		/*::[*/0x0642/*::]*/: { n:"??" }, | 
					
						
							|  |  |  | 		/*::[*/0x0701/*::]*/: { n:"??" }, | 
					
						
							|  |  |  | 		/*::[*/0x0702/*::]*/: { n:"??" }, | 
					
						
							|  |  |  | 		/*::[*/0x0703/*::]*/: { n:"??" }, | 
					
						
							|  |  |  | 		/*::[*/0x0704/*::]*/: { n:"??" }, | 
					
						
							|  |  |  | 		/*::[*/0x0780/*::]*/: { n:"??" }, | 
					
						
							|  |  |  | 		/*::[*/0x0800/*::]*/: { n:"??" }, | 
					
						
							|  |  |  | 		/*::[*/0x0801/*::]*/: { n:"??" }, | 
					
						
							|  |  |  | 		/*::[*/0x0804/*::]*/: { n:"??" }, | 
					
						
							|  |  |  | 		/*::[*/0x0A80/*::]*/: { n:"??" }, | 
					
						
							|  |  |  | 		/*::[*/0x2AF6/*::]*/: { n:"??" }, | 
					
						
							|  |  |  | 		/*::[*/0x3231/*::]*/: { n:"??" }, | 
					
						
							|  |  |  | 		/*::[*/0x6E49/*::]*/: { n:"??" }, | 
					
						
							|  |  |  | 		/*::[*/0x6F44/*::]*/: { n:"??" }, | 
					
						
							|  |  |  | 		/*::[*/0xFFFF/*::]*/: { n:"" } | 
					
						
							| 
									
										
										
										
											2017-04-04 16:09:41 +00:00
										 |  |  | 	}; | 
					
						
							| 
									
										
										
										
											2022-04-25 09:02:14 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-23 09:48:47 +00:00
										 |  |  | 	/* TODO: fill out and verify this table across QP versions */ | 
					
						
							|  |  |  | 	var QPWNFTable = { | 
					
						
							|  |  |  | 		/*::[*/0x05/*::*/: "dd-mmm-yy", | 
					
						
							|  |  |  | 		/*::[*/0x06/*::*/: "dd-mmm", | 
					
						
							|  |  |  | 		/*::[*/0x07/*::*/: "mmm-yy", | 
					
						
							|  |  |  | 		/*::[*/0x08/*::*/: "mm/dd/yy", // Long Date Intl
 | 
					
						
							|  |  |  | 		/*::[*/0x0A/*::*/: "hh:mm:ss AM/PM", | 
					
						
							|  |  |  | 		/*::[*/0x0B/*::*/: "hh:mm AM/PM", | 
					
						
							|  |  |  | 		/*::[*/0x0E/*::*/: "dd-mmm-yyyy", | 
					
						
							|  |  |  | 		/*::[*/0x0F/*::*/: "mmm-yyyy", | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/*::[*/0x22/*::*/: "0.00", | 
					
						
							|  |  |  | 		/*::[*/0x32/*::*/: "0.00;[Red]0.00", | 
					
						
							|  |  |  | 		/*::[*/0x42/*::*/: "0.00;\(0.00\)", | 
					
						
							|  |  |  | 		/*::[*/0x52/*::*/: "0.00;[Red]\(0.00\)", | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/*::[*/162/*::*/: '"$"#,##0;\\("$"#,##0\\)' // slightly different from SSF 5
 | 
					
						
							|  |  |  | 	}; | 
					
						
							| 
									
										
										
										
											2022-04-25 09:02:14 +00:00
										 |  |  | 	/* QPW uses a different set of record types */ | 
					
						
							|  |  |  | 	function qpw_to_workbook_buf(d, opts)/*:Workbook*/ { | 
					
						
							|  |  |  | 		prep_blob(d, 0); | 
					
						
							|  |  |  | 		var o = opts || {}; | 
					
						
							|  |  |  | 		if(DENSE != null && o.dense == null) o.dense = DENSE; | 
					
						
							| 
									
										
										
										
											2022-10-24 01:05:59 +00:00
										 |  |  | 		var s/*:Worksheet*/ = ({}/*:any*/); if(o.dense) s["!data"] = []; | 
					
						
							| 
									
										
										
										
											2022-04-25 09:02:14 +00:00
										 |  |  | 		var SST = [], sname = "", formulae = []; | 
					
						
							|  |  |  | 		var range = {s:{r:-1,c:-1}, e:{r:-1,c:-1}}; | 
					
						
							|  |  |  | 		var cnt = 0, type = 0, C = 0, R = 0; | 
					
						
							|  |  |  | 		var wb = { SheetNames: [], Sheets: {} }; | 
					
						
							| 
									
										
										
										
											2023-06-23 09:48:47 +00:00
										 |  |  | 		var FMTS = []; | 
					
						
							| 
									
										
										
										
											2022-04-25 09:02:14 +00:00
										 |  |  | 		outer: while(d.l < d.length) { | 
					
						
							|  |  |  | 			var RT = d.read_shift(2), length = d.read_shift(2); | 
					
						
							|  |  |  | 			var p = d.slice(d.l, d.l + length); | 
					
						
							|  |  |  | 			prep_blob(p, 0); | 
					
						
							|  |  |  | 			switch(RT) { | 
					
						
							|  |  |  | 				case 0x01: /* BOF */ | 
					
						
							|  |  |  | 					if(p.read_shift(4) != 0x39575051) throw "Bad QPW9 BOF!"; | 
					
						
							|  |  |  | 					break; | 
					
						
							|  |  |  | 				case 0x02: /* EOF */ break outer; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-23 09:48:47 +00:00
										 |  |  | 				case 0x08: /* NF */ break; // TODO: this is tied to custom number formats
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				case 0x0A: /* FORMATS */ { | 
					
						
							|  |  |  | 					var fcnt = p.read_shift(4); | 
					
						
							|  |  |  | 					var step = ((p.length - p.l)/ fcnt)|0; | 
					
						
							|  |  |  | 					for(var ifmt = 0; ifmt < fcnt; ++ifmt) { | 
					
						
							|  |  |  | 						var end = p.l + step; | 
					
						
							|  |  |  | 						var fmt = {}; | 
					
						
							|  |  |  | 						p.l += 2; | 
					
						
							|  |  |  | 						fmt.numFmtId = p.read_shift(2); | 
					
						
							|  |  |  | 						if(QPWNFTable[fmt.numFmtId]) fmt.z = QPWNFTable[fmt.numFmtId]; | 
					
						
							|  |  |  | 						p.l = end; | 
					
						
							|  |  |  | 						FMTS.push(fmt); | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} break; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-09 06:49:17 +00:00
										 |  |  | 				/* TODO: The behavior here should be consistent with Numbers: QP Notebook ~ .TN.SheetArchive, QP Sheet ~ .TST.TableModelArchive */ | 
					
						
							| 
									
										
										
										
											2022-04-25 09:02:14 +00:00
										 |  |  | 				case 0x0401: /* BON */ break; | 
					
						
							|  |  |  | 				case 0x0402: /* EON */ /* TODO: backfill missing sheets based on BON cnt */ break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				case 0x0407: { /* SST */ | 
					
						
							|  |  |  | 					p.l += 12; | 
					
						
							|  |  |  | 					while(p.l < p.length) { | 
					
						
							|  |  |  | 						cnt = p.read_shift(2); | 
					
						
							|  |  |  | 						type = p.read_shift(1); | 
					
						
							|  |  |  | 						SST.push(p.read_shift(cnt, 'cstr')); | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} break; | 
					
						
							|  |  |  | 				case 0x0408: { /* FORMULAE */ | 
					
						
							|  |  |  | 					//p.l += 12;
 | 
					
						
							|  |  |  | 					//while(p.l < p.length) {
 | 
					
						
							|  |  |  | 					//	cnt = p.read_shift(2);
 | 
					
						
							|  |  |  | 					//	formulae.push(p.slice(p.l, p.l + cnt + 1)); p.l += cnt + 1;
 | 
					
						
							|  |  |  | 					//}
 | 
					
						
							|  |  |  | 				} break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				case 0x0601: { /* BOS */ | 
					
						
							|  |  |  | 					var sidx = p.read_shift(2); | 
					
						
							| 
									
										
										
										
											2022-10-24 01:05:59 +00:00
										 |  |  | 					s = ({}/*:any*/); if(o.dense) s["!data"] = []; | 
					
						
							| 
									
										
										
										
											2022-04-25 09:02:14 +00:00
										 |  |  | 					range.s.c = p.read_shift(2); | 
					
						
							|  |  |  | 					range.e.c = p.read_shift(2); | 
					
						
							|  |  |  | 					range.s.r = p.read_shift(4); | 
					
						
							|  |  |  | 					range.e.r = p.read_shift(4); | 
					
						
							|  |  |  | 					p.l += 4; | 
					
						
							|  |  |  | 					if(p.l + 2 < p.length) { | 
					
						
							|  |  |  | 						cnt = p.read_shift(2); | 
					
						
							|  |  |  | 						type = p.read_shift(1); | 
					
						
							|  |  |  | 						sname = cnt == 0 ? "" : p.read_shift(cnt, 'cstr'); | 
					
						
							|  |  |  | 					} | 
					
						
							| 
									
										
										
										
											2022-04-27 08:26:35 +00:00
										 |  |  | 					if(!sname) sname = encode_col(sidx); | 
					
						
							| 
									
										
										
										
											2022-04-25 09:02:14 +00:00
										 |  |  | 					/* TODO: backfill empty sheets */ | 
					
						
							|  |  |  | 				} break; | 
					
						
							|  |  |  | 				case 0x0602: { /* EOS */ | 
					
						
							|  |  |  | 					/* NOTE: QP valid range A1:IV1000000 */ | 
					
						
							|  |  |  | 					if(range.s.c > 0xFF || range.s.r > 999999) break; | 
					
						
							|  |  |  | 					if(range.e.c < range.s.c) range.e.c = range.s.c; | 
					
						
							|  |  |  | 					if(range.e.r < range.s.r) range.e.r = range.s.r; | 
					
						
							|  |  |  | 					s["!ref"] = encode_range(range); | 
					
						
							|  |  |  | 					book_append_sheet(wb, s, sname); // TODO: a barrel roll
 | 
					
						
							|  |  |  | 				} break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				case 0x0A01: { /* COL (like XLS Row, modulo the layout transposition) */ | 
					
						
							|  |  |  | 					C = p.read_shift(2); | 
					
						
							|  |  |  | 					if(range.e.c < C) range.e.c = C; | 
					
						
							|  |  |  | 					if(range.s.c > C) range.s.c = C; | 
					
						
							|  |  |  | 					R = p.read_shift(4); | 
					
						
							|  |  |  | 					if(range.s.r > R) range.s.r = R; | 
					
						
							|  |  |  | 					R = p.read_shift(4); | 
					
						
							|  |  |  | 					if(range.e.r < R) range.e.r = R; | 
					
						
							|  |  |  | 				} break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				case 0x0C01: { /* MulCells (like XLS MulRK, but takes advantage of common column data patterns) */ | 
					
						
							|  |  |  | 					R = p.read_shift(4), cnt = p.read_shift(4); | 
					
						
							|  |  |  | 					if(range.s.r > R) range.s.r = R; | 
					
						
							|  |  |  | 					if(range.e.r < R + cnt - 1) range.e.r = R + cnt - 1; | 
					
						
							| 
									
										
										
										
											2022-10-24 01:05:59 +00:00
										 |  |  | 					var CC = encode_col(C); | 
					
						
							| 
									
										
										
										
											2022-04-25 09:02:14 +00:00
										 |  |  | 					while(p.l < p.length) { | 
					
						
							|  |  |  | 						var cell = { t: "z" }; | 
					
						
							| 
									
										
										
										
											2023-06-23 09:48:47 +00:00
										 |  |  | 						var flags = p.read_shift(1), fmtidx = -1; | 
					
						
							|  |  |  | 						if(flags & 0x80) fmtidx = p.read_shift(2); | 
					
						
							| 
									
										
										
										
											2022-04-25 09:02:14 +00:00
										 |  |  | 						var mul = (flags & 0x40) ? p.read_shift(2) - 1: 0; | 
					
						
							|  |  |  | 						switch(flags & 0x1F) { | 
					
						
							| 
									
										
										
										
											2023-06-23 09:48:47 +00:00
										 |  |  | 							case 0: break; | 
					
						
							| 
									
										
										
										
											2022-04-25 09:02:14 +00:00
										 |  |  | 							case 1: break; | 
					
						
							|  |  |  | 							case 2: cell = { t: "n", v: p.read_shift(2) }; break; | 
					
						
							|  |  |  | 							case 3: cell = { t: "n", v: p.read_shift(2, 'i') }; break; | 
					
						
							| 
									
										
										
										
											2023-06-23 09:48:47 +00:00
										 |  |  | 							case 4: cell = { t: "n", v: parse_RkNumber(p) }; break; | 
					
						
							| 
									
										
										
										
											2022-04-25 09:02:14 +00:00
										 |  |  | 							case 5: cell = { t: "n", v: p.read_shift(8, 'f') }; break; | 
					
						
							|  |  |  | 							case 7: cell = { t: "s", v: SST[type = p.read_shift(4) - 1] }; break; | 
					
						
							|  |  |  | 							case 8: cell = { t: "n", v: p.read_shift(8, 'f') }; p.l += 2; /* cell.f = formulae[p.read_shift(4)]; */ p.l += 4; break; | 
					
						
							|  |  |  | 							default: throw "Unrecognized QPW cell type " + (flags & 0x1F); | 
					
						
							|  |  |  | 						} | 
					
						
							| 
									
										
										
										
											2023-06-23 09:48:47 +00:00
										 |  |  | 						if(fmtidx != -1 && (FMTS[fmtidx - 1]||{}).z) cell.z = FMTS[fmtidx-1].z; | 
					
						
							| 
									
										
										
										
											2022-04-25 09:02:14 +00:00
										 |  |  | 						var delta = 0; | 
					
						
							|  |  |  | 						if(flags & 0x20) switch(flags & 0x1F) { | 
					
						
							|  |  |  | 							case 2: delta = p.read_shift(2); break; | 
					
						
							|  |  |  | 							case 3: delta = p.read_shift(2, 'i'); break; | 
					
						
							|  |  |  | 							case 7: delta = p.read_shift(2); break; | 
					
						
							|  |  |  | 							default: throw "Unsupported delta for QPW cell type " + (flags & 0x1F); | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 						if(!(!o.sheetStubs && cell.t == "z")) { | 
					
						
							| 
									
										
										
										
											2023-06-23 09:48:47 +00:00
										 |  |  | 							var newcell = dup(cell); | 
					
						
							|  |  |  | 							if(cell.t == "n" && cell.z && fmt_is_date(cell.z) && o.cellDates) { | 
					
						
							|  |  |  | 								newcell.v = numdate(cell.v); newcell.t = typeof newcell.v == "number" ? 'n' : 'd'; | 
					
						
							|  |  |  | 							} | 
					
						
							| 
									
										
										
										
											2022-10-24 01:05:59 +00:00
										 |  |  | 							if(s["!data"] != null) { | 
					
						
							|  |  |  | 								if(!s["!data"][R]) s["!data"][R] = []; | 
					
						
							| 
									
										
										
										
											2023-06-23 09:48:47 +00:00
										 |  |  | 								s["!data"][R][C] = newcell; | 
					
						
							|  |  |  | 							} else s[CC + encode_row(R)] = newcell; | 
					
						
							| 
									
										
										
										
											2022-04-25 09:02:14 +00:00
										 |  |  | 						} | 
					
						
							|  |  |  | 						++R; --cnt; | 
					
						
							|  |  |  | 						while(mul-- > 0 && cnt >= 0) { | 
					
						
							|  |  |  | 							if(flags & 0x20) switch(flags & 0x1F) { | 
					
						
							|  |  |  | 								case 2: cell = { t: "n", v: (cell.v + delta) & 0xFFFF }; break; | 
					
						
							|  |  |  | 								case 3: cell = { t: "n", v: (cell.v + delta) & 0xFFFF }; if(cell.v > 0x7FFF) cell.v -= 0x10000; break; | 
					
						
							|  |  |  | 								case 7: cell = { t: "s", v: SST[type = (type + delta) >>> 0] }; break; | 
					
						
							|  |  |  | 								default: throw "Cannot apply delta for QPW cell type " + (flags & 0x1F); | 
					
						
							|  |  |  | 							} else switch(flags & 0x1F) { | 
					
						
							|  |  |  | 								case 1: cell = { t: "z" }; break; | 
					
						
							|  |  |  | 								case 2: cell = { t: "n", v: p.read_shift(2) }; break; | 
					
						
							|  |  |  | 								case 7: cell = { t: "s", v: SST[type = p.read_shift(4) - 1] }; break; | 
					
						
							|  |  |  | 								default: throw "Cannot apply repeat for QPW cell type " + (flags & 0x1F); | 
					
						
							|  |  |  | 							} | 
					
						
							| 
									
										
										
										
											2023-06-23 09:48:47 +00:00
										 |  |  | 							if(fmtidx != -1); | 
					
						
							| 
									
										
										
										
											2022-04-25 09:02:14 +00:00
										 |  |  | 							if(!(!o.sheetStubs && cell.t == "z")) { | 
					
						
							| 
									
										
										
										
											2022-10-24 01:05:59 +00:00
										 |  |  | 								if(s["!data"] != null) { | 
					
						
							|  |  |  | 									if(!s["!data"][R]) s["!data"][R] = []; | 
					
						
							|  |  |  | 									s["!data"][R][C] = cell; | 
					
						
							|  |  |  | 								} else s[CC + encode_row(R)] = cell; | 
					
						
							| 
									
										
										
										
											2022-04-25 09:02:14 +00:00
										 |  |  | 							} | 
					
						
							|  |  |  | 							++R; --cnt; | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				default: break; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			d.l += length; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return wb; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-04 16:09:41 +00:00
										 |  |  | 	return { | 
					
						
							| 
									
										
										
										
											2021-11-08 04:52:18 +00:00
										 |  |  | 		sheet_to_wk1: sheet_to_wk1, | 
					
						
							| 
									
										
										
										
											2021-11-14 04:38:00 +00:00
										 |  |  | 		book_to_wk3: book_to_wk3, | 
					
						
							| 
									
										
										
										
											2017-04-04 16:09:41 +00:00
										 |  |  | 		to_workbook: lotus_to_workbook | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | })(); |