76 lines
2.7 KiB
JavaScript
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 };
|