thecloud
/SimpleSpooler
/amendments
/2
Simple Spooler 0.2 release
thecloud made amendment 2 2 days ago
--- PAP.c Tue Feb 17 09:58:06 2026
+++ PAP.c Mon Feb 23 10:27:55 2026
@@ -5,7 +5,7 @@
* as described in Inside AppleTalk, Second Edition, 1990.
*
* Written by: Ken McLeod, 2026-01-07
- * Last update: 2026-02-16
+ * Last update: 2026-02-23
*
* 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.
@@ -42,6 +42,7 @@ int SendRequest(char connID, char funcID);
int SendResponse(char connID, char funcID);
int SetUpRequestData(char funcID, Ptr reqBuf);
int SetUpResponseData(char funcID, Ptr respBuf);
+void FilterData(long *count, void *data);
void SendTickle(void);
void StartTickling(void);
void StopTickling(void);
@@ -94,6 +95,7 @@ long int gDataLen; /* total data received on current c
int gPrinterType; /* {0..3}, see kPrinterType definitions */
Boolean gColorRibbon;
Boolean gSheetFeeder;
+Boolean gIW1Mode;
Boolean gFinishedQuery = false;
Handle gQueryHdl = nil; /* query sent to us by the LW driver */
int gQueryLength; /* length of query */
@@ -137,16 +139,18 @@ char *PAPFunctionNames[] = {
"Status", /* 9 */
};
-void SetPrinterOptions(Boolean hasColorRibbon, Boolean hasSheetFeeder)
+void SetPrinterOptions(Boolean colorRibbon, Boolean sheetFeeder, Boolean iw1Mode)
{
- gColorRibbon = hasColorRibbon;
- gSheetFeeder = hasSheetFeeder;
+ gColorRibbon = colorRibbon;
+ gSheetFeeder = sheetFeeder;
+ gIW1Mode = iw1Mode;
}
-void GetPrinterOptions(Boolean *hasColorRibbon, Boolean *hasSheetFeeder)
+void GetPrinterOptions(Boolean *colorRibbon, Boolean *sheetFeeder, Boolean *iw1Mode)
{
- if (hasColorRibbon) { *hasColorRibbon = gColorRibbon; }
- if (hasSheetFeeder) { *hasSheetFeeder = gSheetFeeder; }
+ if (colorRibbon) { *colorRibbon = gColorRibbon; }
+ if (sheetFeeder) { *sheetFeeder = gSheetFeeder; }
+ if (iw1Mode) { *iw1Mode = gIW1Mode; }
}
int GetActiveClientConnections(void)
@@ -773,6 +777,7 @@ void HandleResponse_from_ATPRequest(void)
eofByte = 0; /* clear so we ask for more data */
} else {
+ FilterData(&length,data); /* can modify length */
WriteDataToSpoolFile(length,data);
gDataLen += length;
if (++gDataSeq == 0) {
@@ -1180,6 +1185,37 @@ int SetUpResponseData(char funcID, Ptr respBuf)
}
}
return dataLen;
+}
+
+void FilterData(long *count, void *data)
+{
+ /* The AppleTalk ImageWriter driver assumes it is formatting output
+ * for the ImageWriter II. Some of the printer control sequences
+ * it can emit are not understood by an ImageWriter I. We can filter
+ * these out so the unused parameters of the commands are not printed.
+ * Currently, we strip the following IW II-only sequences:
+ * 1B48xxxxxxxx (page size command, plus 4 bytes)
+ * 1B4Bxx (set color command, plus 1 byte)
+ */
+ char *p;
+ long length, index;
+ if (!gIW1Mode) { return; } /* only filter in IW1 compatibility mode */
+
+ p = (char*)data;
+ length = *count;
+ for (index=0; index<length; index++) {
+ if (p[index] != 0x1B) { continue; }
+ if ((length>(index+6)) && (p[index+1] == 0x48)) {
+ BlockMove(&p[index+6],&p[index],(length-index)-6);
+ length -= 6;
+ index -= 1;
+ } else if ((length>(index+3)) && (p[index+1] == 0x4B)) {
+ BlockMove(&p[index+3],&p[index],(length-index)-3);
+ length -= 3;
+ index -= 1;
+ }
+ }
+ *count = length;
}
void SendTickle(void)
--- PAP.h Sun Feb 1 00:41:01 2026
+++ PAP.h Mon Feb 23 00:10:10 2026
@@ -3,7 +3,7 @@
* C Interface to PAP (Printer Access Protocol) routines
*
* Written by: Ken McLeod, 2026-01-07
- * Last update: 2026-01-28
+ * Last update: 2026-02-22
*
* 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.
@@ -43,10 +43,10 @@ extern "C" {
void CheckATP(void);
/* call this prior to SLInit to specify emulated printer options */
-void SetPrinterOptions(Boolean hasColorRibbon, Boolean hasSheetFeeder);
+void SetPrinterOptions(Boolean colorRibbon, Boolean sheetFeeder, Boolean iw1Mode);
/* accessor for options */
-void GetPrinterOptions(Boolean *hasColorRibbon, Boolean *hasSheetFeeder);
+void GetPrinterOptions(Boolean *colorRibbon, Boolean *sheetFeeder, Boolean *iw1Mode);
/* number of active connections (i.e. not idle) */
int GetActiveClientConnections(void);
--- README Tue Feb 17 09:53:04 2026
+++ README Mon Feb 23 11:11:53 2026
@@ -1,4 +1,4 @@
-## Simple Spooler 0.1 ##
+## Simple Spooler 0.2 ##
Copyright (c) 2026, Ken McLeod.
This application acts as a virtual printer on an AppleTalk network, receiving
@@ -37,7 +37,9 @@ A dialog will present the following options:
Select one of the icons representing LaserWriter, ImageWriter LQ, or
ImageWriter to create a virtual printer of that type. For an ImageWriter or
LQ, you can additionally select whether the printer is seen as having a
- color ribbon or a sheet feeder.
+ color ribbon or a sheet feeder. The "ImageWriter 1 mode" checkbox improves
+ compatibility with the original ImageWriter by removing newer printer
+ control codes that only the ImageWriter II understands.
* Print to this port
Select the icon for the local serial port where your ImageWriter printer
@@ -200,3 +202,4 @@ to reproduce it.) Thanks!
**Modification history**
0.1 2026-02-16: first release for testing
+0.2 2026-02-23: added ImageWriter 1 compatibility mode
--- Spooler.c Mon Feb 16 21:55:58 2026
+++ Spooler.c Mon Feb 23 10:10:14 2026
@@ -10,7 +10,7 @@
* file is present in the spool directory.
*
* Written by: Ken McLeod, 2026-01-07
- * Last update: 2026-01-31
+ * Last update: 2026-02-23
*
* Some code was adapted from the Neighborhood Watch sample application
* by Ricardo Batista, found on Apple Developer CD Volume IX, and from the
@@ -76,10 +76,11 @@
#define printerPortItem 11
#define colorRibbonCBoxItem 13
#define sheetFeederCBoxItem 14
-#define printingEnabledItem 15
-#define scheduleUserItem 16
-#define printerTypeUserItem 17
-#define localPortUserItem 18
+#define iw1ModeCBoxItem 15
+#define printingEnabledItem 16
+#define scheduleUserItem 17
+#define printerTypeUserItem 18
+#define localPortUserItem 19
#define logWindowID 128
#define spoolerDialogID 128
@@ -129,6 +130,7 @@ short defaultPortItem = modemPortItem;
Boolean defaultColorRibbon = false;
Boolean defaultSheetFeeder = false;
Boolean defaultPrintEnabled = true;
+Boolean defaultIW1Mode = false;
short curSelectedIndex = 0; /* selected segment in date scheduler */
short schedStartHour = 0; /* default start to 12 AM */
short schedEndHour = 24; /* default end to next 12 AM */
@@ -787,6 +789,9 @@ OSErr StartSpooler(void)
GetDItem(aDialog, sheetFeederCBoxItem, &index, &H, &box);
SetCtlValue((ControlHandle)H,defaultSheetFeeder);
HiliteControl((ControlHandle)H,(defaultPrinterItem==iconLWItem)?255:0);
+ GetDItem(aDialog, iw1ModeCBoxItem, &index, &H, &box);
+ SetCtlValue((ControlHandle)H,defaultIW1Mode);
+ HiliteControl((ControlHandle)H,(defaultPrinterItem==iconLWItem)?255:0);
GetDItem(aDialog, printingEnabledItem, &index, &H, &box);
SetCtlValue((ControlHandle)H,defaultPrintEnabled);
@@ -824,6 +829,9 @@ OSErr StartSpooler(void)
HiliteControl((ControlHandle)H,(item==iconLWItem)?255:0);
GetDItem(aDialog, sheetFeederCBoxItem, &tmpItem, &H, &box);
HiliteControl((ControlHandle)H,(item==iconLWItem)?255:0);
+ GetDItem(aDialog, iw1ModeCBoxItem, &tmpItem, &H, &box);
+ HiliteControl((ControlHandle)H,(item!=iconIWItem)?255:0);
+ if (item!=iconIWItem) { SetCtlValue((ControlHandle)H,0); }
}
else if (item >= modemPortItem && item <= printerPortItem) {
short tmpItem;
@@ -853,19 +861,22 @@ OSErr StartSpooler(void)
}
if (item == okItem) {
short tmpItem;
- Boolean hasColorRibbon, hasSheetFeeder, printEnabled;
+ Boolean hasColorRibbon, hasSheetFeeder, iw1Mode, printEnabled;
GetDItem(aDialog, spoolerNameItem, &tmpItem, &H, &box);
GetIText(H, nameStr);
GetDItem(aDialog, colorRibbonCBoxItem, &tmpItem, &H, &box);
hasColorRibbon = (GetCtlValue((ControlHandle)H) != 0);
GetDItem(aDialog, sheetFeederCBoxItem, &tmpItem, &H, &box);
hasSheetFeeder = (GetCtlValue((ControlHandle)H) != 0);
+ GetDItem(aDialog, iw1ModeCBoxItem, &tmpItem, &H, &box);
+ iw1Mode = (GetCtlValue((ControlHandle)H) != 0);
GetDItem(aDialog, printingEnabledItem, &tmpItem, &H, &box);
printEnabled = (GetCtlValue((ControlHandle)H) != 0);
- SetPrinterOptions(hasColorRibbon, hasSheetFeeder);
+ SetPrinterOptions(hasColorRibbon, hasSheetFeeder,iw1Mode);
defaultColorRibbon = hasColorRibbon;
defaultSheetFeeder = hasSheetFeeder;
defaultPrintEnabled = printEnabled;
+ defaultIW1Mode = iw1Mode;
}
curSelectedIndex = 0;
ReleaseResource((Handle)arrowsPictHdl);
@@ -927,7 +938,7 @@ void DoAbout()
Message(0,"\pSimple Spooler is a basic print spooler application.");
Message(0,"\pIt presents itself as an AppleTalk printer and will");
Message(0,"\prespond to Printer Access Protocol (PAP) messages.");
- Message(0,"\pCopyright © 2026 Ken McLeod.");
+ Message(0,"\pVersion 0.2, Copyright © 2026 Ken McLeod.");
Message(0,sepStr);
}
@@ -939,6 +950,7 @@ void DoStatus()
MessageWithQuotedString(0,"\pPrinter type:",ourType);
MessageWithIntValue(0,"\pColor ribbon:",(defaultColorRibbon)?1:0);
MessageWithIntValue(0,"\pSheet feeder:",(defaultSheetFeeder)?1:0);
+ MessageWithIntValue(0,"\pImageWriter 1 mode:",(defaultIW1Mode)?1:0);
MessageWithQuotedString(0,"\pPrint to port:",ourPort);
MessageWithIntValue(0,"\pPrinting enabled:",(defaultPrintEnabled)?1:0);
MessageWithIntValue(0,"\pScheduled start hour:",schedStartHour);
@@ -964,7 +976,7 @@ void LoadPreferences()
defaultColorRibbon = *((char*)&prefData[8]);
defaultSheetFeeder = *((char*)&prefData[9]);
defaultPrintEnabled = *((char*)&prefData[10]);
- /* reserved char at prefsData[11] */
+ defaultIW1Mode = *((char*)&prefData[11]);
schedStartHour = *((char*)&prefData[12]);
schedEndHour = *((char*)&prefData[13]);
/* window rect in global coordinates */
@@ -982,7 +994,7 @@ void LoadPreferences()
void SavePreferences()
{
char *p, val;
- Boolean hasColorRibbon, hasSheetFeeder, printEnabled;
+ Boolean hasColorRibbon, hasSheetFeeder, iw1Mode, printEnabled;
long length = 4L+2L+8+18+ourName[0]+1+ourType[0]+1+ourPort[0]+1;
Ptr prefData = NewPtrClear(length);
if (!prefData) { return; }
@@ -999,12 +1011,14 @@ void SavePreferences()
val = (ourPort[1] == 'M') ? modemPortItem : printerPortItem;
*((char*)&prefData[7]) = val;
/* offset 8, 9: boolean values of Color Ribbon and Sheet Feeder */
- GetPrinterOptions(&hasColorRibbon,&hasSheetFeeder);
+ GetPrinterOptions(&hasColorRibbon,&hasSheetFeeder,&iw1Mode);
*((char*)&prefData[8]) = (hasColorRibbon) ? -1 : 0;
*((char*)&prefData[9]) = (hasSheetFeeder) ? -1 : 0;
- /* offset 10, 11: boolean values of Print Enabled and TBD */
+ /* offset 10, 11: boolean values of Print Enabled and IW1 Mode */
printEnabled = defaultPrintEnabled;
*((char*)&prefData[10]) = (printEnabled) ? -1 : 0;
+ iw1Mode = defaultIW1Mode;
+ *((char*)&prefData[11]) = (iw1Mode) ? -1 : 0;
/* offset 12: scheduled start hour for printing (1 byte) */
*((char*)&prefData[12]) = (char)(schedStartHour & 0xFF);
/* offset 13: scheduled end hour for printing (1 byte) */
--- Spooler.r Mon Feb 16 20:10:16 2026
+++ Spooler.r Sun Feb 22 23:55:14 2026
@@ -7,7 +7,7 @@
#include "Types.r"
#include "SysTypes.r"
-#define VERSION_STR "0.1"
+#define VERSION_STR "0.2"
/* resource type declarations */
type 'spoo' as 'STR ';
@@ -68,7 +68,7 @@ resource 'DLOG' (128, "Printer Setup") {
};
resource 'DITL' (128) {
- { /* array DITLarray: 18 elements */
+ { /* array DITLarray: 19 elements */
/* [1] */
{191, 344, 211, 410},
Button {
@@ -154,26 +154,32 @@ resource 'DITL' (128) {
"Sheet Feeder"
},
/* [15] */
+ {171, 88, 189, 245},
+ CheckBox {
+ enabled,
+ "ImageWriter 1 mode"
+ },
+ /* [16] */
{133, 276, 151, 358},
CheckBox {
enabled,
"Enabled"
},
- /* [16] */
+ /* [17] */
{153, 292, 171, 402},
UserItem {
enabled
},
- /* [17] */
- {68, 78, 178, 253},
+ /* [18] */
+ {68, 78, 211, 253},
UserItem {
disabled
},
- /* [18] */
- {68, 266, 178, 411},
+ /* [19] */
+ {68, 266, 178, 410},
UserItem {
disabled
- },
+ }
}
};