Files

76 lines
2.7 KiB
JavaScript

// DatPrintOption.opt memory table, as documented in ESTX_파일구조.md.
function readPrintOptions(buffer, onRow) {
if (buffer.length < 24 || buffer.readUInt32LE(0) !== 0xbde01996)
throw Error("인쇄 설정 헤더 오류");
const count = buffer.readUInt16LE(12),
rows = buffer.readUInt16LE(14),
start = buffer.readUInt16LE(22);
if (count > 1024 || rows > 1000 || start > buffer.length) throw Error("인쇄 설정 크기 오류");
const decoder = new TextDecoder("euc-kr", { fatal: true });
let at = 24;
const take = (n) => {
if (n < 0 || at + n > buffer.length) throw Error("인쇄 설정 범위 오류");
const result = buffer.subarray(at, at + n);
at += n;
return result;
};
const byte = () => take(1)[0];
const short = () => take(2).readUInt16LE();
const fields = [];
for (let i = 0; i < count; i++) {
const name = take(byte()).toString("ascii"),
width = short(),
kind = short();
take(2);
const attributes = short();
for (let j = 0; j < attributes; j++) {
take(byte());
const size = short(),
type = short();
if (type === 73) take(short());
else take(size);
}
if (!/^[A-Za-z][A-Za-z0-9_]*$/.test(name)) throw Error("인쇄 설정 필드명 오류");
fields.push({ name, width, kind });
}
if (at > start) throw Error("인쇄 설정 설명자 범위 오류");
at = start;
const result = [];
for (let r = 0; r < rows; r++) {
take(1);
const status = take(Math.ceil(count / 4)),
row = {},
positions = {};
for (let i = 0; i < count; i++) {
const { name, width, kind } = fields[i],
state = (status[i >> 2] >> ((i % 4) * 2)) & 3;
if (state === 1 || state === 2) continue;
if (state !== 0) throw Error("인쇄 설정 필드 상태 오류");
if (
[
"PrintTop",
"PrintBottom",
"PrintLeft",
"PrintRight",
"PrintLineCount",
"PrintGongMethod",
"PrintApplyField",
"PrintSumBottom",
].includes(name)
)
positions[name] = { at, kind, width };
if (kind === 1 && width === 4) row[name] = take(4).readInt32LE();
else if (kind === 3 && width === 2) row[name] = take(2).readInt16LE();
else if (kind === 4 && width === 8) row[name] = take(8).readDoubleLE();
else if (kind === 73 && width === 1) row[name] = decoder.decode(take(byte()));
else if (kind === 75 && width === 4) take(take(4).readUInt32LE());
else throw Error(`인쇄 설정 필드형 오류: ${name}/${kind}/${width}`);
}
result.push(row);
if (onRow) onRow(row, positions);
}
if (at !== buffer.length) throw Error("인쇄 설정 잔여 데이터 오류");
return result;
}
module.exports = { readPrintOptions };