lpstyl.c 48 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097
  1. /*
  2. lpstyl.c
  3. version 0.9.9
  4. Copyright (C) 1996-2000 Monroe Williams (monroe@pobox.com)
  5. All rights reserved.
  6. Redistribution and use in source and binary forms, with or without
  7. modification, are permitted provided that the following conditions
  8. are met:
  9. 1. Redistributions of source code must retain the above copyright
  10. notice, this list of conditions and the following disclaimer.
  11. 2. Redistributions in binary form must reproduce the above copyright
  12. notice, this list of conditions and the following disclaimer in the
  13. documentation and/or other materials provided with the distribution.
  14. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  15. IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  16. OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  17. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  18. INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  19. NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  20. DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  21. THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  22. (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  23. OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  24. -----
  25. This is a printer driver for Apple StyleWriter printers. Here is the
  26. known status of printers it supports:
  27. - Color Stylewriter 2500:
  28. Fully supported in 360x360dpi, B/W and Color.
  29. - Color Stylewriter 2400:
  30. Fully supported in 360x360dpi, B/W and Color.
  31. - Color Stylewriter 2200:
  32. Supposed to work as of 0.9.9 (I haven't seen it, though.)
  33. - Color Stylewriter 1500:
  34. Works in B/W and Color.
  35. - StyleWriter III, StyleWriter 1200:
  36. "Works peachy." -- Charles Broderick, bbroder@mit.edu
  37. - StyleWriter II:
  38. Reported to work quite well.
  39. - StyleWriter I:
  40. Working again as of version 0.9.7.
  41. - Other stylewriters?:
  42. Give it a try. The code will treat any printer it doesn't
  43. recognize like a SWII, so it just might work. (That's how
  44. the SW2400 first worked, anyway.)
  45. Future releases of this driver will have more documentation, including
  46. some explanation of the control codes I have figured out. Stay tuned.
  47. Any feedback should be directed to monroe@pobox.com.
  48. */
  49. /* Version history:
  50. 0.9.9:
  51. - Fixed a problem with identifying the StyleWriter 2400 and 2500.
  52. - Added changes from Paulo Abreu <paulotex@geocities.com>
  53. to support the StyleWriter 2200.
  54. - Initial support for the Apple StyleWriter Ethertalk Adapter
  55. (Apple part number M4877). This is a box which connects a
  56. number of different models of StyleWriter directly to an
  57. Ethernet network. This requires netatalk support on the
  58. machine you're compiling on. It also required an
  59. implementation of a subset of the ADSP protocol for the
  60. Appletalk stack, which is in the file adsp.c. This device
  61. looks very similar to the "Farallon EtherMac iPrint Adapter SL",
  62. (it performs the same function and appears to use the same plastics),
  63. and I'd like to find out if the Farallon device works the same.
  64. 0.9.8:
  65. - Added changes from Takashi Oe <toe@unlinfo.unl.edu> to
  66. support the StyleWriter 1500.
  67. - Made the code's entire concept of paper sizes and margins much
  68. less confused.
  69. - Added A4 paper support. (Finally.)
  70. - Added a mechanism for specifying arbitrary paper sizes on
  71. the command line. -W and -H (yes, capital letters) specify
  72. the width and height of the paper in _pixels_. One pixel is
  73. 1/360 of an inch. In the normal case, these numbers should
  74. match the dimensions of the input file. No validity checking
  75. is done on the paper sizes thus received, and I'm sure one could
  76. make things go rather badly by entering wildly inaccurate numbers.
  77. Be nice.
  78. - Improved out-of-paper handling. The code for all printer
  79. types should now handle out-of-paper conditions by retrying.
  80. 0.9.7:
  81. - Finally got hold of a StyleWriter I.
  82. It didn't work.
  83. It does now.
  84. 0.9.6:
  85. - Incorporated new information about control codes from
  86. Paul Mackerras <paulus@cs.anu.edu.au> to make the
  87. StyleWriter 2500 work.
  88. - Improved out-of-paper handling on 2400/2500. (Instead of
  89. retransmitting data, we now use another control code to make
  90. the printer try again.) Thanks to Paul Mackerras for coming
  91. up with the right control code.
  92. - The driver is now aware of whether a color ink cartridge is
  93. installed in the 2400/2500.
  94. 0.9.5:
  95. - Finally, really fixed the finish-page code to wait for the
  96. right thing. (Hooray for trial and error...)
  97. - Figured out how long a microsecond was (duh...) and fixed the
  98. various retry-loops to sleep for 0.1 second like I originally
  99. intended.
  100. - Now deals with the printer running out of paper by retrying
  101. every 30 seconds until the problem goes away (or someone
  102. puts a stop to it).
  103. - No longer reset before every page. It's unnecessary. Now we
  104. reset before the first page of the job, and after printing
  105. is unpaused with SIGUSR1.
  106. 0.9.4:
  107. - Now recognizes the SW1200/SW3, courtesy of Charles Broderick
  108. <bbroder@mit.edu>.
  109. - Uses non-blocking I/O to read from the printer.
  110. 0.9.3:
  111. - Less confusing comments about the default margins.
  112. - Now checks for what I think are error codes from the printer
  113. and terminates on errors.
  114. - Code that gets printer status is now less likely to hang.
  115. - Disabled the expanded vertical print area on the SW2400 until
  116. I can figure out why it's causing errors on some pages.
  117. 0.9.2:
  118. - Generalized the printable area and margins constants so that they can
  119. be set to different values after the printer is identified. The
  120. SW2400 case in printerSetup now sets larger print area and smaller
  121. margins to match what the 2400 can do. More printers will be added
  122. as I get their specs.
  123. - Added a flag -m to disable cropping for top and left margins.
  124. Use this flag if you want to see the entire image file.
  125. (Files rendered for a full 8.5"x11" page will be offset down and to
  126. the right from where they should be on the page.)
  127. 0.9.1:
  128. - Fixed a problem with waiting for the last part of a page to
  129. print. The problem would cause the next page's reset to
  130. happen too soon, chopping off the last part of the page.
  131. 0.9:
  132. - Fully functional COLOR on a Color Stylewriter 2400!!!
  133. - Added signal handlers for common kill signals that eject the
  134. page and reset the printer.
  135. - Two new input formats: 'bit' and 'bitcmyk'.
  136. - Flags, flags, flags. Type 'lpstyl -?' to see usage.
  137. - Now sets up the serial port properly (57600 baud, raw mode)
  138. using termios.
  139. - Uses a larger buffer size on Color StyleWriter 2400.
  140. 0.2.0d2:
  141. - Fully functional in B&W on a Color StyleWriter 2400 and a
  142. SWII
  143. 0.2.0d1:
  144. - Changed a couple of things to make it work better (but still not
  145. quite right) on a SWII.
  146. - First try at using the printer's buffer more efficiently.
  147. 0.2.0d0:
  148. - First attempt at direct StyleWriter II support, with help from
  149. Jack Howarth <howarth@bromo.med.uc.edu>. This includes the
  150. first attempt at compensating for what looks like a "scanline
  151. differencing" algorithm the SWII uses, conditional on the
  152. returned printer type.
  153. - Included a modification suggested by Stefan Schmiedl
  154. <101321.3101@CompuServe.COM> -- reducing the maximum
  155. amount of data that will be sent at once from 0x10000
  156. to 0x4000. (Apparently, some more complex files caused
  157. the printer's buffer to overflow.)
  158. */
  159. #include <stdio.h>
  160. #include <stdlib.h>
  161. #include <string.h>
  162. #include <ctype.h>
  163. #ifdef unix
  164. #include <sys/types.h>
  165. #include <termios.h>
  166. #include <unistd.h>
  167. #include <errno.h>
  168. #include <signal.h>
  169. #include <fcntl.h>
  170. #else
  171. /* I sometimes compile this under MacOS for various reasons. This
  172. source file gets #included in another one which includes the right
  173. header files and defines dummy versions of various unix-specific functions.
  174. */
  175. #endif
  176. #ifdef ATALK
  177. #include <netatalk/at.h>
  178. #include <atalk/nbp.h>
  179. #include "adsp.h"
  180. #endif
  181. /* Just a few prototypes... Yeah, I was raised on ANSI C. So sue me. */
  182. void fixPageSizes(void);
  183. int main(int argc, char **argv);
  184. int printStdin(void);
  185. size_t encodescanline(unsigned char *src, size_t srcLen, unsigned char *dst);
  186. void sendEncodedData(unsigned char *buffer, size_t size);
  187. void sendrect(long top, long left, long bottom, long right);
  188. size_t inputRead(void *buffer, size_t size);
  189. int inputGetc(void);
  190. void inputPutback(int c);
  191. void printerSetup(void);
  192. size_t comm_printer_read(void *buffer, size_t size);
  193. size_t comm_printer_write(void *buffer, size_t size);
  194. size_t comm_printer_writestring(char *buffer);
  195. void comm_printer_writeFFFx(char x);
  196. int comm_printer_getc(void);
  197. int comm_printer_getc_block(void);
  198. void ejectAndReset(void);
  199. void finishPage(void);
  200. void waitNonBusy(int canHandlePaperOut);
  201. void printerFlushInput(void);
  202. void print_error(char *s);
  203. void print_info(char *s);
  204. void waitStatus(int stat, int canHandlePaperOut);
  205. int getStatus(int which);
  206. /***** Some relevant constants *****/
  207. /* NOTE: To change these values on a per-printer basis, add a case
  208. to the "Printer-specific setup" in printerSetup(). Copying
  209. the SW2400 case is a good place to start.
  210. */
  211. /* size of the printer's buffer */
  212. long MAX_BUFFER = 0x00004000;
  213. /* Default to letter-size paper, which is 8.5 x 11 inches @ 360dpi */
  214. long PAGE_WIDTH = 3060;
  215. long PAGE_HEIGHT = 3960;
  216. long PRINT_WIDTH;
  217. long PRINT_HEIGHT;
  218. long TOP_MARGIN;
  219. long BOTTOM_MARGIN;
  220. long LEFT_MARGIN;
  221. /* number of BYTES of each scanline to leave off the left. (pixels / 8) */
  222. long LEFT_MARGIN_BYTES;
  223. long PRINT_ROWBYTES;
  224. #ifndef nil
  225. #define nil ((void*)0)
  226. #endif
  227. /* Do we really care? */
  228. int verbose = 0;
  229. volatile int paused = 0;
  230. char *ProcName;
  231. void handler();
  232. void cleanup();
  233. void usage(void);
  234. int readFileHeader(void);
  235. size_t readFileScanline(char *bufK, char *bufC, char *bufM, char *bufY);
  236. size_t appendEncode(size_t length, char *in, char *last, char *out);
  237. /* Variables printStdin() needs which can also be set by arguments */
  238. long height = -1, width = -1;
  239. enum
  240. {
  241. FILE_PBMRAW,
  242. FILE_BIT,
  243. FILE_BITCMYK
  244. };
  245. int fileType = FILE_PBMRAW;
  246. int fileIsColor = 0; /* Set to true in readFileHeader if the input
  247. file contains color information. */
  248. int canPrintColor = 0; /* set to true in printerSetup() if a color ink
  249. cartridge is installed. */
  250. int printQuality = 1; /* 0 = draft (not implemented yet), 1 = normal,
  251. 2 = high. */
  252. size_t rowbytes;
  253. enum
  254. {
  255. KIND_SW1,
  256. KIND_SW2,
  257. KIND_SW3,
  258. KIND_SW1500,
  259. KIND_SW2200,
  260. KIND_SW2400,
  261. KIND_SW2500,
  262. KIND_SWUNKNOWN
  263. };
  264. int printerType;
  265. int noMargins = 0;
  266. int doReset = 1;
  267. int bufferHelp = 0;
  268. int atalk_connection = 0;
  269. #ifdef ATALK
  270. char *atalk_username = NULL;
  271. struct adsp_socket s1, s2;
  272. struct adsp_endp end1, end2;
  273. int at_printer_open(char *name);
  274. void at_printer_kill(void);
  275. void at_printer_setstatus(char *status);
  276. #endif
  277. long USLEEP_TIME = 100000; /* 0.1 seconds for usleep() */
  278. void fixPageSizes(void)
  279. {
  280. /* This routine assumes that the following are set up before it is called:
  281. (these depend only on the paper size)
  282. PAGE_WIDTH - width of the paper
  283. PAGE_HEIGHT - height of the paper
  284. (these depend only on the capabilities of the printer's hardware)
  285. PRINT_WIDTH - width of the printer's imageable area
  286. LEFT_MARGIN - printer's left margin
  287. TOP_MARGIN - printer's top margin
  288. BOTTOM_MARGIN - printer's bottom margin
  289. All values are in pixels. There are 360 pixels per inch.
  290. */
  291. /* the height of the printer's imageable area */
  292. PRINT_HEIGHT = PAGE_HEIGHT - (TOP_MARGIN + BOTTOM_MARGIN + 1);
  293. /* The number of imageable bytes in each scanline */
  294. PRINT_ROWBYTES = (PRINT_WIDTH + 7) / 8;
  295. /* The number of bytes to chop off the left of each scanline to make a left margin */
  296. LEFT_MARGIN_BYTES = (LEFT_MARGIN + 7) / 8;
  297. }
  298. int main(int argc, char **argv)
  299. {
  300. int ch;
  301. ProcName = argv[0];
  302. #ifdef ATALK
  303. atalk_username = getlogin();
  304. #endif
  305. /* Enable print pause */
  306. signal(SIGUSR1, handler);
  307. /* Make sure we eject the page if the driver is killed off. */
  308. signal(SIGTERM, cleanup);
  309. signal(SIGHUP, cleanup);
  310. signal(SIGINT, cleanup);
  311. /* Figure out the options */
  312. while((ch = getopt(argc, argv, "a:t:f:h:w:H:W:q:p:u:v?mb")) != -1)
  313. {
  314. switch(ch)
  315. {
  316. case 'f': /* file to open as printer device */
  317. {
  318. int fd;
  319. fd = open(optarg, O_RDWR, 0);
  320. if(fd == -1)
  321. {
  322. perror("open");
  323. exit(1);
  324. }
  325. else
  326. {
  327. dup2(fd, 1);
  328. }
  329. }
  330. break;
  331. case 'a': /* Printer is on an AppleTalk box. */
  332. {
  333. #ifdef ATALK
  334. at_printer_open(optarg);
  335. atalk_connection = 1;
  336. #else
  337. fprintf(stderr, "%s: AppleTalk support not compiled in.\n",
  338. ProcName);
  339. exit(1);
  340. #endif
  341. }
  342. break;
  343. case 'u': /* username for setting status of appletalk printer */
  344. #ifdef ATALK
  345. atalk_username = optarg;
  346. #else
  347. fprintf(stderr, "%s: AppleTalk support not compiled in.\n",
  348. ProcName);
  349. exit(1);
  350. #endif
  351. break;
  352. case 't': /* file format */
  353. if(strcmp(optarg, "pbmraw") == 0)
  354. fileType = FILE_PBMRAW;
  355. else if(strcmp(optarg, "bit") == 0)
  356. fileType = FILE_BIT;
  357. else if(strcmp(optarg, "bitcmyk") == 0)
  358. fileType = FILE_BITCMYK;
  359. else
  360. usage();
  361. break;
  362. case 'p':
  363. if(strcmp(optarg, "letter") == 0)
  364. {
  365. /* Print on U.S. Letter-size paper */
  366. PAGE_WIDTH = 3060; /* 8.5" * 360dpi */
  367. PAGE_HEIGHT = 3960; /* 11" * 360dpi */
  368. }
  369. else if(strcmp(optarg, "a4") == 0)
  370. {
  371. /* Print on A4 paper */
  372. PAGE_WIDTH = 2975; /* about 8.27" * 360dpi */
  373. PAGE_HEIGHT = 4210; /* about 11.69" * 360dpi */
  374. }
  375. else
  376. {
  377. usage();
  378. }
  379. break;
  380. case 'H': /* paper height (in pixels) */
  381. PAGE_HEIGHT = atoi(optarg);
  382. break;
  383. case 'W': /* paper width (in pixels) */
  384. PAGE_WIDTH = atoi(optarg);
  385. break;
  386. case 'h': /* input file height (in pixels) */
  387. height = atoi(optarg);
  388. break;
  389. case 'w': /* input file width (in pixels) */
  390. width = atoi(optarg);
  391. break;
  392. case 'm':
  393. /* don't crop margins */
  394. noMargins = 1;
  395. break;
  396. case 'q': /* print quality (0, 1, or 2) */
  397. printQuality = atoi(optarg);
  398. break;
  399. case 'v':
  400. verbose++;
  401. break;
  402. case 'b':
  403. bufferHelp = 1;
  404. break;
  405. case '?':
  406. default:
  407. usage();
  408. break;
  409. }
  410. }
  411. /* Set up some necessary terminal parameters */
  412. if(!atalk_connection)
  413. {
  414. struct termios t;
  415. tcgetattr(1, &t);
  416. cfmakeraw(&t);
  417. cfsetispeed(&t, B57600);
  418. cfsetospeed(&t, B57600);
  419. if(tcsetattr(1, TCSAFLUSH, &t) == -1)
  420. {
  421. perror("tcsetattr");
  422. exit(1);
  423. }
  424. sleep(1);
  425. }
  426. fprintf(stderr, "%s: printing started, pid = %d.\n", ProcName, getpid());
  427. /* I'd like to do something here so that the driver can be sending data
  428. to the printer and working on the next chunk at the same time.
  429. (On my SE/30, it seems to spend about half of its time doing each.)
  430. Sooner or later, I'll figure out something with pipes or shared
  431. memory or something. Not yet.
  432. */
  433. if(bufferHelp)
  434. {
  435. #if 0
  436. pipe();
  437. dup2(fd, 1);
  438. #endif
  439. }
  440. /* print some jobs */
  441. while(printStdin() == 0)
  442. {
  443. doReset = 0;
  444. if(paused)
  445. {
  446. fprintf(stderr, "%s: printing paused, you may mess with the printer now.\n", ProcName);
  447. while(paused)
  448. pause();
  449. fprintf(stderr, "%s: printing resumed.\n", ProcName);
  450. /* Reset the printer before the next page. Who knows what
  451. they might have done to the poor thing?
  452. */
  453. doReset = 1;
  454. }
  455. }
  456. fprintf(stderr, "%s: printing finished, exiting.\n", ProcName);
  457. #ifdef ATALK
  458. if(atalk_connection)
  459. {
  460. at_printer_kill();
  461. }
  462. #endif
  463. return(0);
  464. }
  465. void usage(void)
  466. {
  467. fprintf(stderr, "usage: lpstyl [-v] [-m] [-q printQuality] [-t pbmraw | bit | bitcmyk]\n");
  468. fprintf(stderr, " [-f printer_device] [-p letter | a4]\n");
  469. fprintf(stderr, " [-h inputHeight] [-w inputWidth]\n");
  470. fprintf(stderr, " [-H paperHeight] [-W paperWidth]\n");
  471. exit(1);
  472. }
  473. void handler()
  474. {
  475. paused = !paused;
  476. if(paused)
  477. fprintf(stderr, "%s: got SIGUSR1, printing will pause after the next page.\n", ProcName);
  478. else
  479. fprintf(stderr, "%s: got SIGUSR1, printing will resume at the next opportunity.\n", ProcName);
  480. }
  481. void cleanup()
  482. {
  483. fprintf(stderr, "%s: Caught a signal, resetting printer.\n", ProcName);
  484. #if ATALK
  485. if(atalk_connection)
  486. {
  487. at_printer_kill();
  488. }
  489. else
  490. #endif
  491. {
  492. /* Reset the printer and eject the page. */
  493. ejectAndReset();
  494. }
  495. fprintf(stderr, "%s: printing stopped, exiting.\n", ProcName);
  496. exit(0);
  497. }
  498. int printStdin(void)
  499. {
  500. long lastRow, curRow;
  501. long printwidth, printheight;
  502. unsigned char *bufK, *lastK;
  503. unsigned char *lastMark, *dataBuf, *curMark, *tempMark;
  504. unsigned char *bufC = nil, *bufM = nil, *bufY = nil, *lastC = nil, *lastM = nil, *lastY = nil;
  505. long result;
  506. int retry;
  507. result = readFileHeader();
  508. if(result != 0)
  509. return(result);
  510. if(verbose)
  511. {
  512. fprintf(stderr, "%s: Got a valid header, input image is %dx%d.\n",
  513. ProcName, (int)width, (int)height);
  514. }
  515. /* This may modify margins, etc. */
  516. printerSetup();
  517. /* start on the data */
  518. rowbytes = (width + 7) >> 3;
  519. printwidth = rowbytes - LEFT_MARGIN_BYTES;
  520. if(printwidth > PRINT_ROWBYTES)
  521. printwidth = PRINT_ROWBYTES;
  522. printheight = height;
  523. if(printheight > PRINT_HEIGHT + TOP_MARGIN)
  524. printheight = PRINT_HEIGHT + TOP_MARGIN;
  525. /* this buffer is intentionally too big. */
  526. dataBuf = malloc(MAX_BUFFER * 2);
  527. bufK = malloc(rowbytes + 8);
  528. lastK = malloc(rowbytes + 8);
  529. /* Check for malloc errors */
  530. if((!bufK) || (!lastK) || (!dataBuf))
  531. {
  532. print_error("Couldn't allocate buffers");
  533. return(-1);
  534. }
  535. else
  536. {
  537. print_info("Buffers have been allocated.");
  538. }
  539. if(fileIsColor && canPrintColor)
  540. {
  541. bufC = malloc(rowbytes + 8);
  542. bufM = malloc(rowbytes + 8);
  543. bufY = malloc(rowbytes + 8);
  544. lastC = malloc(rowbytes + 8);
  545. lastM = malloc(rowbytes + 8);
  546. lastY = malloc(rowbytes + 8);
  547. if((!bufC) || (!bufM) || (!bufY) || (!lastC) || (!lastM) || (!lastY))
  548. {
  549. print_error("Couldn't allocate color buffers");
  550. return(-1);
  551. }
  552. else
  553. {
  554. print_info("Color buffers have been allocated.");
  555. }
  556. }
  557. for(curRow = 0;curRow < TOP_MARGIN;curRow++)
  558. {
  559. /* read in a scanline and ignore it */
  560. readFileScanline(nil, nil, nil, nil);
  561. }
  562. print_info("Skipped top margin.");
  563. curMark = lastMark = dataBuf;
  564. lastRow = curRow;
  565. /* Make sure the "previous" line looks blank. */
  566. memset(lastK, 0, rowbytes + 8);
  567. if(lastC)
  568. memset(lastC, 0, rowbytes + 8);
  569. if(lastM)
  570. memset(lastM, 0, rowbytes + 8);
  571. if(lastY)
  572. memset(lastY, 0, rowbytes + 8);
  573. print_info("Encoding data...");
  574. for(;;)
  575. {
  576. if(curRow < height)
  577. {
  578. /* read a scanline */
  579. result = readFileScanline(bufK, bufC, bufM, bufY);
  580. /* check for input problems */
  581. if(result != rowbytes)
  582. {
  583. print_error("Error reading input file or pipe");
  584. /* eject the page and reset the printer */
  585. ejectAndReset();
  586. return(-1);
  587. }
  588. }
  589. else
  590. {
  591. /* fake it */
  592. memset(bufK, 0, rowbytes);
  593. }
  594. curRow++;
  595. /* encode the scanline */
  596. switch(printerType)
  597. {
  598. case KIND_SW1:
  599. /* encode the scanline into the buffer */
  600. curMark += appendEncode(printwidth, bufK + LEFT_MARGIN_BYTES, nil, curMark);
  601. break;
  602. case KIND_SW1500:
  603. case KIND_SW2200:
  604. case KIND_SW2400:
  605. case KIND_SW2500:
  606. if(fileIsColor && canPrintColor)
  607. {
  608. curMark += appendEncode(printwidth, bufC + LEFT_MARGIN_BYTES, lastC + LEFT_MARGIN_BYTES, curMark);
  609. curMark += appendEncode(printwidth, bufM + LEFT_MARGIN_BYTES, lastM + LEFT_MARGIN_BYTES, curMark);
  610. curMark += appendEncode(printwidth, bufY + LEFT_MARGIN_BYTES, lastY + LEFT_MARGIN_BYTES, curMark);
  611. }
  612. /* FALLTHROUGH */
  613. default:
  614. curMark += appendEncode(printwidth, bufK + LEFT_MARGIN_BYTES, lastK + LEFT_MARGIN_BYTES, curMark);
  615. break;
  616. }
  617. /* swap the buffers */
  618. tempMark = lastK; lastK = bufK; bufK = tempMark;
  619. if(fileIsColor && canPrintColor)
  620. {
  621. tempMark = lastC; lastC = bufC; bufC = tempMark;
  622. tempMark = lastM; lastM = bufM; bufM = tempMark;
  623. tempMark = lastY; lastY = bufY; bufY = tempMark;
  624. }
  625. /* if this chunk put us over the buffer limit... */
  626. if((curMark - dataBuf >= MAX_BUFFER) || (curRow >= printheight))
  627. {
  628. if(curMark - dataBuf < MAX_BUFFER)
  629. {
  630. /* This is the last bit. */
  631. lastMark = curMark;
  632. curRow++;
  633. }
  634. /* wait for a not-busy status */
  635. waitNonBusy(0);
  636. do
  637. {
  638. retry = 0;
  639. /* send the last batch of scanlines */
  640. print_info("Ready to send a block of image data...");
  641. sendrect(lastRow - TOP_MARGIN, 0,
  642. (curRow-2) - TOP_MARGIN, PRINT_WIDTH);
  643. sendEncodedData(dataBuf, (lastMark - dataBuf));
  644. print_info("data sent.");
  645. if(lastRow - TOP_MARGIN == 0)
  646. {
  647. /* This is the first part of the page. */
  648. /* Wait long enough to make sure the printer knows if it's out of paper... */
  649. waitNonBusy(1);
  650. if(getStatus('2') == 4)
  651. {
  652. switch(printerType)
  653. {
  654. default:
  655. /* the printer is out of paper. */
  656. print_error("The printer is out of paper -- trying again in 30 seconds...");
  657. ejectAndReset();
  658. retry = 1;
  659. sleep(30);
  660. break;
  661. case KIND_SW1500:
  662. case KIND_SW2200:
  663. case KIND_SW2400:
  664. case KIND_SW2500:
  665. do
  666. {
  667. print_error("The printer is out of paper -- trying to continue in 5 seconds...");
  668. sleep(5);
  669. comm_printer_writeFFFx('S');
  670. }
  671. while(getStatus('2') == 4);
  672. break;
  673. }
  674. }
  675. }
  676. } while(retry);
  677. if(lastMark != curMark)
  678. {
  679. /* Re-encode the last scanline */
  680. print_info("Encoding data...");
  681. curMark = dataBuf;
  682. /* (no differencing) */
  683. switch(printerType)
  684. {
  685. case KIND_SW1500:
  686. case KIND_SW2200:
  687. case KIND_SW2400:
  688. case KIND_SW2500:
  689. if(fileIsColor && canPrintColor)
  690. {
  691. curMark += appendEncode(printwidth, lastC + LEFT_MARGIN_BYTES, nil, curMark);
  692. curMark += appendEncode(printwidth, lastM + LEFT_MARGIN_BYTES, nil, curMark);
  693. curMark += appendEncode(printwidth, lastY + LEFT_MARGIN_BYTES, nil, curMark);
  694. }
  695. /* FALLTHROUGH */
  696. default:
  697. curMark += appendEncode(printwidth, lastK + LEFT_MARGIN_BYTES, nil, curMark);
  698. lastRow = curRow-1;
  699. break;
  700. }
  701. }
  702. else
  703. {
  704. /* we're done with the page */
  705. print_info("Done with page.");
  706. break;
  707. }
  708. }
  709. lastMark = curMark;
  710. }
  711. /* This was adjusted to do the last bit of the page -- adjust it back. */
  712. curRow--;
  713. print_info("Skipping bottom margin.");
  714. /* skip any extra lines in the input file */
  715. for(;curRow < height;curRow++)
  716. {
  717. /* read in a scanline and ignore it */
  718. readFileScanline(nil, nil, nil, nil);
  719. }
  720. print_info("Skipped bottom margin.");
  721. /* wait for a not-busy status */
  722. waitNonBusy(0);
  723. /* finish printing the page */
  724. finishPage();
  725. /* clean up buffers */
  726. free(bufK);
  727. free(dataBuf);
  728. if(bufC) free(bufC);
  729. if(bufM) free(bufM);
  730. if(bufY) free(bufY);
  731. if(lastC) free(lastC);
  732. if(lastM) free(lastM);
  733. if(lastY) free(lastY);
  734. return(0);
  735. }
  736. int readFileHeader(void)
  737. {
  738. int c, i;
  739. char smallBuf[32];
  740. fileIsColor = 0;
  741. switch(fileType)
  742. {
  743. case FILE_PBMRAW:
  744. /* read the file header (including height and width) */
  745. height = -1;
  746. do
  747. {
  748. c = inputGetc();
  749. switch(c)
  750. {
  751. case -1:
  752. /* end of file -- we're done here. Note that this is not an error */
  753. return(1);
  754. break;
  755. case '#':
  756. /* comment line -- skip it */
  757. while((c = inputGetc()) != 0x0A)
  758. ;
  759. break;
  760. case ' ': case '\n': case '\t':
  761. /* random whitespace... just ignore it. */
  762. break;
  763. case 'P':
  764. /* magic number */
  765. if((c = inputGetc()) != '4')
  766. {
  767. /* bad magic number */
  768. print_error("Bad magic number in input file");
  769. return(-1);
  770. }
  771. /* there should be one whitespace character */
  772. break;
  773. case '0': case '1': case '2': case '3': case '4':
  774. case '5': case '6': case '7': case '8': case '9':
  775. /* read width */
  776. smallBuf[0] = c;
  777. for(i=1;isdigit(c = inputGetc()) && (i < sizeof(smallBuf));i++)
  778. smallBuf[i] = c;
  779. if(!isspace(c))
  780. {
  781. print_error("Bad input file format");
  782. }
  783. smallBuf[i] = 0;
  784. width = atoi(smallBuf);
  785. /* read height */
  786. for(i=0;isdigit(c = inputGetc()) && (i < sizeof(smallBuf));i++)
  787. smallBuf[i] = c;
  788. if(!isspace(c))
  789. {
  790. print_error("Bad input file format");
  791. }
  792. smallBuf[i] = 0;
  793. height = atoi(smallBuf);
  794. break;
  795. default:
  796. print_error("Bad header format in input file");
  797. return(-1);
  798. break;
  799. }
  800. }while(height == -1);
  801. /* the header has been taken care of. The rest of the file is just image data. */
  802. break;
  803. case FILE_BITCMYK:
  804. fileIsColor = 1;
  805. print_info("Input file is in color.");
  806. /* FALLTHROUGH */
  807. case FILE_BIT:
  808. /* These files have no header, but we can make sure we were given
  809. a height and width...
  810. */
  811. if((height == -1) || (width == -1))
  812. {
  813. fprintf(stderr, "%s: Width and height must be specified for 'bit' and 'bitcmyk' files.\n",
  814. ProcName);
  815. return(-1);
  816. }
  817. c = inputGetc();
  818. if(c == -1)
  819. {
  820. /* We're done. Note that this is not an error. */
  821. return(1);
  822. }
  823. else
  824. {
  825. inputPutback(c);
  826. }
  827. break;
  828. }
  829. return(0);
  830. }
  831. size_t readFileScanline(char *bufK, char *bufC, char *bufM, char *bufY)
  832. {
  833. static char *inputBuf = nil;
  834. static size_t inputSize = 0;
  835. size_t result = 0;
  836. switch(fileType)
  837. {
  838. case FILE_PBMRAW:
  839. case FILE_BIT:
  840. /* These two are the same, after the header. */
  841. if(bufK)
  842. {
  843. result = inputRead(bufK, rowbytes);
  844. }
  845. else
  846. {
  847. /* the black buffer is nil -- read into a dummy buffer. */
  848. if(inputSize < rowbytes)
  849. {
  850. /* reallocate the buffer */
  851. if(inputBuf)
  852. free(inputBuf);
  853. inputBuf = malloc(rowbytes);
  854. inputSize = rowbytes;
  855. }
  856. result = inputRead(inputBuf, rowbytes);
  857. }
  858. break;
  859. case FILE_BITCMYK:
  860. {
  861. size_t filerowbytes = ((width * 4) + 7) >> 3;
  862. if(inputSize < filerowbytes)
  863. {
  864. /* reallocate the buffer */
  865. if(inputBuf)
  866. free(inputBuf);
  867. inputBuf = malloc(filerowbytes);
  868. inputSize = filerowbytes;
  869. }
  870. if(inputRead(inputBuf, filerowbytes) != filerowbytes)
  871. {
  872. result = 0;
  873. return(result);
  874. }
  875. else
  876. {
  877. result = rowbytes;
  878. }
  879. if(!bufK)
  880. {
  881. /* skip the hard part. */
  882. return(result);
  883. }
  884. /* ASSUMPTION: any extra bits in the file (due to rowbytes) are 0. */
  885. /* NOTE: I haven't thought through whether this code will work on a
  886. little-endian system. Caveat emptor.
  887. */
  888. /* Convert the bits from chunky to planar */
  889. /* NOTE: This is probably the worst way to do this, but I'm not feeling
  890. inspired at the moment. It should work, and I can replace it later
  891. with something more efficient.
  892. */
  893. if(bufC && bufM && bufY)
  894. {
  895. register unsigned long byte, i;
  896. register unsigned long cmyk = 0;
  897. register unsigned char *input = (unsigned char*)inputBuf;
  898. /* full color */
  899. for(i = 0; i < filerowbytes; i++)
  900. {
  901. static unsigned long bitsTable[] = {
  902. 0x00000000, 0x00000001, 0x00000100, 0x00000101,
  903. 0x00010000, 0x00010001, 0x00010100, 0x00010101,
  904. 0x01000000, 0x01000001, 0x01000100, 0x01000101,
  905. 0x01010000, 0x01010001, 0x01010100, 0x01010101
  906. };
  907. /* get the input */
  908. byte = (*input++) & 0x000000FF;
  909. /* shift everything */
  910. cmyk <<= 2;
  911. /* extract the bits from this nibble */
  912. cmyk |= (bitsTable[(byte >> 4) & 0x0000000F]) << 1;
  913. cmyk |= bitsTable[byte & 0x0000000F];
  914. if((i & 0x03) == 0)
  915. {
  916. /* write the output */
  917. *((unsigned char *)bufK++) = cmyk & 0x000000FF; cmyk >>= 8;
  918. *((unsigned char *)bufY++) = cmyk & 0x000000FF; cmyk >>= 8;
  919. *((unsigned char *)bufM++) = cmyk & 0x000000FF; cmyk >>= 8;
  920. *((unsigned char *)bufC++) = cmyk & 0x000000FF;
  921. cmyk = 0;
  922. }
  923. }
  924. /* Even up the bytes */
  925. for(;(i & 0x03) != 0;i++)
  926. {
  927. /* shift everything */
  928. cmyk <<= 2;
  929. }
  930. /* write the final part */
  931. *((unsigned char *)bufK++) = cmyk & 0x000000FF; cmyk >>= 8;
  932. *((unsigned char *)bufY++) = cmyk & 0x000000FF; cmyk >>= 8;
  933. *((unsigned char *)bufM++) = cmyk & 0x000000FF; cmyk >>= 8;
  934. *((unsigned char *)bufC++) = cmyk & 0x000000FF;
  935. }
  936. else
  937. {
  938. register int byte, i;
  939. register char *input = inputBuf;
  940. register int k = 0;
  941. /* Black channel only */
  942. for(i = 0; i < filerowbytes; i++)
  943. {
  944. /* get the input */
  945. byte = *input++;
  946. /* shift everything */
  947. k <<= 2;
  948. if(byte & 0x10){k |= 2;}
  949. if(byte & 0x01){k |= 1;}
  950. if((i & 0x03) == 0)
  951. {
  952. /* write the output */
  953. *bufK++ = k;
  954. }
  955. }
  956. /* Even up the bytes */
  957. for(;(i & 0x03) != 0;i++)
  958. {
  959. /* shift everything */
  960. k <<= 2;
  961. }
  962. /* write the final byte */
  963. *bufK++ = k;
  964. }
  965. }
  966. break;
  967. }
  968. return(result);
  969. }
  970. size_t appendEncode(size_t length, char *in, char *last, char *out)
  971. {
  972. static char delta[1024]; /* bigger than we'll ever need */
  973. size_t result = 0;
  974. if(last)
  975. {
  976. /* XOR the input with the last scanline */
  977. unsigned char *src1 = in, *src2 = last, *dst = delta;
  978. size_t size = length;
  979. for(;size > 0; size--)
  980. *dst++ = (*src1++) ^ (*src2++);
  981. /* encode the difference into the buffer */
  982. result = encodescanline(delta, length, out);
  983. }
  984. else
  985. {
  986. /* encode the scanline into the buffer */
  987. result = encodescanline(in, length, out);
  988. }
  989. return(result);
  990. }
  991. void ejectAndReset(void)
  992. {
  993. /* Eject the page and reset the printer. */
  994. comm_printer_writeFFFx('I');
  995. }
  996. void finishPage(void)
  997. {
  998. int c;
  999. /* Print the last part of the page. */
  1000. switch(printerType)
  1001. {
  1002. default:
  1003. print_info("finishpage: sending \"0x0C\"");
  1004. comm_printer_writestring("\x0C");
  1005. do
  1006. {
  1007. c = getStatus('1');
  1008. if(verbose > 2)
  1009. {
  1010. fprintf(stderr, "%s: status(1) = 0x%X. \n",
  1011. ProcName, c);
  1012. }
  1013. usleep(USLEEP_TIME);
  1014. }while(c == 1);
  1015. waitNonBusy(0);
  1016. /* XXX -- This may not be necessary */
  1017. /*
  1018. print_info("finishpage: sending \"El\"");
  1019. comm_printer_writestring("El");
  1020. */
  1021. break;
  1022. case KIND_SW1:
  1023. print_info("finishpage: sending \"0x0C\"");
  1024. comm_printer_writestring("\x0C");
  1025. waitNonBusy(0);
  1026. break;
  1027. }
  1028. }
  1029. void waitNonBusy(int canHandlePaperOut)
  1030. {
  1031. print_info("About to wait for a non-busy status...");
  1032. switch(printerType)
  1033. {
  1034. case KIND_SW1500:
  1035. if(canPrintColor)
  1036. {
  1037. /* It seems 1500 sends different "wait" status code when color ink
  1038. cartridge is installed. <toe@unlinfo.unl.edu> */
  1039. waitStatus(0x87, canHandlePaperOut);
  1040. }
  1041. else
  1042. {
  1043. waitStatus(0x9F, canHandlePaperOut);
  1044. }
  1045. break;
  1046. case KIND_SW2500:
  1047. waitStatus(0x80, canHandlePaperOut);
  1048. break;
  1049. case KIND_SW2200:
  1050. waitStatus(0xA3, canHandlePaperOut);
  1051. break;
  1052. case KIND_SW1:
  1053. waitStatus(0xA0, canHandlePaperOut);
  1054. break;
  1055. default:
  1056. waitStatus(0xF8, canHandlePaperOut);
  1057. break;
  1058. }
  1059. #ifdef ATALK
  1060. if(atalk_connection)
  1061. {
  1062. char buf[2];
  1063. buf[0] = 0;
  1064. adsp_write_attn(&end2, 0x0006, buf, 1);
  1065. adsp_read(&end2, buf, 2);
  1066. buf[0] = 0;
  1067. adsp_write_attn(&end2, 0x0006, buf, 1);
  1068. adsp_read(&end2, buf, 2);
  1069. }
  1070. #endif
  1071. }
  1072. #define MAX_RUN 0x3E
  1073. #define MAX_BLOCK 0x3E
  1074. #define RUN_THRESH 0x01
  1075. #define DATA_WHITE 0x00
  1076. #define DATA_BLACK 0xFF
  1077. #define DATA_OTHER 0x0A
  1078. #define MASK_RUNWHT 0x80
  1079. #define MASK_RUNBLK 0xC0
  1080. #define MASK_RUNDATA 0x00
  1081. size_t encodescanline(unsigned char *src, size_t srcLen, unsigned char *dst)
  1082. {
  1083. register signed long s, d, i, runStart, runLen;
  1084. unsigned char runChar;
  1085. /* SPECIAL CASE: check for a blank line */
  1086. for(i=0;i < srcLen;i++)
  1087. if(src[i] != DATA_WHITE)
  1088. break;
  1089. if(i == srcLen)
  1090. {
  1091. *dst = MASK_RUNWHT;
  1092. return(1);
  1093. }
  1094. s = d = 0;
  1095. while(s < srcLen)
  1096. {
  1097. runStart = runLen = 0;
  1098. runChar = DATA_OTHER; /* Just so long as it's not black or white... */
  1099. /* Find the first run */
  1100. for(i = s; (i < srcLen); i++)
  1101. {
  1102. if((runChar == DATA_WHITE) || (runChar == DATA_BLACK))
  1103. {
  1104. if(src[i] != runChar)
  1105. { /* This run is over */
  1106. if(i - runStart >= RUN_THRESH)
  1107. { /* The run was long enough to count. Break out. */
  1108. break;
  1109. }
  1110. else
  1111. { /* The run was too short to count. */
  1112. runChar = DATA_OTHER;
  1113. }
  1114. }
  1115. else
  1116. {
  1117. if(i - runStart >= MAX_RUN)
  1118. { /* This is enough of a run to encode. */
  1119. break;
  1120. }
  1121. }
  1122. }
  1123. else
  1124. { /* runChar == DATA_OTHER */
  1125. if((src[i] == DATA_WHITE) || (src[i] == DATA_BLACK))
  1126. { /* Start a run */
  1127. runChar = src[i];
  1128. runStart = i;
  1129. }
  1130. else if(i - s >= MAX_BLOCK)
  1131. { /* This block is the maximum length. */
  1132. break;
  1133. }
  1134. }
  1135. } /* end for */
  1136. if(runChar != DATA_OTHER)
  1137. {
  1138. /* We were in a run when we broke out. */
  1139. runLen = i - runStart;
  1140. }
  1141. else
  1142. {
  1143. runStart = i;
  1144. runLen = 0;
  1145. }
  1146. if(runStart != s)
  1147. {
  1148. /* Encode a run of random data */
  1149. dst[d++] = runStart - s;
  1150. for(;s < runStart;)
  1151. dst[d++] = src[s++];
  1152. }
  1153. if(runLen > 0)
  1154. {
  1155. /* Encode a run of black or white */
  1156. if(runChar == DATA_BLACK)
  1157. dst[d++] = MASK_RUNBLK + runLen;
  1158. else
  1159. {
  1160. if(s + runLen < srcLen)
  1161. dst[d++] = MASK_RUNWHT + runLen;
  1162. else
  1163. break; /* Let this be taken up with the padding. */
  1164. }
  1165. s += runLen;
  1166. }
  1167. } /* end while */
  1168. /* pad out to the width of the page with white */
  1169. for(;s < PRINT_ROWBYTES;)
  1170. {
  1171. runLen = PRINT_ROWBYTES - s;
  1172. if(runLen > MAX_RUN)
  1173. runLen = MAX_RUN;
  1174. dst[d++] = MASK_RUNWHT + runLen;
  1175. s += runLen;
  1176. }
  1177. return(d);
  1178. }
  1179. void sendEncodedData(unsigned char *buffer, size_t size)
  1180. {
  1181. unsigned char begin[4];
  1182. unsigned char save;
  1183. if(verbose)
  1184. {
  1185. fprintf(stderr, "%s: Sending encoded data (0x%x bytes).\n",
  1186. ProcName, size);
  1187. }
  1188. begin[0] = 'G';
  1189. begin[1] = size & 0x000000FF;
  1190. begin[2] = size >> 8;
  1191. comm_printer_write(begin, 3);
  1192. save = buffer[size];
  1193. buffer[size] = 0;
  1194. comm_printer_write(buffer, size+1);
  1195. buffer[size] = save;
  1196. }
  1197. void sendrect(long top, long left, long bottom, long right)
  1198. {
  1199. unsigned char buffer[9];
  1200. if(verbose)
  1201. {
  1202. fprintf(stderr, "%s: Sending rect %ld,%ld,%ld,%ld.\n",
  1203. ProcName, top, left, bottom, right);
  1204. }
  1205. /* top = 0, bottom = 0xb5 */
  1206. /* left = 0;
  1207. right = PRINT_WIDTH; */
  1208. if(fileIsColor && canPrintColor)
  1209. buffer[0] = 'c';
  1210. else
  1211. buffer[0] = 'R';
  1212. buffer[1] = left & 0x000000FF;
  1213. buffer[2] = left >> 8;
  1214. buffer[3] = top & 0x000000FF;
  1215. buffer[4] = top >> 8;
  1216. buffer[5] = right & 0x000000FF;
  1217. buffer[6] = right >> 8;
  1218. buffer[7] = bottom & 0x000000FF;
  1219. buffer[8] = bottom >> 8;
  1220. comm_printer_write(buffer, 9);
  1221. }
  1222. int inputGetc(void)
  1223. {
  1224. unsigned char c;
  1225. size_t length;
  1226. unsigned long result = 0;
  1227. length = inputRead(&c, 1);
  1228. result = c;
  1229. if(length == 1)
  1230. return(result);
  1231. else
  1232. return(-1);
  1233. }
  1234. void printerSetup(void)
  1235. {
  1236. char smallBuf[32];
  1237. int c, c1, c2, i;
  1238. if(doReset)
  1239. {
  1240. print_info("Resetting printer...");
  1241. ejectAndReset();
  1242. sleep(2);
  1243. #if 1
  1244. do
  1245. {
  1246. usleep(USLEEP_TIME);
  1247. c1 = getStatus('1');
  1248. c2 = getStatus('2');
  1249. c = getStatus('B');
  1250. if(verbose > 2)
  1251. {
  1252. fprintf(stderr, "%s: printer state 1 = 0x%X, 2 = 0x%X, B = 0x%X, \n",
  1253. ProcName, c1, c2, c);
  1254. }
  1255. /* The SW1 shows readiness this way. */
  1256. if((c1 == 1) && (c2 == 0) && (c == 0xA0))
  1257. break;
  1258. }while((c1 == 1) || (c1 == -1));
  1259. #endif
  1260. print_info("Identifying printer...");
  1261. comm_printer_writestring("?");
  1262. usleep(USLEEP_TIME); /* wait long enough for the printer to respond. */
  1263. for(i=0;((c = comm_printer_getc_block()) != -1) && (i < sizeof(smallBuf)-1); i++)
  1264. {
  1265. if(c == 0x0D)
  1266. break;
  1267. smallBuf[i] = c;
  1268. usleep(USLEEP_TIME);
  1269. }
  1270. smallBuf[i] = 0;
  1271. if((c == -1) && (errno != EAGAIN))
  1272. {
  1273. print_error("Something went wrong reading from the printer...");
  1274. fprintf(stderr, "%s: fatal error, exiting.\n", ProcName);
  1275. exit(1);
  1276. }
  1277. /* What kind of printer is it? */
  1278. if(i == 0)
  1279. {
  1280. print_error("Error reading from printer. Is it connected and turned on?");
  1281. fprintf(stderr, "%s: fatal error, exiting.\n", ProcName);
  1282. exit(1);
  1283. }
  1284. else if(!strcmp(smallBuf, "IJ10"))
  1285. {
  1286. printerType = KIND_SW1;
  1287. print_info("Printer is a StyleWriter I.");
  1288. }
  1289. else if(!strcmp(smallBuf, "SW"))
  1290. {
  1291. printerType = KIND_SW2;
  1292. print_info("Printer is a StyleWriter II.");
  1293. }
  1294. else if(!strcmp(smallBuf, "SW3"))
  1295. {
  1296. printerType = KIND_SW3;
  1297. print_info("Printer is a StyleWriter III (1200).");
  1298. }
  1299. else if(!strcmp(smallBuf, "CS"))
  1300. {
  1301. printerType = KIND_SW2400;
  1302. print_info("Printer is a Color StyleWriter 1500, 2200, 2400 or 2500.");
  1303. }
  1304. else
  1305. {
  1306. fprintf(stderr, "%s: Unknown printer ID string \"%s\". Treating it like a StyleWriter II. (Be amazed if this works.)\n",
  1307. ProcName, smallBuf);
  1308. printerType = KIND_SW2;
  1309. }
  1310. /* Printer-specific setup */
  1311. canPrintColor = 0;
  1312. switch(printerType)
  1313. {
  1314. case KIND_SW1:
  1315. /* The buffer on the SW1 is smaller. */
  1316. MAX_BUFFER = 0x00002000;
  1317. /* Otherwise, it's just like the others. */
  1318. /* FALLTHROUGH */
  1319. default:
  1320. PRINT_WIDTH = 2879; /* (360 dpi * 8 inches) - 1 */
  1321. LEFT_MARGIN = 90; /* 0.25 inches * 360 dpi */
  1322. TOP_MARGIN = 90; /* 0.25 inches * 360 dpi */
  1323. BOTTOM_MARGIN = 90; /* 0.25 inches * 360 dpi */
  1324. break;
  1325. case KIND_SW1500:
  1326. case KIND_SW2200:
  1327. case KIND_SW2400:
  1328. case KIND_SW2500:
  1329. i = getStatus('p');
  1330. if (verbose)
  1331. fprintf(stderr, "%s: status(p) = 0x%x\n", ProcName, i);
  1332. switch(i)
  1333. {
  1334. case 0x01:
  1335. print_info("Looks like the printer is really a 2400.");
  1336. printerType = KIND_SW2400;
  1337. break;
  1338. case 0x02:
  1339. print_info("Looks like the printer is really a 2200.");
  1340. printerType = KIND_SW2200;
  1341. break;
  1342. case 0x04:
  1343. print_info("Looks like the printer is really a 1500.");
  1344. printerType = KIND_SW1500;
  1345. break;
  1346. case 0x05:
  1347. print_info("Looks like the printer is really a 2500.");
  1348. printerType = KIND_SW2500;
  1349. break;
  1350. default:
  1351. print_info("Unknown printer subtype! Treating it like a 2400.");
  1352. printerType = KIND_SW2400;
  1353. break;
  1354. }
  1355. comm_printer_writestring("D");
  1356. i = getStatus('H');
  1357. if (verbose)
  1358. fprintf(stderr, "%s: status(H) = 0x%x\n", ProcName, i);
  1359. if(i & 0x0080)
  1360. {
  1361. print_info("A color ink cartridge is installed.");
  1362. canPrintColor = 1;
  1363. }
  1364. else
  1365. {
  1366. print_info("A black ink cartridge is installed.");
  1367. }
  1368. switch(printQuality)
  1369. {
  1370. default:
  1371. comm_printer_writestring("m0nZAH");
  1372. break;
  1373. case 2:
  1374. comm_printer_writestring("m0sAB");
  1375. i = getStatus('R');
  1376. if (verbose)
  1377. fprintf(stderr, "%s: status(R) = 0x%x\n", ProcName, i);
  1378. break;
  1379. comm_printer_writestring("N");
  1380. break;
  1381. }
  1382. /* This thing has a larger buffer,... */
  1383. MAX_BUFFER = 0x00008000;
  1384. /* ...larger print area... */
  1385. PRINT_WIDTH = 2919; /* = (360 dpi * 8.1111....") - 1 */
  1386. LEFT_MARGIN = 72; /* about 0.2" * 360 dpi */
  1387. TOP_MARGIN = 90; /* 0.25 inches * 360 dpi */
  1388. BOTTOM_MARGIN = 90; /* 0.25 inches * 360 dpi */
  1389. /* I think this should work, but it seems to be causing
  1390. errors printing certain files. I'll disable it for now...
  1391. */
  1392. /* TOP_MARGIN = 45;*/ /* about 0.12" * 360 */
  1393. /* BOTTOM_MARGIN = 45;*/ /* about 0.12" * 360 */
  1394. break;
  1395. }
  1396. if(noMargins)
  1397. {
  1398. BOTTOM_MARGIN += TOP_MARGIN;
  1399. TOP_MARGIN = 0;
  1400. LEFT_MARGIN = 0;
  1401. }
  1402. fixPageSizes();
  1403. print_info("The printer is now set up.");
  1404. }
  1405. /* Do as little as needed to start a new page. */
  1406. switch(printerType)
  1407. {
  1408. case KIND_SW1:
  1409. default:
  1410. comm_printer_writestring("nuA");
  1411. break;
  1412. case KIND_SW1500:
  1413. case KIND_SW2200:
  1414. case KIND_SW2400:
  1415. case KIND_SW2500:
  1416. comm_printer_writestring("L");
  1417. break;
  1418. }
  1419. }
  1420. size_t comm_printer_read(void *buffer, size_t size)
  1421. {
  1422. size_t result;
  1423. #ifdef ATALK
  1424. if(atalk_connection)
  1425. {
  1426. result = adsp_read_nonblock(&end2, (char*)buffer, size);
  1427. }
  1428. else
  1429. #endif
  1430. {
  1431. int flags;
  1432. flags = fcntl(1, F_GETFL, 0);
  1433. fcntl(1, F_SETFL, flags | O_NONBLOCK);
  1434. result = read(1, buffer, size);
  1435. fcntl(1, F_SETFL, flags);
  1436. }
  1437. return(result);
  1438. }
  1439. size_t comm_printer_write(void *buffer, size_t size)
  1440. {
  1441. size_t result;
  1442. #ifdef ATALK
  1443. if(atalk_connection)
  1444. {
  1445. result = adsp_write(&end2, (char*)buffer, size);
  1446. }
  1447. else
  1448. #endif
  1449. {
  1450. result = write(1, buffer, size);
  1451. }
  1452. return(result);
  1453. }
  1454. size_t comm_printer_writestring(char *buffer)
  1455. {
  1456. return(comm_printer_write(buffer, strlen(buffer)));
  1457. }
  1458. int comm_printer_getc(void)
  1459. {
  1460. unsigned char c[1];
  1461. size_t length;
  1462. unsigned long result = 0;
  1463. length = comm_printer_read(c, 1);
  1464. result = c[0];
  1465. if(length == 1)
  1466. return(result);
  1467. else
  1468. return(-1);
  1469. }
  1470. void printerFlushInput(void)
  1471. {
  1472. int flags;
  1473. char dummy[2];
  1474. flags = fcntl(1, F_GETFL, 0);
  1475. fcntl(1, F_SETFL, flags | O_NONBLOCK);
  1476. while(read(1, dummy, 1) != EAGAIN)
  1477. {
  1478. /* discard these characters */
  1479. }
  1480. fcntl(1, F_SETFL, flags);
  1481. }
  1482. void comm_printer_writeFFFx(char x)
  1483. {
  1484. unsigned char string[4];
  1485. string[0] = string[1] = string[2] = 0xFF;
  1486. string[3] = x;
  1487. comm_printer_write(string, 4);
  1488. }
  1489. void print_error(char *s)
  1490. {
  1491. /* Do something appropriate with error messages... */
  1492. fprintf(stderr, "%s: %s (%d)\n",
  1493. ProcName, s, errno);
  1494. }
  1495. void print_info(char *s)
  1496. {
  1497. /* Print out a status message */
  1498. if(verbose)
  1499. fprintf(stderr, "%s: %s\n", ProcName, s);
  1500. }
  1501. int comm_printer_getc_block(void)
  1502. {
  1503. int result;
  1504. int i;
  1505. /* wait up to about ten seconds... */
  1506. for(i = 100; i > 0; i--)
  1507. {
  1508. result = comm_printer_getc();
  1509. if(result != -1)
  1510. break;
  1511. else if(errno != EAGAIN)
  1512. {
  1513. /* Something more drastic than no pending input */
  1514. /* MBW -- XXX -- What should happen here? */
  1515. perror("read");
  1516. break;
  1517. }
  1518. usleep(USLEEP_TIME);
  1519. }
  1520. if(result == -1)
  1521. {
  1522. /* Timeout waiting for input from the printer */
  1523. /* MBW -- XXX -- What should happen here? */
  1524. }
  1525. return(result);
  1526. }
  1527. int getStatus(int which)
  1528. {
  1529. comm_printer_writeFFFx(which);
  1530. return(comm_printer_getc_block());
  1531. }
  1532. void waitStatus(int stat, int canHandlePaperOut)
  1533. {
  1534. int c, last = stat;
  1535. int c1 = 0, c2 = 0, last1 = 0, last2 = 0;
  1536. last1 = c1 = getStatus('1');
  1537. last2 = c2 = getStatus('2');
  1538. last = c = getStatus('B');
  1539. while(c != stat)
  1540. {
  1541. usleep(USLEEP_TIME);
  1542. if(verbose)
  1543. {
  1544. if((c != last) || (c1 != last1) || (c2 != last2) || (verbose > 2))
  1545. {
  1546. fprintf(stderr, "%s: printer state 1 = 0x%X, 2 = 0x%X, B = 0x%X, \n",
  1547. ProcName, c1, c2, c);
  1548. }
  1549. }
  1550. switch(c2)
  1551. {
  1552. case 4: /* The printer is out of paper... */
  1553. if(canHandlePaperOut)
  1554. {
  1555. /* The caller will detect and deal with out-of-paper conditions. */
  1556. return;
  1557. }
  1558. switch(printerType)
  1559. {
  1560. default:
  1561. /* MBW -- XXX -- Figure out how to deal with this... */
  1562. fprintf(stderr,
  1563. "%s: The printer is out of paper at a bad time, exiting.\n"
  1564. , ProcName);
  1565. ejectAndReset();
  1566. exit(0);
  1567. break;
  1568. case KIND_SW1500:
  1569. case KIND_SW2200:
  1570. case KIND_SW2400:
  1571. case KIND_SW2500:
  1572. do
  1573. {
  1574. print_error("The printer is out of paper -- trying to continue in 5 seconds...");
  1575. sleep(5);
  1576. comm_printer_writeFFFx('S');
  1577. }
  1578. while(getStatus('2') == 4);
  1579. break;
  1580. }
  1581. break;
  1582. default:
  1583. /* something went wrong... */
  1584. fprintf(stderr,
  1585. "%s: Error code from the printer (0x%X), exiting.\n",
  1586. ProcName, c2);
  1587. ejectAndReset();
  1588. /* Exit code 1 causes lpd to restart and try again.
  1589. I need to think about whether this is the right behavior
  1590. if something is wrong with the printer...
  1591. */
  1592. exit(0);
  1593. break;
  1594. case 0x80:
  1595. case 0:
  1596. /* everything's fine... */
  1597. break;
  1598. }
  1599. last = c;
  1600. last1 = c1;
  1601. last2 = c2;
  1602. c1 = getStatus('1');
  1603. c2 = getStatus('2');
  1604. c = getStatus('B');
  1605. }
  1606. if(verbose)
  1607. {
  1608. fprintf(stderr, "%s: printer state 1 = 0x%X, 2 = 0x%X, B = 0x%X, \n",
  1609. ProcName, c1, c2, c);
  1610. }
  1611. }
  1612. static int inputBack = -1;
  1613. size_t inputRead(void *buffer, size_t size)
  1614. {
  1615. size_t result = 0, len = 0;
  1616. if((inputBack != -1) && (size > result))
  1617. {
  1618. ((char*)buffer)[result] = inputBack & 0x000000FF;
  1619. result++;
  1620. inputBack = -1;
  1621. }
  1622. while(size - result > 0)
  1623. {
  1624. len = read(0, (void*)(((char *)buffer) + result), size - result);
  1625. if(len < 0)
  1626. {
  1627. /* check the error code */
  1628. if(errno != EINTR)
  1629. return(-1);
  1630. else
  1631. {
  1632. print_error("Interrupted system call in input read.");
  1633. usleep(USLEEP_TIME);
  1634. }
  1635. }
  1636. else if(len == 0)
  1637. {
  1638. /* That's all she wrote... */
  1639. return(result);
  1640. }
  1641. else
  1642. result += len;
  1643. }
  1644. return(result);
  1645. }
  1646. void inputPutback(int c)
  1647. {
  1648. inputBack = c;
  1649. }
  1650. #ifdef ATALK
  1651. int at_printer_open(char *name)
  1652. {
  1653. struct printRequest
  1654. {
  1655. u_int32_t port;
  1656. char string[66];
  1657. } __attribute__((packed));
  1658. int result;
  1659. if(verbose > 0)
  1660. {
  1661. fprintf(stderr, "%s:opening appletalk connnection to %s\n",
  1662. ProcName, name);
  1663. }
  1664. if(adsp_open_socket(&s1) < 0)
  1665. {
  1666. fprintf(stderr, "%s:failed to open the socket.\n", ProcName);
  1667. exit(1);
  1668. }
  1669. if(adsp_open_socket(&s2) < 0)
  1670. {
  1671. fprintf(stderr, "%s:failed to open the socket.\n", ProcName);
  1672. exit(1);
  1673. }
  1674. /* Get the status of the printer */
  1675. while(1)
  1676. {
  1677. u_int16_t results, results2;
  1678. char scratch[4];
  1679. if(adsp_connect(&s1, &end1, name) < 0)
  1680. {
  1681. fprintf(stderr, "%s:failed to connect.\n", ProcName);
  1682. exit(1);
  1683. }
  1684. {
  1685. struct printRequest req;
  1686. req.port = htons(s2.local_addr.sat_port);
  1687. strcpy(req.string + 1, atalk_username);
  1688. req.string[0] = strlen(req.string + 1);
  1689. adsp_write_attn(&end1, 0x000b, (char*)&req, sizeof(req));
  1690. }
  1691. if(adsp_read(&end1, (char*)&results, 2) != 2)
  1692. {
  1693. fprintf(stderr, "%s:failed to read result code from printer.\n",
  1694. ProcName);
  1695. exit(1);
  1696. }
  1697. results = ntohs(results);
  1698. if(results == 0)
  1699. {
  1700. break;
  1701. }
  1702. else if(results == 0xFFFF)
  1703. {
  1704. fprintf(stderr, "%s:error opening data connection (%d).\n",
  1705. ProcName, results);
  1706. exit(1);
  1707. }
  1708. else
  1709. {
  1710. u_int16_t jobcount;
  1711. char username[72], status[259];
  1712. /* The printer is busy. */
  1713. scratch[0] = 0;
  1714. adsp_write_attn(&end1, 0x0011, scratch, 1);
  1715. if(adsp_read(&end1, (char*)&jobcount, 2) != 2)
  1716. {
  1717. fprintf(stderr, "%s:failed to read job count from printer.\n",
  1718. ProcName);
  1719. exit(1);
  1720. }
  1721. jobcount = ntohs(jobcount);
  1722. scratch[0] = 0;
  1723. adsp_write_attn(&end1, 0x000e, scratch, 1);
  1724. if(adsp_read(&end1, username, 72) != 72)
  1725. {
  1726. fprintf(stderr, "%s:failed to read user name from printer.\n",
  1727. ProcName);
  1728. exit(1);
  1729. }
  1730. scratch[0] = scratch[1] = 0;
  1731. adsp_write_attn(&end1, 0x0010, scratch, 1);
  1732. if(adsp_read(&end1, status, 259) != 259)
  1733. {
  1734. fprintf(stderr, "%s:failed to read user name from printer.\n",
  1735. ProcName);
  1736. exit(1);
  1737. }
  1738. username[username[6] + 7] = 0;
  1739. status[status[2] + 3] = 0;
  1740. fprintf(stderr,
  1741. "%s:printer busy, %d jobs in queue, user '%s', status '%s'\n",
  1742. ProcName, jobcount, username+7, status+3);
  1743. fprintf(stderr,
  1744. "%s:will retry in 15 seconds.\n",
  1745. ProcName);
  1746. sleep(15);
  1747. }
  1748. scratch[0] = 0;
  1749. adsp_write_attn(&end1, 0x0012, scratch, 1);
  1750. if(adsp_read(&end1, (char*)&results2, 2) != 2)
  1751. {
  1752. fprintf(stderr, "%s:failed to read result code from printer.\n",
  1753. ProcName);
  1754. exit(1);
  1755. }
  1756. adsp_disconnect(&end1);
  1757. if(results == 0 && results2 == 0)
  1758. break;
  1759. }
  1760. do
  1761. {
  1762. result = adsp_listen(&s2, &end2);
  1763. if(result < 0)
  1764. {
  1765. fprintf(stderr, "%s:listen failed.\n", ProcName);
  1766. exit(1);
  1767. }
  1768. } while(result == 0);
  1769. if(adsp_accept(&end2) < 0)
  1770. {
  1771. fprintf(stderr, "%s:accept failed.\n", ProcName);
  1772. exit(1);
  1773. }
  1774. adsp_close_socket(&s1);
  1775. at_printer_setstatus("Printing");
  1776. return(0);
  1777. }
  1778. void at_printer_kill(void)
  1779. {
  1780. char scratch[32];
  1781. /* This whole sequence was determined by examining packet dumps.
  1782. If you don't get it just right, after the disconnect the printer
  1783. tries to open a new connection to the original control socket.
  1784. */
  1785. adsp_fwd_reset(&end2);
  1786. /* Make sure there isn't pending input. */
  1787. adsp_read_nonblock(&end2, scratch, 32);
  1788. scratch[0] = 0;
  1789. adsp_write(&end2, scratch, 1);
  1790. comm_printer_writeFFFx('I');
  1791. scratch[0] = 0x00;
  1792. adsp_write_attn(&end2, 0x0012, scratch, 1);
  1793. adsp_read(&end2, scratch, 2);
  1794. adsp_disconnect(&end2);
  1795. adsp_close_socket(&s2);
  1796. }
  1797. void at_printer_setstatus(char *status)
  1798. {
  1799. char buf[257];
  1800. buf[0] = 0x06;
  1801. buf[1] = 0x47;
  1802. buf[2] = strlen(status);
  1803. strncpy(buf + 3, status, buf[2]);
  1804. adsp_write_attn(&end2, 0x000a, buf, 257);
  1805. adsp_read(&end2, buf, 2);
  1806. }
  1807. #endif