AmendHub

Download:

thecloud

/

SimpleSpooler

/

amendments

/

7

more FilterData compatibility tweaks

- fix bug that failed to remove a filtered byte if it was the last byte
in the buffer being processed
- strip extra linefeeds generated by a reverse feed
- modify filter to remove a subset of 1B5A and 1B44 commands in IW1 mode,
to hopefully improve Scribe compatibility
- reset printer to defaults before starting each print job

thecloud made amendment 7 15 days ago
--- PrintQueue.c Thu Jul 30 16:46:25 2026 +++ PrintQueue.c Wed Aug 5 22:18:36 2026 @@ -4,7 +4,7 @@ * Routines for processing and printing spool files. * * Written by: Ken McLeod, 2026-01-16 - * Last update: 2026-02-03 + * Last update: 2026-08-05 * * This software is provided as-is, with no warranties expressed or implied, * under the terms of the BSD 2-Clause License. See separate "LICENSE" file. @@ -41,7 +41,10 @@ short gSerialRefNum = 0; long gBytesWritten = 0L; long gJobsPrinted = 0L; Boolean gProcessingEscape = false; +Boolean gReverseFeedMode = false; +Boolean gGraphicLineMode = false; short gBytesToRemove = 0; +short gLinefeedsToRemove = 0; void FilterData(long *count, void *data) @@ -54,18 +57,21 @@ void FilterData(long *count, void *data) * In IW1 mode, we filter the following IW II-only control sequences: * 1B48xxxxxxxx (page length command, plus 4 parameter bytes) * 1BF8xxxxxxxx (same as 1B48, but for testing the filter on IW II) - * 1B4Cxxxxxx (page left margin command, plus 3 parameter bytes) * 1B4Bxx (select color command, plus 1 parameter byte) * 1B61xx (print quality command, plus 1 parameter byte) + * 1B5A[01-0F]xx (set switch OFF, plus 2 parameter bytes) + * 1B44[01-0F]xx (set switch ON, plus 2 parameter bytes) * * We can also optionally filter the command that backs up the paper: * 1B72 (set reverse line feeding) + * and keep track of how many linefeeds are made in reverse mode, + * so we can subsequently remove the same number of forward linefeeds. * * Since control sequences can span data blocks, the 1B might have been * sent out before we get the command code. Our filter changes the * command code to FF which will be ignored, and removes the parameter * bytes which follow. (There is no need to filter IW II-only control - * sequences that have no parameters.) + * sequences that have no parameters, since an IW1 just ignores them.) */ char *p; long length, index; @@ -86,25 +92,55 @@ void FilterData(long *count, void *data) switch (p[index]) { case 0xF8: case 0x48: - p[index] = nopCmd; gBytesToRemove = 4; break; - case 0x4C: - p[index] = nopCmd; gBytesToRemove = 3; break; + p[index] = nopCmd; gBytesToRemove = 4; + break; + case 0x5A: + case 0x44: + if (index+1 >= length) { + break; /* can't peek at next byte, oh well */ + } + if (p[index+1] > 0x00 && p[index+1] < 0x10) { + p[index] = nopCmd; gBytesToRemove = 2; + } + break; case 0x4B: case 0x61: - p[index] = nopCmd; gBytesToRemove = 1; break; + p[index] = nopCmd; gBytesToRemove = 1; + break; default: break; } } - if (noReverse && p[index] == 0x72) { - p[index] = nopCmd; + if (noReverse) { + gGraphicLineMode = false; + if (p[index] == 0x72) { + p[index] = nopCmd; + gReverseFeedMode = true; + } else if (p[index] == 0x66) { + gReverseFeedMode = false; + } else if (p[index] == 0x47 || p[index] == 0x67) { + gGraphicLineMode = true; + } } gProcessingEscape = false; continue; } - if (gBytesToRemove > 0 && length > (index+1)) { - /* remove one byte by shifting remaining bytes left */ - BlockMove(&p[index+1],&p[index],(length-index)-1); + if (noReverse && !gGraphicLineMode && p[index] == 0x0A) { + /* this is an actual linefeed and not part of a graphic */ + if (gReverseFeedMode) { + gBytesToRemove = 1; + gLinefeedsToRemove += 1; + } else if (gLinefeedsToRemove > 0) { + gBytesToRemove = 1; + gLinefeedsToRemove -= 1; + } + } + if (gBytesToRemove > 0) { + if (length > index+1) { + /* shift remaining bytes left */ + BlockMove(&p[index+1],&p[index],(length-index)-1); + } + /* remove this byte */ index -= 1; length -= 1; gBytesToRemove -= 1; @@ -163,7 +199,9 @@ void PrintCurrentJob(void) return; } gProcessingEscape = false; + gReverseFeedMode = false; gBytesToRemove = 0; + gLinefeedsToRemove = 0; } /* keep reading more of the current file and sending * to serial port until done, then close the file. @@ -171,6 +209,16 @@ void PrintCurrentJob(void) if (gPrintFileRefNum != 0) { char buf[256]; Boolean readEOF = false; + /* %%% TODO: handshake to make sure printer is actually there! */ + if (gBytesWritten == 0) { + /* reset the printer to defaults before starting job */ + buf[0] = 0x1B; buf[1] = 0x63; count = 2; + err = FSWrite(gSerialRefNum,&count,buf); + if (err != noErr) { + MessageWithIntValue(LOG_ERR_X,"\pUnable to initialize printer:",err); + readEOF = true; /* cannot continue */ + } + } while (!err) { count = sizeof(buf); err = FSRead(gPrintFileRefNum,&count,buf);